diff options
271 files changed, 18486 insertions, 17020 deletions
@@ -273,3 +273,5 @@ a01ef9bed28627f4ca543fbc1d70c79cc297a90f 3.2.9-beta2  987425b1acf4752379b2e1eb20944b4b35d67a85 3.2.8-beta2  d5f263687f43f278107363365938f0a214920a4b 3.3.0-start  dffd0457ee0745de65bf95f0642a5c9e46b8e2f0 viewer-beta-candidate +d5f263687f43f278107363365938f0a214920a4b DRTVWR-119 +d5f263687f43f278107363365938f0a214920a4b 3.3.0-beta1 diff --git a/doc/contributions.txt b/doc/contributions.txt index c5db396c97..3851e62cfb 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -103,6 +103,7 @@ Aleric Inglewood  	STORM-163  	STORM-955  	STORM-960 +	STORM-1793  Ales Beaumont  	VWR-9352  	SNOW-240 @@ -466,6 +467,8 @@ Hiro Sommambulist  	VWR-132  	VWR-136  	VWR-143 +Hitomi Tiponi +	STORM-1741  Holger Gilruth  Horatio Freund  Hoze Menges @@ -594,22 +597,34 @@ Jonathan Yap  	STORM-1659  	STORM-1674  	STORM-1685 +	STORM-1718  	STORM-1721 +	STORM-1718  	STORM-1727  	STORM-1725  	STORM-1719  	STORM-1712  	STORM-1728  	STORM-1736 +	STORM-1804  	STORM-1734  	STORM-1731  	STORM-653  	STORM-1737  	STORM-1733 +	STORM-1741  	STORM-1790 +	STORM-1795  	STORM-1788 +	STORM-1803 +	STORM-1795  	STORM-1799  	STORM-1796 +	STORM-1807 +	STORM-1808 +	STORM-1809 +	STORM-1793 +	STORM-1810  Kadah Coba  	STORM-1060  Jondan Lundquist @@ -645,6 +660,7 @@ Kitty Barnett  	STORM-1001  	STORM-1175      VWR-24217 +	STORM-1804  Kolor Fall  Komiko Okamoto  Korvel Noh @@ -1239,6 +1255,8 @@ WolfPup Lowenhar  	VWR-20741  	VWR-20933  Wundur Primbee +Xellessanova Zenith +	STORM-1793  Xiki Luik  xstorm Radek  YongYong Francois diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index f0b44f97d2..7f747c2eca 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -215,7 +215,7 @@ BOOL LLVorbisDecodeState::initDecode()  		return(FALSE);  	} -	S32 sample_count = ov_pcm_total(&mVF, -1); +	S32 sample_count = (S32)ov_pcm_total(&mVF, -1);  	size_t size_guess = (size_t)sample_count;  	vorbis_info* vi = ov_info(&mVF, -1);  	size_guess *= (vi? vi->channels : 1); diff --git a/indra/llaudio/llaudioengine.h b/indra/llaudio/llaudioengine.h index a47ee7ca7c..28b69e1973 100644 --- a/indra/llaudio/llaudioengine.h +++ b/indra/llaudio/llaudioengine.h @@ -37,6 +37,7 @@  #include "lluuid.h"  #include "llframetimer.h"  #include "llassettype.h" +#include "llextendedstatus.h"  #include "lllistener.h" diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index f3cf950afa..2a0df26384 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -1570,7 +1570,7 @@ BOOL LLBVHLoader::serialize(LLDataPacker& dp)  		constraint_it++)  		{  			U8 byte = constraint_it->mChainLength; -			dp.packU8(byte, "chain_lenght"); +			dp.packU8(byte, "chain_length");  			byte = constraint_it->mConstraintType;  			dp.packU8(byte, "constraint_type"); diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h index bdcc98e402..5cfcdab41c 100644 --- a/indra/llcommon/linden_common.h +++ b/indra/llcommon/linden_common.h @@ -52,34 +52,11 @@  #include <ctime>  #include <iosfwd> -// Work around Microsoft compiler warnings in STL headers -#ifdef LL_WINDOWS -#pragma warning (disable : 4702) // unreachable code -#pragma warning (disable : 4244) // conversion from time_t to S32 -#endif	//	LL_WINDOWS - -// *TODO: Eliminate these, most library .cpp files don't need them. -// Add them to llviewerprecompiledheaders.h if necessary. -#include <list> -#include <map> -#include <vector> -#include <string> - -#ifdef LL_WINDOWS -// Reenable warnings we disabled above -#pragma warning (3 : 4702) // unreachable code, we like level 3, not 4 -// moved msvc warnings to llpreprocessor.h  *TODO - delete this comment after merge conflicts are unlikely -brad -#endif	//	LL_WINDOWS -  // Linden only libs in alpha-order other than stdtypes.h  // *NOTE: Please keep includes here to a minimum, see above.  #include "stdtypes.h"  #include "lldefs.h"  #include "llerror.h" -#include "llextendedstatus.h" -// Don't do this, adds 15K lines of header code to every library file. -//#include "llfasttimer.h"  #include "llfile.h" -#include "llformat.h"  #endif diff --git a/indra/llcommon/llavatarname.cpp b/indra/llcommon/llavatarname.cpp index ba3dd6d6b4..3206843bf4 100644 --- a/indra/llcommon/llavatarname.cpp +++ b/indra/llcommon/llavatarname.cpp @@ -106,6 +106,11 @@ std::string LLAvatarName::getCompleteName() const  std::string LLAvatarName::getLegacyName() const  { +	if (mLegacyFirstName.empty() && mLegacyLastName.empty()) // display names disabled? +	{ +		return mDisplayName; +	} +  	std::string name;  	name.reserve( mLegacyFirstName.size() + 1 + mLegacyLastName.size() );  	name = mLegacyFirstName; diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index db1ea4792b..0855180dcd 100644 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -430,13 +430,13 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL      {          // The new node isn't last. Place it between the previous node and          // the successor. -        newNode = (myprev + mydmi->second)/2.0; +        newNode = (myprev + mydmi->second)/2.f;      }      else      {          // The new node is last. Bump myprev up to the next integer, add          // 1.0 and use that. -        newNode = std::ceil(myprev) + 1.0; +        newNode = std::ceil(myprev) + 1.f;      }      // Now that newNode has a value that places it appropriately in mSignal,      // connect it. diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 75fde8e5ba..1409c55d1c 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -175,7 +175,7 @@ void LLMD5::update(std::istream& stream){    while (stream.good()){      stream.read( (char*)buffer, BLOCK_LEN); 	/* Flawfinder: ignore */		// note that return value of read is unusable. -    len=stream.gcount(); +    len=(int)stream.gcount();      update(buffer, len);    } diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h index 31d5f3d2c7..7fdb537ab5 100644 --- a/indra/llcommon/llpreprocessor.h +++ b/indra/llcommon/llpreprocessor.h @@ -132,7 +132,7 @@  #pragma warning( 3       : 4265 )	// "class has virtual functions, but destructor is not virtual"  #pragma warning( 3      :  4266 )	// 'function' : no override available for virtual member function from base 'type'; function is hidden  #pragma warning (disable : 4180)	// qualifier applied to function type has no meaning; ignored -#pragma warning( disable : 4284 )	// silly MS warning deep inside their <map> include file +//#pragma warning( disable : 4284 )	// silly MS warning deep inside their <map> include file  #pragma warning( disable : 4503 )	// 'decorated name length exceeded, name was truncated'. Does not seem to affect compilation.  #pragma warning( disable : 4800 )	// 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)  #pragma warning( disable : 4996 )	// warning: deprecated @@ -152,6 +152,7 @@  #pragma warning (disable : 4251) // member needs to have dll-interface to be used by clients of class  #pragma warning (disable : 4275) // non dll-interface class used as base for dll-interface class  #pragma warning (disable : 4018) // '<' : signed/unsigned mismatch	 +  #endif	//	LL_MSVC  #if LL_WINDOWS diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 4722421fca..bc66832ad0 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -1,2249 +1,2249 @@ -/**  - * @file llsdserialize.cpp - * @author Phoenix - * @date 2006-03-05 - * @brief Implementation of LLSD parsers and formatters - * - * $LicenseInfo:firstyear=2006&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 "linden_common.h" -#include "llsdserialize.h" -#include "llpointer.h" -#include "llstreamtools.h" // for fullread - -#include <iostream> -#include "apr_base64.h" - -#ifdef LL_STANDALONE -# include <zlib.h> -#else -# include "zlib/zlib.h"  // for davep's dirty little zip functions -#endif - -#if !LL_WINDOWS -#include <netinet/in.h> // htonl & ntohl -#endif - -#include "lldate.h" -#include "llsd.h" -#include "llstring.h" -#include "lluri.h" - -// File constants -static const int MAX_HDR_LEN = 20; -static const char LEGACY_NON_HEADER[] = "<llsd>"; -const std::string LLSD_BINARY_HEADER("LLSD/Binary"); -const std::string LLSD_XML_HEADER("LLSD/XML"); - -//used to deflate a gzipped asset (currently used for navmeshes) +/** 
 + * @file llsdserialize.cpp
 + * @author Phoenix
 + * @date 2006-03-05
 + * @brief Implementation of LLSD parsers and formatters
 + *
 + * $LicenseInfo:firstyear=2006&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 "linden_common.h"
 +#include "llsdserialize.h"
 +#include "llpointer.h"
 +#include "llstreamtools.h" // for fullread
 +
 +#include <iostream>
 +#include "apr_base64.h"
 +
 +#ifdef LL_STANDALONE
 +# include <zlib.h>
 +#else
 +# include "zlib/zlib.h"  // for davep's dirty little zip functions
 +#endif
 +
 +#if !LL_WINDOWS
 +#include <netinet/in.h> // htonl & ntohl
 +#endif
 +
 +#include "lldate.h"
 +#include "llsd.h"
 +#include "llstring.h"
 +#include "lluri.h"
 +
 +// File constants
 +static const int MAX_HDR_LEN = 20;
 +static const char LEGACY_NON_HEADER[] = "<llsd>";
 +const std::string LLSD_BINARY_HEADER("LLSD/Binary");
 +const std::string LLSD_XML_HEADER("LLSD/XML");
 +
 +//used to deflate a gzipped asset (currently used for navmeshes)
  #define windowBits 15
  #define ENABLE_ZLIB_GZIP 32
 - -/** - * LLSDSerialize - */ - -// static -void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options) -{ -	LLPointer<LLSDFormatter> f = NULL; - -	switch (type) -	{ -	case LLSD_BINARY: -		str << "<? " << LLSD_BINARY_HEADER << " ?>\n"; -		f = new LLSDBinaryFormatter; -		break; - -	case LLSD_XML: -		str << "<? " << LLSD_XML_HEADER << " ?>\n"; -		f = new LLSDXMLFormatter; -		break; - -	default: -		llwarns << "serialize request for unknown ELLSD_Serialize" << llendl; -	} - -	if (f.notNull()) -	{ -		f->format(sd, str, options); -	} -} - -// static -bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes) -{ -	LLPointer<LLSDParser> p = NULL; -	char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */ -	int i; -	int inbuf = 0; -	bool legacy_no_header = false; -	bool fail_if_not_legacy = false; -	std::string header; - -	/* -	 * Get the first line before anything. -	 */ -	str.get(hdr_buf, MAX_HDR_LEN, '\n'); -	if (str.fail()) -	{ -		str.clear(); -		fail_if_not_legacy = true; -	} - -	if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */ -	{ -		legacy_no_header = true; -		inbuf = str.gcount(); -	} -	else -	{ -		if (fail_if_not_legacy) -			goto fail; -		/* -		* Remove the newline chars -		*/ -		for (i = 0; i < MAX_HDR_LEN; i++) -		{ -			if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' || -				hdr_buf[i] == '\n') -			{ -				hdr_buf[i] = 0; -				break; -			} -		} -		header = hdr_buf; - -		std::string::size_type start = std::string::npos; -		std::string::size_type end = std::string::npos; -		start = header.find_first_not_of("<? "); -		if (start != std::string::npos) -		{ -			end = header.find_first_of(" ?", start); -		} -		if ((start == std::string::npos) || (end == std::string::npos)) -			goto fail; - -		header = header.substr(start, end - start); -		ws(str); -	} -	/* -	 * Create the parser as appropriate -	 */ -	if (legacy_no_header) -	{	// Create a LLSD XML parser, and parse the first chunk read above -		LLSDXMLParser* x = new LLSDXMLParser(); -		x->parsePart(hdr_buf, inbuf);	// Parse the first part that was already read -		x->parseLines(str, sd);			// Parse the rest of it -		delete x; -		return true; -	} - -	if (header == LLSD_BINARY_HEADER) -	{ -		p = new LLSDBinaryParser; -	} -	else if (header == LLSD_XML_HEADER) -	{ -		p = new LLSDXMLParser; -	} -	else -	{ -		llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl; -	} - -	if (p.notNull()) -	{ -		p->parse(str, sd, max_bytes); -		return true; -	} - -fail: -	llwarns << "deserialize LLSD parse failure" << llendl; -	return false; -} - -/** - * Endian handlers - */ -#if LL_BIG_ENDIAN -U64 ll_htonll(U64 hostlonglong) { return hostlonglong; } -U64 ll_ntohll(U64 netlonglong) { return netlonglong; } -F64 ll_htond(F64 hostlonglong) { return hostlonglong; } -F64 ll_ntohd(F64 netlonglong) { return netlonglong; } -#else -// I read some comments one a indicating that doing an integer add -// here would be faster than a bitwise or. For now, the or has -// programmer clarity, since the intended outcome matches the -// operation. -U64 ll_htonll(U64 hostlonglong) -{ -	return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) | -			((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32)); -} -U64 ll_ntohll(U64 netlonglong) -{ -	return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) | -			((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32)); -} -union LLEndianSwapper -{ -	F64 d; -	U64 i; -}; -F64 ll_htond(F64 hostdouble) -{ -	LLEndianSwapper tmp; -	tmp.d = hostdouble; -	tmp.i = ll_htonll(tmp.i); -	return tmp.d; -} -F64 ll_ntohd(F64 netdouble) -{ -	LLEndianSwapper tmp; -	tmp.d = netdouble; -	tmp.i = ll_ntohll(tmp.i); -	return tmp.d; -} -#endif - -/** - * Local functions. - */ -/** - * @brief Figure out what kind of string it is (raw or delimited) and handoff. - * - * @param istr The stream to read from. - * @param value [out] The string which was found. - * @param max_bytes The maximum possible length of the string. Passing in - * a negative value will skip this check. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes); - -/** - * @brief Parse a delimited string.  - * - * @param istr The stream to read from, with the delimiter already popped. - * @param value [out] The string which was found. - * @param d The delimiter to use. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_string_delim(std::istream& istr, std::string& value, char d); - -/** - * @brief Read a raw string off the stream. - * - * @param istr The stream to read from, with the (len) parameter - * leading the stream. - * @param value [out] The string which was found. - * @param d The delimiter to use. - * @param max_bytes The maximum possible length of the string. Passing in - * a negative value will skip this check. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_string_raw( -	std::istream& istr, -	std::string& value, -	S32 max_bytes); - -/** - * @brief helper method for dealing with the different notation boolean format. - * - * @param istr The stream to read from with the leading character stripped. - * @param data [out] the result of the parse. - * @param compare The string to compare the boolean against - * @param vale The value to assign to data if the parse succeeds. - * @return Returns number of bytes read off of the stream. Returns - * PARSE_FAILURE (-1) on failure. - */ -int deserialize_boolean( -	std::istream& istr, -	LLSD& data, -	const std::string& compare, -	bool value); - -/** - * @brief Do notation escaping of a string to an ostream. - * - * @param value The string to escape and serialize - * @param str The stream to serialize to. - */ -void serialize_string(const std::string& value, std::ostream& str); - - -/** - * Local constants. - */ -static const std::string NOTATION_TRUE_SERIAL("true"); -static const std::string NOTATION_FALSE_SERIAL("false"); - -static const char BINARY_TRUE_SERIAL = '1'; -static const char BINARY_FALSE_SERIAL = '0'; - - -/** - * LLSDParser - */ -LLSDParser::LLSDParser() -	: mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false) -{ -} - -// virtual -LLSDParser::~LLSDParser() -{ } - -S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes) -{ -	mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true; -	mMaxBytesLeft = max_bytes; -	return doParse(istr, data); -} - - -// Parse using routine to get() lines, faster than parse() -S32 LLSDParser::parseLines(std::istream& istr, LLSD& data) -{ -	mCheckLimits = false; -	mParseLines = true; -	return doParse(istr, data); -} - - -int LLSDParser::get(std::istream& istr) const -{ -	if(mCheckLimits) --mMaxBytesLeft; -	return istr.get(); -} - -std::istream& LLSDParser::get( -	std::istream& istr, -	char* s, -	std::streamsize n, -	char delim) const -{ -	istr.get(s, n, delim); -	if(mCheckLimits) mMaxBytesLeft -= istr.gcount(); -	return istr; -} - -std::istream& LLSDParser::get( -		std::istream& istr, -		std::streambuf& sb, -		char delim) const		 -{ -	istr.get(sb, delim); -	if(mCheckLimits) mMaxBytesLeft -= istr.gcount(); -	return istr; -} - -std::istream& LLSDParser::ignore(std::istream& istr) const -{ -	istr.ignore(); -	if(mCheckLimits) --mMaxBytesLeft; -	return istr; -} - -std::istream& LLSDParser::putback(std::istream& istr, char c) const -{ -	istr.putback(c); -	if(mCheckLimits) ++mMaxBytesLeft; -	return istr; -} - -std::istream& LLSDParser::read( -	std::istream& istr, -	char* s, -	std::streamsize n) const -{ -	istr.read(s, n); -	if(mCheckLimits) mMaxBytesLeft -= istr.gcount(); -	return istr; -} - -void LLSDParser::account(S32 bytes) const -{ -	if(mCheckLimits) mMaxBytesLeft -= bytes; -} - - -/** - * LLSDNotationParser - */ -LLSDNotationParser::LLSDNotationParser() -{ -}	 - -// virtual -LLSDNotationParser::~LLSDNotationParser() -{ } - -// virtual -S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const -{ -	// map: { string:object, string:object } -	// array: [ object, object, object ] -	// undef: ! -	// boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE -	// integer: i#### -	// real: r#### -	// uuid: u#### -	// string: "g'day" | 'have a "nice" day' | s(size)"raw data" -	// uri: l"escaped" -	// date: d"YYYY-MM-DDTHH:MM:SS.FFZ" -	// binary: b##"ff3120ab1" | b(size)"raw data" -	char c; -	c = istr.peek(); -	while(isspace(c)) -	{ -		// pop the whitespace. -		c = get(istr); -		c = istr.peek(); -		continue; -	} -	if(!istr.good()) -	{ -		return 0; -	} -	S32 parse_count = 1; -	switch(c) -	{ -	case '{': -	{ -		S32 child_count = parseMap(istr, data); -		if((child_count == PARSE_FAILURE) || data.isUndefined()) -		{ -			parse_count = PARSE_FAILURE; -		} -		else -		{ -			parse_count += child_count; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading map." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case '[': -	{ -		S32 child_count = parseArray(istr, data); -		if((child_count == PARSE_FAILURE) || data.isUndefined()) -		{ -			parse_count = PARSE_FAILURE; -		} -		else -		{ -			parse_count += child_count; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading array." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case '!': -		c = get(istr); -		data.clear(); -		break; - -	case '0': -		c = get(istr); -		data = false; -		break; - -	case 'F': -	case 'f': -		ignore(istr); -		c = istr.peek(); -		if(isalpha(c)) -		{ -			int cnt = deserialize_boolean( -				istr, -				data, -				NOTATION_FALSE_SERIAL, -				false); -			if(PARSE_FAILURE == cnt) parse_count = cnt; -			else account(cnt); -		} -		else -		{ -			data = false; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading boolean." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; - -	case '1': -		c = get(istr); -		data = true; -		break; - -	case 'T': -	case 't': -		ignore(istr); -		c = istr.peek(); -		if(isalpha(c)) -		{ -			int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true); -			if(PARSE_FAILURE == cnt) parse_count = cnt; -			else account(cnt); -		} -		else -		{ -			data = true; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading boolean." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; - -	case 'i': -	{ -		c = get(istr); -		S32 integer = 0; -		istr >> integer; -		data = integer; -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading integer." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case 'r': -	{ -		c = get(istr); -		F64 real = 0.0; -		istr >> real; -		data = real; -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading real." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case 'u': -	{ -		c = get(istr); -		LLUUID id; -		istr >> id; -		data = id; -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading uuid." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case '\"': -	case '\'': -	case 's': -		if(!parseString(istr, data)) -		{ -			parse_count = PARSE_FAILURE; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading string." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; - -	case 'l': -	{ -		c = get(istr); // pop the 'l' -		c = get(istr); // pop the delimiter -		std::string str; -		int cnt = deserialize_string_delim(istr, str, c); -		if(PARSE_FAILURE == cnt) -		{ -			parse_count = PARSE_FAILURE; -		} -		else -		{ -			data = LLURI(str); -			account(cnt); -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading link." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case 'd': -	{ -		c = get(istr); // pop the 'd' -		c = get(istr); // pop the delimiter -		std::string str; -		int cnt = deserialize_string_delim(istr, str, c); -		if(PARSE_FAILURE == cnt) -		{ -			parse_count = PARSE_FAILURE; -		} -		else -		{ -			data = LLDate(str); -			account(cnt); -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading date." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case 'b': -		if(!parseBinary(istr, data)) -		{ -			parse_count = PARSE_FAILURE; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading data." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; - -	default: -		parse_count = PARSE_FAILURE; -		llinfos << "Unrecognized character while parsing: int(" << (int)c -			<< ")" << llendl; -		break; -	} -	if(PARSE_FAILURE == parse_count) -	{ -		data.clear(); -	} -	return parse_count; -} - -S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const -{ -	// map: { string:object, string:object } -	map = LLSD::emptyMap(); -	S32 parse_count = 0; -	char c = get(istr); -	if(c == '{') -	{ -		// eat commas, white -		bool found_name = false; -		std::string name; -		c = get(istr); -		while(c != '}' && istr.good()) -		{ -			if(!found_name) -			{ -				if((c == '\"') || (c == '\'') || (c == 's')) -				{ -					putback(istr, c); -					found_name = true; -					int count = deserialize_string(istr, name, mMaxBytesLeft); -					if(PARSE_FAILURE == count) return PARSE_FAILURE; -					account(count); -				} -				c = get(istr); -			} -			else -			{ -				if(isspace(c) || (c == ':')) -				{ -					c = get(istr); -					continue; -				} -				putback(istr, c); -				LLSD child; -				S32 count = doParse(istr, child); -				if(count > 0) -				{ -					// There must be a value for every key, thus -					// child_count must be greater than 0. -					parse_count += count; -					map.insert(name, child); -				} -				else -				{ -					return PARSE_FAILURE; -				} -				found_name = false; -				c = get(istr); -			} -		} -		if(c != '}') -		{ -			map.clear(); -			return PARSE_FAILURE; -		} -	} -	return parse_count; -} - -S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const -{ -	// array: [ object, object, object ] -	array = LLSD::emptyArray(); -	S32 parse_count = 0; -	char c = get(istr); -	if(c == '[') -	{ -		// eat commas, white -		c = get(istr); -		while((c != ']') && istr.good()) -		{ -			LLSD child; -			if(isspace(c) || (c == ',')) -			{ -				c = get(istr); -				continue; -			} -			putback(istr, c); -			S32 count = doParse(istr, child); -			if(PARSE_FAILURE == count) -			{ -				return PARSE_FAILURE; -			} -			else -			{ -				parse_count += count; -				array.append(child); -			} -			c = get(istr); -		} -		if(c != ']') -		{ -			return PARSE_FAILURE; -		} -	} -	return parse_count; -} - -bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const -{ -	std::string value; -	int count = deserialize_string(istr, value, mMaxBytesLeft); -	if(PARSE_FAILURE == count) return false; -	account(count); -	data = value; -	return true; -} - -bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const -{ -	// binary: b##"ff3120ab1" -	// or: b(len)"..." - -	// I want to manually control those values here to make sure the -	// parser doesn't break when someone changes a constant somewhere -	// else. -	const U32 BINARY_BUFFER_SIZE = 256; -	const U32 STREAM_GET_COUNT = 255; - -	// need to read the base out. -	char buf[BINARY_BUFFER_SIZE];		/* Flawfinder: ignore */ -	get(istr, buf, STREAM_GET_COUNT, '"'); -	char c = get(istr); -	if(c != '"') return false; -	if(0 == strncmp("b(", buf, 2)) -	{ -		// We probably have a valid raw binary stream. determine -		// the size, and read it. -		S32 len = strtol(buf + 2, NULL, 0); -		if(mCheckLimits && (len > mMaxBytesLeft)) return false; -		std::vector<U8> value; -		if(len) -		{ -			value.resize(len); -			account(fullread(istr, (char *)&value[0], len)); -		} -		c = get(istr); // strip off the trailing double-quote -		data = value; -	} -	else if(0 == strncmp("b64", buf, 3)) -	{ -		// *FIX: A bit inefficient, but works for now. To make the -		// format better, I would need to add a hint into the -		// serialization format that indicated how long it was. -		std::stringstream coded_stream; -		get(istr, *(coded_stream.rdbuf()), '\"'); -		c = get(istr); -		std::string encoded(coded_stream.str()); -		S32 len = apr_base64_decode_len(encoded.c_str()); -		std::vector<U8> value; -		if(len) -		{ -			value.resize(len); -			len = apr_base64_decode_binary(&value[0], encoded.c_str()); -			value.resize(len); -		} -		data = value; -	} -	else if(0 == strncmp("b16", buf, 3)) -	{ -		// yay, base 16. We pop the next character which is either a -		// double quote or base 16 data. If it's a double quote, we're -		// done parsing. If it's not, put the data back, and read the -		// stream until the next double quote. -		char* read;	 /*Flawfinder: ignore*/ -		U8 byte; -		U8 byte_buffer[BINARY_BUFFER_SIZE]; -		U8* write; -		std::vector<U8> value; -		c = get(istr); -		while(c != '"') -		{ -			putback(istr, c); -			read = buf; -			write = byte_buffer; -			get(istr, buf, STREAM_GET_COUNT, '"'); -			c = get(istr); -			while(*read != '\0')	 /*Flawfinder: ignore*/ -			{ -				byte = hex_as_nybble(*read++); -				byte = byte << 4; -				byte |= hex_as_nybble(*read++); -				*write++ = byte; -			} -			// copy the data out of the byte buffer -			value.insert(value.end(), byte_buffer, write); -		} -		data = value; -	} -	else -	{ -		return false; -	} -	return true; -} - - -/** - * LLSDBinaryParser - */ -LLSDBinaryParser::LLSDBinaryParser() -{ -} - -// virtual -LLSDBinaryParser::~LLSDBinaryParser() -{ -} - -// virtual -S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const -{ -/** - * Undefined: '!'<br> - * Boolean: 't' for true 'f' for false<br> - * Integer: 'i' + 4 bytes network byte order<br> - * Real: 'r' + 8 bytes IEEE double<br> - * UUID: 'u' + 16 byte unsigned integer<br> - * String: 's' + 4 byte integer size + string<br> - *  strings also secretly support the notation format - * Date: 'd' + 8 byte IEEE double for seconds since epoch<br> - * URI: 'l' + 4 byte integer size + string uri<br> - * Binary: 'b' + 4 byte integer size + binary data<br> - * Array: '[' + 4 byte integer size  + all values + ']'<br> - * Map: '{' + 4 byte integer size  every(key + value) + '}'<br> - *  map keys are serialized as s + 4 byte integer size + string or in the - *  notation format. - */ -	char c; -	c = get(istr); -	if(!istr.good()) -	{ -		return 0; -	} -	S32 parse_count = 1; -	switch(c) -	{ -	case '{': -	{ -		S32 child_count = parseMap(istr, data); -		if((child_count == PARSE_FAILURE) || data.isUndefined()) -		{ -			parse_count = PARSE_FAILURE; -		} -		else -		{ -			parse_count += child_count; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading binary map." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case '[': -	{ -		S32 child_count = parseArray(istr, data); -		if((child_count == PARSE_FAILURE) || data.isUndefined()) -		{ -			parse_count = PARSE_FAILURE; -		} -		else -		{ -			parse_count += child_count; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading binary array." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case '!': -		data.clear(); -		break; - -	case '0': -		data = false; -		break; - -	case '1': -		data = true; -		break; - -	case 'i': -	{ -		U32 value_nbo = 0; -		read(istr, (char*)&value_nbo, sizeof(U32));	 /*Flawfinder: ignore*/ -		data = (S32)ntohl(value_nbo); -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading binary integer." << llendl; -		} -		break; -	} - -	case 'r': -	{ -		F64 real_nbo = 0.0; -		read(istr, (char*)&real_nbo, sizeof(F64));	 /*Flawfinder: ignore*/ -		data = ll_ntohd(real_nbo); -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading binary real." << llendl; -		} -		break; -	} - -	case 'u': -	{ -		LLUUID id; -		read(istr, (char*)(&id.mData), UUID_BYTES);	 /*Flawfinder: ignore*/ -		data = id; -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading binary uuid." << llendl; -		} -		break; -	} - -	case '\'': -	case '"': -	{ -		std::string value; -		int cnt = deserialize_string_delim(istr, value, c); -		if(PARSE_FAILURE == cnt) -		{ -			parse_count = PARSE_FAILURE; -		} -		else -		{ -			data = value; -			account(cnt); -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading binary (notation-style) string." -				<< llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case 's': -	{ -		std::string value; -		if(parseString(istr, value)) -		{ -			data = value; -		} -		else -		{ -			parse_count = PARSE_FAILURE; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading binary string." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case 'l': -	{ -		std::string value; -		if(parseString(istr, value)) -		{ -			data = LLURI(value); -		} -		else -		{ -			parse_count = PARSE_FAILURE; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading binary link." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case 'd': -	{ -		F64 real = 0.0; -		read(istr, (char*)&real, sizeof(F64));	 /*Flawfinder: ignore*/ -		data = LLDate(real); -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading binary date." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	case 'b': -	{ -		// We probably have a valid raw binary stream. determine -		// the size, and read it. -		U32 size_nbo = 0; -		read(istr, (char*)&size_nbo, sizeof(U32));	/*Flawfinder: ignore*/ -		S32 size = (S32)ntohl(size_nbo); -		if(mCheckLimits && (size > mMaxBytesLeft)) -		{ -			parse_count = PARSE_FAILURE; -		} -		else -		{ -			std::vector<U8> value; -			if(size > 0) -			{ -				value.resize(size); -				account(fullread(istr, (char*)&value[0], size)); -			} -			data = value; -		} -		if(istr.fail()) -		{ -			llinfos << "STREAM FAILURE reading binary." << llendl; -			parse_count = PARSE_FAILURE; -		} -		break; -	} - -	default: -		parse_count = PARSE_FAILURE; -		llinfos << "Unrecognized character while parsing: int(" << (int)c -			<< ")" << llendl; -		break; -	} -	if(PARSE_FAILURE == parse_count) -	{ -		data.clear(); -	} -	return parse_count; -} - -S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const -{ -	map = LLSD::emptyMap(); -	U32 value_nbo = 0; -	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/ -	S32 size = (S32)ntohl(value_nbo); -	S32 parse_count = 0; -	S32 count = 0; -	char c = get(istr); -	while(c != '}' && (count < size) && istr.good()) -	{ -		std::string name; -		switch(c) -		{ -		case 'k': -			if(!parseString(istr, name)) -			{ -				return PARSE_FAILURE; -			} -			break; -		case '\'': -		case '"': -		{ -			int cnt = deserialize_string_delim(istr, name, c); -			if(PARSE_FAILURE == cnt) return PARSE_FAILURE; -			account(cnt); -			break; -		} -		} -		LLSD child; -		S32 child_count = doParse(istr, child); -		if(child_count > 0) -		{ -			// There must be a value for every key, thus child_count -			// must be greater than 0. -			parse_count += child_count; -			map.insert(name, child); -		} -		else -		{ -			return PARSE_FAILURE; -		} -		++count; -		c = get(istr); -	} -	if((c != '}') || (count < size)) -	{ -		// Make sure it is correctly terminated and we parsed as many -		// as were said to be there. -		return PARSE_FAILURE; -	} -	return parse_count; -} - -S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const -{ -	array = LLSD::emptyArray(); -	U32 value_nbo = 0; -	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/ -	S32 size = (S32)ntohl(value_nbo); - -	// *FIX: This would be a good place to reserve some space in the -	// array... - -	S32 parse_count = 0; -	S32 count = 0; -	char c = istr.peek(); -	while((c != ']') && (count < size) && istr.good()) -	{ -		LLSD child; -		S32 child_count = doParse(istr, child); -		if(PARSE_FAILURE == child_count) -		{ -			return PARSE_FAILURE; -		} -		if(child_count) -		{ -			parse_count += child_count; -			array.append(child); -		} -		++count; -		c = istr.peek(); -	} -	c = get(istr); -	if((c != ']') || (count < size)) -	{ -		// Make sure it is correctly terminated and we parsed as many -		// as were said to be there. -		return PARSE_FAILURE; -	} -	return parse_count; -} - -bool LLSDBinaryParser::parseString( -	std::istream& istr, -	std::string& value) const -{ -	// *FIX: This is memory inefficient. -	U32 value_nbo = 0; -	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/ -	S32 size = (S32)ntohl(value_nbo); -	if(mCheckLimits && (size > mMaxBytesLeft)) return false; -	std::vector<char> buf; -	if(size) -	{ -		buf.resize(size); -		account(fullread(istr, &buf[0], size)); -		value.assign(buf.begin(), buf.end()); -	} -	return true; -} - - -/** - * LLSDFormatter - */ -LLSDFormatter::LLSDFormatter() : -	mBoolAlpha(false) -{ -} - -// virtual -LLSDFormatter::~LLSDFormatter() -{ } - -void LLSDFormatter::boolalpha(bool alpha) -{ -	mBoolAlpha = alpha; -} - -void LLSDFormatter::realFormat(const std::string& format) -{ -	mRealFormat = format; -} - -void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const -{ -	std::string buffer = llformat(mRealFormat.c_str(), real); -	ostr << buffer; -} - -/** - * LLSDNotationFormatter - */ -LLSDNotationFormatter::LLSDNotationFormatter() -{ -} - -// virtual -LLSDNotationFormatter::~LLSDNotationFormatter() -{ } - -// static -std::string LLSDNotationFormatter::escapeString(const std::string& in) -{ -	std::ostringstream ostr; -	serialize_string(in, ostr); -	return ostr.str(); -} - -// virtual -S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const -{ -	S32 format_count = 1; -	switch(data.type()) -	{ -	case LLSD::TypeMap: -	{ -		ostr << "{"; -		bool need_comma = false; -		LLSD::map_const_iterator iter = data.beginMap(); -		LLSD::map_const_iterator end = data.endMap(); -		for(; iter != end; ++iter) -		{ -			if(need_comma) ostr << ","; -			need_comma = true; -			ostr << '\''; -			serialize_string((*iter).first, ostr); -			ostr << "':"; -			format_count += format((*iter).second, ostr); -		} -		ostr << "}"; -		break; -	} - -	case LLSD::TypeArray: -	{ -		ostr << "["; -		bool need_comma = false; -		LLSD::array_const_iterator iter = data.beginArray(); -		LLSD::array_const_iterator end = data.endArray(); -		for(; iter != end; ++iter) -		{ -			if(need_comma) ostr << ","; -			need_comma = true; -			format_count += format(*iter, ostr); -		} -		ostr << "]"; -		break; -	} - -	case LLSD::TypeUndefined: -		ostr << "!"; -		break; - -	case LLSD::TypeBoolean: -		if(mBoolAlpha || -#if( LL_WINDOWS || __GNUC__ > 2) -		   (ostr.flags() & std::ios::boolalpha) -#else -		   (ostr.flags() & 0x0100) -#endif -			) -		{ -			ostr << (data.asBoolean() -					 ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL); -		} -		else -		{ -			ostr << (data.asBoolean() ? 1 : 0); -		} -		break; - -	case LLSD::TypeInteger: -		ostr << "i" << data.asInteger(); -		break; - -	case LLSD::TypeReal: -		ostr << "r"; -		if(mRealFormat.empty()) -		{ -			ostr << data.asReal(); -		} -		else -		{ -			formatReal(data.asReal(), ostr); -		} -		break; - -	case LLSD::TypeUUID: -		ostr << "u" << data.asUUID(); -		break; - -	case LLSD::TypeString: -		ostr << '\''; -		serialize_string(data.asString(), ostr); -		ostr << '\''; -		break; - -	case LLSD::TypeDate: -		ostr << "d\"" << data.asDate() << "\""; -		break; - -	case LLSD::TypeURI: -		ostr << "l\""; -		serialize_string(data.asString(), ostr); -		ostr << "\""; -		break; - -	case LLSD::TypeBinary: -	{ -		// *FIX: memory inefficient. -		std::vector<U8> buffer = data.asBinary(); -		ostr << "b(" << buffer.size() << ")\""; -		if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); -		ostr << "\""; -		break; -	} - -	default: -		// *NOTE: This should never happen. -		ostr << "!"; -		break; -	} -	return format_count; -} - - -/** - * LLSDBinaryFormatter - */ -LLSDBinaryFormatter::LLSDBinaryFormatter() -{ -} - -// virtual -LLSDBinaryFormatter::~LLSDBinaryFormatter() -{ } - -// virtual -S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const -{ -	S32 format_count = 1; -	switch(data.type()) -	{ -	case LLSD::TypeMap: -	{ -		ostr.put('{'); -		U32 size_nbo = htonl(data.size()); -		ostr.write((const char*)(&size_nbo), sizeof(U32)); -		LLSD::map_const_iterator iter = data.beginMap(); -		LLSD::map_const_iterator end = data.endMap(); -		for(; iter != end; ++iter) -		{ -			ostr.put('k'); -			formatString((*iter).first, ostr); -			format_count += format((*iter).second, ostr); -		} -		ostr.put('}'); -		break; -	} - -	case LLSD::TypeArray: -	{ -		ostr.put('['); -		U32 size_nbo = htonl(data.size()); -		ostr.write((const char*)(&size_nbo), sizeof(U32)); -		LLSD::array_const_iterator iter = data.beginArray(); -		LLSD::array_const_iterator end = data.endArray(); -		for(; iter != end; ++iter) -		{ -			format_count += format(*iter, ostr); -		} -		ostr.put(']'); -		break; -	} - -	case LLSD::TypeUndefined: -		ostr.put('!'); -		break; - -	case LLSD::TypeBoolean: -		if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL); -		else ostr.put(BINARY_FALSE_SERIAL); -		break; - -	case LLSD::TypeInteger: -	{ -		ostr.put('i'); -		U32 value_nbo = htonl(data.asInteger()); -		ostr.write((const char*)(&value_nbo), sizeof(U32)); -		break; -	} - -	case LLSD::TypeReal: -	{ -		ostr.put('r'); -		F64 value_nbo = ll_htond(data.asReal()); -		ostr.write((const char*)(&value_nbo), sizeof(F64)); -		break; -	} - -	case LLSD::TypeUUID: -		ostr.put('u'); -		ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES); -		break; - -	case LLSD::TypeString: -		ostr.put('s'); -		formatString(data.asString(), ostr); -		break; - -	case LLSD::TypeDate: -	{ -		ostr.put('d'); -		F64 value = data.asReal(); -		ostr.write((const char*)(&value), sizeof(F64)); -		break; -	} - -	case LLSD::TypeURI: -		ostr.put('l'); -		formatString(data.asString(), ostr); -		break; - -	case LLSD::TypeBinary: -	{ -		// *FIX: memory inefficient. -		ostr.put('b'); -		std::vector<U8> buffer = data.asBinary(); -		U32 size_nbo = htonl(buffer.size()); -		ostr.write((const char*)(&size_nbo), sizeof(U32)); -		if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size()); -		break; -	} - -	default: -		// *NOTE: This should never happen. -		ostr.put('!'); -		break; -	} -	return format_count; -} - -void LLSDBinaryFormatter::formatString( -	const std::string& string, -	std::ostream& ostr) const -{ -	U32 size_nbo = htonl(string.size()); -	ostr.write((const char*)(&size_nbo), sizeof(U32)); -	ostr.write(string.c_str(), string.size()); -} - -/** - * local functions - */ -int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes) -{ -	int c = istr.get(); -	if(istr.fail()) -	{ -		// No data in stream, bail out but mention the character we -		// grabbed. -		return LLSDParser::PARSE_FAILURE; -	} - -	int rv = LLSDParser::PARSE_FAILURE; -	switch(c) -	{ -	case '\'': -	case '"': -		rv = deserialize_string_delim(istr, value, c); -		break; -	case 's': -		// technically, less than max_bytes, but this is just meant to -		// catch egregious protocol errors. parse errors will be -		// caught in the case of incorrect counts. -		rv = deserialize_string_raw(istr, value, max_bytes); -		break; -	default: -		break; -	} -	if(LLSDParser::PARSE_FAILURE == rv) return rv; -	return rv + 1; // account for the character grabbed at the top. -} - -int deserialize_string_delim( -	std::istream& istr, -	std::string& value, -	char delim) -{ -	std::ostringstream write_buffer; -	bool found_escape = false; -	bool found_hex = false; -	bool found_digit = false; -	U8 byte = 0; -	int count = 0; - -	while (true) -	{ -		int next_byte = istr.get(); -		++count; - -		if(istr.fail()) -		{ -			// If our stream is empty, break out -			value = write_buffer.str(); -			return LLSDParser::PARSE_FAILURE; -		} - -		char next_char = (char)next_byte; // Now that we know it's not EOF -		 -		if(found_escape) -		{ -			// next character(s) is a special sequence. -			if(found_hex) -			{ -				if(found_digit) -				{ -					found_digit = false; -					found_hex = false; -					found_escape = false; -					byte = byte << 4; -					byte |= hex_as_nybble(next_char); -					write_buffer << byte; -					byte = 0; -				} -				else -				{ -					// next character is the first nybble of -					// -					found_digit = true; -					byte = hex_as_nybble(next_char); -				} -			} -			else if(next_char == 'x') -			{ -				found_hex = true; -			} -			else -			{ -				switch(next_char) -				{ -				case 'a': -					write_buffer << '\a'; -					break; -				case 'b': -					write_buffer << '\b'; -					break; -				case 'f': -					write_buffer << '\f'; -					break; -				case 'n': -					write_buffer << '\n'; -					break; -				case 'r': -					write_buffer << '\r'; -					break; -				case 't': -					write_buffer << '\t'; -					break; -				case 'v': -					write_buffer << '\v'; -					break; -				default: -					write_buffer << next_char; -					break; -				} -				found_escape = false; -			} -		} -		else if(next_char == '\\') -		{ -			found_escape = true; -		} -		else if(next_char == delim) -		{ -			break; -		} -		else -		{ -			write_buffer << next_char; -		} -	} - -	value = write_buffer.str(); -	return count; -} - -int deserialize_string_raw( -	std::istream& istr, -	std::string& value, -	S32 max_bytes) -{ -	int count = 0; -	const S32 BUF_LEN = 20; -	char buf[BUF_LEN];		/* Flawfinder: ignore */ -	istr.get(buf, BUF_LEN - 1, ')'); -	count += istr.gcount(); -	int c = istr.get(); -	c = istr.get(); -	count += 2; -	if(((c == '"') || (c == '\'')) && (buf[0] == '(')) -	{ -		// We probably have a valid raw string. determine -		// the size, and read it. -		// *FIX: This is memory inefficient. -		S32 len = strtol(buf + 1, NULL, 0); -		if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE; -		std::vector<char> buf; -		if(len) -		{ -			buf.resize(len); -			count += fullread(istr, (char *)&buf[0], len); -			value.assign(buf.begin(), buf.end()); -		} -		c = istr.get(); -		++count; -		if(!((c == '"') || (c == '\''))) -		{ -			return LLSDParser::PARSE_FAILURE; -		} -	} -	else -	{ -		return LLSDParser::PARSE_FAILURE; -	} -	return count; -} - -static const char* NOTATION_STRING_CHARACTERS[256] = -{ -	"\\x00",	// 0 -	"\\x01",	// 1 -	"\\x02",	// 2 -	"\\x03",	// 3 -	"\\x04",	// 4 -	"\\x05",	// 5 -	"\\x06",	// 6 -	"\\a",		// 7 -	"\\b",		// 8 -	"\\t",		// 9 -	"\\n",		// 10 -	"\\v",		// 11 -	"\\f",		// 12 -	"\\r",		// 13 -	"\\x0e",	// 14 -	"\\x0f",	// 15 -	"\\x10",	// 16 -	"\\x11",	// 17 -	"\\x12",	// 18 -	"\\x13",	// 19 -	"\\x14",	// 20 -	"\\x15",	// 21 -	"\\x16",	// 22 -	"\\x17",	// 23 -	"\\x18",	// 24 -	"\\x19",	// 25 -	"\\x1a",	// 26 -	"\\x1b",	// 27 -	"\\x1c",	// 28 -	"\\x1d",	// 29 -	"\\x1e",	// 30 -	"\\x1f",	// 31 -	" ",		// 32 -	"!",		// 33 -	"\"",		// 34 -	"#",		// 35 -	"$",		// 36 -	"%",		// 37 -	"&",		// 38 -	"\\'",		// 39 -	"(",		// 40 -	")",		// 41 -	"*",		// 42 -	"+",		// 43 -	",",		// 44 -	"-",		// 45 -	".",		// 46 -	"/",		// 47 -	"0",		// 48 -	"1",		// 49 -	"2",		// 50 -	"3",		// 51 -	"4",		// 52 -	"5",		// 53 -	"6",		// 54 -	"7",		// 55 -	"8",		// 56 -	"9",		// 57 -	":",		// 58 -	";",		// 59 -	"<",		// 60 -	"=",		// 61 -	">",		// 62 -	"?",		// 63 -	"@",		// 64 -	"A",		// 65 -	"B",		// 66 -	"C",		// 67 -	"D",		// 68 -	"E",		// 69 -	"F",		// 70 -	"G",		// 71 -	"H",		// 72 -	"I",		// 73 -	"J",		// 74 -	"K",		// 75 -	"L",		// 76 -	"M",		// 77 -	"N",		// 78 -	"O",		// 79 -	"P",		// 80 -	"Q",		// 81 -	"R",		// 82 -	"S",		// 83 -	"T",		// 84 -	"U",		// 85 -	"V",		// 86 -	"W",		// 87 -	"X",		// 88 -	"Y",		// 89 -	"Z",		// 90 -	"[",		// 91 -	"\\\\",		// 92 -	"]",		// 93 -	"^",		// 94 -	"_",		// 95 -	"`",		// 96 -	"a",		// 97 -	"b",		// 98 -	"c",		// 99 -	"d",		// 100 -	"e",		// 101 -	"f",		// 102 -	"g",		// 103 -	"h",		// 104 -	"i",		// 105 -	"j",		// 106 -	"k",		// 107 -	"l",		// 108 -	"m",		// 109 -	"n",		// 110 -	"o",		// 111 -	"p",		// 112 -	"q",		// 113 -	"r",		// 114 -	"s",		// 115 -	"t",		// 116 -	"u",		// 117 -	"v",		// 118 -	"w",		// 119 -	"x",		// 120 -	"y",		// 121 -	"z",		// 122 -	"{",		// 123 -	"|",		// 124 -	"}",		// 125 -	"~",		// 126 -	"\\x7f",	// 127 -	"\\x80",	// 128 -	"\\x81",	// 129 -	"\\x82",	// 130 -	"\\x83",	// 131 -	"\\x84",	// 132 -	"\\x85",	// 133 -	"\\x86",	// 134 -	"\\x87",	// 135 -	"\\x88",	// 136 -	"\\x89",	// 137 -	"\\x8a",	// 138 -	"\\x8b",	// 139 -	"\\x8c",	// 140 -	"\\x8d",	// 141 -	"\\x8e",	// 142 -	"\\x8f",	// 143 -	"\\x90",	// 144 -	"\\x91",	// 145 -	"\\x92",	// 146 -	"\\x93",	// 147 -	"\\x94",	// 148 -	"\\x95",	// 149 -	"\\x96",	// 150 -	"\\x97",	// 151 -	"\\x98",	// 152 -	"\\x99",	// 153 -	"\\x9a",	// 154 -	"\\x9b",	// 155 -	"\\x9c",	// 156 -	"\\x9d",	// 157 -	"\\x9e",	// 158 -	"\\x9f",	// 159 -	"\\xa0",	// 160 -	"\\xa1",	// 161 -	"\\xa2",	// 162 -	"\\xa3",	// 163 -	"\\xa4",	// 164 -	"\\xa5",	// 165 -	"\\xa6",	// 166 -	"\\xa7",	// 167 -	"\\xa8",	// 168 -	"\\xa9",	// 169 -	"\\xaa",	// 170 -	"\\xab",	// 171 -	"\\xac",	// 172 -	"\\xad",	// 173 -	"\\xae",	// 174 -	"\\xaf",	// 175 -	"\\xb0",	// 176 -	"\\xb1",	// 177 -	"\\xb2",	// 178 -	"\\xb3",	// 179 -	"\\xb4",	// 180 -	"\\xb5",	// 181 -	"\\xb6",	// 182 -	"\\xb7",	// 183 -	"\\xb8",	// 184 -	"\\xb9",	// 185 -	"\\xba",	// 186 -	"\\xbb",	// 187 -	"\\xbc",	// 188 -	"\\xbd",	// 189 -	"\\xbe",	// 190 -	"\\xbf",	// 191 -	"\\xc0",	// 192 -	"\\xc1",	// 193 -	"\\xc2",	// 194 -	"\\xc3",	// 195 -	"\\xc4",	// 196 -	"\\xc5",	// 197 -	"\\xc6",	// 198 -	"\\xc7",	// 199 -	"\\xc8",	// 200 -	"\\xc9",	// 201 -	"\\xca",	// 202 -	"\\xcb",	// 203 -	"\\xcc",	// 204 -	"\\xcd",	// 205 -	"\\xce",	// 206 -	"\\xcf",	// 207 -	"\\xd0",	// 208 -	"\\xd1",	// 209 -	"\\xd2",	// 210 -	"\\xd3",	// 211 -	"\\xd4",	// 212 -	"\\xd5",	// 213 -	"\\xd6",	// 214 -	"\\xd7",	// 215 -	"\\xd8",	// 216 -	"\\xd9",	// 217 -	"\\xda",	// 218 -	"\\xdb",	// 219 -	"\\xdc",	// 220 -	"\\xdd",	// 221 -	"\\xde",	// 222 -	"\\xdf",	// 223 -	"\\xe0",	// 224 -	"\\xe1",	// 225 -	"\\xe2",	// 226 -	"\\xe3",	// 227 -	"\\xe4",	// 228 -	"\\xe5",	// 229 -	"\\xe6",	// 230 -	"\\xe7",	// 231 -	"\\xe8",	// 232 -	"\\xe9",	// 233 -	"\\xea",	// 234 -	"\\xeb",	// 235 -	"\\xec",	// 236 -	"\\xed",	// 237 -	"\\xee",	// 238 -	"\\xef",	// 239 -	"\\xf0",	// 240 -	"\\xf1",	// 241 -	"\\xf2",	// 242 -	"\\xf3",	// 243 -	"\\xf4",	// 244 -	"\\xf5",	// 245 -	"\\xf6",	// 246 -	"\\xf7",	// 247 -	"\\xf8",	// 248 -	"\\xf9",	// 249 -	"\\xfa",	// 250 -	"\\xfb",	// 251 -	"\\xfc",	// 252 -	"\\xfd",	// 253 -	"\\xfe",	// 254 -	"\\xff"		// 255 -}; - -void serialize_string(const std::string& value, std::ostream& str) -{ -	std::string::const_iterator it = value.begin(); -	std::string::const_iterator end = value.end(); -	U8 c; -	for(; it != end; ++it) -	{ -		c = (U8)(*it); -		str << NOTATION_STRING_CHARACTERS[c]; -	} -} - -int deserialize_boolean( -	std::istream& istr, -	LLSD& data, -	const std::string& compare, -	bool value) -{ -	// -	// this method is a little goofy, because it gets the stream at -	// the point where the t or f has already been -	// consumed. Basically, parse for a patch to the string passed in -	// starting at index 1. If it's a match: -	//  * assign data to value -	//  * return the number of bytes read -	// otherwise: -	//  * set data to LLSD::null -	//  * return LLSDParser::PARSE_FAILURE (-1) -	// -	int bytes_read = 0; -	std::string::size_type ii = 0; -	char c = istr.peek(); -	while((++ii < compare.size()) -		  && (tolower(c) == (int)compare[ii]) -		  && istr.good()) -	{ -		istr.ignore(); -		++bytes_read; -		c = istr.peek(); -	} -	if(compare.size() != ii) -	{ -		data.clear(); -		return LLSDParser::PARSE_FAILURE; -	} -	data = value; -	return bytes_read; -} - -std::ostream& operator<<(std::ostream& s, const LLSD& llsd) -{ -	s << LLSDNotationStreamer(llsd); -	return s; -} - - -//dirty little zippers -- yell at davep if these are horrid - -//return a string containing gzipped bytes of binary serialized LLSD -// VERY inefficient -- creates several copies of LLSD block in memory -std::string zip_llsd(LLSD& data) -{  -	std::stringstream llsd_strm; - -	LLSDSerialize::toBinary(data, llsd_strm); - -	const U32 CHUNK = 65536; - -	z_stream strm; -	strm.zalloc = Z_NULL; -	strm.zfree = Z_NULL; -	strm.opaque = Z_NULL; - -	S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION); -	if (ret != Z_OK) -	{ -		llwarns << "Failed to compress LLSD block." << llendl; -		return std::string(); -	} - -	std::string source = llsd_strm.str(); - -	U8 out[CHUNK]; - -	strm.avail_in = source.size(); -	strm.next_in = (U8*) source.data(); -	U8* output = NULL; - -	U32 cur_size = 0; - -	U32 have = 0; - -	do -	{ -		strm.avail_out = CHUNK; -		strm.next_out = out; - -		ret = deflate(&strm, Z_FINISH); -		if (ret == Z_OK || ret == Z_STREAM_END) -		{ //copy result into output -			if (strm.avail_out >= CHUNK) -			{ -				free(output); -				llwarns << "Failed to compress LLSD block." << llendl; -				return std::string(); -			} - -			have = CHUNK-strm.avail_out; -			output = (U8*) realloc(output, cur_size+have); -			memcpy(output+cur_size, out, have); -			cur_size += have; -		} -		else  -		{ -			free(output); -			llwarns << "Failed to compress LLSD block." << llendl; -			return std::string(); -		} -	} -	while (ret == Z_OK); - -	std::string::size_type size = cur_size; - -	std::string result((char*) output, size); -	deflateEnd(&strm); -	free(output); - -#if 0 //verify results work with unzip_llsd -	std::istringstream test(result); -	LLSD test_sd; -	if (!unzip_llsd(test_sd, test, result.size())) -	{ -		llerrs << "Invalid compression result!" << llendl; -	} -#endif - -	return result; -} - -//decompress a block of LLSD from provided istream -// not very efficient -- creats a copy of decompressed LLSD block in memory -// and deserializes from that copy using LLSDSerialize -bool unzip_llsd(LLSD& data, std::istream& is, S32 size) -{ -	U8* result = NULL; -	U32 cur_size = 0; -	z_stream strm; -		 -	const U32 CHUNK = 65536; - -	U8 *in = new U8[size]; -	is.read((char*) in, size);  - -	U8 out[CHUNK]; -		 -	strm.zalloc = Z_NULL; -	strm.zfree = Z_NULL; -	strm.opaque = Z_NULL; -	strm.avail_in = size; -	strm.next_in = in; - -	S32 ret = inflateInit(&strm); -	 -	do -	{ -		strm.avail_out = CHUNK; -		strm.next_out = out; -		ret = inflate(&strm, Z_NO_FLUSH); -		if (ret == Z_STREAM_ERROR) -		{ -			inflateEnd(&strm); -			free(result); -			delete [] in; -			return false; -		} -		 -		switch (ret) -		{ -		case Z_NEED_DICT: -			ret = Z_DATA_ERROR; -		case Z_DATA_ERROR: -		case Z_MEM_ERROR: -			inflateEnd(&strm); -			free(result); -			delete [] in; -			return false; -			break; -		} - -		U32 have = CHUNK-strm.avail_out; - -		result = (U8*) realloc(result, cur_size + have); -		memcpy(result+cur_size, out, have); -		cur_size += have; - -	} while (ret == Z_OK); - -	inflateEnd(&strm); -	delete [] in; - -	if (ret != Z_STREAM_END) -	{ -		free(result); -		return false; -	} - -	//result now points to the decompressed LLSD block -	{ -		std::string res_str((char*) result, cur_size); - -		std::string deprecated_header("<? LLSD/Binary ?>"); - -		if (res_str.substr(0, deprecated_header.size()) == deprecated_header) -		{ -			res_str = res_str.substr(deprecated_header.size()+1, cur_size); -		} -		cur_size = res_str.size(); - -		std::istringstream istr(res_str); -		 -		if (!LLSDSerialize::fromBinary(data, istr, cur_size)) -		{ -			llwarns << "Failed to unzip LLSD block" << llendl; -			free(result); -			return false; -		}		 -	} - -	free(result); -	return true; -} -//This unzip function will only work with a gzip header and trailer - while the contents -//of the actual compressed data is the same for either format (gzip vs zlib ), the headers -//and trailers are different for the formats. -U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size ) -{ -	U8* result = NULL; -	U32 cur_size = 0; -	z_stream strm; -		 -	const U32 CHUNK = 0x4000; - -	U8 *in = new U8[size]; -	is.read((char*) in, size);  - -	U8 out[CHUNK]; -		 -	strm.zalloc = Z_NULL; -	strm.zfree = Z_NULL; -	strm.opaque = Z_NULL; -	strm.avail_in = size; -	strm.next_in = in; - -	 -	S32 ret = inflateInit2(&strm,  windowBits | ENABLE_ZLIB_GZIP ); -	do -	{ -		strm.avail_out = CHUNK; -		strm.next_out = out; -		ret = inflate(&strm, Z_NO_FLUSH); -		if (ret == Z_STREAM_ERROR) -		{ -			inflateEnd(&strm); -			free(result); -			delete [] in; -			valid = false; -		} -		 -		switch (ret) -		{ -		case Z_NEED_DICT: -			ret = Z_DATA_ERROR; -		case Z_DATA_ERROR: -		case Z_MEM_ERROR: -			inflateEnd(&strm); -			free(result); -			delete [] in; -			valid = false; -			break; -		} - -		U32 have = CHUNK-strm.avail_out; - -		result = (U8*) realloc(result, cur_size + have); -		memcpy(result+cur_size, out, have); -		cur_size += have; - -	} while (ret == Z_OK); - -	inflateEnd(&strm); -	delete [] in; - -	if (ret != Z_STREAM_END) -	{ -		free(result); -		valid = false; -		return NULL; -	} - -	//result now points to the decompressed LLSD block -	{ -		outsize= cur_size; -		valid = true;		 -	} - -	return result; -} - - +
 +/**
 + * LLSDSerialize
 + */
 +
 +// static
 +void LLSDSerialize::serialize(const LLSD& sd, std::ostream& str, ELLSD_Serialize type, U32 options)
 +{
 +	LLPointer<LLSDFormatter> f = NULL;
 +
 +	switch (type)
 +	{
 +	case LLSD_BINARY:
 +		str << "<? " << LLSD_BINARY_HEADER << " ?>\n";
 +		f = new LLSDBinaryFormatter;
 +		break;
 +
 +	case LLSD_XML:
 +		str << "<? " << LLSD_XML_HEADER << " ?>\n";
 +		f = new LLSDXMLFormatter;
 +		break;
 +
 +	default:
 +		llwarns << "serialize request for unknown ELLSD_Serialize" << llendl;
 +	}
 +
 +	if (f.notNull())
 +	{
 +		f->format(sd, str, options);
 +	}
 +}
 +
 +// static
 +bool LLSDSerialize::deserialize(LLSD& sd, std::istream& str, S32 max_bytes)
 +{
 +	LLPointer<LLSDParser> p = NULL;
 +	char hdr_buf[MAX_HDR_LEN + 1] = ""; /* Flawfinder: ignore */
 +	int i;
 +	int inbuf = 0;
 +	bool legacy_no_header = false;
 +	bool fail_if_not_legacy = false;
 +	std::string header;
 +
 +	/*
 +	 * Get the first line before anything.
 +	 */
 +	str.get(hdr_buf, MAX_HDR_LEN, '\n');
 +	if (str.fail())
 +	{
 +		str.clear();
 +		fail_if_not_legacy = true;
 +	}
 +
 +	if (!strncasecmp(LEGACY_NON_HEADER, hdr_buf, strlen(LEGACY_NON_HEADER))) /* Flawfinder: ignore */
 +	{
 +		legacy_no_header = true;
 +		inbuf = (int)str.gcount();
 +	}
 +	else
 +	{
 +		if (fail_if_not_legacy)
 +			goto fail;
 +		/*
 +		* Remove the newline chars
 +		*/
 +		for (i = 0; i < MAX_HDR_LEN; i++)
 +		{
 +			if (hdr_buf[i] == 0 || hdr_buf[i] == '\r' ||
 +				hdr_buf[i] == '\n')
 +			{
 +				hdr_buf[i] = 0;
 +				break;
 +			}
 +		}
 +		header = hdr_buf;
 +
 +		std::string::size_type start = std::string::npos;
 +		std::string::size_type end = std::string::npos;
 +		start = header.find_first_not_of("<? ");
 +		if (start != std::string::npos)
 +		{
 +			end = header.find_first_of(" ?", start);
 +		}
 +		if ((start == std::string::npos) || (end == std::string::npos))
 +			goto fail;
 +
 +		header = header.substr(start, end - start);
 +		ws(str);
 +	}
 +	/*
 +	 * Create the parser as appropriate
 +	 */
 +	if (legacy_no_header)
 +	{	// Create a LLSD XML parser, and parse the first chunk read above
 +		LLSDXMLParser* x = new LLSDXMLParser();
 +		x->parsePart(hdr_buf, inbuf);	// Parse the first part that was already read
 +		x->parseLines(str, sd);			// Parse the rest of it
 +		delete x;
 +		return true;
 +	}
 +
 +	if (header == LLSD_BINARY_HEADER)
 +	{
 +		p = new LLSDBinaryParser;
 +	}
 +	else if (header == LLSD_XML_HEADER)
 +	{
 +		p = new LLSDXMLParser;
 +	}
 +	else
 +	{
 +		llwarns << "deserialize request for unknown ELLSD_Serialize" << llendl;
 +	}
 +
 +	if (p.notNull())
 +	{
 +		p->parse(str, sd, max_bytes);
 +		return true;
 +	}
 +
 +fail:
 +	llwarns << "deserialize LLSD parse failure" << llendl;
 +	return false;
 +}
 +
 +/**
 + * Endian handlers
 + */
 +#if LL_BIG_ENDIAN
 +U64 ll_htonll(U64 hostlonglong) { return hostlonglong; }
 +U64 ll_ntohll(U64 netlonglong) { return netlonglong; }
 +F64 ll_htond(F64 hostlonglong) { return hostlonglong; }
 +F64 ll_ntohd(F64 netlonglong) { return netlonglong; }
 +#else
 +// I read some comments one a indicating that doing an integer add
 +// here would be faster than a bitwise or. For now, the or has
 +// programmer clarity, since the intended outcome matches the
 +// operation.
 +U64 ll_htonll(U64 hostlonglong)
 +{
 +	return ((U64)(htonl((U32)((hostlonglong >> 32) & 0xFFFFFFFF))) |
 +			((U64)(htonl((U32)(hostlonglong & 0xFFFFFFFF))) << 32));
 +}
 +U64 ll_ntohll(U64 netlonglong)
 +{
 +	return ((U64)(ntohl((U32)((netlonglong >> 32) & 0xFFFFFFFF))) |
 +			((U64)(ntohl((U32)(netlonglong & 0xFFFFFFFF))) << 32));
 +}
 +union LLEndianSwapper
 +{
 +	F64 d;
 +	U64 i;
 +};
 +F64 ll_htond(F64 hostdouble)
 +{
 +	LLEndianSwapper tmp;
 +	tmp.d = hostdouble;
 +	tmp.i = ll_htonll(tmp.i);
 +	return tmp.d;
 +}
 +F64 ll_ntohd(F64 netdouble)
 +{
 +	LLEndianSwapper tmp;
 +	tmp.d = netdouble;
 +	tmp.i = ll_ntohll(tmp.i);
 +	return tmp.d;
 +}
 +#endif
 +
 +/**
 + * Local functions.
 + */
 +/**
 + * @brief Figure out what kind of string it is (raw or delimited) and handoff.
 + *
 + * @param istr The stream to read from.
 + * @param value [out] The string which was found.
 + * @param max_bytes The maximum possible length of the string. Passing in
 + * a negative value will skip this check.
 + * @return Returns number of bytes read off of the stream. Returns
 + * PARSE_FAILURE (-1) on failure.
 + */
 +int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes);
 +
 +/**
 + * @brief Parse a delimited string. 
 + *
 + * @param istr The stream to read from, with the delimiter already popped.
 + * @param value [out] The string which was found.
 + * @param d The delimiter to use.
 + * @return Returns number of bytes read off of the stream. Returns
 + * PARSE_FAILURE (-1) on failure.
 + */
 +int deserialize_string_delim(std::istream& istr, std::string& value, char d);
 +
 +/**
 + * @brief Read a raw string off the stream.
 + *
 + * @param istr The stream to read from, with the (len) parameter
 + * leading the stream.
 + * @param value [out] The string which was found.
 + * @param d The delimiter to use.
 + * @param max_bytes The maximum possible length of the string. Passing in
 + * a negative value will skip this check.
 + * @return Returns number of bytes read off of the stream. Returns
 + * PARSE_FAILURE (-1) on failure.
 + */
 +int deserialize_string_raw(
 +	std::istream& istr,
 +	std::string& value,
 +	S32 max_bytes);
 +
 +/**
 + * @brief helper method for dealing with the different notation boolean format.
 + *
 + * @param istr The stream to read from with the leading character stripped.
 + * @param data [out] the result of the parse.
 + * @param compare The string to compare the boolean against
 + * @param vale The value to assign to data if the parse succeeds.
 + * @return Returns number of bytes read off of the stream. Returns
 + * PARSE_FAILURE (-1) on failure.
 + */
 +int deserialize_boolean(
 +	std::istream& istr,
 +	LLSD& data,
 +	const std::string& compare,
 +	bool value);
 +
 +/**
 + * @brief Do notation escaping of a string to an ostream.
 + *
 + * @param value The string to escape and serialize
 + * @param str The stream to serialize to.
 + */
 +void serialize_string(const std::string& value, std::ostream& str);
 +
 +
 +/**
 + * Local constants.
 + */
 +static const std::string NOTATION_TRUE_SERIAL("true");
 +static const std::string NOTATION_FALSE_SERIAL("false");
 +
 +static const char BINARY_TRUE_SERIAL = '1';
 +static const char BINARY_FALSE_SERIAL = '0';
 +
 +
 +/**
 + * LLSDParser
 + */
 +LLSDParser::LLSDParser()
 +	: mCheckLimits(true), mMaxBytesLeft(0), mParseLines(false)
 +{
 +}
 +
 +// virtual
 +LLSDParser::~LLSDParser()
 +{ }
 +
 +S32 LLSDParser::parse(std::istream& istr, LLSD& data, S32 max_bytes)
 +{
 +	mCheckLimits = (LLSDSerialize::SIZE_UNLIMITED == max_bytes) ? false : true;
 +	mMaxBytesLeft = max_bytes;
 +	return doParse(istr, data);
 +}
 +
 +
 +// Parse using routine to get() lines, faster than parse()
 +S32 LLSDParser::parseLines(std::istream& istr, LLSD& data)
 +{
 +	mCheckLimits = false;
 +	mParseLines = true;
 +	return doParse(istr, data);
 +}
 +
 +
 +int LLSDParser::get(std::istream& istr) const
 +{
 +	if(mCheckLimits) --mMaxBytesLeft;
 +	return istr.get();
 +}
 +
 +std::istream& LLSDParser::get(
 +	std::istream& istr,
 +	char* s,
 +	std::streamsize n,
 +	char delim) const
 +{
 +	istr.get(s, n, delim);
 +	if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount();
 +	return istr;
 +}
 +
 +std::istream& LLSDParser::get(
 +		std::istream& istr,
 +		std::streambuf& sb,
 +		char delim) const		
 +{
 +	istr.get(sb, delim);
 +	if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount();
 +	return istr;
 +}
 +
 +std::istream& LLSDParser::ignore(std::istream& istr) const
 +{
 +	istr.ignore();
 +	if(mCheckLimits) --mMaxBytesLeft;
 +	return istr;
 +}
 +
 +std::istream& LLSDParser::putback(std::istream& istr, char c) const
 +{
 +	istr.putback(c);
 +	if(mCheckLimits) ++mMaxBytesLeft;
 +	return istr;
 +}
 +
 +std::istream& LLSDParser::read(
 +	std::istream& istr,
 +	char* s,
 +	std::streamsize n) const
 +{
 +	istr.read(s, n);
 +	if(mCheckLimits) mMaxBytesLeft -= (int)istr.gcount();
 +	return istr;
 +}
 +
 +void LLSDParser::account(S32 bytes) const
 +{
 +	if(mCheckLimits) mMaxBytesLeft -= bytes;
 +}
 +
 +
 +/**
 + * LLSDNotationParser
 + */
 +LLSDNotationParser::LLSDNotationParser()
 +{
 +}	
 +
 +// virtual
 +LLSDNotationParser::~LLSDNotationParser()
 +{ }
 +
 +// virtual
 +S32 LLSDNotationParser::doParse(std::istream& istr, LLSD& data) const
 +{
 +	// map: { string:object, string:object }
 +	// array: [ object, object, object ]
 +	// undef: !
 +	// boolean: true | false | 1 | 0 | T | F | t | f | TRUE | FALSE
 +	// integer: i####
 +	// real: r####
 +	// uuid: u####
 +	// string: "g'day" | 'have a "nice" day' | s(size)"raw data"
 +	// uri: l"escaped"
 +	// date: d"YYYY-MM-DDTHH:MM:SS.FFZ"
 +	// binary: b##"ff3120ab1" | b(size)"raw data"
 +	char c;
 +	c = istr.peek();
 +	while(isspace(c))
 +	{
 +		// pop the whitespace.
 +		c = get(istr);
 +		c = istr.peek();
 +		continue;
 +	}
 +	if(!istr.good())
 +	{
 +		return 0;
 +	}
 +	S32 parse_count = 1;
 +	switch(c)
 +	{
 +	case '{':
 +	{
 +		S32 child_count = parseMap(istr, data);
 +		if((child_count == PARSE_FAILURE) || data.isUndefined())
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		else
 +		{
 +			parse_count += child_count;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading map." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case '[':
 +	{
 +		S32 child_count = parseArray(istr, data);
 +		if((child_count == PARSE_FAILURE) || data.isUndefined())
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		else
 +		{
 +			parse_count += child_count;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading array." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case '!':
 +		c = get(istr);
 +		data.clear();
 +		break;
 +
 +	case '0':
 +		c = get(istr);
 +		data = false;
 +		break;
 +
 +	case 'F':
 +	case 'f':
 +		ignore(istr);
 +		c = istr.peek();
 +		if(isalpha(c))
 +		{
 +			int cnt = deserialize_boolean(
 +				istr,
 +				data,
 +				NOTATION_FALSE_SERIAL,
 +				false);
 +			if(PARSE_FAILURE == cnt) parse_count = cnt;
 +			else account(cnt);
 +		}
 +		else
 +		{
 +			data = false;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading boolean." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +
 +	case '1':
 +		c = get(istr);
 +		data = true;
 +		break;
 +
 +	case 'T':
 +	case 't':
 +		ignore(istr);
 +		c = istr.peek();
 +		if(isalpha(c))
 +		{
 +			int cnt = deserialize_boolean(istr,data,NOTATION_TRUE_SERIAL,true);
 +			if(PARSE_FAILURE == cnt) parse_count = cnt;
 +			else account(cnt);
 +		}
 +		else
 +		{
 +			data = true;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading boolean." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +
 +	case 'i':
 +	{
 +		c = get(istr);
 +		S32 integer = 0;
 +		istr >> integer;
 +		data = integer;
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading integer." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case 'r':
 +	{
 +		c = get(istr);
 +		F64 real = 0.0;
 +		istr >> real;
 +		data = real;
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading real." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case 'u':
 +	{
 +		c = get(istr);
 +		LLUUID id;
 +		istr >> id;
 +		data = id;
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading uuid." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case '\"':
 +	case '\'':
 +	case 's':
 +		if(!parseString(istr, data))
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading string." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +
 +	case 'l':
 +	{
 +		c = get(istr); // pop the 'l'
 +		c = get(istr); // pop the delimiter
 +		std::string str;
 +		int cnt = deserialize_string_delim(istr, str, c);
 +		if(PARSE_FAILURE == cnt)
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		else
 +		{
 +			data = LLURI(str);
 +			account(cnt);
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading link." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case 'd':
 +	{
 +		c = get(istr); // pop the 'd'
 +		c = get(istr); // pop the delimiter
 +		std::string str;
 +		int cnt = deserialize_string_delim(istr, str, c);
 +		if(PARSE_FAILURE == cnt)
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		else
 +		{
 +			data = LLDate(str);
 +			account(cnt);
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading date." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case 'b':
 +		if(!parseBinary(istr, data))
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading data." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +
 +	default:
 +		parse_count = PARSE_FAILURE;
 +		llinfos << "Unrecognized character while parsing: int(" << (int)c
 +			<< ")" << llendl;
 +		break;
 +	}
 +	if(PARSE_FAILURE == parse_count)
 +	{
 +		data.clear();
 +	}
 +	return parse_count;
 +}
 +
 +S32 LLSDNotationParser::parseMap(std::istream& istr, LLSD& map) const
 +{
 +	// map: { string:object, string:object }
 +	map = LLSD::emptyMap();
 +	S32 parse_count = 0;
 +	char c = get(istr);
 +	if(c == '{')
 +	{
 +		// eat commas, white
 +		bool found_name = false;
 +		std::string name;
 +		c = get(istr);
 +		while(c != '}' && istr.good())
 +		{
 +			if(!found_name)
 +			{
 +				if((c == '\"') || (c == '\'') || (c == 's'))
 +				{
 +					putback(istr, c);
 +					found_name = true;
 +					int count = deserialize_string(istr, name, mMaxBytesLeft);
 +					if(PARSE_FAILURE == count) return PARSE_FAILURE;
 +					account(count);
 +				}
 +				c = get(istr);
 +			}
 +			else
 +			{
 +				if(isspace(c) || (c == ':'))
 +				{
 +					c = get(istr);
 +					continue;
 +				}
 +				putback(istr, c);
 +				LLSD child;
 +				S32 count = doParse(istr, child);
 +				if(count > 0)
 +				{
 +					// There must be a value for every key, thus
 +					// child_count must be greater than 0.
 +					parse_count += count;
 +					map.insert(name, child);
 +				}
 +				else
 +				{
 +					return PARSE_FAILURE;
 +				}
 +				found_name = false;
 +				c = get(istr);
 +			}
 +		}
 +		if(c != '}')
 +		{
 +			map.clear();
 +			return PARSE_FAILURE;
 +		}
 +	}
 +	return parse_count;
 +}
 +
 +S32 LLSDNotationParser::parseArray(std::istream& istr, LLSD& array) const
 +{
 +	// array: [ object, object, object ]
 +	array = LLSD::emptyArray();
 +	S32 parse_count = 0;
 +	char c = get(istr);
 +	if(c == '[')
 +	{
 +		// eat commas, white
 +		c = get(istr);
 +		while((c != ']') && istr.good())
 +		{
 +			LLSD child;
 +			if(isspace(c) || (c == ','))
 +			{
 +				c = get(istr);
 +				continue;
 +			}
 +			putback(istr, c);
 +			S32 count = doParse(istr, child);
 +			if(PARSE_FAILURE == count)
 +			{
 +				return PARSE_FAILURE;
 +			}
 +			else
 +			{
 +				parse_count += count;
 +				array.append(child);
 +			}
 +			c = get(istr);
 +		}
 +		if(c != ']')
 +		{
 +			return PARSE_FAILURE;
 +		}
 +	}
 +	return parse_count;
 +}
 +
 +bool LLSDNotationParser::parseString(std::istream& istr, LLSD& data) const
 +{
 +	std::string value;
 +	int count = deserialize_string(istr, value, mMaxBytesLeft);
 +	if(PARSE_FAILURE == count) return false;
 +	account(count);
 +	data = value;
 +	return true;
 +}
 +
 +bool LLSDNotationParser::parseBinary(std::istream& istr, LLSD& data) const
 +{
 +	// binary: b##"ff3120ab1"
 +	// or: b(len)"..."
 +
 +	// I want to manually control those values here to make sure the
 +	// parser doesn't break when someone changes a constant somewhere
 +	// else.
 +	const U32 BINARY_BUFFER_SIZE = 256;
 +	const U32 STREAM_GET_COUNT = 255;
 +
 +	// need to read the base out.
 +	char buf[BINARY_BUFFER_SIZE];		/* Flawfinder: ignore */
 +	get(istr, buf, STREAM_GET_COUNT, '"');
 +	char c = get(istr);
 +	if(c != '"') return false;
 +	if(0 == strncmp("b(", buf, 2))
 +	{
 +		// We probably have a valid raw binary stream. determine
 +		// the size, and read it.
 +		S32 len = strtol(buf + 2, NULL, 0);
 +		if(mCheckLimits && (len > mMaxBytesLeft)) return false;
 +		std::vector<U8> value;
 +		if(len)
 +		{
 +			value.resize(len);
 +			account((int)fullread(istr, (char *)&value[0], len));
 +		}
 +		c = get(istr); // strip off the trailing double-quote
 +		data = value;
 +	}
 +	else if(0 == strncmp("b64", buf, 3))
 +	{
 +		// *FIX: A bit inefficient, but works for now. To make the
 +		// format better, I would need to add a hint into the
 +		// serialization format that indicated how long it was.
 +		std::stringstream coded_stream;
 +		get(istr, *(coded_stream.rdbuf()), '\"');
 +		c = get(istr);
 +		std::string encoded(coded_stream.str());
 +		S32 len = apr_base64_decode_len(encoded.c_str());
 +		std::vector<U8> value;
 +		if(len)
 +		{
 +			value.resize(len);
 +			len = apr_base64_decode_binary(&value[0], encoded.c_str());
 +			value.resize(len);
 +		}
 +		data = value;
 +	}
 +	else if(0 == strncmp("b16", buf, 3))
 +	{
 +		// yay, base 16. We pop the next character which is either a
 +		// double quote or base 16 data. If it's a double quote, we're
 +		// done parsing. If it's not, put the data back, and read the
 +		// stream until the next double quote.
 +		char* read;	 /*Flawfinder: ignore*/
 +		U8 byte;
 +		U8 byte_buffer[BINARY_BUFFER_SIZE];
 +		U8* write;
 +		std::vector<U8> value;
 +		c = get(istr);
 +		while(c != '"')
 +		{
 +			putback(istr, c);
 +			read = buf;
 +			write = byte_buffer;
 +			get(istr, buf, STREAM_GET_COUNT, '"');
 +			c = get(istr);
 +			while(*read != '\0')	 /*Flawfinder: ignore*/
 +			{
 +				byte = hex_as_nybble(*read++);
 +				byte = byte << 4;
 +				byte |= hex_as_nybble(*read++);
 +				*write++ = byte;
 +			}
 +			// copy the data out of the byte buffer
 +			value.insert(value.end(), byte_buffer, write);
 +		}
 +		data = value;
 +	}
 +	else
 +	{
 +		return false;
 +	}
 +	return true;
 +}
 +
 +
 +/**
 + * LLSDBinaryParser
 + */
 +LLSDBinaryParser::LLSDBinaryParser()
 +{
 +}
 +
 +// virtual
 +LLSDBinaryParser::~LLSDBinaryParser()
 +{
 +}
 +
 +// virtual
 +S32 LLSDBinaryParser::doParse(std::istream& istr, LLSD& data) const
 +{
 +/**
 + * Undefined: '!'<br>
 + * Boolean: 't' for true 'f' for false<br>
 + * Integer: 'i' + 4 bytes network byte order<br>
 + * Real: 'r' + 8 bytes IEEE double<br>
 + * UUID: 'u' + 16 byte unsigned integer<br>
 + * String: 's' + 4 byte integer size + string<br>
 + *  strings also secretly support the notation format
 + * Date: 'd' + 8 byte IEEE double for seconds since epoch<br>
 + * URI: 'l' + 4 byte integer size + string uri<br>
 + * Binary: 'b' + 4 byte integer size + binary data<br>
 + * Array: '[' + 4 byte integer size  + all values + ']'<br>
 + * Map: '{' + 4 byte integer size  every(key + value) + '}'<br>
 + *  map keys are serialized as s + 4 byte integer size + string or in the
 + *  notation format.
 + */
 +	char c;
 +	c = get(istr);
 +	if(!istr.good())
 +	{
 +		return 0;
 +	}
 +	S32 parse_count = 1;
 +	switch(c)
 +	{
 +	case '{':
 +	{
 +		S32 child_count = parseMap(istr, data);
 +		if((child_count == PARSE_FAILURE) || data.isUndefined())
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		else
 +		{
 +			parse_count += child_count;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading binary map." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case '[':
 +	{
 +		S32 child_count = parseArray(istr, data);
 +		if((child_count == PARSE_FAILURE) || data.isUndefined())
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		else
 +		{
 +			parse_count += child_count;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading binary array." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case '!':
 +		data.clear();
 +		break;
 +
 +	case '0':
 +		data = false;
 +		break;
 +
 +	case '1':
 +		data = true;
 +		break;
 +
 +	case 'i':
 +	{
 +		U32 value_nbo = 0;
 +		read(istr, (char*)&value_nbo, sizeof(U32));	 /*Flawfinder: ignore*/
 +		data = (S32)ntohl(value_nbo);
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading binary integer." << llendl;
 +		}
 +		break;
 +	}
 +
 +	case 'r':
 +	{
 +		F64 real_nbo = 0.0;
 +		read(istr, (char*)&real_nbo, sizeof(F64));	 /*Flawfinder: ignore*/
 +		data = ll_ntohd(real_nbo);
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading binary real." << llendl;
 +		}
 +		break;
 +	}
 +
 +	case 'u':
 +	{
 +		LLUUID id;
 +		read(istr, (char*)(&id.mData), UUID_BYTES);	 /*Flawfinder: ignore*/
 +		data = id;
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading binary uuid." << llendl;
 +		}
 +		break;
 +	}
 +
 +	case '\'':
 +	case '"':
 +	{
 +		std::string value;
 +		int cnt = deserialize_string_delim(istr, value, c);
 +		if(PARSE_FAILURE == cnt)
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		else
 +		{
 +			data = value;
 +			account(cnt);
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading binary (notation-style) string."
 +				<< llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case 's':
 +	{
 +		std::string value;
 +		if(parseString(istr, value))
 +		{
 +			data = value;
 +		}
 +		else
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading binary string." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case 'l':
 +	{
 +		std::string value;
 +		if(parseString(istr, value))
 +		{
 +			data = LLURI(value);
 +		}
 +		else
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading binary link." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case 'd':
 +	{
 +		F64 real = 0.0;
 +		read(istr, (char*)&real, sizeof(F64));	 /*Flawfinder: ignore*/
 +		data = LLDate(real);
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading binary date." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	case 'b':
 +	{
 +		// We probably have a valid raw binary stream. determine
 +		// the size, and read it.
 +		U32 size_nbo = 0;
 +		read(istr, (char*)&size_nbo, sizeof(U32));	/*Flawfinder: ignore*/
 +		S32 size = (S32)ntohl(size_nbo);
 +		if(mCheckLimits && (size > mMaxBytesLeft))
 +		{
 +			parse_count = PARSE_FAILURE;
 +		}
 +		else
 +		{
 +			std::vector<U8> value;
 +			if(size > 0)
 +			{
 +				value.resize(size);
 +				account((int)fullread(istr, (char*)&value[0], size));
 +			}
 +			data = value;
 +		}
 +		if(istr.fail())
 +		{
 +			llinfos << "STREAM FAILURE reading binary." << llendl;
 +			parse_count = PARSE_FAILURE;
 +		}
 +		break;
 +	}
 +
 +	default:
 +		parse_count = PARSE_FAILURE;
 +		llinfos << "Unrecognized character while parsing: int(" << (int)c
 +			<< ")" << llendl;
 +		break;
 +	}
 +	if(PARSE_FAILURE == parse_count)
 +	{
 +		data.clear();
 +	}
 +	return parse_count;
 +}
 +
 +S32 LLSDBinaryParser::parseMap(std::istream& istr, LLSD& map) const
 +{
 +	map = LLSD::emptyMap();
 +	U32 value_nbo = 0;
 +	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
 +	S32 size = (S32)ntohl(value_nbo);
 +	S32 parse_count = 0;
 +	S32 count = 0;
 +	char c = get(istr);
 +	while(c != '}' && (count < size) && istr.good())
 +	{
 +		std::string name;
 +		switch(c)
 +		{
 +		case 'k':
 +			if(!parseString(istr, name))
 +			{
 +				return PARSE_FAILURE;
 +			}
 +			break;
 +		case '\'':
 +		case '"':
 +		{
 +			int cnt = deserialize_string_delim(istr, name, c);
 +			if(PARSE_FAILURE == cnt) return PARSE_FAILURE;
 +			account(cnt);
 +			break;
 +		}
 +		}
 +		LLSD child;
 +		S32 child_count = doParse(istr, child);
 +		if(child_count > 0)
 +		{
 +			// There must be a value for every key, thus child_count
 +			// must be greater than 0.
 +			parse_count += child_count;
 +			map.insert(name, child);
 +		}
 +		else
 +		{
 +			return PARSE_FAILURE;
 +		}
 +		++count;
 +		c = get(istr);
 +	}
 +	if((c != '}') || (count < size))
 +	{
 +		// Make sure it is correctly terminated and we parsed as many
 +		// as were said to be there.
 +		return PARSE_FAILURE;
 +	}
 +	return parse_count;
 +}
 +
 +S32 LLSDBinaryParser::parseArray(std::istream& istr, LLSD& array) const
 +{
 +	array = LLSD::emptyArray();
 +	U32 value_nbo = 0;
 +	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
 +	S32 size = (S32)ntohl(value_nbo);
 +
 +	// *FIX: This would be a good place to reserve some space in the
 +	// array...
 +
 +	S32 parse_count = 0;
 +	S32 count = 0;
 +	char c = istr.peek();
 +	while((c != ']') && (count < size) && istr.good())
 +	{
 +		LLSD child;
 +		S32 child_count = doParse(istr, child);
 +		if(PARSE_FAILURE == child_count)
 +		{
 +			return PARSE_FAILURE;
 +		}
 +		if(child_count)
 +		{
 +			parse_count += child_count;
 +			array.append(child);
 +		}
 +		++count;
 +		c = istr.peek();
 +	}
 +	c = get(istr);
 +	if((c != ']') || (count < size))
 +	{
 +		// Make sure it is correctly terminated and we parsed as many
 +		// as were said to be there.
 +		return PARSE_FAILURE;
 +	}
 +	return parse_count;
 +}
 +
 +bool LLSDBinaryParser::parseString(
 +	std::istream& istr,
 +	std::string& value) const
 +{
 +	// *FIX: This is memory inefficient.
 +	U32 value_nbo = 0;
 +	read(istr, (char*)&value_nbo, sizeof(U32));		 /*Flawfinder: ignore*/
 +	S32 size = (S32)ntohl(value_nbo);
 +	if(mCheckLimits && (size > mMaxBytesLeft)) return false;
 +	std::vector<char> buf;
 +	if(size)
 +	{
 +		buf.resize(size);
 +		account((int)fullread(istr, &buf[0], size));
 +		value.assign(buf.begin(), buf.end());
 +	}
 +	return true;
 +}
 +
 +
 +/**
 + * LLSDFormatter
 + */
 +LLSDFormatter::LLSDFormatter() :
 +	mBoolAlpha(false)
 +{
 +}
 +
 +// virtual
 +LLSDFormatter::~LLSDFormatter()
 +{ }
 +
 +void LLSDFormatter::boolalpha(bool alpha)
 +{
 +	mBoolAlpha = alpha;
 +}
 +
 +void LLSDFormatter::realFormat(const std::string& format)
 +{
 +	mRealFormat = format;
 +}
 +
 +void LLSDFormatter::formatReal(LLSD::Real real, std::ostream& ostr) const
 +{
 +	std::string buffer = llformat(mRealFormat.c_str(), real);
 +	ostr << buffer;
 +}
 +
 +/**
 + * LLSDNotationFormatter
 + */
 +LLSDNotationFormatter::LLSDNotationFormatter()
 +{
 +}
 +
 +// virtual
 +LLSDNotationFormatter::~LLSDNotationFormatter()
 +{ }
 +
 +// static
 +std::string LLSDNotationFormatter::escapeString(const std::string& in)
 +{
 +	std::ostringstream ostr;
 +	serialize_string(in, ostr);
 +	return ostr.str();
 +}
 +
 +// virtual
 +S32 LLSDNotationFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
 +{
 +	S32 format_count = 1;
 +	switch(data.type())
 +	{
 +	case LLSD::TypeMap:
 +	{
 +		ostr << "{";
 +		bool need_comma = false;
 +		LLSD::map_const_iterator iter = data.beginMap();
 +		LLSD::map_const_iterator end = data.endMap();
 +		for(; iter != end; ++iter)
 +		{
 +			if(need_comma) ostr << ",";
 +			need_comma = true;
 +			ostr << '\'';
 +			serialize_string((*iter).first, ostr);
 +			ostr << "':";
 +			format_count += format((*iter).second, ostr);
 +		}
 +		ostr << "}";
 +		break;
 +	}
 +
 +	case LLSD::TypeArray:
 +	{
 +		ostr << "[";
 +		bool need_comma = false;
 +		LLSD::array_const_iterator iter = data.beginArray();
 +		LLSD::array_const_iterator end = data.endArray();
 +		for(; iter != end; ++iter)
 +		{
 +			if(need_comma) ostr << ",";
 +			need_comma = true;
 +			format_count += format(*iter, ostr);
 +		}
 +		ostr << "]";
 +		break;
 +	}
 +
 +	case LLSD::TypeUndefined:
 +		ostr << "!";
 +		break;
 +
 +	case LLSD::TypeBoolean:
 +		if(mBoolAlpha ||
 +#if( LL_WINDOWS || __GNUC__ > 2)
 +		   (ostr.flags() & std::ios::boolalpha)
 +#else
 +		   (ostr.flags() & 0x0100)
 +#endif
 +			)
 +		{
 +			ostr << (data.asBoolean()
 +					 ? NOTATION_TRUE_SERIAL : NOTATION_FALSE_SERIAL);
 +		}
 +		else
 +		{
 +			ostr << (data.asBoolean() ? 1 : 0);
 +		}
 +		break;
 +
 +	case LLSD::TypeInteger:
 +		ostr << "i" << data.asInteger();
 +		break;
 +
 +	case LLSD::TypeReal:
 +		ostr << "r";
 +		if(mRealFormat.empty())
 +		{
 +			ostr << data.asReal();
 +		}
 +		else
 +		{
 +			formatReal(data.asReal(), ostr);
 +		}
 +		break;
 +
 +	case LLSD::TypeUUID:
 +		ostr << "u" << data.asUUID();
 +		break;
 +
 +	case LLSD::TypeString:
 +		ostr << '\'';
 +		serialize_string(data.asString(), ostr);
 +		ostr << '\'';
 +		break;
 +
 +	case LLSD::TypeDate:
 +		ostr << "d\"" << data.asDate() << "\"";
 +		break;
 +
 +	case LLSD::TypeURI:
 +		ostr << "l\"";
 +		serialize_string(data.asString(), ostr);
 +		ostr << "\"";
 +		break;
 +
 +	case LLSD::TypeBinary:
 +	{
 +		// *FIX: memory inefficient.
 +		std::vector<U8> buffer = data.asBinary();
 +		ostr << "b(" << buffer.size() << ")\"";
 +		if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
 +		ostr << "\"";
 +		break;
 +	}
 +
 +	default:
 +		// *NOTE: This should never happen.
 +		ostr << "!";
 +		break;
 +	}
 +	return format_count;
 +}
 +
 +
 +/**
 + * LLSDBinaryFormatter
 + */
 +LLSDBinaryFormatter::LLSDBinaryFormatter()
 +{
 +}
 +
 +// virtual
 +LLSDBinaryFormatter::~LLSDBinaryFormatter()
 +{ }
 +
 +// virtual
 +S32 LLSDBinaryFormatter::format(const LLSD& data, std::ostream& ostr, U32 options) const
 +{
 +	S32 format_count = 1;
 +	switch(data.type())
 +	{
 +	case LLSD::TypeMap:
 +	{
 +		ostr.put('{');
 +		U32 size_nbo = htonl(data.size());
 +		ostr.write((const char*)(&size_nbo), sizeof(U32));
 +		LLSD::map_const_iterator iter = data.beginMap();
 +		LLSD::map_const_iterator end = data.endMap();
 +		for(; iter != end; ++iter)
 +		{
 +			ostr.put('k');
 +			formatString((*iter).first, ostr);
 +			format_count += format((*iter).second, ostr);
 +		}
 +		ostr.put('}');
 +		break;
 +	}
 +
 +	case LLSD::TypeArray:
 +	{
 +		ostr.put('[');
 +		U32 size_nbo = htonl(data.size());
 +		ostr.write((const char*)(&size_nbo), sizeof(U32));
 +		LLSD::array_const_iterator iter = data.beginArray();
 +		LLSD::array_const_iterator end = data.endArray();
 +		for(; iter != end; ++iter)
 +		{
 +			format_count += format(*iter, ostr);
 +		}
 +		ostr.put(']');
 +		break;
 +	}
 +
 +	case LLSD::TypeUndefined:
 +		ostr.put('!');
 +		break;
 +
 +	case LLSD::TypeBoolean:
 +		if(data.asBoolean()) ostr.put(BINARY_TRUE_SERIAL);
 +		else ostr.put(BINARY_FALSE_SERIAL);
 +		break;
 +
 +	case LLSD::TypeInteger:
 +	{
 +		ostr.put('i');
 +		U32 value_nbo = htonl(data.asInteger());
 +		ostr.write((const char*)(&value_nbo), sizeof(U32));
 +		break;
 +	}
 +
 +	case LLSD::TypeReal:
 +	{
 +		ostr.put('r');
 +		F64 value_nbo = ll_htond(data.asReal());
 +		ostr.write((const char*)(&value_nbo), sizeof(F64));
 +		break;
 +	}
 +
 +	case LLSD::TypeUUID:
 +		ostr.put('u');
 +		ostr.write((const char*)(&(data.asUUID().mData)), UUID_BYTES);
 +		break;
 +
 +	case LLSD::TypeString:
 +		ostr.put('s');
 +		formatString(data.asString(), ostr);
 +		break;
 +
 +	case LLSD::TypeDate:
 +	{
 +		ostr.put('d');
 +		F64 value = data.asReal();
 +		ostr.write((const char*)(&value), sizeof(F64));
 +		break;
 +	}
 +
 +	case LLSD::TypeURI:
 +		ostr.put('l');
 +		formatString(data.asString(), ostr);
 +		break;
 +
 +	case LLSD::TypeBinary:
 +	{
 +		// *FIX: memory inefficient.
 +		ostr.put('b');
 +		std::vector<U8> buffer = data.asBinary();
 +		U32 size_nbo = htonl(buffer.size());
 +		ostr.write((const char*)(&size_nbo), sizeof(U32));
 +		if(buffer.size()) ostr.write((const char*)&buffer[0], buffer.size());
 +		break;
 +	}
 +
 +	default:
 +		// *NOTE: This should never happen.
 +		ostr.put('!');
 +		break;
 +	}
 +	return format_count;
 +}
 +
 +void LLSDBinaryFormatter::formatString(
 +	const std::string& string,
 +	std::ostream& ostr) const
 +{
 +	U32 size_nbo = htonl(string.size());
 +	ostr.write((const char*)(&size_nbo), sizeof(U32));
 +	ostr.write(string.c_str(), string.size());
 +}
 +
 +/**
 + * local functions
 + */
 +int deserialize_string(std::istream& istr, std::string& value, S32 max_bytes)
 +{
 +	int c = istr.get();
 +	if(istr.fail())
 +	{
 +		// No data in stream, bail out but mention the character we
 +		// grabbed.
 +		return LLSDParser::PARSE_FAILURE;
 +	}
 +
 +	int rv = LLSDParser::PARSE_FAILURE;
 +	switch(c)
 +	{
 +	case '\'':
 +	case '"':
 +		rv = deserialize_string_delim(istr, value, c);
 +		break;
 +	case 's':
 +		// technically, less than max_bytes, but this is just meant to
 +		// catch egregious protocol errors. parse errors will be
 +		// caught in the case of incorrect counts.
 +		rv = deserialize_string_raw(istr, value, max_bytes);
 +		break;
 +	default:
 +		break;
 +	}
 +	if(LLSDParser::PARSE_FAILURE == rv) return rv;
 +	return rv + 1; // account for the character grabbed at the top.
 +}
 +
 +int deserialize_string_delim(
 +	std::istream& istr,
 +	std::string& value,
 +	char delim)
 +{
 +	std::ostringstream write_buffer;
 +	bool found_escape = false;
 +	bool found_hex = false;
 +	bool found_digit = false;
 +	U8 byte = 0;
 +	int count = 0;
 +
 +	while (true)
 +	{
 +		int next_byte = istr.get();
 +		++count;
 +
 +		if(istr.fail())
 +		{
 +			// If our stream is empty, break out
 +			value = write_buffer.str();
 +			return LLSDParser::PARSE_FAILURE;
 +		}
 +
 +		char next_char = (char)next_byte; // Now that we know it's not EOF
 +		
 +		if(found_escape)
 +		{
 +			// next character(s) is a special sequence.
 +			if(found_hex)
 +			{
 +				if(found_digit)
 +				{
 +					found_digit = false;
 +					found_hex = false;
 +					found_escape = false;
 +					byte = byte << 4;
 +					byte |= hex_as_nybble(next_char);
 +					write_buffer << byte;
 +					byte = 0;
 +				}
 +				else
 +				{
 +					// next character is the first nybble of
 +					//
 +					found_digit = true;
 +					byte = hex_as_nybble(next_char);
 +				}
 +			}
 +			else if(next_char == 'x')
 +			{
 +				found_hex = true;
 +			}
 +			else
 +			{
 +				switch(next_char)
 +				{
 +				case 'a':
 +					write_buffer << '\a';
 +					break;
 +				case 'b':
 +					write_buffer << '\b';
 +					break;
 +				case 'f':
 +					write_buffer << '\f';
 +					break;
 +				case 'n':
 +					write_buffer << '\n';
 +					break;
 +				case 'r':
 +					write_buffer << '\r';
 +					break;
 +				case 't':
 +					write_buffer << '\t';
 +					break;
 +				case 'v':
 +					write_buffer << '\v';
 +					break;
 +				default:
 +					write_buffer << next_char;
 +					break;
 +				}
 +				found_escape = false;
 +			}
 +		}
 +		else if(next_char == '\\')
 +		{
 +			found_escape = true;
 +		}
 +		else if(next_char == delim)
 +		{
 +			break;
 +		}
 +		else
 +		{
 +			write_buffer << next_char;
 +		}
 +	}
 +
 +	value = write_buffer.str();
 +	return count;
 +}
 +
 +int deserialize_string_raw(
 +	std::istream& istr,
 +	std::string& value,
 +	S32 max_bytes)
 +{
 +	int count = 0;
 +	const S32 BUF_LEN = 20;
 +	char buf[BUF_LEN];		/* Flawfinder: ignore */
 +	istr.get(buf, BUF_LEN - 1, ')');
 +	count += (int)istr.gcount();
 +	int c = istr.get();
 +	c = istr.get();
 +	count += 2;
 +	if(((c == '"') || (c == '\'')) && (buf[0] == '('))
 +	{
 +		// We probably have a valid raw string. determine
 +		// the size, and read it.
 +		// *FIX: This is memory inefficient.
 +		S32 len = strtol(buf + 1, NULL, 0);
 +		if((max_bytes>0)&&(len>max_bytes)) return LLSDParser::PARSE_FAILURE;
 +		std::vector<char> buf;
 +		if(len)
 +		{
 +			buf.resize(len);
 +			count += (int)fullread(istr, (char *)&buf[0], len);
 +			value.assign(buf.begin(), buf.end());
 +		}
 +		c = istr.get();
 +		++count;
 +		if(!((c == '"') || (c == '\'')))
 +		{
 +			return LLSDParser::PARSE_FAILURE;
 +		}
 +	}
 +	else
 +	{
 +		return LLSDParser::PARSE_FAILURE;
 +	}
 +	return count;
 +}
 +
 +static const char* NOTATION_STRING_CHARACTERS[256] =
 +{
 +	"\\x00",	// 0
 +	"\\x01",	// 1
 +	"\\x02",	// 2
 +	"\\x03",	// 3
 +	"\\x04",	// 4
 +	"\\x05",	// 5
 +	"\\x06",	// 6
 +	"\\a",		// 7
 +	"\\b",		// 8
 +	"\\t",		// 9
 +	"\\n",		// 10
 +	"\\v",		// 11
 +	"\\f",		// 12
 +	"\\r",		// 13
 +	"\\x0e",	// 14
 +	"\\x0f",	// 15
 +	"\\x10",	// 16
 +	"\\x11",	// 17
 +	"\\x12",	// 18
 +	"\\x13",	// 19
 +	"\\x14",	// 20
 +	"\\x15",	// 21
 +	"\\x16",	// 22
 +	"\\x17",	// 23
 +	"\\x18",	// 24
 +	"\\x19",	// 25
 +	"\\x1a",	// 26
 +	"\\x1b",	// 27
 +	"\\x1c",	// 28
 +	"\\x1d",	// 29
 +	"\\x1e",	// 30
 +	"\\x1f",	// 31
 +	" ",		// 32
 +	"!",		// 33
 +	"\"",		// 34
 +	"#",		// 35
 +	"$",		// 36
 +	"%",		// 37
 +	"&",		// 38
 +	"\\'",		// 39
 +	"(",		// 40
 +	")",		// 41
 +	"*",		// 42
 +	"+",		// 43
 +	",",		// 44
 +	"-",		// 45
 +	".",		// 46
 +	"/",		// 47
 +	"0",		// 48
 +	"1",		// 49
 +	"2",		// 50
 +	"3",		// 51
 +	"4",		// 52
 +	"5",		// 53
 +	"6",		// 54
 +	"7",		// 55
 +	"8",		// 56
 +	"9",		// 57
 +	":",		// 58
 +	";",		// 59
 +	"<",		// 60
 +	"=",		// 61
 +	">",		// 62
 +	"?",		// 63
 +	"@",		// 64
 +	"A",		// 65
 +	"B",		// 66
 +	"C",		// 67
 +	"D",		// 68
 +	"E",		// 69
 +	"F",		// 70
 +	"G",		// 71
 +	"H",		// 72
 +	"I",		// 73
 +	"J",		// 74
 +	"K",		// 75
 +	"L",		// 76
 +	"M",		// 77
 +	"N",		// 78
 +	"O",		// 79
 +	"P",		// 80
 +	"Q",		// 81
 +	"R",		// 82
 +	"S",		// 83
 +	"T",		// 84
 +	"U",		// 85
 +	"V",		// 86
 +	"W",		// 87
 +	"X",		// 88
 +	"Y",		// 89
 +	"Z",		// 90
 +	"[",		// 91
 +	"\\\\",		// 92
 +	"]",		// 93
 +	"^",		// 94
 +	"_",		// 95
 +	"`",		// 96
 +	"a",		// 97
 +	"b",		// 98
 +	"c",		// 99
 +	"d",		// 100
 +	"e",		// 101
 +	"f",		// 102
 +	"g",		// 103
 +	"h",		// 104
 +	"i",		// 105
 +	"j",		// 106
 +	"k",		// 107
 +	"l",		// 108
 +	"m",		// 109
 +	"n",		// 110
 +	"o",		// 111
 +	"p",		// 112
 +	"q",		// 113
 +	"r",		// 114
 +	"s",		// 115
 +	"t",		// 116
 +	"u",		// 117
 +	"v",		// 118
 +	"w",		// 119
 +	"x",		// 120
 +	"y",		// 121
 +	"z",		// 122
 +	"{",		// 123
 +	"|",		// 124
 +	"}",		// 125
 +	"~",		// 126
 +	"\\x7f",	// 127
 +	"\\x80",	// 128
 +	"\\x81",	// 129
 +	"\\x82",	// 130
 +	"\\x83",	// 131
 +	"\\x84",	// 132
 +	"\\x85",	// 133
 +	"\\x86",	// 134
 +	"\\x87",	// 135
 +	"\\x88",	// 136
 +	"\\x89",	// 137
 +	"\\x8a",	// 138
 +	"\\x8b",	// 139
 +	"\\x8c",	// 140
 +	"\\x8d",	// 141
 +	"\\x8e",	// 142
 +	"\\x8f",	// 143
 +	"\\x90",	// 144
 +	"\\x91",	// 145
 +	"\\x92",	// 146
 +	"\\x93",	// 147
 +	"\\x94",	// 148
 +	"\\x95",	// 149
 +	"\\x96",	// 150
 +	"\\x97",	// 151
 +	"\\x98",	// 152
 +	"\\x99",	// 153
 +	"\\x9a",	// 154
 +	"\\x9b",	// 155
 +	"\\x9c",	// 156
 +	"\\x9d",	// 157
 +	"\\x9e",	// 158
 +	"\\x9f",	// 159
 +	"\\xa0",	// 160
 +	"\\xa1",	// 161
 +	"\\xa2",	// 162
 +	"\\xa3",	// 163
 +	"\\xa4",	// 164
 +	"\\xa5",	// 165
 +	"\\xa6",	// 166
 +	"\\xa7",	// 167
 +	"\\xa8",	// 168
 +	"\\xa9",	// 169
 +	"\\xaa",	// 170
 +	"\\xab",	// 171
 +	"\\xac",	// 172
 +	"\\xad",	// 173
 +	"\\xae",	// 174
 +	"\\xaf",	// 175
 +	"\\xb0",	// 176
 +	"\\xb1",	// 177
 +	"\\xb2",	// 178
 +	"\\xb3",	// 179
 +	"\\xb4",	// 180
 +	"\\xb5",	// 181
 +	"\\xb6",	// 182
 +	"\\xb7",	// 183
 +	"\\xb8",	// 184
 +	"\\xb9",	// 185
 +	"\\xba",	// 186
 +	"\\xbb",	// 187
 +	"\\xbc",	// 188
 +	"\\xbd",	// 189
 +	"\\xbe",	// 190
 +	"\\xbf",	// 191
 +	"\\xc0",	// 192
 +	"\\xc1",	// 193
 +	"\\xc2",	// 194
 +	"\\xc3",	// 195
 +	"\\xc4",	// 196
 +	"\\xc5",	// 197
 +	"\\xc6",	// 198
 +	"\\xc7",	// 199
 +	"\\xc8",	// 200
 +	"\\xc9",	// 201
 +	"\\xca",	// 202
 +	"\\xcb",	// 203
 +	"\\xcc",	// 204
 +	"\\xcd",	// 205
 +	"\\xce",	// 206
 +	"\\xcf",	// 207
 +	"\\xd0",	// 208
 +	"\\xd1",	// 209
 +	"\\xd2",	// 210
 +	"\\xd3",	// 211
 +	"\\xd4",	// 212
 +	"\\xd5",	// 213
 +	"\\xd6",	// 214
 +	"\\xd7",	// 215
 +	"\\xd8",	// 216
 +	"\\xd9",	// 217
 +	"\\xda",	// 218
 +	"\\xdb",	// 219
 +	"\\xdc",	// 220
 +	"\\xdd",	// 221
 +	"\\xde",	// 222
 +	"\\xdf",	// 223
 +	"\\xe0",	// 224
 +	"\\xe1",	// 225
 +	"\\xe2",	// 226
 +	"\\xe3",	// 227
 +	"\\xe4",	// 228
 +	"\\xe5",	// 229
 +	"\\xe6",	// 230
 +	"\\xe7",	// 231
 +	"\\xe8",	// 232
 +	"\\xe9",	// 233
 +	"\\xea",	// 234
 +	"\\xeb",	// 235
 +	"\\xec",	// 236
 +	"\\xed",	// 237
 +	"\\xee",	// 238
 +	"\\xef",	// 239
 +	"\\xf0",	// 240
 +	"\\xf1",	// 241
 +	"\\xf2",	// 242
 +	"\\xf3",	// 243
 +	"\\xf4",	// 244
 +	"\\xf5",	// 245
 +	"\\xf6",	// 246
 +	"\\xf7",	// 247
 +	"\\xf8",	// 248
 +	"\\xf9",	// 249
 +	"\\xfa",	// 250
 +	"\\xfb",	// 251
 +	"\\xfc",	// 252
 +	"\\xfd",	// 253
 +	"\\xfe",	// 254
 +	"\\xff"		// 255
 +};
 +
 +void serialize_string(const std::string& value, std::ostream& str)
 +{
 +	std::string::const_iterator it = value.begin();
 +	std::string::const_iterator end = value.end();
 +	U8 c;
 +	for(; it != end; ++it)
 +	{
 +		c = (U8)(*it);
 +		str << NOTATION_STRING_CHARACTERS[c];
 +	}
 +}
 +
 +int deserialize_boolean(
 +	std::istream& istr,
 +	LLSD& data,
 +	const std::string& compare,
 +	bool value)
 +{
 +	//
 +	// this method is a little goofy, because it gets the stream at
 +	// the point where the t or f has already been
 +	// consumed. Basically, parse for a patch to the string passed in
 +	// starting at index 1. If it's a match:
 +	//  * assign data to value
 +	//  * return the number of bytes read
 +	// otherwise:
 +	//  * set data to LLSD::null
 +	//  * return LLSDParser::PARSE_FAILURE (-1)
 +	//
 +	int bytes_read = 0;
 +	std::string::size_type ii = 0;
 +	char c = istr.peek();
 +	while((++ii < compare.size())
 +		  && (tolower(c) == (int)compare[ii])
 +		  && istr.good())
 +	{
 +		istr.ignore();
 +		++bytes_read;
 +		c = istr.peek();
 +	}
 +	if(compare.size() != ii)
 +	{
 +		data.clear();
 +		return LLSDParser::PARSE_FAILURE;
 +	}
 +	data = value;
 +	return bytes_read;
 +}
 +
 +std::ostream& operator<<(std::ostream& s, const LLSD& llsd)
 +{
 +	s << LLSDNotationStreamer(llsd);
 +	return s;
 +}
 +
 +
 +//dirty little zippers -- yell at davep if these are horrid
 +
 +//return a string containing gzipped bytes of binary serialized LLSD
 +// VERY inefficient -- creates several copies of LLSD block in memory
 +std::string zip_llsd(LLSD& data)
 +{ 
 +	std::stringstream llsd_strm;
 +
 +	LLSDSerialize::toBinary(data, llsd_strm);
 +
 +	const U32 CHUNK = 65536;
 +
 +	z_stream strm;
 +	strm.zalloc = Z_NULL;
 +	strm.zfree = Z_NULL;
 +	strm.opaque = Z_NULL;
 +
 +	S32 ret = deflateInit(&strm, Z_BEST_COMPRESSION);
 +	if (ret != Z_OK)
 +	{
 +		llwarns << "Failed to compress LLSD block." << llendl;
 +		return std::string();
 +	}
 +
 +	std::string source = llsd_strm.str();
 +
 +	U8 out[CHUNK];
 +
 +	strm.avail_in = source.size();
 +	strm.next_in = (U8*) source.data();
 +	U8* output = NULL;
 +
 +	U32 cur_size = 0;
 +
 +	U32 have = 0;
 +
 +	do
 +	{
 +		strm.avail_out = CHUNK;
 +		strm.next_out = out;
 +
 +		ret = deflate(&strm, Z_FINISH);
 +		if (ret == Z_OK || ret == Z_STREAM_END)
 +		{ //copy result into output
 +			if (strm.avail_out >= CHUNK)
 +			{
 +				free(output);
 +				llwarns << "Failed to compress LLSD block." << llendl;
 +				return std::string();
 +			}
 +
 +			have = CHUNK-strm.avail_out;
 +			output = (U8*) realloc(output, cur_size+have);
 +			memcpy(output+cur_size, out, have);
 +			cur_size += have;
 +		}
 +		else 
 +		{
 +			free(output);
 +			llwarns << "Failed to compress LLSD block." << llendl;
 +			return std::string();
 +		}
 +	}
 +	while (ret == Z_OK);
 +
 +	std::string::size_type size = cur_size;
 +
 +	std::string result((char*) output, size);
 +	deflateEnd(&strm);
 +	free(output);
 +
 +#if 0 //verify results work with unzip_llsd
 +	std::istringstream test(result);
 +	LLSD test_sd;
 +	if (!unzip_llsd(test_sd, test, result.size()))
 +	{
 +		llerrs << "Invalid compression result!" << llendl;
 +	}
 +#endif
 +
 +	return result;
 +}
 +
 +//decompress a block of LLSD from provided istream
 +// not very efficient -- creats a copy of decompressed LLSD block in memory
 +// and deserializes from that copy using LLSDSerialize
 +bool unzip_llsd(LLSD& data, std::istream& is, S32 size)
 +{
 +	U8* result = NULL;
 +	U32 cur_size = 0;
 +	z_stream strm;
 +		
 +	const U32 CHUNK = 65536;
 +
 +	U8 *in = new U8[size];
 +	is.read((char*) in, size); 
 +
 +	U8 out[CHUNK];
 +		
 +	strm.zalloc = Z_NULL;
 +	strm.zfree = Z_NULL;
 +	strm.opaque = Z_NULL;
 +	strm.avail_in = size;
 +	strm.next_in = in;
 +
 +	S32 ret = inflateInit(&strm);
 +	
 +	do
 +	{
 +		strm.avail_out = CHUNK;
 +		strm.next_out = out;
 +		ret = inflate(&strm, Z_NO_FLUSH);
 +		if (ret == Z_STREAM_ERROR)
 +		{
 +			inflateEnd(&strm);
 +			free(result);
 +			delete [] in;
 +			return false;
 +		}
 +		
 +		switch (ret)
 +		{
 +		case Z_NEED_DICT:
 +			ret = Z_DATA_ERROR;
 +		case Z_DATA_ERROR:
 +		case Z_MEM_ERROR:
 +			inflateEnd(&strm);
 +			free(result);
 +			delete [] in;
 +			return false;
 +			break;
 +		}
 +
 +		U32 have = CHUNK-strm.avail_out;
 +
 +		result = (U8*) realloc(result, cur_size + have);
 +		memcpy(result+cur_size, out, have);
 +		cur_size += have;
 +
 +	} while (ret == Z_OK);
 +
 +	inflateEnd(&strm);
 +	delete [] in;
 +
 +	if (ret != Z_STREAM_END)
 +	{
 +		free(result);
 +		return false;
 +	}
 +
 +	//result now points to the decompressed LLSD block
 +	{
 +		std::string res_str((char*) result, cur_size);
 +
 +		std::string deprecated_header("<? LLSD/Binary ?>");
 +
 +		if (res_str.substr(0, deprecated_header.size()) == deprecated_header)
 +		{
 +			res_str = res_str.substr(deprecated_header.size()+1, cur_size);
 +		}
 +		cur_size = res_str.size();
 +
 +		std::istringstream istr(res_str);
 +		
 +		if (!LLSDSerialize::fromBinary(data, istr, cur_size))
 +		{
 +			llwarns << "Failed to unzip LLSD block" << llendl;
 +			free(result);
 +			return false;
 +		}		
 +	}
 +
 +	free(result);
 +	return true;
 +}
 +//This unzip function will only work with a gzip header and trailer - while the contents
 +//of the actual compressed data is the same for either format (gzip vs zlib ), the headers
 +//and trailers are different for the formats.
 +U8* unzip_llsdNavMesh( bool& valid, unsigned int& outsize, std::istream& is, S32 size )
 +{
 +	U8* result = NULL;
 +	U32 cur_size = 0;
 +	z_stream strm;
 +		
 +	const U32 CHUNK = 0x4000;
 +
 +	U8 *in = new U8[size];
 +	is.read((char*) in, size); 
 +
 +	U8 out[CHUNK];
 +		
 +	strm.zalloc = Z_NULL;
 +	strm.zfree = Z_NULL;
 +	strm.opaque = Z_NULL;
 +	strm.avail_in = size;
 +	strm.next_in = in;
 +
 +	
 +	S32 ret = inflateInit2(&strm,  windowBits | ENABLE_ZLIB_GZIP );
 +	do
 +	{
 +		strm.avail_out = CHUNK;
 +		strm.next_out = out;
 +		ret = inflate(&strm, Z_NO_FLUSH);
 +		if (ret == Z_STREAM_ERROR)
 +		{
 +			inflateEnd(&strm);
 +			free(result);
 +			delete [] in;
 +			valid = false;
 +		}
 +		
 +		switch (ret)
 +		{
 +		case Z_NEED_DICT:
 +			ret = Z_DATA_ERROR;
 +		case Z_DATA_ERROR:
 +		case Z_MEM_ERROR:
 +			inflateEnd(&strm);
 +			free(result);
 +			delete [] in;
 +			valid = false;
 +			break;
 +		}
 +
 +		U32 have = CHUNK-strm.avail_out;
 +
 +		result = (U8*) realloc(result, cur_size + have);
 +		memcpy(result+cur_size, out, have);
 +		cur_size += have;
 +
 +	} while (ret == Z_OK);
 +
 +	inflateEnd(&strm);
 +	delete [] in;
 +
 +	if (ret != Z_STREAM_END)
 +	{
 +		free(result);
 +		valid = false;
 +		return NULL;
 +	}
 +
 +	//result now points to the decompressed LLSD block
 +	{
 +		outsize= cur_size;
 +		valid = true;		
 +	}
 +
 +	return result;
 +}
 +
 +
 diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index be9db53906..34b3dbb99a 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -464,7 +464,7 @@ S32 LLSDXMLParser::Impl::parseLines(std::istream& input, LLSD& data)  			}  		} -		status = XML_ParseBuffer(mParser, num_read, false); +		status = XML_ParseBuffer(mParser, (int)num_read, false);  		if (status == XML_STATUS_ERROR)  		{  			break; diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index 65c7297cbf..532d3f9341 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -308,7 +308,7 @@ class LLSDParam<T>                              \  {                                               \  public:                                         \      LLSDParam(const LLSD& value):               \ -        _value(value.AS())                      \ +        _value((T)value.AS())                      \      {}                                          \                                                  \      operator T() const { return _value; }       \ diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index b2c495d093..057257057f 100644 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -593,7 +593,7 @@ void LLStatTime::stop()  {      if ( LLStatAccum::SCALE_PER_FRAME == scale )      { -        return mTotalTimeInFrame; +        return (F32)mTotalTimeInFrame;      }      else      { diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 38054b636e..9ebc6de7f4 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -83,7 +83,7 @@ U32 micro_sleep(U64 us, U32 max_yields)  {      // max_yields is unused; just fiddle with it to avoid warnings.      max_yields = 0; -    ms_sleep(us / 1000); +	ms_sleep((U32)(us / 1000));      return 0;  }  #elif LL_LINUX || LL_SOLARIS || LL_DARWIN diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 3461aa3e6c..d6dcde4b9f 100644 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -250,7 +250,7 @@ void LLCrashLogger::gatherFiles()  		if(minidump_stream.is_open())  		{  			minidump_stream.seekg(0, std::ios::end); -			size_t length = minidump_stream.tellg(); +			size_t length = (size_t)minidump_stream.tellg();  			minidump_stream.seekg(0, std::ios::beg);  			LLSD::Binary data; diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index cc8cb66d73..8241746a74 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -501,10 +501,10 @@ void LLImageCompressionTester::outputTestRecord(LLSD *sd)  	F32 decompressionRate = 0.0f;  	F32 compressionRate   = 0.0f; -	F32 totalkBInDecompression  = (F32)(mTotalBytesInDecompression)  / 1000.0; -	F32 totalkBOutDecompression = (F32)(mTotalBytesOutDecompression) / 1000.0; -	F32 totalkBInCompression    = (F32)(mTotalBytesInCompression)    / 1000.0; -	F32 totalkBOutCompression   = (F32)(mTotalBytesOutCompression)   / 1000.0; +	F32 totalkBInDecompression  = (F32)(mTotalBytesInDecompression)  / 1000.f; +	F32 totalkBOutDecompression = (F32)(mTotalBytesOutDecompression) / 1000.f; +	F32 totalkBInCompression    = (F32)(mTotalBytesInCompression)    / 1000.f; +	F32 totalkBOutCompression   = (F32)(mTotalBytesOutCompression)   / 1000.f;  	if (!is_approx_zero(mTotalTimeDecompression))  	{ diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 76760aa414..fbf23bc3f0 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -405,7 +405,7 @@ U32 LLInventoryItem::getCRC32() const  	//lldebugs << "7 crc: " << std::hex << crc << std::dec << llendl;  	crc += mSaleInfo.getCRC32();  	//lldebugs << "8 crc: " << std::hex << crc << std::dec << llendl; -	crc += mCreationDate; +	crc += (U32)mCreationDate;  	//lldebugs << "9 crc: " << std::hex << crc << std::dec << llendl;  	return crc;  } @@ -521,7 +521,7 @@ void LLInventoryItem::packMessage(LLMessageSystem* msg) const  	mSaleInfo.packMessage(msg);  	msg->addStringFast(_PREHASH_Name, mName);  	msg->addStringFast(_PREHASH_Description, mDescription); -	msg->addS32Fast(_PREHASH_CreationDate, mCreationDate); +	msg->addS32Fast(_PREHASH_CreationDate, (S32)mCreationDate);  	U32 crc = getCRC32();  	msg->addU32Fast(_PREHASH_CRC, crc);  } diff --git a/indra/llmath/llcalcparser.h b/indra/llmath/llcalcparser.h index bd9c8c2519..e0ad270266 100644 --- a/indra/llmath/llcalcparser.h +++ b/indra/llmath/llcalcparser.h @@ -174,7 +174,7 @@ private:  	F32 _log(const F32& a) const { return log(a); }  	F32 _exp(const F32& a) const { return exp(a); }  	F32 _fabs(const F32& a) const { return fabs(a); } -	F32 _floor(const F32& a) const { return llfloor(a); } +	F32 _floor(const F32& a) const { return (F32)llfloor(a); }  	F32 _ceil(const F32& a) const { return llceil(a); }  	F32 _atan2(const F32& a,const F32& b) const { return atan2(a,b); } diff --git a/indra/llmath/llcoord.h b/indra/llmath/llcoord.h index 706ad92787..1f617e649e 100644 --- a/indra/llmath/llcoord.h +++ b/indra/llmath/llcoord.h @@ -26,80 +26,80 @@  #ifndef LL_LLCOORD_H  #define LL_LLCOORD_H +struct LLCoordCommon +{ +	LLCoordCommon(S32 x, S32 y) : mX(x), mY(y) {} +	LLCoordCommon() : mX(0), mY(0) {} +	S32 mX; +	S32 mY; +}; +  // A two-dimensional pixel value -class LLCoord +template<typename COORD_FRAME> +class LLCoord : protected COORD_FRAME  {  public: -	S32		mX; -	S32		mY; +	typedef LLCoord<COORD_FRAME> self_t; +	typename COORD_FRAME::value_t	mX; +	typename COORD_FRAME::value_t	mY;  	LLCoord():	mX(0), mY(0)  	{}  	LLCoord(S32 x, S32 y): mX(x), mY(y)  	{} -	virtual ~LLCoord() -	{} -	virtual void set(S32 x, S32 y)		{ mX = x; mY = y; } -}; +	LLCoord(const LLCoordCommon& other) +	{ +		COORD_FRAME::convertFromCommon(other); +	} +	LLCoordCommon convert() const +	{ +		return COORD_FRAME::convertToCommon(); +	} -// GL coordinates start in the client region of a window, -// with left, bottom = 0, 0 -class LLCoordGL : public LLCoord -{ -public: -	LLCoordGL() : LLCoord() -	{} -	LLCoordGL(S32 x, S32 y) : LLCoord(x, y) -	{} -	bool operator==(const LLCoordGL& other) const { return mX == other.mX && mY == other.mY; } -	bool operator!=(const LLCoordGL& other) const { return !(*this == other); } -}; +	void set(S32 x, S32 y) { mX = x; mY = y;} +	bool operator==(const self_t& other) const { return mX == other.mX && mY == other.mY; } +	bool operator!=(const self_t& other) const { return !(*this == other); } -//bool operator ==(const LLCoordGL& a, const LLCoordGL& b); +}; -// Window coords include things like window borders, -// menu regions, etc. -class LLCoordWindow : public LLCoord +struct LL_COORD_TYPE_GL   { -public: -	LLCoordWindow() : LLCoord() -	{} -	LLCoordWindow(S32 x, S32 y) : LLCoord(x, y) -	{} -	bool operator==(const LLCoordWindow& other) const { return mX == other.mX && mY == other.mY; } -	bool operator!=(const LLCoordWindow& other) const { return !(*this == other); } -}; +	typedef S32 value_t; +	LLCoordCommon convertToCommon() const +	{ +		const LLCoord<LL_COORD_TYPE_GL>& self = static_cast<const LLCoord<LL_COORD_TYPE_GL>&>(*this); +		return LLCoordCommon(self.mX, self.mY); +	} + +	void convertFromCommon(const LLCoordCommon& from) +	{ +		LLCoord<LL_COORD_TYPE_GL>& self = static_cast<LLCoord<LL_COORD_TYPE_GL>&>(*this); +		self.mX = from.mX; +		self.mY = from.mY; +	} +}; -// Screen coords start at left, top = 0, 0 -class LLCoordScreen : public LLCoord +struct LL_COORD_TYPE_WINDOW   { -public: -	LLCoordScreen() : LLCoord() -	{} -	LLCoordScreen(S32 x, S32 y) : LLCoord(x, y) -	{} -	bool operator==(const LLCoordScreen& other) const { return mX == other.mX && mY == other.mY; } -	bool operator!=(const LLCoordScreen& other) const { return !(*this == other); } +	typedef S32 value_t; + +	LLCoordCommon convertToCommon() const; +	void convertFromCommon(const LLCoordCommon& from);  }; -class LLCoordFont : public LLCoord +struct LL_COORD_TYPE_SCREEN   { -public: -	F32 mZ; -	 -	LLCoordFont() : LLCoord(), mZ(0.f) -	{} -	LLCoordFont(S32 x, S32 y, F32 z = 0) : LLCoord(x,y), mZ(z) -	{} -	 -	void set(S32 x, S32 y) { LLCoord::set(x,y); mZ = 0.f; } -	void set(S32 x, S32 y, F32 z) { mX = x; mY = y; mZ = z; } -	bool operator==(const LLCoordFont& other) const { return mX == other.mX && mY == other.mY; } -	bool operator!=(const LLCoordFont& other) const { return !(*this == other); } +	typedef S32 value_t; + +	LLCoordCommon convertToCommon() const; +	void convertFromCommon(const LLCoordCommon& from);  }; -	 + +typedef LLCoord<LL_COORD_TYPE_GL> LLCoordGL; +typedef LLCoord<LL_COORD_TYPE_WINDOW> LLCoordWindow; +typedef LLCoord<LL_COORD_TYPE_SCREEN> LLCoordScreen;  #endif diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 761fc171c4..cc9744756f 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -2904,7 +2904,7 @@ F32 LLVolume::sculptGetSurfaceArea()  			// compute the area of the quad by taking the length of the cross product of the two triangles  			LLVector3 cross1 = (p1 - p2) % (p1 - p3);  			LLVector3 cross2 = (p4 - p2) % (p4 - p3); -			area += (cross1.magVec() + cross2.magVec()) / 2.0; +			area += (cross1.magVec() + cross2.magVec()) / 2.f;  		}  	} @@ -5890,7 +5890,7 @@ F32 find_vertex_score(LLVCacheVertexData& data)  	}  	//bonus points for having low valence -	F32 valence_boost = powf(data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); +	F32 valence_boost = powf((F32)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower);  	score += FindVertexScore_ValenceBoostScale * valence_boost;  	return score; diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index bad4deb4de..6a1b4143cf 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -858,25 +858,25 @@ LLSD LLMatrix4::getValue() const  void LLMatrix4::setValue(const LLSD& data)   { -	mMatrix[0][0] = data[0].asReal(); -	mMatrix[0][1] = data[1].asReal(); -	mMatrix[0][2] = data[2].asReal(); -	mMatrix[0][3] = data[3].asReal(); - -	mMatrix[1][0] = data[4].asReal(); -	mMatrix[1][1] = data[5].asReal(); -	mMatrix[1][2] = data[6].asReal(); -	mMatrix[1][3] = data[7].asReal(); - -	mMatrix[2][0] = data[8].asReal(); -	mMatrix[2][1] = data[9].asReal(); -	mMatrix[2][2] = data[10].asReal(); -	mMatrix[2][3] = data[11].asReal(); - -	mMatrix[3][0] = data[12].asReal(); -	mMatrix[3][1] = data[13].asReal(); -	mMatrix[3][2] = data[14].asReal(); -	mMatrix[3][3] = data[15].asReal(); +	mMatrix[0][0] = (F32)data[0].asReal(); +	mMatrix[0][1] = (F32)data[1].asReal(); +	mMatrix[0][2] = (F32)data[2].asReal(); +	mMatrix[0][3] = (F32)data[3].asReal(); + +	mMatrix[1][0] = (F32)data[4].asReal(); +	mMatrix[1][1] = (F32)data[5].asReal(); +	mMatrix[1][2] = (F32)data[6].asReal(); +	mMatrix[1][3] = (F32)data[7].asReal(); + +	mMatrix[2][0] = (F32)data[8].asReal(); +	mMatrix[2][1] = (F32)data[9].asReal(); +	mMatrix[2][2] = (F32)data[10].asReal(); +	mMatrix[2][3] = (F32)data[11].asReal(); + +	mMatrix[3][0] = (F32)data[12].asReal(); +	mMatrix[3][1] = (F32)data[13].asReal(); +	mMatrix[3][2] = (F32)data[14].asReal(); +	mMatrix[3][3] = (F32)data[15].asReal();  } diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index 3bcaffc275..b93d429feb 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -271,10 +271,10 @@ void LLCurl::Easy::releaseEasyHandle(CURL* handle)  		if(sFreeHandles.size() < MAX_NUM_FREE_HANDLES)  		{ -			sFreeHandles.insert(handle); -		} -		else -		{ +		sFreeHandles.insert(handle); +	} +	else +	{  			LLCurl::deleteEasyHandle(handle) ;  		}  	} @@ -453,9 +453,9 @@ size_t curlReadCallback(char* data, size_t size, size_t nmemb, void* user_data)  	LLCurl::Easy* easy = (LLCurl::Easy*)user_data;  	S32 n = size * nmemb; -	S32 startpos = easy->getInput().tellg(); +	S32 startpos = (S32)easy->getInput().tellg();  	easy->getInput().seekg(0, std::ios::end); -	S32 endpos = easy->getInput().tellg(); +	S32 endpos = (S32)easy->getInput().tellg();  	easy->getInput().seekg(startpos, std::ios::beg);  	S32 maxn = endpos - startpos;  	n = llmin(n, maxn); @@ -560,16 +560,16 @@ LLCurl::Multi::Multi(F32 idle_time_out)  	}  	//llassert_always(mCurlMultiHandle);	 -	 +  	if(mCurlMultiHandle)  	{ -		if(LLCurl::getCurlThread()->getThreaded()) -		{ -			mMutexp = new LLMutex(NULL) ; -			mDeletionMutexp = new LLMutex(NULL) ; -			mEasyMutexp = new LLMutex(NULL) ; -		} -		LLCurl::getCurlThread()->addMulti(this) ; +	if(LLCurl::getCurlThread()->getThreaded()) +	{ +		mMutexp = new LLMutex(NULL) ; +		mDeletionMutexp = new LLMutex(NULL) ; +		mEasyMutexp = new LLMutex(NULL) ; +	} +	LLCurl::getCurlThread()->addMulti(this) ;  		mIdleTimeOut = idle_time_out ;  		if(mIdleTimeOut < LLCurl::sCurlRequestTimeOut) @@ -577,8 +577,8 @@ LLCurl::Multi::Multi(F32 idle_time_out)  			mIdleTimeOut = LLCurl::sCurlRequestTimeOut ;  		} -		++gCurlMultiCount; -	} +	++gCurlMultiCount; +}  }  LLCurl::Multi::~Multi() @@ -617,7 +617,7 @@ void LLCurl::Multi::cleanup()  	mDeletionMutexp = NULL ;  	delete mEasyMutexp ;  	mEasyMutexp = NULL ; -	 +  	mQueued = 0 ;  	mState = STATE_COMPLETED; @@ -738,7 +738,7 @@ bool LLCurl::Multi::doPerform()  		}  		mQueued = q;	 -		setState(STATE_COMPLETED) ;		 +		setState(STATE_COMPLETED) ;  		mIdleTimer.reset() ;  	}  	else if(mIdleTimer.getElapsedTimeF32() > mIdleTimeOut) //idle for too long, remove it. @@ -911,8 +911,8 @@ bool LLCurlThread::CurlRequest::processRequest()  		if(!completed)  		{ -			setPriority(LLQueuedThread::PRIORITY_LOW) ; -		} +		setPriority(LLQueuedThread::PRIORITY_LOW) ; +	}  	}  	return completed ; @@ -922,7 +922,7 @@ void LLCurlThread::CurlRequest::finishRequest(bool completed)  {  	if(mMulti->isDead())  	{ -		mCurlThread->deleteMulti(mMulti) ; +	mCurlThread->deleteMulti(mMulti) ;  	}  	else  	{ @@ -968,8 +968,8 @@ void LLCurlThread::killMulti(LLCurl::Multi* multi)  	if(multi->isValid())  	{ -		multi->markDead() ; -	} +	multi->markDead() ; +}  	else  	{  		deleteMulti(multi) ; @@ -1033,7 +1033,7 @@ void LLCurlRequest::addMulti()  		mActiveRequestCount = 0 ;  		return;  	} - +	  	mMultiSet.insert(multi);  	mActiveMulti = multi;  	mActiveRequestCount = 0; @@ -1229,15 +1229,15 @@ LLCurlEasyRequest::LLCurlEasyRequest()  	if(mMulti->isValid())  	{ -		mEasy = mMulti->allocEasy(); -		if (mEasy) -		{ -			mEasy->setErrorBuffer(); -			mEasy->setCA(); -			// Set proxy settings if configured to do so. -			LLProxy::getInstance()->applyProxySettings(mEasy); -		} +	mEasy = mMulti->allocEasy(); +	if (mEasy) +	{ +		mEasy->setErrorBuffer(); +		mEasy->setCA(); +		// Set proxy settings if configured to do so. +		LLProxy::getInstance()->applyProxySettings(mEasy);  	} +}  	else  	{  		LLCurl::getCurlThread()->killMulti(mMulti) ; diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp index 231cb7ca8f..0c325a68aa 100644 --- a/indra/llmessage/llhttpclient.cpp +++ b/indra/llmessage/llhttpclient.cpp @@ -158,7 +158,7 @@ namespace  			if(fstream.is_open())  			{  				fstream.seekg(0, std::ios::end); -				U32 fileSize = fstream.tellg(); +				U32 fileSize = (U32)fstream.tellg();  				fstream.seekg(0, std::ios::beg);  				std::vector<char> fileBuffer(fileSize);  				fstream.read(&fileBuffer[0], fileSize); diff --git a/indra/llmessage/llmime.cpp b/indra/llmessage/llmime.cpp index 943a734927..9d9c4ebd68 100644 --- a/indra/llmessage/llmime.cpp +++ b/indra/llmessage/llmime.cpp @@ -388,7 +388,7 @@ bool LLMimeParser::Impl::parseHeaders(  		// not to read past limit when we get() the newline.  		S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);  		istr.getline(mBuffer, max_get, '\r'); -		mScanCount += istr.gcount(); +		mScanCount += (S32)istr.gcount();  		int c = istr.get();  		if(EOF == c)  		{ @@ -496,7 +496,7 @@ void LLMimeParser::Impl::scanPastSeparator(  		// past limit when we get() the newline.  		S32 max_get = llmin((S32)LINE_BUFFER_LENGTH, limit - mScanCount - 1);  		istr.getline(mBuffer, max_get, '\r'); -		mScanCount += istr.gcount(); +		mScanCount += (S32)istr.gcount();  		if(istr.gcount() >= LINE_BUFFER_LENGTH - 1)  		{  			// that's way too long to be a separator, so ignore it. diff --git a/indra/llmessage/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp index 9148c9dd15..1c93c12d99 100644 --- a/indra/llmessage/llsdmessage.cpp +++ b/indra/llmessage/llsdmessage.cpp @@ -88,7 +88,7 @@ bool LLSDMessage::httpListener(const LLSD& request)                                                         request,                                                         url, "POST", reply, error),                         LLSD(),      // headers -                       timeout); +                       (F32)timeout);      return false;  } diff --git a/indra/llmessage/llsdmessagebuilder.cpp b/indra/llmessage/llsdmessagebuilder.cpp index 2698a271ee..615221e0ad 100644 --- a/indra/llmessage/llsdmessagebuilder.cpp +++ b/indra/llmessage/llsdmessagebuilder.cpp @@ -317,7 +317,7 @@ void LLSDMessageBuilder::copyFromMessageData(const LLMsgData& data)  			// S64 not supported in LLSD so we just truncate it  			case MVT_S64: -				addS32(varname, *(S64*)mvci.getData()); +				addS32(varname, (S32)*(S64*)mvci.getData());  				break;  			case MVT_F32: diff --git a/indra/llmessage/llxfer.h b/indra/llmessage/llxfer.h index 989e8b2cab..f9348eb11f 100644 --- a/indra/llmessage/llxfer.h +++ b/indra/llmessage/llxfer.h @@ -29,6 +29,7 @@  #include "message.h"  #include "lltimer.h" +#include "llextendedstatus.h"  const S32 LL_XFER_LARGE_PAYLOAD = 7680; diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index d0b0e178b8..6a425cfe98 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -3147,7 +3147,7 @@ bool LLMessageSystem::generateDigestForWindowAndUUIDs(char* digest, const S32 wi  		LL_ERRS("Messaging") << "Trying to generate complex digest on a machine without a shared secret!" << llendl;  	} -	U32 now = time(NULL); +	U32 now = (U32)time(NULL);  	now /= window; @@ -3167,7 +3167,7 @@ bool LLMessageSystem::isMatchingDigestForWindowAndUUIDs(const char* digest, cons  	}  	char our_digest[MD5HEX_STR_SIZE];	/* Flawfinder: ignore */ -	U32 now = time(NULL); +	U32 now = (U32)time(NULL);  	now /= window; @@ -3213,7 +3213,7 @@ bool LLMessageSystem::generateDigestForWindow(char* digest, const S32 window) co  		LL_ERRS("Messaging") << "Trying to generate simple digest on a machine without a shared secret!" << llendl;  	} -	U32 now = time(NULL); +	U32 now = (U32)time(NULL);  	now /= window; diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index 82e8227ffe..fccbf37a8d 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -56,8 +56,9 @@ std::string LLFontGL::sAppDir;  LLColor4 LLFontGL::sShadowColor(0.f, 0.f, 0.f, 1.f);  LLFontRegistry* LLFontGL::sFontRegistry = NULL; -LLCoordFont LLFontGL::sCurOrigin; -std::vector<LLCoordFont> LLFontGL::sOriginStack; +LLCoordGL LLFontGL::sCurOrigin; +F32 LLFontGL::sCurDepth; +std::vector<std::pair<LLCoordGL, F32> > LLFontGL::sOriginStack;  const F32 EXT_X_BEARING = 1.f;  const F32 EXT_Y_BEARING = 0.f; @@ -68,20 +69,6 @@ const F32 PIXEL_CORRECTION_DISTANCE = 0.01f;  const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture  const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; -static F32 llfont_round_x(F32 x) -{ -	//return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX; -	//return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY; -	return x; -} - -static F32 llfont_round_y(F32 y) -{ -	//return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY; -	//return llfloor(y+0.5f); -	return y; -} -  LLFontGL::LLFontGL()  {  } @@ -115,23 +102,23 @@ static LLFastTimer::DeclareTimer FTM_RENDER_FONTS("Fonts");  S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, const LLRect& rect, const LLColor4 &color, HAlign halign, VAlign valign, U8 style,   					 ShadowType shadow, S32 max_chars, F32* right_x, BOOL use_ellipses) const  { -	F32 x = rect.mLeft; +	F32 x = (F32)rect.mLeft;  	F32 y = 0.f;  	switch(valign)  	{  	case TOP: -		y = rect.mTop; +		y = (F32)rect.mTop;  		break;  	case VCENTER: -		y = rect.getCenterY(); +		y = (F32)rect.getCenterY();  		break;  	case BASELINE:  	case BOTTOM: -		y = rect.mBottom; +		y = (F32)rect.mBottom;  		break;  	default: -		y = rect.mBottom; +		y = (F32)rect.mBottom;  		break;  	}  	return render(wstr, begin_offset, x, y, color, halign, valign, style, shadow, max_chars, rect.getWidth(), right_x, use_ellipses); @@ -177,21 +164,11 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons  	gGL.loadUIIdentity(); -	//gGL.translateUI(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY), sCurOrigin.mZ); - -	// this code snaps the text origin to a pixel grid to start with -	//F32 pixel_offset_x = llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); -	//F32 pixel_offset_y = llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); -	//gGL.translateUI(-pixel_offset_x, -pixel_offset_y, 0.f); -  	LLVector2 origin(floorf(sCurOrigin.mX*sScaleX), floorf(sCurOrigin.mY*sScaleY)); -	// snap the text origin to a pixel grid to start with -	origin.mV[VX] -= llround((F32)sCurOrigin.mX) - (sCurOrigin.mX); -	origin.mV[VY] -= llround((F32)sCurOrigin.mY) - (sCurOrigin.mY); -	// Depth translation, so that floating text appears 'inworld' -	// and is correclty occluded. -	gGL.translatef(0.f,0.f,sCurOrigin.mZ); +	// Depth translation, so that floating text appears 'in-world' +	// and is correctly occluded. +	gGL.translatef(0.f,0.f,sCurDepth);  	S32 chars_drawn = 0;  	S32 i; @@ -215,16 +192,17 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons  	cur_y = ((F32)y * sScaleY) + origin.mV[VY];  	// Offset y by vertical alignment. +	// use unscaled font metrics here  	switch (valign)  	{  	case TOP: -		cur_y -= mFontFreetype->getAscenderHeight(); +		cur_y -= llceil(mFontFreetype->getAscenderHeight());  		break;  	case BOTTOM: -		cur_y += mFontFreetype->getDescenderHeight(); +		cur_y += llceil(mFontFreetype->getDescenderHeight());  		break;  	case VCENTER: -		cur_y -= (mFontFreetype->getAscenderHeight() - mFontFreetype->getDescenderHeight()) / 2.f; +		cur_y -= llceil((llceil(mFontFreetype->getAscenderHeight()) - llceil(mFontFreetype->getDescenderHeight())) / 2.f);  		break;  	case BASELINE:  		// Baseline, do nothing. @@ -250,7 +228,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons  	cur_render_y = cur_y;  	cur_render_x = cur_x; -	F32 start_x = llround(cur_x); +	F32 start_x = (F32)llround(cur_x);  	const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache(); @@ -334,10 +312,10 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons  				(fgi->mXBitmapOffset + fgi->mWidth) * inv_width,  				(fgi->mYBitmapOffset - PAD_UVY) * inv_height);  		// snap glyph origin to whole screen pixel -		LLRectf screen_rect(llround(cur_render_x + (F32)fgi->mXBearing), -				    llround(cur_render_y + (F32)fgi->mYBearing), -				    llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, -				    llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); +		LLRectf screen_rect((F32)llround(cur_render_x + (F32)fgi->mXBearing), +				    (F32)llround(cur_render_y + (F32)fgi->mYBearing), +				    (F32)llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, +				    (F32)llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight);  		if (glyph_count >= GLYPH_BATCH_SIZE)  		{ @@ -390,12 +368,12 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons  	//FIXME: add underline as glyph?  	if (style_to_add & UNDERLINE)  	{ -		F32 descender = mFontFreetype->getDescenderHeight(); +		F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight());  		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);  		gGL.begin(LLRender::LINES); -		gGL.vertex2f(start_x, cur_y - (descender)); -		gGL.vertex2f(cur_x, cur_y - (descender)); +		gGL.vertex2f(start_x, cur_y - descender); +		gGL.vertex2f(cur_x, cur_y - descender);  		gGL.end();  	} @@ -444,19 +422,9 @@ S32 LLFontGL::renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y  }  // font metrics - override for LLFontFreetype that returns units of virtual pixels -F32 LLFontGL::getLineHeight() const +S32 LLFontGL::getLineHeight() const  {  -	return (F32)llround(mFontFreetype->getLineHeight() / sScaleY);  -} - -F32 LLFontGL::getAscenderHeight() const -{  -	return (F32)llround(mFontFreetype->getAscenderHeight() / sScaleY);  -} - -F32 LLFontGL::getDescenderHeight() const -{  -	return (F32)llround(mFontFreetype->getDescenderHeight() / sScaleY);  +	return llceil(mFontFreetype->getAscenderHeight() / sScaleY) + llceil(mFontFreetype->getDescenderHeight() / sScaleY);  }  S32 LLFontGL::getWidth(const std::string& utf8text) const @@ -645,7 +613,7 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch  		}  		// Round after kerning. -		cur_x = llround(cur_x); +		cur_x = (F32)llround(cur_x);  		drawn_x = cur_x;  	} @@ -716,7 +684,7 @@ S32	LLFontGL::firstDrawableChar(const llwchar* wchars, F32 max_pixels, S32 text_  		}  		// Round after kerning. -		total_width = llround(total_width); +		total_width = (F32)llround(total_width);  	}  	if (drawable_chars == 0) @@ -799,7 +767,7 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t  		// Round after kerning. -		cur_x = llround(cur_x); +		cur_x = (F32)llround(cur_x);  	}  	return llmin(max_chars, pos - begin_offset); @@ -1146,22 +1114,22 @@ void LLFontGL::renderQuad(LLVector3* vertex_out, LLVector2* uv_out, LLColor4U* c  {  	S32 index = 0; -	vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mRight), llfont_round_y(screen_rect.mTop), 0.f); +	vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mTop, 0.f);  	uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);  	colors_out[index] = color;  	index++; -	vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mLeft), llfont_round_y(screen_rect.mTop), 0.f); +	vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mTop, 0.f);  	uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);  	colors_out[index] = color;  	index++; -	vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mLeft), llfont_round_y(screen_rect.mBottom), 0.f); +	vertex_out[index] = LLVector3(screen_rect.mLeft, screen_rect.mBottom, 0.f);  	uv_out[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);  	colors_out[index] = color;  	index++; -	vertex_out[index] = LLVector3(llfont_round_x(screen_rect.mRight), llfont_round_y(screen_rect.mBottom), 0.f); +	vertex_out[index] = LLVector3(screen_rect.mRight, screen_rect.mBottom, 0.f);  	uv_out[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);  	colors_out[index] = color;  } diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index dc8d848ed2..74bdbb43e7 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -115,9 +115,7 @@ public:  	S32 renderUTF8(const std::string &text, S32 begin_offset, S32 x, S32 y, const LLColor4 &color, HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const;  	// font metrics - override for LLFontFreetype that returns units of virtual pixels -	F32 getLineHeight() const; -	F32 getAscenderHeight() const; -	F32 getDescenderHeight() const; +	S32 getLineHeight() const;  	S32 getWidth(const std::string& utf8text) const;  	S32 getWidth(const llwchar* wchars) const; @@ -188,8 +186,9 @@ public:  	static std::string getFontPathLocal();  	static std::string getFontPathSystem(); -	static LLCoordFont sCurOrigin; -	static std::vector<LLCoordFont> sOriginStack; +	static LLCoordGL sCurOrigin; +	static F32			sCurDepth; +	static std::vector<std::pair<LLCoordGL, F32> > sOriginStack;  	static LLColor4 sShadowColor; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 6b2852670a..3773568ad8 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -64,10 +64,23 @@ BOOL shouldChange(const LLVector4& v1, const LLVector4& v2)  }  LLShaderFeatures::LLShaderFeatures() -: calculatesLighting(false), isShiny(false), isFullbright(false), hasWaterFog(false), -hasTransport(false), hasSkinning(false), hasObjectSkinning(false), hasAtmospherics(false), isSpecular(false), -hasGamma(false), hasLighting(false), isAlphaLighting(false), calculatesAtmospherics(false), mIndexedTextureChannels(0), disableTextureIndex(false), -hasAlphaMask(false) +	: atmosphericHelpers(false) +	, calculatesLighting(false) +	, calculatesAtmospherics(false) +	, hasLighting(false) +	, isAlphaLighting(false) +	, isShiny(false) +	, isFullbright(false) +	, isSpecular(false) +	, hasWaterFog(false) +	, hasTransport(false) +	, hasSkinning(false) +	, hasObjectSkinning(false) +	, hasAtmospherics(false) +	, hasGamma(false) +	, mIndexedTextureChannels(0) +	, disableTextureIndex(false) +	, hasAlphaMask(false)  {  } diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index 00b4b0dbd4..7873fe3c4e 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -33,6 +33,7 @@  class LLShaderFeatures  {  public: +	bool atmosphericHelpers;  	bool calculatesLighting;  	bool calculatesAtmospherics;  	bool hasLighting; // implies no transport (it's possible to have neither though) diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 1a03aeebb7..908443e8cf 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -94,13 +94,16 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader)  		}  	} -	if (features->calculatesLighting) +	if (features->calculatesLighting || features->atmosphericHelpers)  	{  		if (!shader->attachObject("windlight/atmosphericsHelpersV.glsl"))  		{  			return FALSE;  		} +	} +	if (features->calculatesLighting) +	{  		if (features->isSpecular)  		{  			if (!shader->attachObject("lighting/lightFuncSpecularV.glsl")) diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 79d1beb33a..b562c91e3e 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -53,31 +53,31 @@ U32 nhpo2(U32 v)  //============================================================================
  //static
 -LLVBOPool LLVertexBuffer::sStreamVBOPool;
 -LLVBOPool LLVertexBuffer::sDynamicVBOPool;
 -LLVBOPool LLVertexBuffer::sStreamIBOPool;
 -LLVBOPool LLVertexBuffer::sDynamicIBOPool;
 +LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
 +LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
 +LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
 +LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
  U32 LLVBOPool::sBytesPooled = 0;
 -LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL ;
 +LLPrivateMemoryPool* LLVertexBuffer::sPrivatePoolp = NULL;
  U32 LLVertexBuffer::sBindCount = 0;
  U32 LLVertexBuffer::sSetCount = 0;
  S32 LLVertexBuffer::sCount = 0;
  S32 LLVertexBuffer::sGLCount = 0;
  S32 LLVertexBuffer::sMappedCount = 0;
 -BOOL LLVertexBuffer::sDisableVBOMapping = FALSE ;
 -BOOL LLVertexBuffer::sEnableVBOs = TRUE;
 +bool LLVertexBuffer::sDisableVBOMapping = false;
 +bool LLVertexBuffer::sEnableVBOs = true;
  U32 LLVertexBuffer::sGLRenderBuffer = 0;
  U32 LLVertexBuffer::sGLRenderArray = 0;
  U32 LLVertexBuffer::sGLRenderIndices = 0;
  U32 LLVertexBuffer::sLastMask = 0;
 -BOOL LLVertexBuffer::sVBOActive = FALSE;
 -BOOL LLVertexBuffer::sIBOActive = FALSE;
 +bool LLVertexBuffer::sVBOActive = false;
 +bool LLVertexBuffer::sIBOActive = false;
  U32 LLVertexBuffer::sAllocatedBytes = 0;
 -BOOL LLVertexBuffer::sMapped = FALSE;
 -BOOL LLVertexBuffer::sUseStreamDraw = TRUE;
 -BOOL LLVertexBuffer::sUseVAO = FALSE;
 -BOOL LLVertexBuffer::sPreferStreamDraw = FALSE;
 +bool LLVertexBuffer::sMapped = false;
 +bool LLVertexBuffer::sUseStreamDraw = true;
 +bool LLVertexBuffer::sUseVAO = false;
 +bool LLVertexBuffer::sPreferStreamDraw = false;
  const U32 FENCE_WAIT_TIME_NANOSECONDS = 10000;  //1 ms
 @@ -204,15 +204,15 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)  	Record rec;
  	rec.mGLName = name;
  	rec.mClientData = buffer;
 -
 -	sBytesPooled += size;
 -
 -	if (!LLVertexBuffer::sDisableVBOMapping && mUsage == GL_DYNAMIC_DRAW_ARB)
 +	
 +	if (buffer == NULL)
 +	
  	{
  		glDeleteBuffersARB(1, &rec.mGLName);
  	}
  	else
  	{
 +		sBytesPooled += size;
  	mFreeList[i].push_back(rec);
  }
  }
 @@ -283,7 +283,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)  {
  	if (sLastMask != data_mask)
  	{
 -		BOOL error = FALSE;
 +		bool error = false;
  		if (LLGLSLShader::sNoFixedFunction)
  		{
 @@ -344,7 +344,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)  						{
  							if (gDebugSession)
  							{
 -								error = TRUE;
 +								error = true;
  								gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl;
  							}
  							else
 @@ -364,7 +364,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask)  					{ //needs to be disabled, make sure it was (DEBUG TEMPORARY)
  						if (gDebugSession)
  						{
 -							error = TRUE;
 +							error = true;
  							gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl;
  						}
  						else
 @@ -430,7 +430,7 @@ void LLVertexBuffer::drawArrays(U32 mode, const std::vector<LLVector3>& pos, con  	U32 count = pos.size();
  	llassert_always(norm.size() >= pos.size());
 -	llassert_always(count > 0) ;
 +	llassert_always(count > 0);
  	unbind();
 @@ -548,7 +548,7 @@ void LLVertexBuffer::validateRange(U32 start, U32 end, U32 count, U32 indices_of  void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indices_offset) const
  {
  	validateRange(start, end, count, indices_offset);
 -	mMappable = FALSE;
 +	mMappable = false;
  	gGL.syncMatrices();
  	llassert(mNumVerts >= 0);
 @@ -603,7 +603,7 @@ void LLVertexBuffer::drawRange(U32 mode, U32 start, U32 end, U32 count, U32 indi  void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const
  {
  	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
 -	mMappable = FALSE;
 +	mMappable = false;
  	gGL.syncMatrices();
  	llassert(mNumIndices >= 0);
 @@ -649,7 +649,7 @@ void LLVertexBuffer::draw(U32 mode, U32 count, U32 indices_offset) const  void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const
  {
  	llassert(!LLGLSLShader::sNoFixedFunction || LLGLSLShader::sCurBoundShaderPtr != NULL);
 -	mMappable = FALSE;
 +	mMappable = false;
  	gGL.syncMatrices();
  	llassert(mNumVerts >= 0);
 @@ -668,7 +668,7 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const  	}
  	else
  	{
 -		BOOL uvb = useVBOs();
 +		bool uvb = useVBOs();
  		if (mGLBuffer != sGLRenderBuffer || uvb != sVBOActive)
  		{
  			llerrs << "Wrong vertex buffer bound." << llendl;
 @@ -690,23 +690,13 @@ void LLVertexBuffer::drawArrays(U32 mode, U32 first, U32 count) const  //static
  void LLVertexBuffer::initClass(bool use_vbo, bool no_vbo_mapping)
  {
 -	sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject ;
 -	sDisableVBOMapping = sEnableVBOs && no_vbo_mapping ;
 +	sEnableVBOs = use_vbo && gGLManager.mHasVertexBufferObject;
 +	sDisableVBOMapping = sEnableVBOs && no_vbo_mapping;
 -	if(!sPrivatePoolp)
 +	if (!sPrivatePoolp)
  	{ 
 -		sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC) ;
 +		sPrivatePoolp = LLPrivateMemoryPoolManager::getInstance()->newPool(LLPrivateMemoryPool::STATIC);
  	}
 -
 -	sStreamVBOPool.mType = GL_ARRAY_BUFFER_ARB;
 -	sStreamVBOPool.mUsage= GL_STREAM_DRAW_ARB;
 -	sStreamIBOPool.mType = GL_ELEMENT_ARRAY_BUFFER_ARB;
 -	sStreamIBOPool.mUsage= GL_STREAM_DRAW_ARB;
 -
 -	sDynamicVBOPool.mType = GL_ARRAY_BUFFER_ARB;
 -	sDynamicVBOPool.mUsage= GL_DYNAMIC_DRAW_ARB;
 -	sDynamicIBOPool.mType = GL_ELEMENT_ARRAY_BUFFER_ARB;
 -	sDynamicIBOPool.mUsage= GL_DYNAMIC_DRAW_ARB;
  }
  //static 
 @@ -719,18 +709,18 @@ void LLVertexBuffer::unbind()  #endif
  		sGLRenderArray = 0;
  		sGLRenderIndices = 0;
 -		sIBOActive = FALSE;
 +		sIBOActive = false;
  	}
  	if (sVBOActive)
  	{
  		glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
 -		sVBOActive = FALSE;
 +		sVBOActive = false;
  	}
  	if (sIBOActive)
  	{
  		glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
 -		sIBOActive = FALSE;
 +		sIBOActive = false;
  	}
  	sGLRenderBuffer = 0;
 @@ -752,73 +742,81 @@ void LLVertexBuffer::cleanupClass()  	if(sPrivatePoolp)
  	{
 -		LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp) ;
 -		sPrivatePoolp = NULL ;
 +		LLPrivateMemoryPoolManager::getInstance()->deletePool(sPrivatePoolp);
 +		sPrivatePoolp = NULL;
  	}
  }
  //----------------------------------------------------------------------------
 -LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
 -	LLRefCount(),
 -
 -	mNumVerts(0),
 -	mNumIndices(0),
 -	mUsage(usage),
 -	mGLBuffer(0),
 -	mGLArray(0),
 -	mGLIndices(0), 
 -	mMappedData(NULL),
 -	mMappedIndexData(NULL), 
 -	mVertexLocked(FALSE),
 -	mIndexLocked(FALSE),
 -	mFinal(FALSE),
 -	mEmpty(TRUE),
 -	mFence(NULL)
 +S32 LLVertexBuffer::determineUsage(S32 usage)
  {
 -	LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
 -	mFence = NULL;
 +	S32 ret_usage = usage;
 +
  	if (!sEnableVBOs)
  	{
 -		mUsage = 0 ; 
 +		ret_usage = 0;
  	}
 -
 -	if (mUsage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
 +	
 +	if (ret_usage == GL_STREAM_DRAW_ARB && !sUseStreamDraw)
  	{
 -		mUsage = 0;
 +		ret_usage = 0;
  	}
 -	if (mUsage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
 +	if (ret_usage == GL_DYNAMIC_DRAW_ARB && sPreferStreamDraw)
  	{
 -		mUsage = GL_STREAM_DRAW_ARB;
 +		ret_usage = GL_STREAM_DRAW_ARB;
  	}
 -
 -	if (mUsage == 0 && LLRender::sGLCoreProfile)
 +	
 +	if (ret_usage == 0 && LLRender::sGLCoreProfile)
  	{ //MUST use VBOs for all rendering
 -		mUsage = GL_STREAM_DRAW_ARB;
 +		ret_usage = GL_STREAM_DRAW_ARB;
  	}
 -
 -	if (mUsage && mUsage != GL_STREAM_DRAW_ARB)
 +	
 +	if (ret_usage && ret_usage != GL_STREAM_DRAW_ARB)
  	{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
  		if (sDisableVBOMapping)
  		{ //always use stream draw if VBO mapping is disabled
 -			mUsage = GL_STREAM_DRAW_ARB;
 +			ret_usage = GL_STREAM_DRAW_ARB;
  		}
  		else
  		{
 -		mUsage = GL_DYNAMIC_DRAW_ARB;
 +ret_usage = GL_DYNAMIC_DRAW_ARB;
 +
  	}
  	}
 +	return ret_usage;
 +}
 -	if (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping)
 -	{
 -		mMappable = TRUE;
 -	}
 -	else
 -	{
 -		mMappable = FALSE;
 -	}
 +LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :
 +	LLRefCount(),
 +
 +	mNumVerts(0),
 +	mNumIndices(0),
 +	mAlignedOffset(0),
 +	mAlignedIndexOffset(0),
 +	mSize(0),
 +	mIndicesSize(0),
 +	mTypeMask(typemask),
 +	mUsage(LLVertexBuffer::determineUsage(usage)),
 +	mGLBuffer(0),
 +	mGLIndices(0),
 +	mGLArray(0),
 +	mMappedData(NULL),
 +	mMappedIndexData(NULL),
 +	mMappedDataUsingVBOs(false),
 +	mMappedIndexDataUsingVBOs(false),
 +	mVertexLocked(false),
 +	mIndexLocked(false),
 +	mFinal(false),
 +	mEmpty(true),
 +	mMappable(false),
 +	mFence(NULL)
 +{
 +	LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR);
 +
 +	mMappable = (mUsage == GL_DYNAMIC_DRAW_ARB && !sDisableVBOMapping);
  	//zero out offsets
  	for (U32 i = 0; i < TYPE_MAX; i++)
 @@ -826,12 +824,6 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) :  		mOffsets[i] = 0;
  	}
 -	mTypeMask = typemask;
 -	mSize = 0;
 -	mIndicesSize = 0;
 -	mAlignedOffset = 0;
 -	mAlignedIndexOffset = 0;
 -
  	sCount++;
  }
 @@ -903,7 +895,7 @@ LLVertexBuffer::~LLVertexBuffer()  	mFence = NULL;
 -	llassert_always(!mMappedData && !mMappedIndexData) ;
 +	llassert_always(!mMappedData && !mMappedIndexData);
  };
  void LLVertexBuffer::placeFence() const
 @@ -1012,9 +1004,11 @@ void LLVertexBuffer::createGLBuffer(U32 size)  		return;
  	}
 -	mEmpty = TRUE;
 +	mEmpty = true;
 -	if (useVBOs())
 +	mMappedDataUsingVBOs = useVBOs();
 +	
 +	if (mMappedDataUsingVBOs)
  	{
  		genBuffer(size);
  	}
 @@ -1041,12 +1035,14 @@ void LLVertexBuffer::createGLIndices(U32 size)  		return;
  	}
 -	mEmpty = TRUE;
 +	mEmpty = true;
  	//pad by 16 bytes for aligned copies
  	size += 16;
 -	if (useVBOs())
 +	mMappedIndexDataUsingVBOs = useVBOs();
 +
 +	if (mMappedIndexDataUsingVBOs)
  	{
  		//pad by another 16 bytes for VBO pointer adjustment
  		size += 16;
 @@ -1066,15 +1062,15 @@ void LLVertexBuffer::destroyGLBuffer()  	LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_BUFFER);
  	if (mGLBuffer)
  	{
 -		if (useVBOs())
 +		if (mMappedDataUsingVBOs)
  		{
  			releaseBuffer();
  		}
  		else
  		{
 -			FREE_MEM(sPrivatePoolp, (void*) mMappedData) ;
 +			FREE_MEM(sPrivatePoolp, (void*) mMappedData);
  			mMappedData = NULL;
 -			mEmpty = TRUE;
 +			mEmpty = true;
  		}
  	}
 @@ -1087,15 +1083,15 @@ void LLVertexBuffer::destroyGLIndices()  	LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_INDICES);
  	if (mGLIndices)
  	{
 -		if (useVBOs())
 +		if (mMappedIndexDataUsingVBOs)
  		{
  			releaseIndices();
  		}
  		else
  		{
 -			FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData) ;
 +			FREE_MEM(sPrivatePoolp, (void*) mMappedIndexData);
  			mMappedIndexData = NULL;
 -			mEmpty = TRUE;
 +			mEmpty = true;
  		}
  	}
 @@ -1280,16 +1276,10 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices)  	}
  }
 -BOOL LLVertexBuffer::useVBOs() const
 +bool LLVertexBuffer::useVBOs() const
  {
  	//it's generally ineffective to use VBO for things that are streaming on apple
 -		
 -	if (!mUsage)
 -	{
 -		return FALSE;
 -	}
 -
 -	return TRUE;
 +	return (mUsage != 0);
  }
  //----------------------------------------------------------------------------
 @@ -1369,7 +1359,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo  		if (!mVertexLocked)
  		{
  			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES);
 -			mVertexLocked = TRUE;
 +			mVertexLocked = true;
  			sMappedCount++;
  			stop_glerror();	
 @@ -1448,17 +1438,17 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo  			{
  				log_glerror();
 -			//check the availability of memory
 -			LLMemory::logMemoryInfo(TRUE) ; 
 +				//check the availability of memory
 +				LLMemory::logMemoryInfo(true);
  				if(mMappable)
  				{			
  					//--------------------
  					//print out more debug info before crash
 -					llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl ;
 -					GLint size ;
 -					glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size) ;
 -					llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl ;
 +					llinfos << "vertex buffer size: (num verts : num indices) = " << getNumVerts() << " : " << getNumIndices() << llendl;
 +					GLint size;
 +					glGetBufferParameterivARB(GL_ARRAY_BUFFER_ARB, GL_BUFFER_SIZE_ARB, &size);
 +					llinfos << "GL_ARRAY_BUFFER_ARB size is " << size << llendl;
  					//--------------------
  					GLint buff;
 @@ -1473,7 +1463,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo  				}
  				else
  				{
 -					llerrs << "memory allocation for vertex data failed." << llendl ;
 +					llerrs << "memory allocation for vertex data failed." << llendl;
  				}
  			}
  		}
 @@ -1548,7 +1538,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range  		{
  			LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES);
 -			mIndexLocked = TRUE;
 +			mIndexLocked = true;
  			sMappedCount++;
  			stop_glerror();	
 @@ -1627,7 +1617,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range  		if (!mMappedIndexData)
  		{
  			log_glerror();
 -			LLMemory::logMemoryInfo(TRUE) ;
 +			LLMemory::logMemoryInfo(true);
  			if(mMappable)
  			{
 @@ -1642,7 +1632,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range  			}
  			else
  			{
 -				llerrs << "memory allocation for Index data failed. " << llendl ;
 +				llerrs << "memory allocation for Index data failed. " << llendl;
  			}
  		}
  	}
 @@ -1673,10 +1663,10 @@ void LLVertexBuffer::unmapBuffer()  	LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER);
  	if (!useVBOs())
  	{
 -		return ; //nothing to unmap
 +		return; //nothing to unmap
  	}
 -	bool updated_all = false ;
 +	bool updated_all = false;
  	if (mMappedData && mVertexLocked)
  	{
 @@ -1743,7 +1733,7 @@ void LLVertexBuffer::unmapBuffer()  			mMappedData = NULL;
  		}
 -		mVertexLocked = FALSE ;
 +		mVertexLocked = false;
  		sMappedCount--;
  	}
 @@ -1807,16 +1797,16 @@ void LLVertexBuffer::unmapBuffer()  			glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
  			stop_glerror();
 -			mMappedIndexData = NULL ;
 +			mMappedIndexData = NULL;
  		}
 -		mIndexLocked = FALSE ;
 +		mIndexLocked = false;
  		sMappedCount--;
  	}
  	if(updated_all)
  	{
 -		mEmpty = FALSE;
 +		mEmpty = false;
  	}
  }
 @@ -1836,12 +1826,12 @@ template <class T,S32 type> struct VertexBufferStrider  			if (ptr == NULL)
  			{
  				llwarns << "mapIndexBuffer failed!" << llendl;
 -				return FALSE;
 +				return false;
  			}
  			strider = (T*)ptr;
  			strider.setStride(0);
 -			return TRUE;
 +			return true;
  		}
  		else if (vbo.hasDataType(type))
  		{
 @@ -1852,18 +1842,18 @@ template <class T,S32 type> struct VertexBufferStrider  			if (ptr == NULL)
  			{
  				llwarns << "mapVertexBuffer failed!" << llendl;
 -				return FALSE;
 +				return false;
  			}
  			strider = (T*)ptr;
  			strider.setStride(stride);
 -			return TRUE;
 +			return true;
  		}
  		else
  		{
  			llerrs << "VertexBufferStrider could not find valid vertex data." << llendl;
  		}
 -		return FALSE;
 +		return false;
  	}
  };
 @@ -1962,7 +1952,7 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind)  		glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
  		sGLRenderBuffer = mGLBuffer;
  		sBindCount++;
 -		sVBOActive = TRUE;
 +		sVBOActive = true;
  		if (mGLArray)
  		{
 @@ -1994,7 +1984,7 @@ bool LLVertexBuffer::bindGLIndices(bool force_bind)  		sGLRenderIndices = mGLIndices;
  		stop_glerror();
  		sBindCount++;
 -		sIBOActive = TRUE;
 +		sIBOActive = true;
  		ret = true;
  	}
 @@ -2016,7 +2006,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)  	LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_BUFFER);
  	//set up pointers if the data mask is different ...
 -	BOOL setup = (sLastMask != data_mask);
 +	bool setup = (sLastMask != data_mask);
  	if (gDebugGL && data_mask != 0)
  	{ //make sure data requirements are fulfilled
 @@ -2050,21 +2040,17 @@ void LLVertexBuffer::setBuffer(U32 data_mask)  		if (mGLArray)
  		{
  			bindGLArray();
 -			setup = FALSE; //do NOT perform pointer setup if using VAO
 +			setup = false; //do NOT perform pointer setup if using VAO
  		}
  		else
  		{
 -			if (bindGLBuffer())
 -			{
 -				setup = TRUE;
 -			}
 -			if (bindGLIndices())
 -			{
 -				setup = TRUE;
 -			}
 +			const bool bindBuffer = bindGLBuffer();
 +			const bool bindIndices = bindGLIndices();
 +			
 +			setup = setup || bindBuffer || bindIndices;
  		}
 -		BOOL error = FALSE;
 +		bool error = false;
  		if (gDebugGL && !mGLArray)
  		{
  			GLint buff;
 @@ -2073,7 +2059,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)  			{
  				if (gDebugSession)
  				{
 -					error = TRUE;
 +					error = true;
  					gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl;
  				}
  				else
 @@ -2089,7 +2075,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)  				{
  					if (gDebugSession)
  					{
 -						error = TRUE;
 +						error = true;
  						gFailLog << "Invalid GL index buffer bound: " << buff <<  std::endl;
  					}
  					else
 @@ -2111,7 +2097,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)  #endif
  			sGLRenderArray = 0;
  			sGLRenderIndices = 0;
 -			sIBOActive = FALSE;
 +			sIBOActive = false;
  		}
  		if (mGLBuffer)
 @@ -2120,13 +2106,13 @@ void LLVertexBuffer::setBuffer(U32 data_mask)  			{
  				glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
  				sBindCount++;
 -				sVBOActive = FALSE;
 -				setup = TRUE; // ... or a VBO is deactivated
 +				sVBOActive = false;
 +				setup = true; // ... or a VBO is deactivated
  			}
  			if (sGLRenderBuffer != mGLBuffer)
  			{
  				sGLRenderBuffer = mGLBuffer;
 -				setup = TRUE; // ... or a client memory pointer changed
 +				setup = true; // ... or a client memory pointer changed
  			}
  		}
  		if (mGLIndices)
 @@ -2135,7 +2121,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask)  			{
  				glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
  				sBindCount++;
 -				sIBOActive = FALSE;
 +				sIBOActive = false;
  			}
  			sGLRenderIndices = mGLIndices;
 @@ -2223,19 +2209,19 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)  		{
  			S32 loc = TYPE_WEIGHT;
  			void* ptr = (void*)(base + mOffsets[TYPE_WEIGHT]);
 -			glVertexAttribPointerARB(loc, 1, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
 +			glVertexAttribPointerARB(loc, 1, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT], ptr);
  		}
  		if (data_mask & MAP_WEIGHT4)
  		{
  			S32 loc = TYPE_WEIGHT4;
  			void* ptr = (void*)(base+mOffsets[TYPE_WEIGHT4]);
 -			glVertexAttribPointerARB(loc, 4, GL_FLOAT, FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
 +			glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_FALSE, LLVertexBuffer::sTypeSize[TYPE_WEIGHT4], ptr);
  		}
  		if (data_mask & MAP_CLOTHWEIGHT)
  		{
  			S32 loc = TYPE_CLOTHWEIGHT;
  			void* ptr = (void*)(base + mOffsets[TYPE_CLOTHWEIGHT]);
 -			glVertexAttribPointerARB(loc, 4, GL_FLOAT, TRUE,  LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
 +			glVertexAttribPointerARB(loc, 4, GL_FLOAT, GL_TRUE,  LLVertexBuffer::sTypeSize[TYPE_CLOTHWEIGHT], ptr);
  		}
  		if (data_mask & MAP_TEXTURE_INDEX)
  		{
 diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index e1cbfd3b61..d859199663 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -55,9 +55,14 @@ class LLVBOPool  {  public:  	static U32 sBytesPooled; +	 +	LLVBOPool(U32 vboUsage, U32 vboType) +		: mUsage(vboUsage) +		, mType(vboType) +	{} -	U32 mUsage; -	U32 mType; +	const U32 mUsage; +	const U32 mType;  	//size MUST be a power of 2  	volatile U8* allocate(U32& name, U32 size); @@ -88,7 +93,7 @@ public:  //============================================================================  // base class  -class LLPrivateMemoryPool ; +class LLPrivateMemoryPool;  class LLVertexBuffer : public LLRefCount  {  public: @@ -103,6 +108,7 @@ public:  	};  	LLVertexBuffer(const LLVertexBuffer& rhs) +		: mUsage(rhs.mUsage)  	{  		*this = rhs;  	} @@ -118,9 +124,9 @@ public:  	static LLVBOPool sStreamIBOPool;  	static LLVBOPool sDynamicIBOPool; -	static BOOL	sUseStreamDraw; -	static BOOL sUseVAO; -	static BOOL	sPreferStreamDraw; +	static bool	sUseStreamDraw; +	static bool sUseVAO; +	static bool	sPreferStreamDraw;  	static void initClass(bool use_vbo, bool no_vbo_mapping);  	static void cleanupClass(); @@ -201,7 +207,7 @@ protected:  	void 	destroyGLIndices();  	void	updateNumVerts(S32 nverts);  	void	updateNumIndices(S32 nindices);  -	virtual BOOL	useVBOs() const; +	bool	useVBOs() const;  	void	unmapBuffer();  public: @@ -239,8 +245,8 @@ public:  	bool getClothWeightStrider(LLStrider<LLVector4>& strider, S32 index=0, S32 count = -1, bool map_range = false); -	BOOL isEmpty() const					{ return mEmpty; } -	BOOL isLocked() const					{ return mVertexLocked || mIndexLocked; } +	bool isEmpty() const					{ return mEmpty; } +	bool isLocked() const					{ return mVertexLocked || mIndexLocked; }  	S32 getNumVerts() const					{ return mNumVerts; }  	S32 getNumIndices() const				{ return mNumIndices; } @@ -254,7 +260,7 @@ public:  	volatile U8* getMappedIndices() const			{ return mMappedIndexData; }  	S32 getOffset(S32 type) const			{ return mOffsets[type]; }  	S32 getUsage() const					{ return mUsage; } -	BOOL isWriteable() const				{ return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? TRUE : FALSE; } +	bool isWriteable() const				{ return (mMappable || mUsage == GL_STREAM_DRAW_ARB) ? true : false; }  	void draw(U32 mode, U32 count, U32 indices_offset) const;  	void drawArrays(U32 mode, U32 offset, U32 count) const; @@ -274,18 +280,25 @@ protected:  	S32		mSize;  	S32		mIndicesSize;  	U32		mTypeMask; -	S32		mUsage;			// GL usage + +	const S32		mUsage;			// GL usage +	  	U32		mGLBuffer;		// GL VBO handle  	U32		mGLIndices;		// GL IBO handle  	U32		mGLArray;		// GL VAO handle  	volatile U8* mMappedData;	// pointer to currently mapped data (NULL if unmapped)  	volatile U8* mMappedIndexData;	// pointer to currently mapped indices (NULL if unmapped) -	BOOL	mVertexLocked;			// if TRUE, vertex buffer is being or has been written to in client memory -	BOOL	mIndexLocked;			// if TRUE, index buffer is being or has been written to in client memory -	BOOL	mFinal;			// if TRUE, buffer can not be mapped again -	BOOL	mEmpty;			// if TRUE, client buffer is empty (or NULL). Old values have been discarded.	 -	mutable BOOL	mMappable;     // if TRUE, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData) + +	U32		mMappedDataUsingVBOs : 1; +	U32		mMappedIndexDataUsingVBOs : 1; +	U32		mVertexLocked : 1;			// if true, vertex buffer is being or has been written to in client memory +	U32		mIndexLocked : 1;			// if true, index buffer is being or has been written to in client memory +	U32		mFinal : 1;			// if true, buffer can not be mapped again +	U32		mEmpty : 1;			// if true, client buffer is empty (or NULL). Old values have been discarded.	 +	 +	mutable bool	mMappable;     // if true, use memory mapping to upload data (otherwise doublebuffer and use glBufferSubData) +  	S32		mOffsets[TYPE_MAX];  	std::vector<MappedRegion> mMappedVertexRegions; @@ -296,26 +309,27 @@ protected:  	void placeFence() const;  	void waitFence() const; +	static S32 determineUsage(S32 usage);  private: -	static LLPrivateMemoryPool* sPrivatePoolp ; +	static LLPrivateMemoryPool* sPrivatePoolp;  public:  	static S32 sCount;  	static S32 sGLCount;  	static S32 sMappedCount; -	static BOOL sMapped; +	static bool sMapped;  	typedef std::list<LLVertexBuffer*> buffer_list_t; -	static BOOL sDisableVBOMapping; //disable glMapBufferARB -	static BOOL sEnableVBOs; +	static bool sDisableVBOMapping; //disable glMapBufferARB +	static bool sEnableVBOs;  	static S32 sTypeSize[TYPE_MAX];  	static U32 sGLMode[LLRender::NUM_MODES];  	static U32 sGLRenderBuffer;  	static U32 sGLRenderArray;  	static U32 sGLRenderIndices; -	static BOOL sVBOActive; -	static BOOL sIBOActive; +	static bool sVBOActive; +	static bool sIBOActive;  	static U32 sLastMask;  	static U32 sAllocatedBytes;  	static U32 sBindCount; diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 7a5f9f9fd6..c025cd7939 100644 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -976,7 +976,7 @@ void LLAccordionCtrlTab::drawChild(const LLRect& root_rect,LLView* child)  			gGL.matrixMode(LLRender::MM_MODELVIEW);  			LLUI::pushMatrix();  			{ -				LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom, 0.f); +				LLUI::translate((F32)child->getRect().mLeft, (F32)child->getRect().mBottom);  				child->draw();  			} diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index f0d92d597a..705fe16559 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -908,9 +908,9 @@ void LLButton::draw()  		// Not sure if it is really needed. Probably S32_MAX should be always passed as max_chars.  		mLastDrawCharsCount = mGLFont->render(label, 0,  			(F32)x, -			(F32)(mBottomVPad + y_offset), +			(F32)(getRect().getHeight() / 2 + mBottomVPad),  			label_color % alpha, -			mHAlign, LLFontGL::BOTTOM, +			mHAlign, LLFontGL::VCENTER,  			LLFontGL::NORMAL,  			mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW,  			S32_MAX, text_width, diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 89d8842393..806d2ef3f6 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -613,7 +613,7 @@ void LLComboBox::showList()  	}  	mList->setOrigin(rect.mLeft, rect.mBottom);  	mList->reshape(rect.getWidth(), rect.getHeight()); -	mList->translateIntoRect(root_view_local, FALSE); +	mList->translateIntoRect(root_view_local);  	// Make sure we didn't go off bottom of screen  	S32 x, y; diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 42e6c3c786..5f69c6af31 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -244,7 +244,7 @@ void LLDragHandleTop::reshapeTitleBox()  	const LLFontGL* font = LLFontGL::getFontSansSerif();  	S32 title_width = getRect().getWidth();  	title_width -= LEFT_PAD + 2 * BORDER_PAD + getButtonsRect().getWidth(); -	S32 title_height = llround(font->getLineHeight()); +	S32 title_height = font->getLineHeight();  	LLRect title_rect;  	title_rect.setLeftTopAndSize(   		LEFT_PAD,  diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 33548151fd..22b20969fc 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -270,6 +270,7 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)  	mMinimizeSignal(NULL)  //	mNotificationContext(NULL)  { +	mPosition.setFloater(*this);  //	mNotificationContext = new LLFloaterNotificationContext(getHandle());  	// Clicks stop here. @@ -925,7 +926,7 @@ void LLFloater::applyPositioning(LLFloater* other)  			setOrigin(mSpecifiedLeft, mSpecifiedBottom);  			const LLRect& snap_rect = gFloaterView->getSnapRect();  			translate(snap_rect.mLeft, snap_rect.mBottom); -			translateIntoRect(snap_rect, FALSE); +			translateIntoRect(snap_rect);  		}  		break; @@ -949,7 +950,7 @@ void LLFloater::applyPositioning(LLFloater* other)  			setOrigin(horizontal_offset, vertical_offset - rect_height);  			translate(snap_rect.mLeft, snap_rect.mBottom); -			translateIntoRect(snap_rect, FALSE); +			translateIntoRect(snap_rect);  		}  		break; @@ -1681,6 +1682,8 @@ LLFloater* LLFloater::getClosableFloaterFromFocus()  	{  		if (it->hasFocus())  		{ +			LLFloater& floater = *it; +			focused_floater = &floater;  			break;  		}  	} @@ -1800,7 +1803,7 @@ void LLFloater::draw()  				const LLFontGL* font = LLFontGL::getFontSansSerif();  				LLRect r = getRect(); -				gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1,  +				gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - font->getLineHeight() - 1,   					titlebar_focus_color % alpha, 0, TRUE);  			}  		} @@ -2641,6 +2644,8 @@ void LLFloaterView::refresh()  	}  } +const S32 FLOATER_MIN_VISIBLE_PIXELS = 16; +  void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_outside)  {  	if (floater->getParent() != this) @@ -2694,7 +2699,7 @@ void LLFloaterView::adjustToFitScreen(LLFloater* floater, BOOL allow_partial_out  	}  	// move window fully onscreen -	if (floater->translateIntoRect( getSnapRect(), allow_partial_outside )) +	if (floater->translateIntoRect( getSnapRect(), allow_partial_outside ? FLOATER_MIN_VISIBLE_PIXELS : S32_MAX ))  	{  		floater->clearSnapTarget();  	} @@ -3269,3 +3274,112 @@ void LLFloater::stackWith(LLFloater& other)  	setShape(next_rect);  } +LLCoordFloater::LLCoordFloater(F32 x, F32 y, LLFloater& floater) +:	coord_t((S32)x, (S32)y) +{ +	mFloater = floater.getHandle(); +} + + +LLCoordFloater::LLCoordFloater(const LLCoordCommon& other, LLFloater& floater) +{ +	mFloater = floater.getHandle(); +	convertFromCommon(other); +} + +LLCoordFloater& LLCoordFloater::operator=(const LLCoordFloater& other) +{ +	mFloater = other.mFloater; +	coord_t::operator =(other); +	return *this; +} + +void LLCoordFloater::setFloater(LLFloater& floater) +{ +	mFloater = floater.getHandle(); +} + +bool LLCoordFloater::operator==(const LLCoordFloater& other) const  +{  +	return mX == other.mX && mY == other.mY && mFloater == other.mFloater;  +} + +LLCoordCommon LL_COORD_FLOATER::convertToCommon() const +{ +	const LLCoordFloater& self = static_cast<const LLCoordFloater&>(*this); + +	LLRect snap_rect = gFloaterView->getSnapRect(); +	LLFloater* floaterp = mFloater.get(); +	S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0; +	S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0; +	LLCoordCommon out; +	if (self.mX < -0.5f) +	{ +		out.mX = llround(rescale(self.mX, -1.f, -0.5f, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft)); +	} +	else if (self.mX > 0.5f) +	{ +		out.mX = llround(rescale(self.mX, 0.5f, 1.f, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS)); +	} +	else +	{ +		out.mX = llround(rescale(self.mX, -0.5f, 0.5f, snap_rect.mLeft, snap_rect.mRight - floater_width)); +	} + +	if (self.mY < -0.5f) +	{ +		out.mY = llround(rescale(self.mY, -1.f, -0.5f, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom)); +	} +	else if (self.mY > 0.5f) +	{ +		out.mY = llround(rescale(self.mY, 0.5f, 1.f, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS)); +	} +	else +	{ +		out.mY = llround(rescale(self.mY, -0.5f, 0.5f, snap_rect.mBottom, snap_rect.mTop - floater_height)); +	} + +	// return center point instead of lower left +	out.mX += floater_width / 2; +	out.mY += floater_height / 2; + +	return out; +} + +void LL_COORD_FLOATER::convertFromCommon(const LLCoordCommon& from) +{ +	LLCoordFloater& self = static_cast<LLCoordFloater&>(*this); +	LLRect snap_rect = gFloaterView->getSnapRect(); +	LLFloater* floaterp = mFloater.get(); +	S32 floater_width = floaterp ? floaterp->getRect().getWidth() : 0; +	S32 floater_height = floaterp ? floaterp->getRect().getHeight() : 0; + +	S32 from_x = from.mX - floater_width / 2; +	S32 from_y = from.mY - floater_height / 2; + +	if (from_x < snap_rect.mLeft) +	{ +		self.mX = rescale(from_x, snap_rect.mLeft - (floater_width - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mLeft, -1.f, -0.5f); +	} +	else if (from_x + floater_width > snap_rect.mRight) +	{ +		self.mX = rescale(from_x, snap_rect.mRight - floater_width, snap_rect.mRight - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f); +	} +	else +	{ +		self.mX = rescale(from_x, snap_rect.mLeft, snap_rect.mRight - floater_width, -0.5f, 0.5f); +	} + +	if (from_y < snap_rect.mBottom) +	{ +		self.mY = rescale(from_y, snap_rect.mBottom - (floater_height - FLOATER_MIN_VISIBLE_PIXELS), snap_rect.mBottom, -1.f, -0.5f); +	} +	else if (from_y + floater_height > snap_rect.mTop) +	{ +		self.mY = rescale(from_y, snap_rect.mTop - floater_height, snap_rect.mTop - FLOATER_MIN_VISIBLE_PIXELS, 0.5f, 1.f); +	} +	else +	{ +		self.mY = rescale(from_y, snap_rect.mBottom, snap_rect.mTop - floater_height, -0.5f, 0.5f); +	} +} diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 59b35d206f..a7cc9ae961 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -82,6 +82,37 @@ namespace LLInitParam  	};  } +struct LL_COORD_FLOATER +{ +	typedef F32 value_t; + +	LLCoordCommon convertToCommon() const; +	void convertFromCommon(const LLCoordCommon& from); +protected: +	LLHandle<LLFloater> mFloater; +}; + +struct LLCoordFloater : LLCoord<LL_COORD_FLOATER> +{ +	typedef LLCoord<LL_COORD_FLOATER> coord_t; + +	LLCoordFloater() {} +	LLCoordFloater(F32 x, F32 y, LLFloater& floater); +	LLCoordFloater(const LLCoordCommon& other, LLFloater& floater); + +	LLCoordFloater& operator=(const LLCoordCommon& other) +	{ +		convertFromCommon(other); +		return *this; +	} + +	LLCoordFloater& operator=(const LLCoordFloater& other); + +	bool operator==(const LLCoordFloater& other) const; +	bool operator!=(const LLCoordFloater& other) const { return !(*this == other); } + +	void setFloater(LLFloater& floater); +};  class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>  { @@ -184,7 +215,7 @@ public:  	bool initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::string& filename, LLXMLNodePtr output_node = NULL);  	/*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false); -	/*virtual*/ BOOL canSnapTo(const LLView* other_view); +	/*virtual*/ BOOL canSnapTo(const LLView* other_view);   	/*virtual*/ void setSnappedTo(const LLView* snap_view);  	/*virtual*/ void setFocus( BOOL b );  	/*virtual*/ void setIsChrome(BOOL is_chrome); @@ -425,6 +456,7 @@ private:  	LLFloaterEnums::EOpenPositioning	mOpenPositioning;  	S32									mSpecifiedLeft;  	S32									mSpecifiedBottom; +	LLCoordFloater	mPosition;  	S32				mMinWidth;  	S32				mMinHeight; diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index 2f1c2a47c9..ae262f794e 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -36,7 +36,7 @@  #include "llcriticaldamp.h"  #include "boost/foreach.hpp" -static const F32 MIN_FRACTIONAL_SIZE = 0.0001f; +static const F32 MIN_FRACTIONAL_SIZE = 0.0f;  static const F32 MAX_FRACTIONAL_SIZE = 1.f;  static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack"); @@ -129,6 +129,12 @@ void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientatio  		? getRect().getWidth()  		: getRect().getHeight())); +	if (mAutoResize == FALSE  +		&& mUserResize == TRUE  +		&& mMinDim == -1 ) +	{ +		setMinDim(layout_dim); +	}  	mTargetDim = llmax(layout_dim, getMinDim());  } @@ -306,7 +312,6 @@ void LLLayoutStack::updateLayout()  	bool animation_in_progress = animatePanels();  	F32 total_visible_fraction = 0.f; -	F32 total_open_fraction = 0.f;  	S32 space_to_distribute = (mOrientation == HORIZONTAL)  							? getRect().getWidth()  							: getRect().getHeight(); @@ -318,20 +323,17 @@ void LLLayoutStack::updateLayout()  		if (panelp->mAutoResize)  		{  			panelp->mTargetDim = panelp->getRelevantMinDim(); -			if (!panelp->mCollapsed && panelp->getVisible()) -			{ -				total_open_fraction += panelp->mFractionalSize; -			}  		}  		space_to_distribute -= panelp->getVisibleDim() + llround((F32)mPanelSpacing * panelp->getVisibleAmount()); -		total_visible_fraction += panelp->mFractionalSize; +		total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor();  	} -	llassert(total_visible_fraction < 1.01f); +	llassert(total_visible_fraction < 1.05f);  	// don't need spacing after last panel  	space_to_distribute += panelp ? llround((F32)mPanelSpacing * panelp->getVisibleAmount()) : 0; +	S32 remaining_space = space_to_distribute;  	F32 fraction_distributed = 0.f;  	if (space_to_distribute > 0 && total_visible_fraction > 0.f)  	{	// give space proportionally to visible auto resize panels @@ -343,26 +345,23 @@ void LLLayoutStack::updateLayout()  				S32 delta = llround((F32)space_to_distribute * fraction_to_distribute);  				fraction_distributed += fraction_to_distribute;  				panelp->mTargetDim += delta; +				remaining_space -= delta;  			}  		}  	} -	if (fraction_distributed < total_visible_fraction) -	{	// distribute any left over pixels to non-collapsed, visible panels -		F32 fraction_left = total_visible_fraction - fraction_distributed; -		S32 space_left = llround((F32)space_to_distribute * (fraction_left / total_visible_fraction)); +	// distribute any left over pixels to non-collapsed, visible panels +	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) +	{ +		if (remaining_space == 0) break; -		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) +		if (panelp->mAutoResize  +			&& !panelp->mCollapsed  +			&& panelp->getVisible())  		{ -			if (panelp->mAutoResize  -				&& !panelp->mCollapsed  -				&& panelp->getVisible()) -			{ -				S32 space_for_panel = llmax(0, llround((F32)space_left * (panelp->mFractionalSize / total_open_fraction))); -				panelp->mTargetDim += space_for_panel; -				space_left -= space_for_panel; -				total_open_fraction -= panelp->mFractionalSize; -			} +			S32 space_for_panel = remaining_space > 0 ? 1 : -1; +			panelp->mTargetDim += space_for_panel; +			remaining_space -= space_for_panel;  		}  	} @@ -494,33 +493,46 @@ void LLLayoutStack::updateClass()  void LLLayoutStack::updateFractionalSizes()  { -	F32 total_resizable_dim = 0; -	S32 num_auto_resize_panels = 0; +	F32 total_resizable_dim = 0.f;  	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)  	{  		if (panelp->mAutoResize)  		{  			total_resizable_dim += llmax(0, panelp->getLayoutDim() - panelp->getRelevantMinDim()); -			num_auto_resize_panels++;  		}  	} -	F32 total_fractional_size = 0.f; -	  	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels)  	{  		if (panelp->mAutoResize)  		{  			F32 panel_resizable_dim = llmax(MIN_FRACTIONAL_SIZE, (F32)(panelp->getLayoutDim() - panelp->getRelevantMinDim()));  			panelp->mFractionalSize = panel_resizable_dim > 0.f  -										? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE) -										: MIN_FRACTIONAL_SIZE; -			total_fractional_size += panelp->mFractionalSize; +				? llclamp(panel_resizable_dim / total_resizable_dim, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE) +				: MIN_FRACTIONAL_SIZE;  			llassert(!llisnan(panelp->mFractionalSize));  		}  	} +	normalizeFractionalSizes(); +} + + +void LLLayoutStack::normalizeFractionalSizes() +{ +	S32 num_auto_resize_panels = 0; +	F32 total_fractional_size = 0.f; +	 +	BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) +	{ +		if (panelp->mAutoResize) +		{ +			total_fractional_size += panelp->mFractionalSize; +			num_auto_resize_panels++; +		} +	} +  	if (total_fractional_size == 0.f)  	{ // equal distribution  		BOOST_FOREACH(LLLayoutPanel* panelp, mPanels) @@ -632,7 +644,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&  	F32 total_visible_fraction = 0.f;  	F32 delta_auto_resize_headroom = 0.f; -	F32 total_auto_resize_headroom = 0.f; +	F32 original_auto_resize_headroom = 0.f;  	LLLayoutPanel* other_resize_panel = NULL;  	LLLayoutPanel* following_panel = NULL; @@ -641,8 +653,11 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&  	{  		if (panelp->mAutoResize)  		{ -			total_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); -			total_visible_fraction += panelp->mFractionalSize * panelp->getAutoResizeFactor(); +			original_auto_resize_headroom += (F32)(panelp->mTargetDim - panelp->getRelevantMinDim()); +			if (panelp->getVisible() && !panelp->mCollapsed) +			{ +				total_visible_fraction += panelp->mFractionalSize; +			}  		}  		if (panelp == resized_panel) @@ -656,18 +671,25 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&  		}  	} -	if (resized_panel->mAutoResize == FALSE) + +	if (resized_panel->mAutoResize)  	{ -		delta_auto_resize_headroom += -delta_dim; +		if (!other_resize_panel || !other_resize_panel->mAutoResize) +		{ +			delta_auto_resize_headroom += delta_dim;	 +		}  	} -	if (other_resize_panel && other_resize_panel->mAutoResize == FALSE) +	else   	{ -		delta_auto_resize_headroom += delta_dim; +		if (!other_resize_panel || other_resize_panel->mAutoResize) +		{ +			delta_auto_resize_headroom -= delta_dim; +		}  	}  	F32 fraction_given_up = 0.f;  	F32 fraction_remaining = 1.f; -	F32 updated_auto_resize_headroom = total_auto_resize_headroom + delta_auto_resize_headroom; +	F32 updated_auto_resize_headroom = original_auto_resize_headroom + delta_auto_resize_headroom;  	enum  	{ @@ -691,14 +713,15 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&  		case BEFORE_RESIZED_PANEL:  			if (panelp->mAutoResize)  			{	// freeze current size as fraction of overall auto_resize space -				F32 fractional_adjustment_factor = total_auto_resize_headroom / updated_auto_resize_headroom; +				F32 fractional_adjustment_factor = updated_auto_resize_headroom == 0.f +													? 1.f +													: original_auto_resize_headroom / updated_auto_resize_headroom;  				F32 new_fractional_size = llclamp(panelp->mFractionalSize * fractional_adjustment_factor,  													MIN_FRACTIONAL_SIZE,  													MAX_FRACTIONAL_SIZE); -				F32 fraction_delta = (new_fractional_size - panelp->mFractionalSize); -				fraction_given_up -= fraction_delta; +				fraction_given_up -= new_fractional_size - panelp->mFractionalSize;  				fraction_remaining -= panelp->mFractionalSize; -				panelp->mFractionalSize += fraction_delta; +				panelp->mFractionalSize = new_fractional_size;  				llassert(!llisnan(panelp->mFractionalSize));  			}  			else @@ -711,7 +734,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&  			{	// freeze new size as fraction  				F32 new_fractional_size = (updated_auto_resize_headroom == 0.f)  					? MAX_FRACTIONAL_SIZE -					: llclamp((F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE); +					: llclamp(total_visible_fraction * (F32)(new_dim - panelp->getRelevantMinDim()) / updated_auto_resize_headroom, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);  				fraction_given_up -= new_fractional_size - panelp->mFractionalSize;  				fraction_remaining -= panelp->mFractionalSize;  				panelp->mFractionalSize = new_fractional_size; @@ -720,7 +743,6 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&  			else  			{	// freeze new size as original size  				panelp->mTargetDim = new_dim; -				fraction_remaining -= fraction_given_up;  			}  			which_panel = NEXT_PANEL;  			break; @@ -728,14 +750,14 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&  			if (panelp->mAutoResize)  			{  				fraction_remaining -= panelp->mFractionalSize; -				if (fraction_given_up != 0.f) +				if (resized_panel->mAutoResize)  				{  					panelp->mFractionalSize = llclamp(panelp->mFractionalSize + fraction_given_up, MIN_FRACTIONAL_SIZE, MAX_FRACTIONAL_SIZE);  					fraction_given_up = 0.f;  				}  				else  				{ -					F32 new_fractional_size = llclamp((F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom)  +					F32 new_fractional_size = llclamp(total_visible_fraction * (F32)(panelp->mTargetDim - panelp->getRelevantMinDim() + delta_auto_resize_headroom)   														/ updated_auto_resize_headroom,  													MIN_FRACTIONAL_SIZE,  													MAX_FRACTIONAL_SIZE); @@ -750,7 +772,7 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&  			which_panel = AFTER_RESIZED_PANEL;  			break;  		case AFTER_RESIZED_PANEL: -			if (panelp->mAutoResize) +			if (panelp->mAutoResize && fraction_given_up != 0.f)  			{  				panelp->mFractionalSize = llclamp(panelp->mFractionalSize + (panelp->mFractionalSize / fraction_remaining) * fraction_given_up,  												MIN_FRACTIONAL_SIZE, @@ -760,6 +782,8 @@ void LLLayoutStack::updatePanelRect( LLLayoutPanel* resized_panel, const LLRect&  			break;  		}  	} +	updateLayout(); +	normalizeFractionalSizes();  }  void LLLayoutStack::reshape(S32 width, S32 height, BOOL called_from_parent) diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index efe93f6def..d32caec5f9 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -72,7 +72,7 @@ public:  	/*virtual*/ void draw();  	/*virtual*/ void removeChild(LLView*);  	/*virtual*/ BOOL postBuild(); -	/*virtual*/ bool addChild(LLView* child, S32 tab_group = 0); +	/*virtual*/ bool addChild(LLView* child, S32 tab_groupdatefractuiona = 0);  	/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); @@ -112,6 +112,7 @@ private:  	LLLayoutPanel* findEmbeddedPanel(LLPanel* panelp) const;  	LLLayoutPanel* findEmbeddedPanelByName(const std::string& name) const;  	void updateFractionalSizes(); +	void normalizeFractionalSizes();  	void updatePanelRect( LLLayoutPanel* param1, const LLRect& new_rect );  	S32 mPanelSpacing; @@ -154,10 +155,10 @@ public:  	void setVisible(BOOL visible);  	S32 getLayoutDim() const; -	S32 getMinDim() const { return (mMinDim >= 0 || mAutoResize) ? llmax(0, mMinDim) : getLayoutDim(); } +	S32 getMinDim() const { return llmax(0, mMinDim); }  	void setMinDim(S32 value) { mMinDim = value; } -	S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : mMinDim; } +	S32 getExpandedMinDim() const { return mExpandedMinDim >= 0 ? mExpandedMinDim : getMinDim(); }  	void setExpandedMinDim(S32 value) { mExpandedMinDim = value; }  	S32 getRelevantMinDim() const diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 06dfc90d83..7e84814c51 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -1630,7 +1630,7 @@ void LLLineEditor::draw()  	LLRect background( 0, getRect().getHeight(), getRect().getWidth(), 0 );  	background.stretch( -mBorderThickness ); -	S32 lineeditor_v_pad = llround((background.getHeight() - mGLFont->getLineHeight())/2); +	S32 lineeditor_v_pad = (background.getHeight() - mGLFont->getLineHeight()) / 2;  	drawBackground(); diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index 95ecbb1c94..ff6928ffda 100644 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -317,7 +317,7 @@ void LLMenuItemGL::setJumpKey(KEY key)  // virtual   U32 LLMenuItemGL::getNominalHeight( void ) const   {  -	return llround(mFont->getLineHeight()) + MENU_ITEM_PADDING;  +	return mFont->getLineHeight() + MENU_ITEM_PADDING;  }  //virtual @@ -508,19 +508,19 @@ void LLMenuItemGL::draw( void )  	{  		if( !mDrawBoolLabel.empty() )  		{ -			mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, +			mFont->render( mDrawBoolLabel.getWString(), 0, (F32)LEFT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,  						   LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );  		} -		mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, +		mFont->render( mLabel.getWString(), 0, (F32)LEFT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,  					   LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );  		if( !mDrawAccelLabel.empty() )  		{ -			mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, +			mFont->render( mDrawAccelLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PLAIN_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,  						   LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );  		}  		if( !mDrawBranchLabel.empty() )  		{ -			mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f) + 1.f, color, +			mFont->render( mDrawBranchLabel.getWString(), 0, (F32)getRect().mRight - (F32)RIGHT_PAD_PIXELS, ((F32)MENU_ITEM_PADDING / 2.f), color,  						   LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );  		}  	} @@ -1966,7 +1966,7 @@ void LLMenuGL::arrange( void )  		// *FIX: create the item first and then ask for its dimensions?  		S32 spillover_item_width = PLAIN_PAD_PIXELS + LLFontGL::getFontSansSerif()->getWidth( std::string("More") ); // *TODO: Translate -		S32 spillover_item_height = llround(LLFontGL::getFontSansSerif()->getLineHeight()) + MENU_ITEM_PADDING; +		S32 spillover_item_height = LLFontGL::getFontSansSerif()->getLineHeight() + MENU_ITEM_PADDING;  		// Scrolling support  		item_list_t::iterator first_visible_item_iter; @@ -3082,7 +3082,7 @@ void LLMenuGL::showPopup(LLView* spawning_view, LLMenuGL* menu, S32 x, S32 y)  		mouse_y + MOUSE_CURSOR_PADDING,   		CURSOR_WIDTH + MOUSE_CURSOR_PADDING * 2,   		CURSOR_HEIGHT + MOUSE_CURSOR_PADDING * 2); -	menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect, FALSE ); +	menu->translateIntoRectWithExclusion( menu_region_rect, mouse_rect );  	menu->getParent()->sendChildToFront(menu);  } @@ -3425,7 +3425,7 @@ void LLMenuHolderGL::draw()  		LLUI::pushMatrix();  		{ -			LLUI::translate((F32)item_rect.mLeft, (F32)item_rect.mBottom, 0.f); +			LLUI::translate((F32)item_rect.mLeft, (F32)item_rect.mBottom);  			selecteditem->getMenu()->drawBackground(selecteditem, interpolant);  			selecteditem->draw();  		} diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index d232e27ef2..8aa548b974 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1412,6 +1412,7 @@ void addPathIfExists(const std::string& new_path, std::vector<std::string>& path  bool LLNotifications::loadTemplates()  { +	llinfos << "Reading notifications template" << llendl;  	std::vector<std::string> search_paths;  	std::string skin_relative_path = gDirUtilp->getDirDelimiter() + LLUI::getSkinPath() + gDirUtilp->getDirDelimiter() + "notifications.xml"; @@ -1484,6 +1485,8 @@ bool LLNotifications::loadTemplates()  		mTemplates[notification.name] = LLNotificationTemplatePtr(new LLNotificationTemplate(notification));  	} +	llinfos << "...done" << llendl; +  	return true;  } diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index ad4cc20d9a..20bed050ad 100644 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -378,23 +378,21 @@ void LLScrollContainer::calcVisibleSize( S32 *visible_width, S32 *visible_height  	if (!mHideScrollbar)  	{ -		if( *visible_height < doc_height ) +		// Note: 1 pixel change can happen on final animation and should not trigger  +		// the display of sliders. +		if ((doc_height - *visible_height) > 1)  		{  			*show_v_scrollbar = TRUE;  			*visible_width -= scrollbar_size;  		} - -		if( *visible_width < doc_width ) +		if ((doc_width - *visible_width) > 1)  		{  			*show_h_scrollbar = TRUE;  			*visible_height -= scrollbar_size; - -			// Must retest now that visible_height has changed -			if( !*show_v_scrollbar && (*visible_height < doc_height) ) -			{ -				*show_v_scrollbar = TRUE; -				*visible_width -= scrollbar_size; -			} +			// Note: Do *not* recompute *show_v_scrollbar here because with +			// the (- scrollbar_size) we just did we will always add a vertical scrollbar +			// even if the height of the items is actually less than the visible size. +			// Fear not though: there's enough calcVisibleSize() calls to add a vertical slider later.  		}  	}  } diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 9d25c7180d..8000efad0e 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -232,7 +232,7 @@ BOOL LLScrollListText::getVisible() const  //virtual   S32 LLScrollListText::getHeight() const  { -	return llround(mFont->getLineHeight()); +	return mFont->getLineHeight();  } @@ -306,7 +306,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col  			break;  		}  		LLRect highlight_rect(left - 2,  -				llround(mFont->getLineHeight()) + 1,  +				mFont->getLineHeight() + 1,   				left + mFont->getWidth(mText.getString(), mHighlightOffset, mHighlightCount) + 1,   				1);  		mRoundedRectImage->draw(highlight_rect, highlight_color); @@ -329,7 +329,7 @@ void LLScrollListText::draw(const LLColor4& color, const LLColor4& highlight_col  		break;  	}  	mFont->render(mText.getWString(), 0,  -					start_x, 2.f, +					start_x, 0.f,  					display_color,  					mFontAlignment,  					LLFontGL::BOTTOM,  diff --git a/indra/llui/llscrolllistitem.cpp b/indra/llui/llscrolllistitem.cpp index d95752e31c..5a1e96ab03 100644 --- a/indra/llui/llscrolllistitem.cpp +++ b/indra/llui/llscrolllistitem.cpp @@ -138,7 +138,7 @@ void LLScrollListItem::draw(const LLRect& rect, const LLColor4& fg_color, const  		LLUI::pushMatrix();  		{ -			LLUI::translate((F32) cur_x, (F32) rect.mBottom, 0.0f); +			LLUI::translate((F32) cur_x, (F32) rect.mBottom);  			cell->draw( fg_color, highlight_color );  		} diff --git a/indra/llui/llscrolllistitem.h b/indra/llui/llscrolllistitem.h index 611df729b4..13655b5873 100644 --- a/indra/llui/llscrolllistitem.h +++ b/indra/llui/llscrolllistitem.h @@ -33,10 +33,10 @@  #include "v4color.h"  #include "llinitparam.h"  #include "llscrolllistcell.h" +#include "llcoord.h"  #include <vector> -class LLCoordGL;  class LLCheckBoxCtrl;  class LLResizeBar;  class LLScrollListCtrl; diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 0040be45c7..7aeeae298f 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -1192,7 +1192,10 @@ void LLTextBase::reflow()  		// shrink document to minimum size (visible portion of text widget)  		// to force inlined widgets with follows set to shrink -		mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight()); +		if (mWordWrap) +		{ +			mDocumentView->reshape(mVisibleTextRect.getWidth(), mDocumentView->getRect().getHeight()); +		}  		S32 cur_top = 0; @@ -2157,7 +2160,7 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const  	{   		// return default height rect in upper left  		local_rect = content_window_rect; -		local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight()); +		local_rect.mBottom = local_rect.mTop - mDefaultFont->getLineHeight();  		return local_rect;  	} @@ -2380,6 +2383,9 @@ S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction)  void LLTextBase::updateRects()  { +	LLRect old_text_rect = mVisibleTextRect; +	mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect(); +  	if (mLineInfoList.empty())   	{  		mTextBoundingRect = LLRect(0, mVPad, mHPad, 0); @@ -2395,10 +2401,24 @@ void LLTextBase::updateRects()  		}  		mTextBoundingRect.mTop += mVPad; -		// subtract a pixel off the bottom to deal with rounding errors in measuring font height -		mTextBoundingRect.mBottom -= 1; -		S32 delta_pos = -mTextBoundingRect.mBottom; +		S32 delta_pos = 0; +		 +		switch(mVAlign) +		{ +		case LLFontGL::TOP: +			delta_pos = llmax(mVisibleTextRect.getHeight() - mTextBoundingRect.mTop, -mTextBoundingRect.mBottom); +			break; +		case LLFontGL::VCENTER: +			delta_pos = (llmax(mVisibleTextRect.getHeight() - mTextBoundingRect.mTop, -mTextBoundingRect.mBottom) + (mVisibleTextRect.mBottom - mTextBoundingRect.mBottom)) / 2; +			break; +		case LLFontGL::BOTTOM: +			delta_pos = mVisibleTextRect.mBottom - mTextBoundingRect.mBottom; +			break; +		case LLFontGL::BASELINE: +			// do nothing +			break; +		}  		// move line segments to fit new document rect  		for (line_list_t::iterator it = mLineInfoList.begin(); it != mLineInfoList.end(); ++it)  		{ @@ -2408,8 +2428,9 @@ void LLTextBase::updateRects()  	}  	// update document container dimensions according to text contents -	LLRect doc_rect = mTextBoundingRect; +	LLRect doc_rect;  	// use old mVisibleTextRect constraint document to width of viewable region +	doc_rect.mBottom = llmin(mVisibleTextRect.mBottom,  mTextBoundingRect.mBottom);  	doc_rect.mLeft = 0;  	// allow horizontal scrolling? @@ -2419,11 +2440,22 @@ void LLTextBase::updateRects()  	doc_rect.mRight = mScroller   		? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)  		: mVisibleTextRect.getWidth(); +	doc_rect.mTop = llmax(mVisibleTextRect.mTop, mTextBoundingRect.mTop);  	if (!mScroller)  	{  		// push doc rect to top of text widget -		doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop); +		switch(mVAlign) +		{ +		case LLFontGL::TOP: +			doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop); +			break; +		case LLFontGL::VCENTER: +			doc_rect.translate(0, (mVisibleTextRect.getHeight() - doc_rect.mTop) / 2); +		case LLFontGL::BOTTOM: +		default: +			break; +		}  	}  	mDocumentView->setShape(doc_rect); @@ -2431,7 +2463,6 @@ void LLTextBase::updateRects()  	//update mVisibleTextRect *after* mDocumentView has been resized  	// so that scrollbars are added if document needs to scroll  	// since mVisibleTextRect does not include scrollbars -	LLRect old_text_rect = mVisibleTextRect;  	mVisibleTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();  	//FIXME: replace border with image?  	if (mBorderVisible) @@ -2444,9 +2475,27 @@ void LLTextBase::updateRects()  	}  	// update document container again, using new mVisibleTextRect (that has scrollbars enabled as needed) +	doc_rect.mBottom = llmin(mVisibleTextRect.mBottom,  mTextBoundingRect.mBottom); +	doc_rect.mLeft = 0;  	doc_rect.mRight = mScroller   		? llmax(mVisibleTextRect.getWidth(), mTextBoundingRect.mRight)  		: mVisibleTextRect.getWidth(); +	doc_rect.mTop = llmax(mVisibleTextRect.mTop, mTextBoundingRect.mTop); +	if (!mScroller) +	{ +		// push doc rect to top of text widget +		switch(mVAlign) +		{ +		case LLFontGL::TOP: +			doc_rect.translate(0, mVisibleTextRect.getHeight() - doc_rect.mTop); +			break; +		case LLFontGL::VCENTER: +			doc_rect.translate(0, (mVisibleTextRect.getHeight() - doc_rect.mTop) / 2); +		case LLFontGL::BOTTOM: +		default: +			break; +		} +	}  	mDocumentView->setShape(doc_rect);  } @@ -2560,8 +2609,7 @@ BOOL LLTextSegment::handleScrollWheel(S32 x, S32 y, S32 clicks) { return FALSE;  BOOL LLTextSegment::handleToolTip(S32 x, S32 y, MASK mask) { return FALSE; }  const std::string&	LLTextSegment::getName() const   { -	static std::string empty_string(""); -	return empty_string;  +	return LLStringUtil::null;  }  void LLTextSegment::onMouseCaptureLost() {}  void LLTextSegment::screenPointToLocal(S32 screen_x, S32 screen_y, S32* local_x, S32* local_y) const {} @@ -2578,7 +2626,7 @@ LLNormalTextSegment::LLNormalTextSegment( LLStyleConstSP style, S32 start, S32 e  	mToken(NULL),  	mEditor(editor)  { -	mFontHeight = llceil(mStyle->getFont()->getLineHeight()); +	mFontHeight = mStyle->getFont()->getLineHeight();  	LLUIImagePtr image = mStyle->getImage();  	if (image.notNull()) @@ -2594,7 +2642,7 @@ LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32  {  	mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color)); -	mFontHeight = llceil(mStyle->getFont()->getLineHeight()); +	mFontHeight = mStyle->getFont()->getLineHeight();  }  LLNormalTextSegment::~LLNormalTextSegment() @@ -2962,11 +3010,11 @@ LLLineBreakTextSegment::LLLineBreakTextSegment(S32 pos):LLTextSegment(pos,pos+1)  {  	LLStyleSP s( new LLStyle(LLStyle::Params().visible(true))); -	mFontHeight = llceil(s->getFont()->getLineHeight()); +	mFontHeight = s->getFont()->getLineHeight();  }  LLLineBreakTextSegment::LLLineBreakTextSegment(LLStyleConstSP style,S32 pos):LLTextSegment(pos,pos+1)  { -	mFontHeight = llceil(style->getFont()->getLineHeight()); +	mFontHeight = style->getFont()->getLineHeight();  }  LLLineBreakTextSegment::~LLLineBreakTextSegment()  { @@ -3003,7 +3051,7 @@ static const S32 IMAGE_HPAD = 3;  bool LLImageTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const  {  	width = 0; -	height = llceil(mStyle->getFont()->getLineHeight());; +	height = mStyle->getFont()->getLineHeight();  	LLUIImagePtr image = mStyle->getImage();  	if( num_chars>0 && image.notNull()) diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp index 3a23ce1cac..3409b6817d 100644 --- a/indra/llui/lltexteditor.cpp +++ b/indra/llui/lltexteditor.cpp @@ -1992,7 +1992,7 @@ void LLTextEditor::drawPreeditMarker()  		return;  	} -	const S32 line_height = llround( mDefaultFont->getLineHeight() ); +	const S32 line_height = mDefaultFont->getLineHeight();  	S32 line_start = getLineStart(cur_line);  	S32 line_y = mVisibleTextRect.mTop - line_height; @@ -2715,7 +2715,7 @@ BOOL LLTextEditor::getPreeditLocation(S32 query_offset, LLCoordGL *coord, LLRect      const LLWString textString(getWText());  	const llwchar * const text = textString.c_str(); -	const S32 line_height = llround(mDefaultFont->getLineHeight()); +	const S32 line_height = mDefaultFont->getLineHeight();  	if (coord)  	{ @@ -2818,7 +2818,7 @@ void LLTextEditor::markAsPreedit(S32 position, S32 length)  S32 LLTextEditor::getPreeditFontSize() const  { -	return llround(mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]); +	return llround((F32)mDefaultFont->getLineHeight() * LLUI::sGLScaleFactor.mV[VY]);  }  BOOL LLTextEditor::isDirty() const diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 9b31a6449d..81ea0ebf0c 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -827,7 +827,7 @@ void LLToolBar::draw()  	// rect may have shifted during layout  	LLUI::popMatrix();  	LLUI::pushMatrix(); -	LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom, 0.f); +	LLUI::translate((F32)getRect().mLeft, (F32)getRect().mBottom);  	// Position the caret   	LLIconCtrl* caret = getChild<LLIconCtrl>("caret"); diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp index 23cdd9ad9a..f737d48abf 100644 --- a/indra/llui/lltooltip.cpp +++ b/indra/llui/lltooltip.cpp @@ -180,6 +180,7 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)  	params.font = p.font;  	params.use_ellipses = true;  	params.wrap = p.wrap; +	params.font_valign = LLFontGL::VCENTER;  	params.parse_urls = false; // disallow hyperlinks in tooltips, as they want to spawn their own explanatory tooltips  	mTextBox = LLUICtrlFactory::create<LLTextBox> (params);  	addChild(mTextBox); @@ -190,7 +191,6 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)  	{  		LLButton::Params icon_params;  		icon_params.name = "tooltip_info"; -		icon_params.label(""); // provid label but set to empty so name does not overwrite it -angela  		LLRect icon_rect;  		LLUIImage* imagep = p.image;  		TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16); @@ -291,6 +291,12 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)  	S32 text_width = llmin(p.max_width(), mTextBox->getTextPixelWidth());  	S32 text_height = mTextBox->getTextPixelHeight();  	mTextBox->reshape(text_width, text_height); +	if (mInfoButton) +	{ +		LLRect text_rect = mTextBox->getRect(); +		LLRect icon_rect = mInfoButton->getRect(); +		mTextBox->translate(0, icon_rect.getCenterY() - text_rect.getCenterY()); +	}  	// reshape tooltip panel to fit text box  	LLRect tooltip_rect = calcBoundingRect(); @@ -299,6 +305,8 @@ void LLToolTip::initFromParams(const LLToolTip::Params& p)  	tooltip_rect.mBottom = 0;  	tooltip_rect.mLeft = 0; +	mTextBox->reshape(mTextBox->getRect().getWidth(), llmax(mTextBox->getRect().getHeight(), tooltip_rect.getHeight() - 2 * mPadding)); +  	setShape(tooltip_rect);  } diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 6b74c5a6be..b5e27616b7 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -972,43 +972,53 @@ void gl_ring( F32 radius, F32 width, const LLColor4& center_color, const LLColor  // Draw gray and white checkerboard with black border  void gl_rect_2d_checkerboard(const LLRect& rect, GLfloat alpha)  { -	// Initialize the first time this is called. -	const S32 PIXELS = 32; -	static GLubyte checkerboard[PIXELS * PIXELS]; -	static BOOL first = TRUE; -	if( first ) -	{ -		for( S32 i = 0; i < PIXELS; i++ ) +	if (!LLGLSLShader::sNoFixedFunction) +	{  +		// Initialize the first time this is called. +		const S32 PIXELS = 32; +		static GLubyte checkerboard[PIXELS * PIXELS]; +		static BOOL first = TRUE; +		if( first )  		{ -			for( S32 j = 0; j < PIXELS; j++ ) +			for( S32 i = 0; i < PIXELS; i++ )  			{ -				checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; +				for( S32 j = 0; j < PIXELS; j++ ) +				{ +					checkerboard[i * PIXELS + j] = ((i & 1) ^ (j & 1)) * 0xFF; +				}  			} +			first = FALSE;  		} -		first = FALSE; -	} -	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -	// ...white squares -	gGL.color4f( 1.f, 1.f, 1.f, alpha ); -	gl_rect_2d(rect); +		// ...white squares +		gGL.color4f( 1.f, 1.f, 1.f, alpha ); +		gl_rect_2d(rect); -	// ...gray squares -	gGL.color4f( .7f, .7f, .7f, alpha ); -	gGL.flush(); +		// ...gray squares +		gGL.color4f( .7f, .7f, .7f, alpha ); +		gGL.flush(); -	if (!LLGLSLShader::sNoFixedFunction) -	{ //polygon stipple is deprecated  		glPolygonStipple( checkerboard );  		LLGLEnable polygon_stipple(GL_POLYGON_STIPPLE);  		gl_rect_2d(rect);  	}  	else -	{ -		gl_rect_2d(rect); +	{ //polygon stipple is deprecated, use "Checker" texture +		LLPointer<LLUIImage> img = LLUI::getUIImage("Checker"); +		gGL.getTexUnit(0)->bind(img->getImage()); +		gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_WRAP); +		gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + +		LLColor4 color(1.f, 1.f, 1.f, alpha); +		LLRectf uv_rect(0, 0, rect.getWidth()/32.f, rect.getHeight()/32.f); + +		gl_draw_scaled_image(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), +			img->getImage(), color, uv_rect);  	} +	  	gGL.flush();  } @@ -1688,21 +1698,22 @@ void LLUI::translate(F32 x, F32 y, F32 z)  	gGL.translateUI(x,y,z);  	LLFontGL::sCurOrigin.mX += (S32) x;  	LLFontGL::sCurOrigin.mY += (S32) y; -	LLFontGL::sCurOrigin.mZ += z; +	LLFontGL::sCurDepth += z;  }  //static  void LLUI::pushMatrix()  {  	gGL.pushUIMatrix(); -	LLFontGL::sOriginStack.push_back(LLFontGL::sCurOrigin); +	LLFontGL::sOriginStack.push_back(std::make_pair(LLFontGL::sCurOrigin, LLFontGL::sCurDepth));  }  //static  void LLUI::popMatrix()  {  	gGL.popUIMatrix(); -	LLFontGL::sCurOrigin = *LLFontGL::sOriginStack.rbegin(); +	LLFontGL::sCurOrigin = LLFontGL::sOriginStack.back().first; +	LLFontGL::sCurDepth = LLFontGL::sOriginStack.back().second;  	LLFontGL::sOriginStack.pop_back();  } @@ -1712,7 +1723,7 @@ void LLUI::loadIdentity()  	gGL.loadUIIdentity();   	LLFontGL::sCurOrigin.mX = 0;  	LLFontGL::sCurOrigin.mY = 0; -	LLFontGL::sCurOrigin.mZ = 0; +	LLFontGL::sCurDepth = 0.f;  }  //static @@ -1735,10 +1746,7 @@ void LLUI::setMousePositionScreen(S32 x, S32 y)  	screen_x = llround((F32)x * sGLScaleFactor.mV[VX]);  	screen_y = llround((F32)y * sGLScaleFactor.mV[VY]); -	LLCoordWindow window_point; -	LLView::getWindow()->convertCoords(LLCoordGL(screen_x, screen_y), &window_point); - -	LLView::getWindow()->setCursorPosition(window_point); +	LLView::getWindow()->setCursorPosition(LLCoordGL(screen_x, screen_y).convert());  }  //static  @@ -1746,8 +1754,7 @@ void LLUI::getMousePositionScreen(S32 *x, S32 *y)  {  	LLCoordWindow cursor_pos_window;  	getWindow()->getCursorPosition(&cursor_pos_window); -	LLCoordGL cursor_pos_gl; -	getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); +	LLCoordGL cursor_pos_gl(cursor_pos_window.convert());  	*x = llround((F32)cursor_pos_gl.mX / sGLScaleFactor.mV[VX]);  	*y = llround((F32)cursor_pos_gl.mY / sGLScaleFactor.mV[VX]);  } @@ -2052,7 +2059,7 @@ void LLUI::positionViewNearMouse(LLView* view, S32 spawn_x, S32 spawn_y)  	// Start at spawn position (using left/top)  	view->setOrigin( local_x, local_y - view->getRect().getHeight());  	// Make sure we're on-screen and not overlapping the mouse -	view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect, FALSE ); +	view->translateIntoRectWithExclusion( virtual_window_rect, mouse_rect );  }  LLView* LLUI::resolvePath(LLView* context, const std::string& path) diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp index ac69d3bf85..c4e073ccdb 100644 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -128,17 +128,13 @@ void LLUIString::updateResult() const  	}  	mResult = mOrig; -	// get the defailt args + local args -	if (!mArgs || mArgs->empty()) +	// get the default args + local args +	LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs(); +	if (mArgs && !mArgs->empty())  	{ -		LLStringUtil::format(mResult, LLTrans::getDefaultArgs()); -	} -	else -	{ -		LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs();  		combined_args.insert(mArgs->begin(), mArgs->end()); -		LLStringUtil::format(mResult, combined_args);  	} +	LLStringUtil::format(mResult, combined_args);  }  void LLUIString::updateWResult() const diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index e1ee0a5b14..421166dcd4 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -1106,7 +1106,7 @@ void LLView::drawChildren()  				{  					LLUI::pushMatrix();  					{ -						LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); +						LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom);  						// flag the fact we are in draw here, in case overridden draw() method attempts to remove this widget  						viewp->mInDraw = true;  						viewp->draw(); @@ -1159,7 +1159,7 @@ void LLView::drawDebugRect()  		if (getUseBoundingRect())  		{ -			LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom, 0.f); +			LLUI::translate((F32)mBoundingRect.mLeft - (F32)mRect.mLeft, (F32)mBoundingRect.mBottom - (F32)mRect.mBottom);  		}  		LLRect debug_rect = getUseBoundingRect() ? mBoundingRect : mRect; @@ -1231,7 +1231,7 @@ void LLView::drawChild(LLView* childp, S32 x_offset, S32 y_offset, BOOL force_dr  			gGL.matrixMode(LLRender::MM_MODELVIEW);  			LLUI::pushMatrix();  			{ -				LLUI::translate((F32)childp->getRect().mLeft + x_offset, (F32)childp->getRect().mBottom + y_offset, 0.f); +				LLUI::translate((F32)childp->getRect().mLeft + x_offset, (F32)childp->getRect().mBottom + y_offset);  				childp->draw();  			}  			LLUI::popMatrix(); @@ -1300,7 +1300,10 @@ void LLView::reshape(S32 width, S32 height, BOOL called_from_parent)  			S32 delta_x = child_rect.mLeft - viewp->getRect().mLeft;  			S32 delta_y = child_rect.mBottom - viewp->getRect().mBottom;  			viewp->translate( delta_x, delta_y ); -			viewp->reshape(child_rect.getWidth(), child_rect.getHeight()); +			if (child_rect.getWidth() != viewp->getRect().getWidth() || child_rect.getHeight() != viewp->getRect().getHeight()) +			{ +				viewp->reshape(child_rect.getWidth(), child_rect.getHeight()); +			}  		}  	} @@ -1616,59 +1619,30 @@ LLView* LLView::findNextSibling(LLView* child)  } -LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BOOL allow_partial_outside) +LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, S32 min_overlap_pixels)  {  	LLCoordGL delta; -	if (allow_partial_outside) -	{ -		const S32 KEEP_ONSCREEN_PIXELS = 16; +	const S32 KEEP_ONSCREEN_PIXELS_WIDTH = llmin(min_overlap_pixels, input.getWidth()); +	const S32 KEEP_ONSCREEN_PIXELS_HEIGHT = llmin(min_overlap_pixels, input.getHeight()); -		if( input.mRight - KEEP_ONSCREEN_PIXELS < constraint.mLeft ) -		{ -			delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS); -		} -		else -		if( input.mLeft + KEEP_ONSCREEN_PIXELS > constraint.mRight ) -		{ -			delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS); -		} +	if( input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH < constraint.mLeft ) +	{ +		delta.mX = constraint.mLeft - (input.mRight - KEEP_ONSCREEN_PIXELS_WIDTH); +	} +	else if( input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH > constraint.mRight ) +	{ +		delta.mX = constraint.mRight - (input.mLeft + KEEP_ONSCREEN_PIXELS_WIDTH); +	} -		if( input.mTop > constraint.mTop ) -		{ -			delta.mY = constraint.mTop - input.mTop; -		} -		else -		if( input.mTop - KEEP_ONSCREEN_PIXELS < constraint.mBottom ) -		{ -			delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS); -		} +	if( input.mTop > constraint.mTop ) +	{ +		delta.mY = constraint.mTop - input.mTop;  	}  	else +	if( input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT < constraint.mBottom )  	{ -		if( input.mLeft < constraint.mLeft ) -		{ -			delta.mX = constraint.mLeft - input.mLeft; -		} -		else -		if( input.mRight > constraint.mRight ) -		{ -			delta.mX = constraint.mRight - input.mRight; -			// compensate for left edge possible going off screen -			delta.mX += llmax( 0, input.getWidth() - constraint.getWidth() ); -		} - -		if( input.mTop > constraint.mTop ) -		{ -			delta.mY = constraint.mTop - input.mTop; -		} -		else -		if( input.mBottom < constraint.mBottom ) -		{ -			delta.mY = constraint.mBottom - input.mBottom; -			// compensate for top edge possible going off screen -			delta.mY -= llmax( 0, input.getHeight() - constraint.getHeight() ); -		} +		delta.mY = constraint.mBottom - (input.mTop - KEEP_ONSCREEN_PIXELS_HEIGHT);  	}  	return delta; @@ -1677,9 +1651,9 @@ LLCoordGL getNeededTranslation(const LLRect& input, const LLRect& constraint, BO  // Moves the view so that it is entirely inside of constraint.  // If the view will not fit because it's too big, aligns with the top and left.  // (Why top and left?  That's where the drag bars are for floaters.) -BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outside ) +BOOL LLView::translateIntoRect(const LLRect& constraint, S32 min_overlap_pixels)  { -	LLCoordGL translation = getNeededTranslation(getRect(), constraint, allow_partial_outside); +	LLCoordGL translation = getNeededTranslation(getRect(), constraint, min_overlap_pixels);  	if (translation.mX != 0 || translation.mY != 0)  	{ @@ -1691,9 +1665,9 @@ BOOL LLView::translateIntoRect(const LLRect& constraint, BOOL allow_partial_outs  // move this view into "inside" but not onto "exclude"  // NOTE: if this view is already contained in "inside", we ignore the "exclude" rect -BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside ) +BOOL LLView::translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, S32 min_overlap_pixels)  { -	LLCoordGL translation = getNeededTranslation(getRect(), inside, allow_partial_outside); +	LLCoordGL translation = getNeededTranslation(getRect(), inside, min_overlap_pixels);  	if (translation.mX != 0 || translation.mY != 0)  	{ diff --git a/indra/llui/llview.h b/indra/llui/llview.h index f1fac5f69c..fd19309a56 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -370,8 +370,8 @@ public:  	virtual void	reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);  	virtual void	translate( S32 x, S32 y );  	void			setOrigin( S32 x, S32 y )	{ mRect.translate( x - mRect.mLeft, y - mRect.mBottom ); } -	BOOL			translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside ); -	BOOL			translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, BOOL allow_partial_outside ); +	BOOL			translateIntoRect( const LLRect& constraint, S32 min_overlap_pixels = S32_MAX); +	BOOL			translateIntoRectWithExclusion( const LLRect& inside, const LLRect& exclude, S32 min_overlap_pixels = S32_MAX);  	void			centerWithin(const LLRect& bounds);  	void	setShape(const LLRect& new_rect, bool by_user = false); diff --git a/indra/llvfs/lllfsthread.cpp b/indra/llvfs/lllfsthread.cpp index 3d3ed9f6d4..073b1af2a1 100644 --- a/indra/llvfs/lllfsthread.cpp +++ b/indra/llvfs/lllfsthread.cpp @@ -45,7 +45,7 @@ void LLLFSThread::initClass(bool local_is_threaded)  //static  S32 LLLFSThread::updateClass(U32 ms_elapsed)  { -	sLocal->update(ms_elapsed); +	sLocal->update((F32)ms_elapsed);  	return sLocal->getPending();  } diff --git a/indra/llvfs/llvfsthread.cpp b/indra/llvfs/llvfsthread.cpp index 254f8b55ba..a57e2b15ab 100644 --- a/indra/llvfs/llvfsthread.cpp +++ b/indra/llvfs/llvfsthread.cpp @@ -46,7 +46,7 @@ void LLVFSThread::initClass(bool local_is_threaded)  //static  S32 LLVFSThread::updateClass(U32 ms_elapsed)  { -	sLocal->update(ms_elapsed); +	sLocal->update((F32)ms_elapsed);  	return sLocal->getPending();  } diff --git a/indra/llwindow/lldragdropwin32.cpp b/indra/llwindow/lldragdropwin32.cpp index d4d444eb28..15acddd987 100644 --- a/indra/llwindow/lldragdropwin32.cpp +++ b/indra/llwindow/lldragdropwin32.cpp @@ -124,10 +124,9 @@ class LLDragDropWin32Target:  						ScreenToClient( mAppWindowHandle, &pt2 );  						LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); -						window_imp->convertCoords(cursor_coord_window, &gl_coord);  						MASK mask = gKeyboard->currentMask(TRUE); -						LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,  +						LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,   							LLWindowCallbacks::DNDA_START_TRACKING, mDropUrl );  						switch (result) @@ -180,10 +179,9 @@ class LLDragDropWin32Target:  					ScreenToClient( mAppWindowHandle, &pt2 );  					LLCoordWindow cursor_coord_window( pt2.x, pt2.y ); -					window_imp->convertCoords(cursor_coord_window, &gl_coord);  					MASK mask = gKeyboard->currentMask(TRUE); -					LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( gl_coord, mask,  +					LLWindowCallbacks::DragNDropResult result = window_imp->completeDragNDropRequest( cursor_coord_window.convert(), mask,   						LLWindowCallbacks::DNDA_TRACK, mDropUrl );  					switch (result) @@ -237,15 +235,13 @@ class LLDragDropWin32Target:  				LLWindowWin32 *window_imp = (LLWindowWin32 *)GetWindowLong( mAppWindowHandle, GWL_USERDATA );  				if ( NULL != window_imp )  				{ -					LLCoordGL gl_coord( 0, 0 ); -  					POINT pt_client;  					pt_client.x = pt.x;  					pt_client.y = pt.y;  					ScreenToClient( mAppWindowHandle, &pt_client );  					LLCoordWindow cursor_coord_window( pt_client.x, pt_client.y ); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); +					LLCoordGL gl_coord(cursor_coord_window.convert());  					llinfos << "### (Drop) URL is: " << mDropUrl << llendl;  					llinfos << "###        raw coords are: " << pt.x << " x " << pt.y << llendl;  					llinfos << "###	    client coords are: " << pt_client.x << " x " << pt_client.y << llendl; diff --git a/indra/llwindow/llwindow.cpp b/indra/llwindow/llwindow.cpp index 2e9e31bfea..6834b34387 100644 --- a/indra/llwindow/llwindow.cpp +++ b/indra/llwindow/llwindow.cpp @@ -436,3 +436,42 @@ BOOL LLWindowManager::isWindowValid(LLWindow *window)  {  	return sWindowList.find(window) != sWindowList.end();  } + +//coordinate conversion utility funcs that forward to llwindow +LLCoordCommon LL_COORD_TYPE_WINDOW::convertToCommon() const +{ +	const LLCoordWindow& self = static_cast<const LLCoordWindow&>(*this); + +	LLWindow* windowp = &(*LLWindow::beginInstances()); +	LLCoordGL out; +	windowp->convertCoords(self, &out); +	return out.convert(); +} + +void LL_COORD_TYPE_WINDOW::convertFromCommon(const LLCoordCommon& from) +{ +	LLCoordWindow& self = static_cast<LLCoordWindow&>(*this); + +	LLWindow* windowp = &(*LLWindow::beginInstances()); +	LLCoordGL from_gl(from); +	windowp->convertCoords(from_gl, &self); +} + +LLCoordCommon LL_COORD_TYPE_SCREEN::convertToCommon() const +{ +	const LLCoordScreen& self = static_cast<const LLCoordScreen&>(*this); + +	LLWindow* windowp = &(*LLWindow::beginInstances()); +	LLCoordGL out; +	windowp->convertCoords(self, &out); +	return out.convert(); +} + +void LL_COORD_TYPE_SCREEN::convertFromCommon(const LLCoordCommon& from) +{ +	LLCoordScreen& self = static_cast<LLCoordScreen&>(*this); + +	LLWindow* windowp = &(*LLWindow::beginInstances()); +	LLCoordGL from_gl(from); +	windowp->convertCoords(from_gl, &self); +} diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index cab2d0a8fb..d2971581d2 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -39,7 +39,7 @@ class LLWindowCallbacks;  // Refer to llwindow_test in test/common/llwindow for usage example -class LLWindow +class LLWindow : public LLInstanceTracker<LLWindow>  {  public:  	struct LLWindowResolution diff --git a/indra/llwindow/llwindowcallbacks.cpp b/indra/llwindow/llwindowcallbacks.cpp index c2705bbf74..9712ae1d91 100644 --- a/indra/llwindow/llwindowcallbacks.cpp +++ b/indra/llwindow/llwindowcallbacks.cpp @@ -28,8 +28,6 @@  #include "llwindowcallbacks.h" -#include "llcoord.h" -  //  // LLWindowCallbacks  // diff --git a/indra/llwindow/llwindowcallbacks.h b/indra/llwindow/llwindowcallbacks.h index 8572b442f1..7da5959700 100644 --- a/indra/llwindow/llwindowcallbacks.h +++ b/indra/llwindow/llwindowcallbacks.h @@ -26,7 +26,7 @@  #ifndef LLWINDOWCALLBACKS_H  #define LLWINDOWCALLBACKS_H -class LLCoordGL; +#include "llcoord.h"  class LLWindow;  class LLWindowCallbacks diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 228fbefd19..ebc3203f14 100644 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -1065,6 +1065,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO  		return FALSE;  	} +	LL_INFOS("Window") << "Device context retrieved." << llendl ; +  	if (!(pixel_format = ChoosePixelFormat(mhDC, &pfd)))  	{  		close(); @@ -1073,6 +1075,8 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO  		return FALSE;  	} +	LL_INFOS("Window") << "Pixel format chosen." << llendl ; +  	// Verify what pixel format we actually received.  	if (!DescribePixelFormat(mhDC, pixel_format, sizeof(PIXELFORMATDESCRIPTOR),  		&pfd)) @@ -1541,24 +1545,16 @@ void LLWindowWin32::moveWindow( const LLCoordScreen& position, const LLCoordScre  BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)  { -	LLCoordScreen screen_pos; -  	mMousePositionModified = TRUE;  	if (!mWindowHandle)  	{  		return FALSE;  	} -	if (!convertCoords(position, &screen_pos)) -	{ -		return FALSE; -	}  	// Inform the application of the new mouse position (needed for per-frame  	// hover/picking to function). -	LLCoordGL gl_pos; -	convertCoords(position, &gl_pos); -	mCallbacks->handleMouseMove(this, gl_pos, (MASK)0); +	mCallbacks->handleMouseMove(this, position.convert(), (MASK)0);  	// DEV-18951 VWR-8524 Camera moves wildly when alt-clicking.  	// Because we have preemptively notified the application of the new @@ -1568,24 +1564,23 @@ BOOL LLWindowWin32::setCursorPosition(const LLCoordWindow position)  	while (PeekMessage(&msg, NULL, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE))  	{ } -	return SetCursorPos(screen_pos.mX, screen_pos.mY); +	LLCoordScreen screen_pos(position.convert()); +	return ::SetCursorPos(screen_pos.mX, screen_pos.mY);  }  BOOL LLWindowWin32::getCursorPosition(LLCoordWindow *position)  {  	POINT cursor_point; -	LLCoordScreen screen_pos; -	if (!mWindowHandle || -		!GetCursorPos(&cursor_point)) +	if (!mWindowHandle  +		|| !GetCursorPos(&cursor_point) +		|| !position)  	{  		return FALSE;  	} -	screen_pos.mX = cursor_point.x; -	screen_pos.mY = cursor_point.y; - -	return convertCoords(screen_pos, position); +	*position = LLCoordScreen(cursor_point.x, cursor_point.y).convert(); +	return TRUE;  }  void LLWindowWin32::hideCursor() @@ -2163,15 +2158,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_  				// If we don't do this, many clicks could get buffered up, and if the  				// first click changes the cursor position, all subsequent clicks  				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window;  				if (window_imp->mMousePositionModified)  				{ +					LLCoordWindow cursor_coord_window;  					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); +					gl_coord = cursor_coord_window.convert();  				}  				else  				{ -					window_imp->convertCoords(window_coord, &gl_coord); +					gl_coord = window_coord.convert();  				}  				MASK mask = gKeyboard->currentMask(TRUE);  				// generate move event to update mouse coordinates @@ -2193,15 +2188,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_  				// If we don't do this, many clicks could get buffered up, and if the  				// first click changes the cursor position, all subsequent clicks  				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window;  				if (window_imp->mMousePositionModified)  				{ +					LLCoordWindow cursor_coord_window;  					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); +					gl_coord = cursor_coord_window.convert();  				}  				else  				{ -					window_imp->convertCoords(window_coord, &gl_coord); +					gl_coord = window_coord.convert();  				}  				MASK mask = gKeyboard->currentMask(TRUE);  				// generate move event to update mouse coordinates @@ -2226,15 +2221,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_  				// If we don't do this, many clicks could get buffered up, and if the  				// first click changes the cursor position, all subsequent clicks  				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window;  				if (window_imp->mMousePositionModified)  				{ +					LLCoordWindow cursor_coord_window;  					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); +					gl_coord = cursor_coord_window.convert();  				}  				else  				{ -					window_imp->convertCoords(window_coord, &gl_coord); +					gl_coord = window_coord.convert();  				}  				MASK mask = gKeyboard->currentMask(TRUE);  				// generate move event to update mouse coordinates @@ -2261,15 +2256,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_  				// If we don't do this, many clicks could get buffered up, and if the  				// first click changes the cursor position, all subsequent clicks  				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window;  				if (window_imp->mMousePositionModified)  				{ +					LLCoordWindow cursor_coord_window;  					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); +					gl_coord = cursor_coord_window.convert();  				}  				else  				{ -					window_imp->convertCoords(window_coord, &gl_coord); +					gl_coord = window_coord.convert();  				}  				MASK mask = gKeyboard->currentMask(TRUE);  				// generate move event to update mouse coordinates @@ -2290,15 +2285,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_  				// If we don't do this, many clicks could get buffered up, and if the  				// first click changes the cursor position, all subsequent clicks  				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window;  				if (window_imp->mMousePositionModified)  				{ +					LLCoordWindow cursor_coord_window;  					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); +					gl_coord = cursor_coord_window.convert();  				}  				else  				{ -					window_imp->convertCoords(window_coord, &gl_coord); +					gl_coord = window_coord.convert();  				}  				MASK mask = gKeyboard->currentMask(TRUE);  				// generate move event to update mouse coordinates @@ -2325,15 +2320,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_  				// If we don't do this, many clicks could get buffered up, and if the  				// first click changes the cursor position, all subsequent clicks  				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window;  				if (window_imp->mMousePositionModified)  				{ +					LLCoordWindow cursor_coord_window;  					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); +					gl_coord = cursor_coord_window.convert();  				}  				else  				{ -					window_imp->convertCoords(window_coord, &gl_coord); +					gl_coord = window_coord.convert();  				}  				MASK mask = gKeyboard->currentMask(TRUE);  				// generate move event to update mouse coordinates @@ -2354,15 +2349,15 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_  				// If we don't do this, many clicks could get buffered up, and if the  				// first click changes the cursor position, all subsequent clicks  				// will occur at the wrong location.  JC -				LLCoordWindow cursor_coord_window;  				if (window_imp->mMousePositionModified)  				{ +					LLCoordWindow cursor_coord_window;  					window_imp->getCursorPosition(&cursor_coord_window); -					window_imp->convertCoords(cursor_coord_window, &gl_coord); +					gl_coord = cursor_coord_window.convert();  				}  				else  				{ -					window_imp->convertCoords(window_coord, &gl_coord); +					gl_coord = window_coord.convert();  				}  				MASK mask = gKeyboard->currentMask(TRUE);  				// generate move event to update mouse coordinates @@ -2434,9 +2429,8 @@ LRESULT CALLBACK LLWindowWin32::mainWindowProc(HWND h_wnd, UINT u_msg, WPARAM w_  		case WM_MOUSEMOVE:  			{  				window_imp->mCallbacks->handlePingWatchdog(window_imp, "Main:WM_MOUSEMOVE"); -				window_imp->convertCoords(window_coord, &gl_coord);  				MASK mask = gKeyboard->currentMask(TRUE); -				window_imp->mCallbacks->handleMouseMove(window_imp, gl_coord, mask); +				window_imp->mCallbacks->handleMouseMove(window_imp, window_coord.convert(), mask);  				return 0;  			} @@ -3324,7 +3318,7 @@ void LLWindowWin32::setLanguageTextInput( const LLCoordGL & position )  			LLWinImm::setCompositionWindow( himc, &ime_form ); -			sWinIMEWindowPosition.set( win_pos.mX, win_pos.mY ); +			sWinIMEWindowPosition = win_pos;  		}  		LLWinImm::releaseContext(mWindowHandle, himc); diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index bf38a8b062..597031ec70 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -92,6 +92,8 @@ typedef enum e_control_type  class LLControlVariable : public LLRefCount  { +	LOG_CLASS(LLControlVariable); +  	friend class LLControlGroup;  public: @@ -180,6 +182,8 @@ T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& contro  //const U32 STRING_CACHE_SIZE = 10000;  class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>  { +	LOG_CLASS(LLControlGroup); +  protected:  	typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t;  	ctrl_name_table_t mNameTable; diff --git a/indra/llxml/llxmlnode.cpp b/indra/llxml/llxmlnode.cpp index 2b4a0fc2a1..2ffb0d8503 100644 --- a/indra/llxml/llxmlnode.cpp +++ b/indra/llxml/llxmlnode.cpp @@ -631,13 +631,14 @@ bool LLXMLNode::updateNode(  	}  	//update all of node's children with updateNodes children that match name -	LLXMLNodePtr child; +	LLXMLNodePtr child = node->getFirstChild(); +	LLXMLNodePtr last_child = child;  	LLXMLNodePtr updateChild;  	for (updateChild = update_node->getFirstChild(); updateChild.notNull();   		 updateChild = updateChild->getNextSibling())  	{ -		for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) +		while(child.notNull())  		{  			std::string nodeName;  			std::string updateName; @@ -656,6 +657,22 @@ bool LLXMLNode::updateNode(  			if ((nodeName != "") && (updateName == nodeName))  			{  				updateNode(child, updateChild); +				last_child = child; +				child = child->getNextSibling(); +				if (child.isNull()) +				{ +					child = node->getFirstChild(); +				} +				break; +			} +			 +			child = child->getNextSibling(); +			if (child.isNull()) +			{ +				child = node->getFirstChild(); +			} +			if (child == last_child) +			{  				break;  			}  		} @@ -784,7 +801,7 @@ bool LLXMLNode::parseStream(  	while(str.good())  	{  		str.read((char*)buffer, BUFSIZE); -		int count = str.gcount(); +		int count = (int)str.gcount();  		if (XML_Parse(my_parser, (const char *)buffer, count, !str.good()) != XML_STATUS_OK)  		{ @@ -882,11 +899,8 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root,  	for (itor = paths.begin(), ++itor; itor != paths.end(); ++itor)  	{ -		std::string nodeName; -		std::string updateName; -  		std::string layer_filename = *itor; -		if(layer_filename.empty()) +		if(layer_filename.empty() || layer_filename == filename)  		{  			// no localized version of this file, that's ok, keep looking  			continue; @@ -898,6 +912,9 @@ bool LLXMLNode::getLayeredXMLNode(LLXMLNodePtr& root,  			return false;  		} +		std::string nodeName; +		std::string updateName; +  		updateRoot->getAttributeString("name", updateName);  		root->getAttributeString("name", nodeName); diff --git a/indra/llxuixml/llinitparam.h b/indra/llxuixml/llinitparam.h index ab20957760..4ab1d891a3 100644 --- a/indra/llxuixml/llinitparam.h +++ b/indra/llxuixml/llinitparam.h @@ -1253,15 +1253,16 @@ namespace LLInitParam  			return mValues.back();  		} -		void add(const value_t& item) +		self_t& add(const value_t& item)  		{  			param_value_t param_value;  			param_value.setValue(item);  			mValues.push_back(param_value);  			setProvided(); +			return *this;  		} -		void add(const typename name_value_lookup_t::name_t& name) +		self_t& add(const typename name_value_lookup_t::name_t& name)  		{  			value_t value; @@ -1271,6 +1272,8 @@ namespace LLInitParam  				add(value);  				mValues.back().setValueName(name);  			} + +			return *this;  		}  		// implicit conversion @@ -1441,13 +1444,14 @@ namespace LLInitParam  			return mValues.back();  		} -		void add(const value_t& item) +		self_t& add(const value_t& item)  		{  			mValues.push_back(item);  			setProvided(); +			return *this;  		} -		void add(const typename name_value_lookup_t::name_t& name) +		self_t& add(const typename name_value_lookup_t::name_t& name)  		{  			value_t value; @@ -1457,6 +1461,7 @@ namespace LLInitParam  				add(value);  				mValues.back().setValueName(name);  			} +			return *this;  		}  		// implicit conversion diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index 999f754dcf..24328202cb 100644 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -705,7 +705,7 @@ private:  		// look up "Display Name" in meta data  		OSType meta_data_key = kQTMetaDataCommonKeyDisplayName;  		QTMetaDataItem item = kQTMetaDataItemUninitialized; -		result = QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard,  +		result = (OSErr)QTMetaDataGetNextItem( media_data_ref, kQTMetaDataStorageFormatWildcard,   										0, kQTMetaDataKeyFormatCommon,   										(const UInt8 *)&meta_data_key,   										sizeof( meta_data_key ), &item ); @@ -714,14 +714,14 @@ private:  		// find the size of the title  		ByteCount size; -		result = QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size ); +		result = (OSErr)QTMetaDataGetItemValue( media_data_ref, item, NULL, 0, &size );  		if ( noErr != result || size <= 0 /*|| size > 1024  FIXME: arbitrary limit */ )   			return false;  		// allocate some space and grab it  		UInt8* item_data = new UInt8[ size + 1 ];  		memset( item_data, 0, ( size + 1 ) * sizeof( UInt8 ) ); -		result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL ); +		result = (OSErr)QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );  		if ( noErr != result )   		{  			delete [] item_data; diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp index 47f8dcd545..1812abd7d5 100644 --- a/indra/media_plugins/webkit/media_plugin_webkit.cpp +++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp @@ -991,7 +991,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)  		{  			if(message_name == "set_volume")  			{ -				F32 volume = message_in.getValueReal("volume"); +				F32 volume = (F32)message_in.getValueReal("volume");  				setVolume(volume);  			}  		} @@ -1057,9 +1057,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)  				S32 height = message_in.getValueS32("height");  				S32 texture_width = message_in.getValueS32("texture_width");  				S32 texture_height = message_in.getValueS32("texture_height"); -				mBackgroundR = message_in.getValueReal("background_r"); -				mBackgroundG = message_in.getValueReal("background_g"); -				mBackgroundB = message_in.getValueReal("background_b"); +				mBackgroundR = (F32)message_in.getValueReal("background_r"); +				mBackgroundG = (F32)message_in.getValueReal("background_g"); +				mBackgroundB = (F32)message_in.getValueReal("background_b");  //				mBackgroundA = message_in.setValueReal("background_a");		// Ignore any alpha  				if(!name.empty()) @@ -1245,9 +1245,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)  			if(message_name == "js_agent_location")  			{  #if LLQTWEBKIT_API_VERSION >= 9 -				F32 x = message_in.getValueReal("x"); -				F32 y = message_in.getValueReal("y"); -				F32 z = message_in.getValueReal("z"); +				F32 x = (F32)message_in.getValueReal("x"); +				F32 y = (F32)message_in.getValueReal("y"); +				F32 z = (F32)message_in.getValueReal("z");  				LLQtWebKit::getInstance()->setAgentLocation( x, y, z );  				LLQtWebKit::getInstance()->emitLocation();  #endif @@ -1256,9 +1256,9 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)  			if(message_name == "js_agent_global_location")  			{  #if LLQTWEBKIT_API_VERSION >= 9 -				F32 x = message_in.getValueReal("x"); -				F32 y = message_in.getValueReal("y"); -				F32 z = message_in.getValueReal("z"); +				F32 x = (F32)message_in.getValueReal("x"); +				F32 y = (F32)message_in.getValueReal("y"); +				F32 z = (F32)message_in.getValueReal("z");  				LLQtWebKit::getInstance()->setAgentGlobalLocation( x, y, z );  				LLQtWebKit::getInstance()->emitLocation();  #endif @@ -1267,7 +1267,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)  			if(message_name == "js_agent_orientation")  			{  #if LLQTWEBKIT_API_VERSION >= 9 -				F32 angle = message_in.getValueReal("angle"); +				F32 angle = (F32)message_in.getValueReal("angle");  				LLQtWebKit::getInstance()->setAgentOrientation( angle );  				LLQtWebKit::getInstance()->emitLocation();  #endif @@ -1323,7 +1323,7 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)  			else if(message_name == "set_page_zoom_factor")  			{  #if LLQTWEBKIT_API_VERSION >= 15 -				F32 factor = message_in.getValueReal("factor"); +				F32 factor = (F32)message_in.getValueReal("factor");  				LLQtWebKit::getInstance()->setPageZoomFactor(factor);  #else  				llwarns << "Ignoring setPageZoomFactor message (llqtwebkit version is too old)." << llendl; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 36b7e136d0..500163c030 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -166,7 +166,7 @@ set(viewer_SOURCE_FILES      llfirstuse.cpp      llflexibleobject.cpp      llfloaterabout.cpp -    llfloateranimpreview.cpp +    llfloaterbvhpreview.cpp      llfloaterauction.cpp      llfloateravatar.cpp      llfloateravatarpicker.cpp @@ -733,7 +733,7 @@ set(viewer_HEADER_FILES      llfirstuse.h      llflexibleobject.h      llfloaterabout.h -    llfloateranimpreview.h +    llfloaterbvhpreview.h      llfloaterauction.h      llfloateravatar.h      llfloateravatarpicker.h @@ -1367,7 +1367,9 @@ if (WINDOWS)          DXGUID_LIBRARY          ) +# see EXP-1765 - theory is opengl32.lib needs to be included before gdi32.lib (windows libs)      set(viewer_LIBRARIES +        opengl32          ${WINDOWS_LIBRARIES}          comdlg32          ${DINPUT_LIBRARY} @@ -1377,7 +1379,6 @@ if (WINDOWS)          odbccp32          ole32          oleaut32 -        opengl32          shell32          Vfw32          winspool diff --git a/indra/newview/app_settings/commands.xml b/indra/newview/app_settings/commands.xml index d3253bc381..ff4d9ceb93 100644 --- a/indra/newview/app_settings/commands.xml +++ b/indra/newview/app_settings/commands.xml @@ -37,6 +37,8 @@             tooltip_ref="Command_Build_Tooltip"             execute_function="Build.Toggle"             execute_parameters="build" +           is_enabled_function="Build.Enabled" +           is_enabled_parameters="build"             is_running_function="Floater.IsOpen"             is_running_parameters="build"             /> diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index 77a76e6bf7..eb2b0834e9 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -4282,6 +4282,17 @@          <key>Value</key>          <integer>0</integer>      </map> +    <key>InventoryInboxToggleState</key> +    <map> +        <key>Comment</key> +        <string>Stores the open/closed state of inventory Received items panel</string> +        <key>Persist</key> +        <integer>1</integer> +        <key>Type</key> +        <string>Boolean</string> +        <key>Value</key> +        <integer>0</integer> +    </map>  	<key>InventoryLinking</key>  	<map>  		<key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl index 40b0cf47ac..eada38eaaa 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl @@ -55,6 +55,12 @@ uniform vec3 light_direction[8];  uniform vec3 light_attenuation[8];   uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ +        float a = max(dot(n,l),0.0); +        return a; +} +  float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)  {  	//get light vector diff --git a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl index 8c96d55342..5c36118a50 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/alphaV.glsl @@ -64,6 +64,12 @@ uniform vec3 light_direction[8];  uniform vec3 light_attenuation[8];   uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ +        float a = max(dot(n,l),0.0); +        return a; +} +  float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)  {  	//get light vector diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl index c0edddc40a..d6149fcc32 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl @@ -59,6 +59,12 @@ uniform vec3 light_direction[8];  uniform vec3 light_attenuation[8];   uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ +        float a = max(dot(n,l),0.0); +        return a; +} +  float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)  {  	//get light vector diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl index 64e094e3c5..17f425475c 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl @@ -50,18 +50,18 @@ uniform vec4 sunlight_color;  uniform vec4 ambient;  uniform vec4 blue_horizon;  uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; +uniform float haze_horizon; +uniform float haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 max_y; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float max_y;  uniform vec4 glow;  uniform vec4 cloud_color; -uniform vec4 cloud_scale; +uniform float cloud_scale;  void main()  { @@ -77,7 +77,7 @@ void main()  	// Set altitude  	if (P.y > 0.)  	{ -		P *= (max_y.x / P.y); +		P *= (max_y / P.y);  	}  	else  	{ @@ -99,12 +99,12 @@ void main()  	// Sunlight attenuation effect (hue and brightness) due to atmosphere  	// this is used later for sunlight modulation at various altitudes -	light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x); +	light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);  	// Calculate relative weights -	temp1 = blue_density + haze_density.x; +	temp1 = blue_density + haze_density;  	blue_weight = blue_density / temp1; -	haze_weight = haze_density.x / temp1; +	haze_weight = haze_density / temp1;  	// Compute sunlight from P & lightnorm (for long rays like sky)  	temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); @@ -112,7 +112,7 @@ void main()  	sunlight *= exp( - light_atten * temp2.y);  	// Distance -	temp2.z = Plen * density_multiplier.x; +	temp2.z = Plen * density_multiplier;  	// Transparency (-> temp1)  	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati @@ -136,14 +136,14 @@ void main()  	// Increase ambient when there are more clouds  	vec4 tmpAmbient = ambient; -	tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;  +	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;   	// Dim sunlight by cloud shadow percentage -	sunlight *= (1. - cloud_shadow.x); +	sunlight *= (1. - cloud_shadow);  	// Haze color below cloud  	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient) -				+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient) +				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)  			 );	  	// CLOUDS @@ -164,13 +164,13 @@ void main()  	vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);  	// Make a nice cloud density based on the cloud_shadow value that was passed in. -	vary_CloudDensity = 2. * (cloud_shadow.x - 0.25); +	vary_CloudDensity = 2. * (cloud_shadow - 0.25);  	// Texture coords  	vary_texcoord0 = texcoord0;  	vary_texcoord0.xy -= 0.5; -	vary_texcoord0.xy /= cloud_scale.x; +	vary_texcoord0.xy /= cloud_scale;  	vary_texcoord0.xy += 0.5;  	vary_texcoord1 = vary_texcoord0; diff --git a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl index 721de18e0b..cb7603f4fd 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/skyV.glsl @@ -44,19 +44,17 @@ uniform vec4 sunlight_color;  uniform vec4 ambient;  uniform vec4 blue_horizon;  uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; +uniform float haze_horizon; +uniform float haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 max_y; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float max_y;  uniform vec4 glow;  uniform vec4 cloud_color; -uniform vec4 cloud_scale; -  void main()  { @@ -71,7 +69,7 @@ void main()  	// Set altitude  	if (P.y > 0.)  	{ -		P *= (max_y.x / P.y); +		P *= (max_y / P.y);  	}  	else  	{ @@ -93,12 +91,12 @@ void main()  	// Sunlight attenuation effect (hue and brightness) due to atmosphere  	// this is used later for sunlight modulation at various altitudes -	light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x); +	light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);  	// Calculate relative weights -	temp1 = blue_density + haze_density.x; +	temp1 = blue_density + haze_density;  	blue_weight = blue_density / temp1; -	haze_weight = haze_density.x / temp1; +	haze_weight = haze_density / temp1;  	// Compute sunlight from P & lightnorm (for long rays like sky)  	temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); @@ -106,7 +104,7 @@ void main()  	sunlight *= exp( - light_atten * temp2.y);  	// Distance -	temp2.z = Plen * density_multiplier.x; +	temp2.z = Plen * density_multiplier;  	// Transparency (-> temp1)  	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati @@ -131,20 +129,20 @@ void main()  	// Haze color above cloud  	vary_HazeColor = (	  blue_horizon * blue_weight * (sunlight + ambient) -				+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + ambient) +				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient)  			 );	  	// Increase ambient when there are more clouds  	vec4 tmpAmbient = ambient; -	tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;  +	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;   	// Dim sunlight by cloud shadow percentage -	sunlight *= (1. - cloud_shadow.x); +	sunlight *= (1. - cloud_shadow);  	// Haze color below cloud  	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient) -				+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient) +				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)  			 );	  	// Final atmosphere additive diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl index 51110ae4df..0c53a4ffa5 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl @@ -51,12 +51,12 @@ uniform vec4 sunlight_color;  uniform vec4 ambient;  uniform vec4 blue_horizon;  uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 distance_multiplier; -uniform vec4 max_y; +uniform float haze_horizon; +uniform float haze_density; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float distance_multiplier; +uniform float max_y;  uniform vec4 glow;  uniform float scene_light_strength;  uniform mat3 env_mat; @@ -159,13 +159,13 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {  	//sunlight attenuation effect (hue and brightness) due to atmosphere  	//this is used later for sunlight modulation at various altitudes -	light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); +	light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);  		//I had thought blue_density and haze_density should have equal weighting,  		//but attenuation due to haze_density tends to seem too strong -	temp1 = blue_density + vec4(haze_density.r); +	temp1 = blue_density + vec4(haze_density);  	blue_weight = blue_density / temp1; -	haze_weight = vec4(haze_density.r) / temp1; +	haze_weight = vec4(haze_density) / temp1;  	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)  	temp2.y = max(0.0, tmpLightnorm.y); @@ -173,12 +173,12 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {  	sunlight *= exp( - light_atten * temp2.y);  	// main atmospheric scattering line integral -	temp2.z = Plen * density_multiplier.x; +	temp2.z = Plen * density_multiplier;  	// Transparency (-> temp1) -	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati +	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati  	// compiler gets confused. -	temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); +	temp1 = exp(-temp1 * temp2.z * distance_multiplier);  	//final atmosphere attenuation factor  	setAtmosAttenuation(temp1.rgb); @@ -199,7 +199,7 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {  	temp2.x += .25;  	//increase ambient when there are more clouds -	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; +	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;  	/*  decrease value and saturation (that in HSV, not HSL) for occluded areas  	 * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html @@ -213,8 +213,8 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {  	//haze color  	setAdditiveColor( -		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient) -	  + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x +		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) +	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x  		  + tmpAmbient)));  	//brightness of surface both sunlight and ambient diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl index 83815b1786..9629cfe824 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl @@ -61,6 +61,12 @@ uniform vec3 light_direction[8];  uniform vec3 light_attenuation[8];   uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ +        float a = max(dot(n,l),0.0); +        return a; +} +  float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)  {  //get light vector diff --git a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl index 1660f9687e..1586aab0f2 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/alphaV.glsl @@ -63,6 +63,12 @@ uniform vec3 light_direction[8];  uniform vec3 light_attenuation[8];   uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ +        float a = max(dot(n,l),0.0); +        return a; +} +  float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)  {  	//get light vector diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl index 84c27edb26..44aaa98b97 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl @@ -60,6 +60,12 @@ uniform vec3 light_direction[8];  uniform vec3 light_attenuation[8];   uniform vec3 light_diffuse[8]; +float calcDirectionalLight(vec3 n, vec3 l) +{ +        float a = max(dot(n,l),0.0); +        return a; +} +  float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)  {  	//get light vector diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl index 97f3063a9e..27ea77b5a2 100644 --- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl +++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl @@ -51,12 +51,12 @@ uniform vec4 sunlight_color;  uniform vec4 ambient;  uniform vec4 blue_horizon;  uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 distance_multiplier; -uniform vec4 max_y; +uniform float haze_horizon; +uniform float haze_density; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float distance_multiplier; +uniform float max_y;  uniform vec4 glow;  uniform float scene_light_strength;  uniform mat3 env_mat; @@ -161,13 +161,13 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {  	//sunlight attenuation effect (hue and brightness) due to atmosphere  	//this is used later for sunlight modulation at various altitudes -	light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); +	light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);  		//I had thought blue_density and haze_density should have equal weighting,  		//but attenuation due to haze_density tends to seem too strong -	temp1 = blue_density + vec4(haze_density.r); +	temp1 = blue_density + vec4(haze_density);  	blue_weight = blue_density / temp1; -	haze_weight = vec4(haze_density.r) / temp1; +	haze_weight = vec4(haze_density) / temp1;  	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)  	temp2.y = max(0.0, tmpLightnorm.y); @@ -175,12 +175,12 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {  	sunlight *= exp( - light_atten * temp2.y);  	// main atmospheric scattering line integral -	temp2.z = Plen * density_multiplier.x; +	temp2.z = Plen * density_multiplier;  	// Transparency (-> temp1) -	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati +	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati  	// compiler gets confused. -	temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); +	temp1 = exp(-temp1 * temp2.z * distance_multiplier);  	//final atmosphere attenuation factor  	setAtmosAttenuation(temp1.rgb); @@ -201,7 +201,7 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {  	temp2.x += .25;  	//increase ambient when there are more clouds -	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; +	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;  	/*  decrease value and saturation (that in HSV, not HSL) for occluded areas  	 * // for HSV color/geometry used here, see http://gimp-savvy.com/BOOK/index.html?node52.html @@ -215,8 +215,8 @@ void calcAtmospherics(vec3 inPositionEye, float ambFactor) {  	//haze color  	setAdditiveColor( -		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient) -	  + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x +		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) +	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x  		  + tmpAmbient)));  	//brightness of surface both sunlight and ambient diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl index 6a83be1426..da3d922017 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsV.glsl @@ -47,12 +47,12 @@ uniform vec4 sunlight_color;  uniform vec4 ambient;  uniform vec4 blue_horizon;  uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 distance_multiplier; -uniform vec4 max_y; +uniform float haze_horizon; +uniform float haze_density; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float distance_multiplier; +uniform float max_y;  uniform vec4 glow;  void calcAtmospherics(vec3 inPositionEye) { @@ -61,8 +61,8 @@ void calcAtmospherics(vec3 inPositionEye) {  	setPositionEye(P);  	//(TERRAIN) limit altitude -	if (P.y > max_y.x) P *= (max_y.x / P.y); -	if (P.y < -max_y.x) P *= (-max_y.x / P.y); +	if (P.y > max_y) P *= (max_y / P.y); +	if (P.y < -max_y) P *= (-max_y / P.y);  	vec3 tmpLightnorm = lightnorm.xyz; @@ -78,13 +78,13 @@ void calcAtmospherics(vec3 inPositionEye) {  	//sunlight attenuation effect (hue and brightness) due to atmosphere  	//this is used later for sunlight modulation at various altitudes -	light_atten = (blue_density * 1.0 + vec4(haze_density.r) * 0.25) * (density_multiplier.x * max_y.x); +	light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);  		//I had thought blue_density and haze_density should have equal weighting,  		//but attenuation due to haze_density tends to seem too strong -	temp1 = blue_density + vec4(haze_density.r); +	temp1 = blue_density + vec4(haze_density);  	blue_weight = blue_density / temp1; -	haze_weight = vec4(haze_density.r) / temp1; +	haze_weight = vec4(haze_density) / temp1;  	//(TERRAIN) compute sunlight from lightnorm only (for short rays like terrain)  	temp2.y = max(0.0, tmpLightnorm.y); @@ -92,12 +92,12 @@ void calcAtmospherics(vec3 inPositionEye) {  	sunlight *= exp( - light_atten * temp2.y);  	// main atmospheric scattering line integral -	temp2.z = Plen * density_multiplier.x; +	temp2.z = Plen * density_multiplier;  	// Transparency (-> temp1) -	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier.x in a variable because the ati +	// ATI Bugfix -- can't store temp1*temp2.z*distance_multiplier in a variable because the ati  	// compiler gets confused. -	temp1 = exp(-temp1 * temp2.z * distance_multiplier.x); +	temp1 = exp(-temp1 * temp2.z * distance_multiplier);  	//final atmosphere attenuation factor  	setAtmosAttenuation(temp1.rgb); @@ -122,12 +122,12 @@ void calcAtmospherics(vec3 inPositionEye) {  	//increase ambient when there are more clouds -	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow.x * 0.5; +	vec4 tmpAmbient = ambient + (vec4(1.) - ambient) * cloud_shadow * 0.5;  	//haze color  	setAdditiveColor( -		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow.x) + tmpAmbient) -	  + (haze_horizon.r * haze_weight) * (sunlight*(1.-cloud_shadow.x) * temp2.x +		vec3(blue_horizon * blue_weight * (sunlight*(1.-cloud_shadow) + tmpAmbient) +	  + (haze_horizon * haze_weight) * (sunlight*(1.-cloud_shadow) * temp2.x  		  + tmpAmbient)));  	//brightness of surface both sunlight and ambient diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl index c5bb52169c..c1dd45cd67 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl @@ -49,18 +49,18 @@ uniform vec4 sunlight_color;  uniform vec4 ambient;  uniform vec4 blue_horizon;  uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; +uniform float haze_horizon; +uniform float haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 max_y; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float max_y;  uniform vec4 glow;  uniform vec4 cloud_color; -uniform vec4 cloud_scale; +uniform float cloud_scale;  void main()  { @@ -76,7 +76,7 @@ void main()  	// Set altitude  	if (P.y > 0.)  	{ -		P *= (max_y.x / P.y); +		P *= (max_y / P.y);  	}  	else  	{ @@ -98,12 +98,12 @@ void main()  	// Sunlight attenuation effect (hue and brightness) due to atmosphere  	// this is used later for sunlight modulation at various altitudes -	light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x); +	light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);  	// Calculate relative weights -	temp1 = blue_density + haze_density.x; +	temp1 = blue_density + haze_density;  	blue_weight = blue_density / temp1; -	haze_weight = haze_density.x / temp1; +	haze_weight = haze_density / temp1;  	// Compute sunlight from P & lightnorm (for long rays like sky)  	temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); @@ -111,7 +111,7 @@ void main()  	sunlight *= exp( - light_atten * temp2.y);  	// Distance -	temp2.z = Plen * density_multiplier.x; +	temp2.z = Plen * density_multiplier;  	// Transparency (-> temp1)  	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati @@ -135,14 +135,14 @@ void main()  	// Increase ambient when there are more clouds  	vec4 tmpAmbient = ambient; -	tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;  +	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;   	// Dim sunlight by cloud shadow percentage -	sunlight *= (1. - cloud_shadow.x); +	sunlight *= (1. - cloud_shadow);  	// Haze color below cloud  	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient) -				+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient) +				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)  			 );	  	// CLOUDS @@ -163,13 +163,13 @@ void main()  	vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - temp1);  	// Make a nice cloud density based on the cloud_shadow value that was passed in. -	vary_CloudDensity = 2. * (cloud_shadow.x - 0.25); +	vary_CloudDensity = 2. * (cloud_shadow - 0.25);  	// Texture coords  	vary_texcoord0 = texcoord0;  	vary_texcoord0.xy -= 0.5; -	vary_texcoord0.xy /= cloud_scale.x; +	vary_texcoord0.xy /= cloud_scale;  	vary_texcoord0.xy += 0.5;  	vary_texcoord1 = vary_texcoord0; diff --git a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl index 46773cf89f..3788ddaf2d 100644 --- a/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl +++ b/indra/newview/app_settings/shaders/class2/windlight/skyV.glsl @@ -42,19 +42,17 @@ uniform vec4 sunlight_color;  uniform vec4 ambient;  uniform vec4 blue_horizon;  uniform vec4 blue_density; -uniform vec4 haze_horizon; -uniform vec4 haze_density; +uniform float haze_horizon; +uniform float haze_density; -uniform vec4 cloud_shadow; -uniform vec4 density_multiplier; -uniform vec4 max_y; +uniform float cloud_shadow; +uniform float density_multiplier; +uniform float max_y;  uniform vec4 glow;  uniform vec4 cloud_color; -uniform vec4 cloud_scale; -  void main()  { @@ -68,7 +66,7 @@ void main()  	// Set altitude  	if (P.y > 0.)  	{ -		P *= (max_y.x / P.y); +		P *= (max_y / P.y);  	}  	else  	{ @@ -87,15 +85,14 @@ void main()  	vec4 sunlight = sunlight_color;  	vec4 light_atten; -  	// Sunlight attenuation effect (hue and brightness) due to atmosphere  	// this is used later for sunlight modulation at various altitudes -	light_atten = (blue_density * 1.0 + haze_density.x * 0.25) * (density_multiplier.x * max_y.x); +	light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);  	// Calculate relative weights -	temp1 = blue_density + haze_density.x; +	temp1 = blue_density + haze_density;  	blue_weight = blue_density / temp1; -	haze_weight = haze_density.x / temp1; +	haze_weight = haze_density / temp1;  	// Compute sunlight from P & lightnorm (for long rays like sky)  	temp2.y = max(0., max(0., Pn.y) * 1.0 + lightnorm.y ); @@ -103,7 +100,7 @@ void main()  	sunlight *= exp( - light_atten * temp2.y);  	// Distance -	temp2.z = Plen * density_multiplier.x; +	temp2.z = Plen * density_multiplier;  	// Transparency (-> temp1)  	// ATI Bugfix -- can't store temp1*temp2.z in a variable because the ati @@ -128,20 +125,20 @@ void main()  	// Haze color above cloud  	vary_HazeColor = (	  blue_horizon * blue_weight * (sunlight + ambient) -				+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + ambient) +				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + ambient)  			 );	  	// Increase ambient when there are more clouds  	vec4 tmpAmbient = ambient; -	tmpAmbient += (1. - tmpAmbient) * cloud_shadow.x * 0.5;  +	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;   	// Dim sunlight by cloud shadow percentage -	sunlight *= (1. - cloud_shadow.x); +	sunlight *= (1. - cloud_shadow);  	// Haze color below cloud  	vec4 additiveColorBelowCloud = (	  blue_horizon * blue_weight * (sunlight + tmpAmbient) -				+ (haze_horizon.r * haze_weight) * (sunlight * temp2.x + tmpAmbient) +				+ (haze_horizon * haze_weight) * (sunlight * temp2.x + tmpAmbient)  			 );	  	// Final atmosphere additive diff --git a/indra/newview/featuretable.txt b/indra/newview/featuretable.txt index 0f33d40ac3..76bb2b0976 100644 --- a/indra/newview/featuretable.txt +++ b/indra/newview/featuretable.txt @@ -42,7 +42,6 @@ RenderGamma					1	0  RenderGlowResolutionPow		1	9  RenderGround				1	1  RenderMaxPartCount			1	8192 -RenderNightBrightness		1	1.0  RenderObjectBump			1	1  RenderLocalLights			1	1  RenderReflectionDetail		1	4 diff --git a/indra/newview/featuretable_linux.txt b/indra/newview/featuretable_linux.txt index 8142311a55..5e217e000a 100644 --- a/indra/newview/featuretable_linux.txt +++ b/indra/newview/featuretable_linux.txt @@ -43,7 +43,6 @@ RenderGlowResolutionPow		1	9  RenderGround				1	1  RenderLocalLights			1	1  RenderMaxPartCount			1	8192 -RenderNightBrightness		1	1.0  RenderObjectBump			1	1  RenderReflectionDetail		1	4  RenderTerrainDetail			1	1 diff --git a/indra/newview/featuretable_mac.txt b/indra/newview/featuretable_mac.txt index 942c043081..915a012a39 100644 --- a/indra/newview/featuretable_mac.txt +++ b/indra/newview/featuretable_mac.txt @@ -43,7 +43,6 @@ RenderGlowResolutionPow			1	9  RenderGround					1	1  RenderLocalLights				1	1  RenderMaxPartCount				1	8192 -RenderNightBrightness			1	1.0  RenderObjectBump				1	1  RenderReflectionDetail			1	4  RenderTerrainDetail				1	1 diff --git a/indra/newview/featuretable_xp.txt b/indra/newview/featuretable_xp.txt index 278d601860..ae2cf910f2 100644 --- a/indra/newview/featuretable_xp.txt +++ b/indra/newview/featuretable_xp.txt @@ -43,7 +43,6 @@ RenderGlowResolutionPow		1	9  RenderGround				1	1  RenderLocalLights			1	1  RenderMaxPartCount			1	8192 -RenderNightBrightness		1	1.0  RenderObjectBump			1	1  RenderReflectionDetail		1	4  RenderTerrainDetail			1	1 diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 9fb66fe630..8fd6c2605f 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -170,11 +170,7 @@ bool LLAgent::isActionAllowed(const LLSD& sdname)  	const std::string& param = sdname.asString(); -	if (param == "build") -	{ -		retval = gAgent.canEditParcel(); -	} -	else if (param == "speak") +	if (param == "speak")  	{  		if ( gAgent.isVoiceConnected() &&   			LLViewerParcelMgr::getInstance()->allowAgentVoice() && diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index 09305a5b4d..dd02a74a38 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -817,7 +817,10 @@ void LLAgentWearables::popWearable(const LLWearableType::EType type, U32 index)  	if (wearable)  	{  		mWearableDatas[type].erase(mWearableDatas[type].begin() + index); +		if (isAgentAvatarValid()) +		{  		gAgentAvatarp->wearableUpdated(wearable->getType(), TRUE); +		}  		wearable->setLabelUpdated();  	}  } diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 647ace7ee3..6931b55c4c 100644 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -30,7 +30,8 @@  #include "llmemtype.h" -#include "llwindowwin32.cpp" // *FIX: for setting gIconResource. +#include "llwindowwin32.h" // *FIX: for setting gIconResource. +#include "llgl.h"  #include "res/resource.h" // *FIX: for setting gIconResource.  #include <fcntl.h>		//_O_APPEND diff --git a/indra/newview/llcallfloater.cpp b/indra/newview/llcallfloater.cpp index e3217668c5..f2375bfa4f 100644 --- a/indra/newview/llcallfloater.cpp +++ b/indra/newview/llcallfloater.cpp @@ -188,7 +188,7 @@ void LLCallFloater::draw()  	// Need to resort the participant list if it's in sort by recent speaker order.  	if (mParticipants) -		mParticipants->updateRecentSpeakersOrder(); +		mParticipants->update();  	LLFloater::draw();  } @@ -333,6 +333,7 @@ void LLCallFloater::refreshParticipantList()  	if (!non_avatar_caller)  	{ +		llassert(mParticipants == NULL); // check for possible memory leak  		mParticipants = new LLParticipantList(mSpeakerManager, mAvatarList, true, mVoiceType != VC_GROUP_CHAT && mVoiceType != VC_AD_HOC_CHAT, false);  		mParticipants->setValidateSpeakerCallback(boost::bind(&LLCallFloater::validateSpeaker, this, _1));  		const U32 speaker_sort_order = gSavedSettings.getU32("SpeakerParticipantDefaultOrder"); diff --git a/indra/newview/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp index 2abfbf37ca..935dcb74b0 100644 --- a/indra/newview/llexpandabletextbox.cpp +++ b/indra/newview/llexpandabletextbox.cpp @@ -55,7 +55,7 @@ public:  		else  		{  			width = mEditor.getDocumentView()->getRect().getWidth() - mEditor.getHPad();  -			height = llceil(mStyle->getFont()->getLineHeight()); +			height = mStyle->getFont()->getLineHeight();  		}  		return true;  	} diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 233038daba..9664aa7dbe 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -149,7 +149,7 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)  LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y)  { -	S32 idx = (getRect().getHeight() - y) / ((S32) LLFontGL::getFontMonospace()->getLineHeight()+2) - 5; +	S32 idx = (getRect().getHeight() - y) / (LLFontGL::getFontMonospace()->getLineHeight()+2) - 5;  	if (idx >= 0 && idx < (S32)ft_display_idx.size())  	{ @@ -552,7 +552,7 @@ void LLFastTimerView::draw()  	// update rectangle that includes timer bars  	mBarRect.mLeft = xleft;  	mBarRect.mRight = getRect().getWidth(); -	mBarRect.mTop = ytop - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4); +	mBarRect.mTop = ytop - (LLFontGL::getFontMonospace()->getLineHeight() + 4);  	mBarRect.mBottom = margin + LINE_GRAPH_HEIGHT;  	y = ytop; @@ -846,7 +846,7 @@ void LLFastTimerView::draw()  				tdesc = llformat("%4.2f ms", ms);  			x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(tdesc)-5; -			y = mGraphRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight()); +			y = mGraphRect.mTop - LLFontGL::getFontMonospace()->getLineHeight();  			LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white,  										 LLFontGL::LEFT, LLFontGL::TOP); diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp index 8024755e86..8986a694f9 100644 --- a/indra/newview/llfilepicker.cpp +++ b/indra/newview/llfilepicker.cpp @@ -49,7 +49,7 @@ LLFilePicker LLFilePicker::sInstance;  #if LL_WINDOWS  #define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0"  #define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0" -#define ANIM_FILTER L"Animations (*.bvh)\0*.bvh\0" +#define ANIM_FILTER L"Animations (*.bvh; *.anim)\0*.bvh;*.anim\0"  #define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0"  #ifdef _CORY_TESTING  #define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0" @@ -593,8 +593,10 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB  						}  						else if (filter == FFLOAD_ANIM)  						{ -							if (fileInfo.filetype != 'BVH ' &&  -								(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) +							if (fileInfo.filetype != 'BVH ' && +								fileInfo.filetype != 'ANIM' && +								(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("bvh"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) && +								fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("anim"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))  							)  							{  								result = false; @@ -1073,8 +1075,11 @@ void LLFilePicker::chooser_responder(GtkWidget *widget, gint response, gpointer  	}  	// set the default path for this usage context. -	picker->mContextToPathMap[picker->mCurContextName] = -		gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget)); +	const char* cur_folder = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(widget)); +	if (cur_folder != NULL) +	{ +		picker->mContextToPathMap[picker->mCurContextName] = cur_folder; +	}  	gtk_widget_destroy(widget);  	gtk_main_quit(); @@ -1196,10 +1201,14 @@ static std::string add_wav_filter_to_gtkchooser(GtkWindow *picker)  						    LLTrans::getString("sound_files") + " (*.wav)");  } -static std::string add_bvh_filter_to_gtkchooser(GtkWindow *picker) +static std::string add_anim_filter_to_gtkchooser(GtkWindow *picker)  { -	return add_simple_pattern_filter_to_gtkchooser(picker,  "*.bvh", -						       LLTrans::getString("animation_files") + " (*.bvh)"); +	GtkFileFilter *gfilter = gtk_file_filter_new(); +	gtk_file_filter_add_pattern(gfilter, "*.bvh"); +	gtk_file_filter_add_pattern(gfilter, "*.anim"); +	std::string filtername = LLTrans::getString("animation_files") + " (*.bvh; *.anim)"; +	add_common_filters_to_gtkchooser(gfilter, picker, filtername); +	return filtername;  }  static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker) @@ -1351,7 +1360,7 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter, bool blocking )  			filtername = add_wav_filter_to_gtkchooser(picker);  			break;  		case FFLOAD_ANIM: -			filtername = add_bvh_filter_to_gtkchooser(picker); +			filtername = add_anim_filter_to_gtkchooser(picker);  			break;  		case FFLOAD_COLLADA:  			filtername = add_collada_filter_to_gtkchooser(picker); diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index aa66fcf9b8..0290e7cdf0 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -63,6 +63,11 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(select_callback_t callback,  	// *TODO: Use a key to allow this not to be an effective singleton  	LLFloaterAvatarPicker* floater =   		LLFloaterReg::showTypedInstance<LLFloaterAvatarPicker>("avatar_picker"); +	if (!floater) +	{ +		llwarns << "Cannot instantiate avatar picker" << llendl; +		return NULL; +	}  	floater->mSelectionCallback = callback;  	floater->setAllowMultiple(allow_multiple); diff --git a/indra/newview/llfloaterbuildoptions.cpp b/indra/newview/llfloaterbuildoptions.cpp index 86c1bf0534..1b65d8d683 100644 --- a/indra/newview/llfloaterbuildoptions.cpp +++ b/indra/newview/llfloaterbuildoptions.cpp @@ -41,13 +41,9 @@  // Methods  // -void commit_grid_mode(LLUICtrl *); -  LLFloaterBuildOptions::LLFloaterBuildOptions(const LLSD& key) -  : LLFloater(key), -    mComboGridMode(NULL) +  : LLFloater(key)  { -	mCommitCallbackRegistrar.add("GridOptions.gridMode", boost::bind(&commit_grid_mode,_1));  }  LLFloaterBuildOptions::~LLFloaterBuildOptions() @@ -55,45 +51,9 @@ LLFloaterBuildOptions::~LLFloaterBuildOptions()  BOOL LLFloaterBuildOptions::postBuild()  { -	mComboGridMode = getChild<LLComboBox>("combobox grid mode"); -  	return TRUE;  } -void LLFloaterBuildOptions::setGridMode(EGridMode mode) -{ -	mComboGridMode->setCurrentByIndex((S32)mode); -} - -void LLFloaterBuildOptions::updateGridMode() -{ -	if (mComboGridMode) -	{ -		S32 index = mComboGridMode->getCurrentIndex(); -		mComboGridMode->removeall(); - -		switch (mObjectSelection->getSelectType()) -		{ -		case SELECT_TYPE_HUD: -		  mComboGridMode->add(getString("grid_screen_text")); -		  mComboGridMode->add(getString("grid_local_text")); -		  break; -		case SELECT_TYPE_WORLD: -		  mComboGridMode->add(getString("grid_world_text")); -		  mComboGridMode->add(getString("grid_local_text")); -		  mComboGridMode->add(getString("grid_reference_text")); -		  break; -		case SELECT_TYPE_ATTACHMENT: -		  mComboGridMode->add(getString("grid_attachment_text")); -		  mComboGridMode->add(getString("grid_local_text")); -		  mComboGridMode->add(getString("grid_reference_text")); -		  break; -		} - -		mComboGridMode->setCurrentByIndex(index); -	} -} -  // virtual  void LLFloaterBuildOptions::onOpen(const LLSD& key)  { @@ -105,10 +65,3 @@ void LLFloaterBuildOptions::onClose(bool app_quitting)  {  	mObjectSelection = NULL;  } - -void commit_grid_mode(LLUICtrl *ctrl) -{ -	LLComboBox* combo = (LLComboBox*)ctrl; - -	LLSelectMgr::getInstance()->setGridMode((EGridMode)combo->getCurrentIndex()); -} diff --git a/indra/newview/llfloaterbuildoptions.h b/indra/newview/llfloaterbuildoptions.h index 7f3811bf1c..02c56cb6a9 100644 --- a/indra/newview/llfloaterbuildoptions.h +++ b/indra/newview/llfloaterbuildoptions.h @@ -35,7 +35,6 @@  #include "llfloater.h"  #include "llselectmgr.h" -class LLComboBox;  class LLObjectSelection;  typedef LLSafeHandle<LLObjectSelection> LLObjectSelectionHandle; @@ -44,23 +43,17 @@ class LLFloaterBuildOptions  	:	public LLFloater  {  public: -  	virtual BOOL postBuild();  	/*virtual*/ void onOpen(const LLSD& key);  	/*virtual*/	void onClose(bool app_quitting); -	void setGridMode(EGridMode mode); -	void updateGridMode(); -  private: -  	friend class LLFloaterReg;  	LLFloaterBuildOptions(const LLSD& key);  	~LLFloaterBuildOptions(); -	LLComboBox*	mComboGridMode;  	LLObjectSelectionHandle	mObjectSelection;  };  #endif diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp index ee8487b160..087b0007e1 100644 --- a/indra/newview/llfloaterbuy.cpp +++ b/indra/newview/llfloaterbuy.cpp @@ -239,8 +239,9 @@ void LLFloaterBuy::inventoryChanged(LLViewerObject* obj,  		// Compute icon for this item  		BOOL item_is_multi = FALSE; -		if ( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED  +		if (( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED  			|| inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS) +			&& !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK))  		{  			item_is_multi = TRUE;  		} diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloaterbvhpreview.cpp index 2a3512e21a..b050a638dc 100644 --- a/indra/newview/llfloateranimpreview.cpp +++ b/indra/newview/llfloaterbvhpreview.cpp @@ -1,6 +1,6 @@  /**  - * @file llfloateranimpreview.cpp - * @brief LLFloaterAnimPreview class implementation + * @file llfloaterbvhpreview.cpp + * @brief LLFloaterBvhPreview class implementation   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code @@ -26,7 +26,7 @@  #include "llviewerprecompiledheaders.h" -#include "llfloateranimpreview.h" +#include "llfloaterbvhpreview.h"  #include "llbvhloader.h"  #include "lldatapacker.h" @@ -115,9 +115,9 @@ std::string STATUS[] =  };  //----------------------------------------------------------------------------- -// LLFloaterAnimPreview() +// LLFloaterBvhPreview()  //----------------------------------------------------------------------------- -LLFloaterAnimPreview::LLFloaterAnimPreview(const std::string& filename) :  +LLFloaterBvhPreview::LLFloaterBvhPreview(const std::string& filename) :   	LLFloaterNameDesc(filename)  {  	mLastMouseX = 0; @@ -153,35 +153,35 @@ LLFloaterAnimPreview::LLFloaterAnimPreview(const std::string& filename) :  //-----------------------------------------------------------------------------  // setAnimCallbacks()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::setAnimCallbacks() +void LLFloaterBvhPreview::setAnimCallbacks()  { -	getChild<LLUICtrl>("playback_slider")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onSliderMove, this)); +	getChild<LLUICtrl>("playback_slider")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onSliderMove, this)); -	getChild<LLUICtrl>("preview_base_anim")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitBaseAnim, this)); +	getChild<LLUICtrl>("preview_base_anim")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitBaseAnim, this));  	getChild<LLUICtrl>("preview_base_anim")->setValue("Standing"); -	getChild<LLUICtrl>("priority")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitPriority, this)); -	getChild<LLUICtrl>("loop_check")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitLoop, this)); -	getChild<LLUICtrl>("loop_in_point")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitLoopIn, this)); -	getChild<LLUICtrl>("loop_in_point")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateLoopIn, this, _1)); -	getChild<LLUICtrl>("loop_out_point")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitLoopOut, this)); -	getChild<LLUICtrl>("loop_out_point")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateLoopOut, this, _1)); +	getChild<LLUICtrl>("priority")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitPriority, this)); +	getChild<LLUICtrl>("loop_check")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitLoop, this)); +	getChild<LLUICtrl>("loop_in_point")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitLoopIn, this)); +	getChild<LLUICtrl>("loop_in_point")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateLoopIn, this, _1)); +	getChild<LLUICtrl>("loop_out_point")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitLoopOut, this)); +	getChild<LLUICtrl>("loop_out_point")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateLoopOut, this, _1)); -	getChild<LLUICtrl>("hand_pose_combo")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitHandPose, this)); +	getChild<LLUICtrl>("hand_pose_combo")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitHandPose, this)); -	getChild<LLUICtrl>("emote_combo")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitEmote, this)); +	getChild<LLUICtrl>("emote_combo")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitEmote, this));  	getChild<LLUICtrl>("emote_combo")->setValue("[None]"); -	getChild<LLUICtrl>("ease_in_time")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitEaseIn, this)); -	getChild<LLUICtrl>("ease_in_time")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateEaseIn, this, _1)); -	getChild<LLUICtrl>("ease_out_time")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitEaseOut, this)); -	getChild<LLUICtrl>("ease_out_time")->setValidateBeforeCommit( boost::bind(&LLFloaterAnimPreview::validateEaseOut, this, _1)); +	getChild<LLUICtrl>("ease_in_time")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitEaseIn, this)); +	getChild<LLUICtrl>("ease_in_time")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateEaseIn, this, _1)); +	getChild<LLUICtrl>("ease_out_time")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitEaseOut, this)); +	getChild<LLUICtrl>("ease_out_time")->setValidateBeforeCommit( boost::bind(&LLFloaterBvhPreview::validateEaseOut, this, _1));  }  //-----------------------------------------------------------------------------  // postBuild()  //----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::postBuild() +BOOL LLFloaterBvhPreview::postBuild()  {  	LLKeyframeMotion* motionp = NULL;  	LLBVHLoader* loaderp = NULL; @@ -191,7 +191,7 @@ BOOL LLFloaterAnimPreview::postBuild()  		return FALSE;  	} -	getChild<LLUICtrl>("name_form")->setCommitCallback(boost::bind(&LLFloaterAnimPreview::onCommitName, this)); +	getChild<LLUICtrl>("name_form")->setCommitCallback(boost::bind(&LLFloaterBvhPreview::onCommitName, this));  	childSetAction("ok_btn", onBtnOK, this);  	setDefaultBtn(); @@ -203,15 +203,15 @@ BOOL LLFloaterAnimPreview::postBuild()  	mPreviewImageRect.set(0.f, 1.f, 1.f, 0.f);  	mPlayButton = getChild<LLButton>( "play_btn"); -	mPlayButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnPlay, this)); +	mPlayButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnPlay, this));  	mPlayButton->setVisible(true);  	mPauseButton = getChild<LLButton>( "pause_btn"); -	mPauseButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnPause, this)); +	mPauseButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnPause, this));  	mPauseButton->setVisible(false);  	mStopButton = getChild<LLButton>( "stop_btn"); -	mStopButton->setClickedCallback(boost::bind(&LLFloaterAnimPreview::onBtnStop, this)); +	mStopButton->setClickedCallback(boost::bind(&LLFloaterBvhPreview::onBtnStop, this));  	getChildView("bad_animation_text")->setVisible(FALSE); @@ -363,9 +363,9 @@ BOOL LLFloaterAnimPreview::postBuild()  }  //----------------------------------------------------------------------------- -// LLFloaterAnimPreview() +// LLFloaterBvhPreview()  //----------------------------------------------------------------------------- -LLFloaterAnimPreview::~LLFloaterAnimPreview() +LLFloaterBvhPreview::~LLFloaterBvhPreview()  {  	mAnimPreview = NULL; @@ -375,7 +375,7 @@ LLFloaterAnimPreview::~LLFloaterAnimPreview()  //-----------------------------------------------------------------------------  // draw()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::draw() +void LLFloaterBvhPreview::draw()  {  	LLFloater::draw();  	LLRect r = getRect(); @@ -414,7 +414,7 @@ void LLFloaterAnimPreview::draw()  //-----------------------------------------------------------------------------  // resetMotion()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::resetMotion() +void LLFloaterBvhPreview::resetMotion()  {  	LLVOAvatar* avatarp = mAnimPreview->getDummyAvatar();  	BOOL paused = avatarp->areAnimationsPaused(); @@ -450,7 +450,7 @@ void LLFloaterAnimPreview::resetMotion()  //-----------------------------------------------------------------------------  // handleMouseDown()  //----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleMouseDown(S32 x, S32 y, MASK mask) +BOOL LLFloaterBvhPreview::handleMouseDown(S32 x, S32 y, MASK mask)  {  	if (mPreviewRect.pointInRect(x, y))  	{ @@ -468,7 +468,7 @@ BOOL LLFloaterAnimPreview::handleMouseDown(S32 x, S32 y, MASK mask)  //-----------------------------------------------------------------------------  // handleMouseUp()  //----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleMouseUp(S32 x, S32 y, MASK mask) +BOOL LLFloaterBvhPreview::handleMouseUp(S32 x, S32 y, MASK mask)  {  	gFocusMgr.setMouseCapture(FALSE);  	gViewerWindow->showCursor(); @@ -478,7 +478,7 @@ BOOL LLFloaterAnimPreview::handleMouseUp(S32 x, S32 y, MASK mask)  //-----------------------------------------------------------------------------  // handleHover()  //----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask) +BOOL LLFloaterBvhPreview::handleHover(S32 x, S32 y, MASK mask)  {  	MASK local_mask = mask & ~MASK_ALT; @@ -533,7 +533,7 @@ BOOL LLFloaterAnimPreview::handleHover(S32 x, S32 y, MASK mask)  //-----------------------------------------------------------------------------  // handleScrollWheel()  //----------------------------------------------------------------------------- -BOOL LLFloaterAnimPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) +BOOL LLFloaterBvhPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)  {  	mAnimPreview->zoom((F32)clicks * -0.2f);  	mAnimPreview->requestUpdate(); @@ -544,7 +544,7 @@ BOOL LLFloaterAnimPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)  //-----------------------------------------------------------------------------  // onMouseCaptureLost()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onMouseCaptureLost() +void LLFloaterBvhPreview::onMouseCaptureLost()  {  	gViewerWindow->showCursor();  } @@ -552,7 +552,7 @@ void LLFloaterAnimPreview::onMouseCaptureLost()  //-----------------------------------------------------------------------------  // onBtnPlay()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnPlay() +void LLFloaterBvhPreview::onBtnPlay()  {  	if (!getEnabled())  		return; @@ -576,7 +576,7 @@ void LLFloaterAnimPreview::onBtnPlay()  //-----------------------------------------------------------------------------  // onBtnPause()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnPause() +void LLFloaterBvhPreview::onBtnPause()  {  	if (!getEnabled())  		return; @@ -598,7 +598,7 @@ void LLFloaterAnimPreview::onBtnPause()  //-----------------------------------------------------------------------------  // onBtnStop()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnStop() +void LLFloaterBvhPreview::onBtnStop()  {  	if (!getEnabled())  		return; @@ -614,7 +614,7 @@ void LLFloaterAnimPreview::onBtnStop()  //-----------------------------------------------------------------------------  // onSliderMove()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onSliderMove() +void LLFloaterBvhPreview::onSliderMove()  {  	if (!getEnabled())  		return; @@ -639,7 +639,7 @@ void LLFloaterAnimPreview::onSliderMove()  //-----------------------------------------------------------------------------  // onCommitBaseAnim()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitBaseAnim() +void LLFloaterBvhPreview::onCommitBaseAnim()  {  	if (!getEnabled())  		return; @@ -668,7 +668,7 @@ void LLFloaterAnimPreview::onCommitBaseAnim()  //-----------------------------------------------------------------------------  // onCommitLoop()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitLoop() +void LLFloaterBvhPreview::onCommitLoop()  {  	if (!getEnabled())  		return; @@ -687,7 +687,7 @@ void LLFloaterAnimPreview::onCommitLoop()  //-----------------------------------------------------------------------------  // onCommitLoopIn()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitLoopIn() +void LLFloaterBvhPreview::onCommitLoopIn()  {  	if (!getEnabled())  		return; @@ -707,7 +707,7 @@ void LLFloaterAnimPreview::onCommitLoopIn()  //-----------------------------------------------------------------------------  // onCommitLoopOut()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitLoopOut() +void LLFloaterBvhPreview::onCommitLoopOut()  {  	if (!getEnabled())  		return; @@ -727,7 +727,7 @@ void LLFloaterAnimPreview::onCommitLoopOut()  //-----------------------------------------------------------------------------  // onCommitName()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitName() +void LLFloaterBvhPreview::onCommitName()  {  	if (!getEnabled())  		return; @@ -746,7 +746,7 @@ void LLFloaterAnimPreview::onCommitName()  //-----------------------------------------------------------------------------  // onCommitHandPose()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitHandPose() +void LLFloaterBvhPreview::onCommitHandPose()  {  	if (!getEnabled())  		return; @@ -757,7 +757,7 @@ void LLFloaterAnimPreview::onCommitHandPose()  //-----------------------------------------------------------------------------  // onCommitEmote()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitEmote() +void LLFloaterBvhPreview::onCommitEmote()  {  	if (!getEnabled())  		return; @@ -768,7 +768,7 @@ void LLFloaterAnimPreview::onCommitEmote()  //-----------------------------------------------------------------------------  // onCommitPriority()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitPriority() +void LLFloaterBvhPreview::onCommitPriority()  {  	if (!getEnabled())  		return; @@ -782,7 +782,7 @@ void LLFloaterAnimPreview::onCommitPriority()  //-----------------------------------------------------------------------------  // onCommitEaseIn()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitEaseIn() +void LLFloaterBvhPreview::onCommitEaseIn()  {  	if (!getEnabled())  		return; @@ -797,7 +797,7 @@ void LLFloaterAnimPreview::onCommitEaseIn()  //-----------------------------------------------------------------------------  // onCommitEaseOut()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onCommitEaseOut() +void LLFloaterBvhPreview::onCommitEaseOut()  {  	if (!getEnabled())  		return; @@ -812,7 +812,7 @@ void LLFloaterAnimPreview::onCommitEaseOut()  //-----------------------------------------------------------------------------  // validateEaseIn()  //----------------------------------------------------------------------------- -bool LLFloaterAnimPreview::validateEaseIn(const LLSD& data) +bool LLFloaterBvhPreview::validateEaseIn(const LLSD& data)  {  	if (!getEnabled())  		return false; @@ -832,7 +832,7 @@ bool LLFloaterAnimPreview::validateEaseIn(const LLSD& data)  //-----------------------------------------------------------------------------  // validateEaseOut()  //----------------------------------------------------------------------------- -bool LLFloaterAnimPreview::validateEaseOut(const LLSD& data) +bool LLFloaterBvhPreview::validateEaseOut(const LLSD& data)  {  	if (!getEnabled())  		return false; @@ -852,7 +852,7 @@ bool LLFloaterAnimPreview::validateEaseOut(const LLSD& data)  //-----------------------------------------------------------------------------  // validateLoopIn()  //----------------------------------------------------------------------------- -bool LLFloaterAnimPreview::validateLoopIn(const LLSD& data) +bool LLFloaterBvhPreview::validateLoopIn(const LLSD& data)  {  	if (!getEnabled())  		return false; @@ -880,7 +880,7 @@ bool LLFloaterAnimPreview::validateLoopIn(const LLSD& data)  //-----------------------------------------------------------------------------  // validateLoopOut()  //----------------------------------------------------------------------------- -bool LLFloaterAnimPreview::validateLoopOut(const LLSD& data) +bool LLFloaterBvhPreview::validateLoopOut(const LLSD& data)  {  	if (!getEnabled())  		return false; @@ -909,7 +909,7 @@ bool LLFloaterAnimPreview::validateLoopOut(const LLSD& data)  //-----------------------------------------------------------------------------  // refresh()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::refresh() +void LLFloaterBvhPreview::refresh()  {  	// Are we showing the play button (default) or the pause button?  	bool show_play = true; @@ -958,9 +958,9 @@ void LLFloaterAnimPreview::refresh()  //-----------------------------------------------------------------------------  // onBtnOK()  //----------------------------------------------------------------------------- -void LLFloaterAnimPreview::onBtnOK(void* userdata) +void LLFloaterBvhPreview::onBtnOK(void* userdata)  { -	LLFloaterAnimPreview* floaterp = (LLFloaterAnimPreview*)userdata; +	LLFloaterBvhPreview* floaterp = (LLFloaterBvhPreview*)userdata;  	if (!floaterp->getEnabled()) return;  	if (floaterp->mAnimPreview) diff --git a/indra/newview/llfloateranimpreview.h b/indra/newview/llfloaterbvhpreview.h index f1ffb6547f..b81cc6e3a5 100644 --- a/indra/newview/llfloateranimpreview.h +++ b/indra/newview/llfloaterbvhpreview.h @@ -1,6 +1,6 @@  /**  - * @file llfloateranimpreview.h - * @brief LLFloaterAnimPreview class definition + * @file llfloaterbvhpreview.h + * @brief LLFloaterBvhPreview class definition   *   * $LicenseInfo:firstyear=2004&license=viewerlgpl$   * Second Life Viewer Source Code @@ -24,14 +24,15 @@   * $/LicenseInfo$   */ -#ifndef LL_LLFLOATERANIMPREVIEW_H -#define LL_LLFLOATERANIMPREVIEW_H +#ifndef LL_LLFLOATERBVHPREVIEW_H +#define LL_LLFLOATERBVHPREVIEW_H  #include "llassettype.h"  #include "llfloaternamedesc.h"  #include "lldynamictexture.h"  #include "llcharacter.h"  #include "llquaternion.h" +#include "llextendedstatus.h"  class LLVOAvatar;  class LLViewerJointMesh; @@ -67,11 +68,11 @@ protected:  	LLPointer<LLVOAvatar>			mDummyAvatar;  }; -class LLFloaterAnimPreview : public LLFloaterNameDesc +class LLFloaterBvhPreview : public LLFloaterNameDesc  {  public: -	LLFloaterAnimPreview(const std::string& filename); -	virtual ~LLFloaterAnimPreview(); +	LLFloaterBvhPreview(const std::string& filename); +	virtual ~LLFloaterBvhPreview();  	BOOL postBuild(); @@ -128,4 +129,4 @@ protected:  	std::map<std::string, LLUUID>	mIDList;  }; -#endif  // LL_LLFLOATERANIMPREVIEW_H +#endif  // LL_LLFLOATERBVHPREVIEW_H diff --git a/indra/newview/llfloatereditsky.cpp b/indra/newview/llfloatereditsky.cpp index abee7b5dc9..352361ce9e 100644 --- a/indra/newview/llfloatereditsky.cpp +++ b/indra/newview/llfloatereditsky.cpp @@ -151,8 +151,8 @@ void LLFloaterEditSky::initCallbacks(void)  	getChild<LLUICtrl>("WLBlueHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlMoved, this, _1, ¶m_mgr.mBlueHorizon));  	// haze density, horizon, mult, and altitude -	getChild<LLUICtrl>("WLHazeDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, ¶m_mgr.mHazeDensity)); -	getChild<LLUICtrl>("WLHazeHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onColorControlRMoved, this, _1, ¶m_mgr.mHazeHorizon)); +	getChild<LLUICtrl>("WLHazeDensity")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, ¶m_mgr.mHazeDensity)); +	getChild<LLUICtrl>("WLHazeHorizon")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, ¶m_mgr.mHazeHorizon));  	getChild<LLUICtrl>("WLDensityMult")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, ¶m_mgr.mDensityMult));  	getChild<LLUICtrl>("WLMaxAltitude")->setCommitCallback(boost::bind(&LLFloaterEditSky::onFloatControlMoved, this, _1, ¶m_mgr.mMaxAlt)); @@ -220,15 +220,14 @@ void LLFloaterEditSky::syncControls()  	setColorSwatch("WLBlueHorizon", param_mgr->mBlueHorizon, WL_BLUE_HORIZON_DENSITY_SCALE);  	// haze density, horizon, mult, and altitude -	param_mgr->mHazeDensity = cur_params.getVector(param_mgr->mHazeDensity.mName, err); -	childSetValue("WLHazeDensity", param_mgr->mHazeDensity.r); -	param_mgr->mHazeHorizon = cur_params.getVector(param_mgr->mHazeHorizon.mName, err); -	childSetValue("WLHazeHorizon", param_mgr->mHazeHorizon.r); -	param_mgr->mDensityMult = cur_params.getVector(param_mgr->mDensityMult.mName, err); -	childSetValue("WLDensityMult", param_mgr->mDensityMult.x * -		param_mgr->mDensityMult.mult); -	param_mgr->mMaxAlt = cur_params.getVector(param_mgr->mMaxAlt.mName, err); -	childSetValue("WLMaxAltitude", param_mgr->mMaxAlt.x); +	param_mgr->mHazeDensity = cur_params.getFloat(param_mgr->mHazeDensity.mName, err); +	childSetValue("WLHazeDensity", (F32) param_mgr->mHazeDensity); +	param_mgr->mHazeHorizon = cur_params.getFloat(param_mgr->mHazeHorizon.mName, err); +	childSetValue("WLHazeHorizon", (F32) param_mgr->mHazeHorizon); +	param_mgr->mDensityMult = cur_params.getFloat(param_mgr->mDensityMult.mName, err); +	childSetValue("WLDensityMult", ((F32) param_mgr->mDensityMult) * param_mgr->mDensityMult.mult); +	param_mgr->mMaxAlt = cur_params.getFloat(param_mgr->mMaxAlt.mName, err); +	childSetValue("WLMaxAltitude", (F32) param_mgr->mMaxAlt);  	// blue density  	param_mgr->mBlueDensity = cur_params.getVector(param_mgr->mBlueDensity.mName, err); @@ -273,10 +272,10 @@ void LLFloaterEditSky::syncControls()  	childSetValue("WLCloudDetailDensity", param_mgr->mCloudDetail.b);  	// Cloud extras -	param_mgr->mCloudCoverage = cur_params.getVector(param_mgr->mCloudCoverage.mName, err); -	param_mgr->mCloudScale = cur_params.getVector(param_mgr->mCloudScale.mName, err); -	childSetValue("WLCloudCoverage", param_mgr->mCloudCoverage.x); -	childSetValue("WLCloudScale", param_mgr->mCloudScale.x); +	param_mgr->mCloudCoverage = cur_params.getFloat(param_mgr->mCloudCoverage.mName, err); +	param_mgr->mCloudScale = cur_params.getFloat(param_mgr->mCloudScale.mName, err); +	childSetValue("WLCloudCoverage", (F32) param_mgr->mCloudCoverage); +	childSetValue("WLCloudScale", (F32) param_mgr->mCloudScale);  	// cloud scrolling  	bool lockX = !param_mgr->mCurParams.getEnableCloudScrollX(); @@ -306,13 +305,13 @@ void LLFloaterEditSky::syncControls()  	childSetValue("WLCloudScrollX", param_mgr->mCurParams.getCloudScrollX() - 10.0f);  	childSetValue("WLCloudScrollY", param_mgr->mCurParams.getCloudScrollY() - 10.0f); -	param_mgr->mDistanceMult = cur_params.getVector(param_mgr->mDistanceMult.mName, err); -	childSetValue("WLDistanceMult", param_mgr->mDistanceMult.x); +	param_mgr->mDistanceMult = cur_params.getFloat(param_mgr->mDistanceMult.mName, err); +	childSetValue("WLDistanceMult", (F32) param_mgr->mDistanceMult);  	// Tweak extras -	param_mgr->mWLGamma = cur_params.getVector(param_mgr->mWLGamma.mName, err); -	childSetValue("WLGamma", param_mgr->mWLGamma.x); +	param_mgr->mWLGamma = cur_params.getFloat(param_mgr->mWLGamma.mName, err); +	childSetValue("WLGamma", (F32) param_mgr->mWLGamma);  	childSetValue("WLStarAlpha", param_mgr->mCurParams.getStarBrightness());  } diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp index 895e16adef..4f2a6ec1b7 100644 --- a/indra/newview/llfloatermediasettings.cpp +++ b/indra/newview/llfloatermediasettings.cpp @@ -312,3 +312,9 @@ bool LLFloaterMediaSettings::haveValuesChanged() const  	return values_changed;  } +bool LLFloaterMediaSettings::instanceExists() +{ +	return LLFloaterReg::findTypedInstance<LLFloaterMediaSettings>("media_settings"); +} + + diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h index ecc55d2cbc..1d25530986 100644 --- a/indra/newview/llfloatermediasettings.h +++ b/indra/newview/llfloatermediasettings.h @@ -45,6 +45,7 @@ public:  	/*virtual*/ void onClose(bool app_quitting);  	static LLFloaterMediaSettings* getInstance(); +	static bool instanceExists();  	static void apply();  	static void initValues( const LLSD& media_settings , bool editable);  	static void clearValues( bool editable); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 9122e5a8f5..7448f2bb2a 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -4525,7 +4525,17 @@ void LLModelPreview::updateStatusMessages()  		}  	} -	if (mFMP->childGetValue("physics_lod_combo").asString() == "From file") +	 +	LLCtrlSelectionInterface* iface = fmp->childGetSelectionInterface("physics_lod_combo"); +	S32 which_mode = 0;  +	S32 file_mode = 1; +	if (iface) +	{ +		which_mode = iface->getFirstSelectedIndex(); +		file_mode = iface->getItemCount() - 1; +	} + +	if (which_mode == file_mode)  	{  		mFMP->childEnable("physics_file");  		mFMP->childEnable("physics_browse"); diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp index 66f0fc3cd7..27b1c3b9cd 100644 --- a/indra/newview/llfloaternamedesc.cpp +++ b/indra/newview/llfloaternamedesc.cpp @@ -207,6 +207,25 @@ BOOL LLFloaterSoundPreview::postBuild()  //----------------------------------------------------------------------------- +// LLFloaterAnimPreview() +//----------------------------------------------------------------------------- + +LLFloaterAnimPreview::LLFloaterAnimPreview(const LLSD& filename ) +	: LLFloaterNameDesc(filename) +{ +} + +BOOL LLFloaterAnimPreview::postBuild() +{ +	if (!LLFloaterNameDesc::postBuild()) +	{ +		return FALSE; +	} +	getChild<LLUICtrl>("ok_btn")->setCommitCallback(boost::bind(&LLFloaterNameDesc::onBtnOK, this)); +	return TRUE; +} + +//-----------------------------------------------------------------------------  // LLFloaterScriptPreview()  //----------------------------------------------------------------------------- diff --git a/indra/newview/llfloaternamedesc.h b/indra/newview/llfloaternamedesc.h index 69bbccaf80..41643681ac 100644 --- a/indra/newview/llfloaternamedesc.h +++ b/indra/newview/llfloaternamedesc.h @@ -64,6 +64,13 @@ public:  	virtual BOOL postBuild();  }; +class LLFloaterAnimPreview : public LLFloaterNameDesc +{ +public: +	LLFloaterAnimPreview(const LLSD& filename ); +	virtual BOOL postBuild(); +}; +  class LLFloaterScriptPreview : public LLFloaterNameDesc  {  public: diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index a333989e7e..173b0e538c 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -741,7 +741,8 @@ void LLFloaterPreference::onClose(bool app_quitting)  void LLFloaterPreference::onOpenHardwareSettings()  { -	LLFloaterReg::showInstance("prefs_hardware_settings"); +	LLFloater* floater = LLFloaterReg::showInstance("prefs_hardware_settings"); +	addDependentFloater(floater, FALSE);  }  // static   void LLFloaterPreference::onBtnOK() @@ -1800,7 +1801,46 @@ void LLPanelPreference::updateMediaAutoPlayCheckbox(LLUICtrl* ctrl)  	}  } +class LLPanelPreferencePrivacy : public LLPanelPreference +{ +public: +	LLPanelPreferencePrivacy() +	{ +		mAccountIndependentSettings.push_back("VoiceCallsFriendsOnly"); +		mAccountIndependentSettings.push_back("AutoDisengageMic"); +	} + +	/*virtual*/ void saveSettings() +	{ +		LLPanelPreference::saveSettings(); + +		// Don't save (=erase from the saved values map) per-account privacy settings +		// if we're not logged in, otherwise they will be reset to defaults on log off. +		if (LLStartUp::getStartupState() != STATE_STARTED) +		{ +			// Erase only common settings, assuming there are no color settings on Privacy page. +			for (control_values_map_t::iterator it = mSavedValues.begin(); it != mSavedValues.end(); ) +			{ +				const std::string setting = it->first->getName(); +				if (std::find(mAccountIndependentSettings.begin(), +					mAccountIndependentSettings.end(), setting) == mAccountIndependentSettings.end()) +				{ +					mSavedValues.erase(it++); +				} +				else +				{ +					++it; +				} +			} +		} +	} + +private: +	std::list<std::string> mAccountIndependentSettings; +}; +  static LLRegisterPanelClassWrapper<LLPanelPreferenceGraphics> t_pref_graph("panel_preference_graphics"); +static LLRegisterPanelClassWrapper<LLPanelPreferencePrivacy> t_pref_privacy("panel_preference_privacy");  BOOL LLPanelPreferenceGraphics::postBuild()  { diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 7ee3294478..ec5994e917 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -198,15 +198,17 @@ public:  	virtual void saveSettings();  	class Updater; + +protected: +	typedef std::map<LLControlVariable*, LLSD> control_values_map_t; +	control_values_map_t mSavedValues; +  private:  	//for "Only friends and groups can call or IM me"  	static void showFriendsOnlyWarning(LLUICtrl*, const LLSD&);  	//for "Show my Favorite Landmarks at Login"  	static void showFavoritesOnLoginWarning(LLUICtrl* checkbox, const LLSD& value); -	typedef std::map<LLControlVariable*, LLSD> control_values_map_t; -	control_values_map_t mSavedValues; -  	typedef std::map<std::string, LLColor4> string_color_map_t;  	string_color_map_t mSavedColors; diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index c402de66e8..ae45949b4a 100644 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -33,6 +33,7 @@  #include "llfloater.h"  #include "llhost.h"  #include "llpanel.h" +#include "llextendedstatus.h"  #include "llenvmanager.h" // for LLEnvironmentSettings diff --git a/indra/newview/llfloaterreporter.h b/indra/newview/llfloaterreporter.h index cd98f7be57..7d68431710 100644 --- a/indra/newview/llfloaterreporter.h +++ b/indra/newview/llfloaterreporter.h @@ -31,6 +31,7 @@  #include "llfloater.h"  #include "lluuid.h"  #include "v3math.h" +#include "llextendedstatus.h"  class LLAvatarName;  class LLMessageSystem; diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index a0d1a32e12..b691db1049 100644 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -106,7 +106,11 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std:  	if (objectp)  	{  		objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, LLViewerTexture::BOOST_UI)); -		floater_label = llformat("%s(%.2f, %.2f)", user_name.c_str(), objectp->getPositionRegion().mV[VX], objectp->getPositionRegion().mV[VY]); +		floater_label = llformat("%s(%.0f, %.0f, %.0f)", +						user_name.c_str(), +						objectp->getPositionRegion().mV[VX], +						objectp->getPositionRegion().mV[VY], +						objectp->getPositionRegion().mV[VZ]);  	}  	else  	{ diff --git a/indra/newview/llfloatersidepanelcontainer.cpp b/indra/newview/llfloatersidepanelcontainer.cpp index be7a53491d..5385977d95 100644 --- a/indra/newview/llfloatersidepanelcontainer.cpp +++ b/indra/newview/llfloatersidepanelcontainer.cpp @@ -59,7 +59,10 @@ LLPanel* LLFloaterSidePanelContainer::openChildPanel(const std::string& panel_na  	LLView* view = findChildView(panel_name, true);  	if (!view) return NULL; -	openFloater(); +	if (!getVisible()) +	{ +		openFloater(); +	}  	LLPanel* panel = NULL; diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp index bd5b5f4eb0..6978e6a430 100644 --- a/indra/newview/llfloatertools.cpp +++ b/indra/newview/llfloatertools.cpp @@ -36,6 +36,7 @@  #include "llagentcamera.h"  #include "llbutton.h"  #include "llcheckboxctrl.h" +#include "llcombobox.h"  #include "lldraghandle.h"  #include "llerror.h"  #include "llfloaterbuildoptions.h" @@ -103,6 +104,7 @@ const std::string PANEL_NAMES[LLFloaterTools::PANEL_COUNT] =  // Local prototypes +void commit_grid_mode(LLUICtrl *ctrl);  void commit_select_component(void *data);  void click_show_more(void*);  void click_popup_info(void*); @@ -252,6 +254,7 @@ BOOL	LLFloaterTools::postBuild()  	getChild<LLUICtrl>("checkbox uniform")->setValue((BOOL)gSavedSettings.getBOOL("ScaleUniform"));  	mCheckStretchTexture	= getChild<LLCheckBoxCtrl>("checkbox stretch textures");  	getChild<LLUICtrl>("checkbox stretch textures")->setValue((BOOL)gSavedSettings.getBOOL("ScaleStretchTextures")); +	mComboGridMode			= getChild<LLComboBox>("combobox grid mode");  	mCheckStretchUniformLabel = getChild<LLTextBox>("checkbox uniform label");  	// @@ -330,6 +333,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)  	mCheckSnapToGrid(NULL),  	mBtnGridOptions(NULL),  	mTitleMedia(NULL), +	mComboGridMode(NULL),  	mCheckStretchUniform(NULL),  	mCheckStretchTexture(NULL),  	mCheckStretchUniformLabel(NULL), @@ -386,6 +390,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)  	mCommitCallbackRegistrar.add("BuildTool.commitRadioMove",	boost::bind(&commit_radio_group_move,_1));  	mCommitCallbackRegistrar.add("BuildTool.commitRadioEdit",	boost::bind(&commit_radio_group_edit,_1)); +	mCommitCallbackRegistrar.add("BuildTool.gridMode",			boost::bind(&commit_grid_mode,_1));  	mCommitCallbackRegistrar.add("BuildTool.selectComponent",	boost::bind(&commit_select_component, this));  	mCommitCallbackRegistrar.add("BuildTool.gridOptions",		boost::bind(&LLFloaterTools::onClickGridOptions,this));  	mCommitCallbackRegistrar.add("BuildTool.applyToSelection",	boost::bind(&click_apply_to_selection, this)); @@ -687,6 +692,33 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask)  		mRadioGroupEdit->setValue("radio select face");  	} +	if (mComboGridMode)  +	{ +		mComboGridMode->setVisible( edit_visible ); +		S32 index = mComboGridMode->getCurrentIndex(); +		mComboGridMode->removeall(); + +		switch (mObjectSelection->getSelectType()) +		{ +			case SELECT_TYPE_HUD: +				mComboGridMode->add(getString("grid_screen_text")); +				mComboGridMode->add(getString("grid_local_text")); +				break; +			case SELECT_TYPE_WORLD: +				mComboGridMode->add(getString("grid_world_text")); +				mComboGridMode->add(getString("grid_local_text")); +				mComboGridMode->add(getString("grid_reference_text")); +				break; +			case SELECT_TYPE_ATTACHMENT: +				mComboGridMode->add(getString("grid_attachment_text")); +				mComboGridMode->add(getString("grid_local_text")); +				mComboGridMode->add(getString("grid_reference_text")); +				break; +		} + +		mComboGridMode->setCurrentByIndex(index); +	} +  	// Snap to grid disabled for grab tool - very confusing  	if (mCheckSnapToGrid) mCheckSnapToGrid->setVisible( edit_visible /* || tool == LLToolGrab::getInstance() */ );  	if (mBtnGridOptions) mBtnGridOptions->setVisible( edit_visible /* || tool == LLToolGrab::getInstance() */ ); @@ -1037,6 +1069,13 @@ void LLFloaterTools::setObjectType( LLPCode pcode )  	gFocusMgr.setMouseCapture(NULL);  } +void commit_grid_mode(LLUICtrl *ctrl) +{ +	LLComboBox* combo = (LLComboBox*)ctrl; + +	LLSelectMgr::getInstance()->setGridMode((EGridMode)combo->getCurrentIndex()); +} +  void LLFloaterTools::onClickGridOptions()  { @@ -1144,7 +1183,7 @@ void LLFloaterTools::updateLandImpacts()  	childSetTextArg("remaining_capacity", "[CAPACITY_STRING]", remaining_capacity_str);  	// Update land impacts info in the weights floater -	LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::getTypedInstance<LLFloaterObjectWeights>("object_weights"); +	LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::findTypedInstance<LLFloaterObjectWeights>("object_weights");  	if(object_weights_floater)  	{  		object_weights_floater->updateLandImpacts(parcel); @@ -1234,6 +1273,7 @@ void LLFloaterTools::getMediaState()  		}  	} func; +	  	// check if all faces have media(or, all dont have media)  	LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue( &func, bool_has_media ); diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h index 63ed9dc82b..7a19d093a4 100644 --- a/indra/newview/llfloatertools.h +++ b/indra/newview/llfloatertools.h @@ -33,6 +33,7 @@  class LLButton;  class LLCheckBoxCtrl; +class LLComboBox;  class LLPanelPermissions;  class LLPanelObject;  class LLPanelVolume; @@ -140,6 +141,7 @@ public:  	LLCheckBoxCtrl*	mCheckSnapToGrid;  	LLButton*		mBtnGridOptions; +	LLComboBox*		mComboGridMode;  	LLCheckBoxCtrl*	mCheckStretchUniform;  	LLCheckBoxCtrl*	mCheckStretchTexture; diff --git a/indra/newview/llfloatertranslationsettings.cpp b/indra/newview/llfloatertranslationsettings.cpp index 428a02e9f0..1a17183efd 100644 --- a/indra/newview/llfloatertranslationsettings.cpp +++ b/indra/newview/llfloatertranslationsettings.cpp @@ -293,6 +293,6 @@ void LLFloaterTranslationSettings::onBtnOK()  	gSavedSettings.setString("TranslationService", getSelectedService());  	gSavedSettings.setString("BingTranslateAPIKey", getEnteredBingKey());  	gSavedSettings.setString("GoogleTranslateAPIKey", getEnteredGoogleKey()); -	LLNearbyChatBar::getInstance()->enableTranslationCheckbox(LLTranslate::isTranslationConfigured()); +	LLNearbyChatBar::getInstance()->showTranslationCheckbox(LLTranslate::isTranslationConfigured());  	closeFloater(false);  } diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp index e0d7d67f7d..86001e4146 100644 --- a/indra/newview/llfolderview.cpp +++ b/indra/newview/llfolderview.cpp @@ -255,7 +255,7 @@ LLFolderView::LLFolderView(const Params& p)  	LLRect new_r = LLRect(rect.mLeft + ICON_PAD,  			      rect.mTop - TEXT_PAD,  			      rect.mRight, -			      rect.mTop - TEXT_PAD - llfloor(font->getLineHeight())); +			      rect.mTop - TEXT_PAD - font->getLineHeight());  	text_p.rect(new_r);  	text_p.name(std::string(p.name));  	text_p.font(font); @@ -388,7 +388,7 @@ void LLFolderView::setOpenArrangeRecursively(BOOL openitem, ERecurseType recurse  static LLFastTimer::DeclareTimer FTM_ARRANGE("Arrange"); -// This view grows and shinks to enclose all of its children items and folders. +// This view grows and shrinks to enclose all of its children items and folders.  S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_generation )  {  	if (getListener()->getUUID().notNull()) @@ -414,7 +414,7 @@ S32 LLFolderView::arrange( S32* unused_width, S32* unused_height, S32 filter_gen  		getRoot()->getFilter()->getShowFolderState();  	S32 total_width = LEFT_PAD; -	S32 running_height = mDebugFilters ? llceil(LLFontGL::getFontMonospace()->getLineHeight()) : 0; +	S32 running_height = mDebugFilters ? LLFontGL::getFontMonospace()->getLineHeight() : 0;  	S32 target_height = running_height;  	S32 parent_item_height = getRect().getHeight(); @@ -527,15 +527,15 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)  		LLView::reshape(width, height, called_from_parent);  		scroll_rect = mScrollContainer->getContentWindowRect();  	} -	width = llmax(mMinWidth, scroll_rect.getWidth()); +	width  = llmax(mMinWidth, scroll_rect.getWidth());  	height = llmax(mRunningHeight, scroll_rect.getHeight()); -	// restrict width with scroll container's width -	if (mUseEllipses) +	// Restrict width within scroll container's width +	if (mUseEllipses && mScrollContainer) +	{  		width = scroll_rect.getWidth(); - +	}  	LLView::reshape(width, height, called_from_parent); -  	mReshapeSignal(mSelectedItems, FALSE);  } @@ -912,7 +912,7 @@ void LLFolderView::draw()  	}  	else if (mShowEmptyMessage)  	{ -		if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration()) +		if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mCompletedFilterGeneration < mFilter->getMinRequiredGeneration())  		{  			mStatusText = LLTrans::getString("Searching");  		} @@ -1966,7 +1966,7 @@ void LLFolderView::scrollToShowSelection()  	// However we allow scrolling for folder views with mAutoSelectOverride  	// (used in Places SP) as an exception because the selection in them  	// is not reset during items filtering. See STORM-133. -	if ( (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() || mAutoSelectOverride) +	if ( (!LLInventoryModelBackgroundFetch::instance().folderFetchActive() || mAutoSelectOverride)  			&& mSelectedItems.size() )  	{  		mNeedsScroll = TRUE; @@ -1994,7 +1994,7 @@ void LLFolderView::scrollToShowItem(LLFolderViewItem* item, const LLRect& constr  		LLRect visible_doc_rect = mScrollContainer->getVisibleContentRect();  		S32 icon_height = mIcon.isNull() ? 0 : mIcon->getHeight();  -		S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight());  +		S32 label_height = getLabelFontForStyle(mLabelStyle)->getLineHeight();   		// when navigating with keyboard, only move top of opened folder on screen, otherwise show whole folder  		S32 max_height_to_show = item->isOpen() && mScrollContainer->hasFocus() ? (llmax( icon_height, label_height ) + ICON_PAD) : local_rect.getHeight();  diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 8d6114c887..afad27b4e0 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -410,8 +410,8 @@ BOOL LLFolderViewItem::addToFolder(LLFolderViewFolder* folder, LLFolderView* roo  } -// Finds width and height of this object and it's children.  Also -// makes sure that this view and it's children are the right size. +// Finds width and height of this object and its children.  Also +// makes sure that this view and its children are the right size.  S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)  {  	const Params& p = LLUICtrlFactory::getDefaultParams<LLFolderViewItem>(); @@ -423,7 +423,7 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)  		: 0;  	if (mLabelWidthDirty)  	{ -		mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mSearchableLabel);  +		mLabelWidth = ARROW_SIZE + TEXT_PAD + ICON_WIDTH + ICON_PAD + getLabelFontForStyle(mLabelStyle)->getWidth(mLabel) + getLabelFontForStyle(mLabelStyle)->getWidth(mLabelSuffix) + TEXT_PAD_RIGHT;   		mLabelWidthDirty = false;  	} @@ -1045,7 +1045,7 @@ void LLFolderViewItem::draw()  	}  	if ((mIsLoading  		&&	mTimeSinceRequestStart.getElapsedTimeF32() >= gSavedSettings.getF32("FolderLoadingMessageWaitTime")) -			||	(LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() +			||	(LLInventoryModelBackgroundFetch::instance().folderFetchActive()  				&&	root_is_loading  				&&	mShowLoadStatus))  	{ diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h index 2fc79f5765..4e8dc2da16 100644 --- a/indra/newview/llfolderviewitem.h +++ b/indra/newview/llfolderviewitem.h @@ -114,6 +114,7 @@ public:  	static const S32 ICON_PAD = 2;  	static const S32 ICON_WIDTH = 16;  	static const S32 TEXT_PAD = 1; +	static const S32 TEXT_PAD_RIGHT = 4;  	static const S32 ARROW_SIZE = 12;  	static const S32 MAX_FOLDER_ITEM_OVERLAP = 2;  	// animation parameters diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp index bbf66ca750..129cddda45 100644 --- a/indra/newview/llgrouplist.cpp +++ b/indra/newview/llgrouplist.cpp @@ -123,6 +123,22 @@ BOOL LLGroupList::handleRightMouseDown(S32 x, S32 y, MASK mask)  	return handled;  } +// virtual +BOOL LLGroupList::handleDoubleClick(S32 x, S32 y, MASK mask) +{ +	BOOL handled = LLView::handleDoubleClick(x, y, mask); +	// Handle double click only for the selected item in the list, skip clicks on empty space. +	if (handled) +	{ +		if (mDoubleClickSignal) +		{ +			(*mDoubleClickSignal)(this, x, y, mask); +		} +	} + +	return handled; +} +  void LLGroupList::setNameFilter(const std::string& filter)  {  	std::string filter_upper = filter; diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h index d7051db891..8abf14b3d0 100644 --- a/indra/newview/llgrouplist.h +++ b/indra/newview/llgrouplist.h @@ -51,6 +51,7 @@ public:  	virtual void draw(); // from LLView  	/*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); // from LLView +	/*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); // from LLView  	void setNameFilter(const std::string& filter);  	void toggleIcons(); diff --git a/indra/newview/llhudrender.cpp b/indra/newview/llhudrender.cpp index 122711a86d..dff310ecf9 100644 --- a/indra/newview/llhudrender.cpp +++ b/indra/newview/llhudrender.cpp @@ -138,7 +138,7 @@ void hud_render_text(const LLWString &wstr, const LLVector3 &pos_agent,  	LLUI::translate((F32) winX*1.0f/LLFontGL::sScaleX, (F32) winY*1.0f/(LLFontGL::sScaleY), -(((F32) winZ*2.f)-1.f));  	F32 right_x; -	font.render(wstr, 0, 0, 0, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x); +	font.render(wstr, 0, 0, 1, color, LLFontGL::LEFT, LLFontGL::BASELINE, style, shadow, wstr.length(), 1000, &right_x);  	LLUI::popMatrix();  	gGL.popMatrix(); diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 24a876c59a..579b6008ae 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -227,7 +227,7 @@ void LLHUDText::renderText()  			 segment_iter != mTextSegments.end(); ++segment_iter )  		{  			const LLFontGL* fontp = segment_iter->mFont; -			y_offset -= fontp->getLineHeight(); +			y_offset -= fontp->getLineHeight() - 1; // correction factor to match legacy font metrics  			U8 style = segment_iter->mStyle;  			LLFontGL::ShadowType shadow = LLFontGL::DROP_SHADOW; @@ -480,8 +480,6 @@ void LLHUDText::updateSize()  	F32 width = 0.f;  	S32 max_lines = getMaxLines(); -	//S32 lines = (max_lines < 0) ? (S32)mTextSegments.size() : llmin((S32)mTextSegments.size(), max_lines); -	//F32 height = (F32)mFontp->getLineHeight() * (lines + mLabelSegments.size());  	S32 start_segment;  	if (max_lines < 0) start_segment = 0; @@ -491,7 +489,7 @@ void LLHUDText::updateSize()  	while (iter != mTextSegments.end())  	{  		const LLFontGL* fontp = iter->mFont; -		height += fontp->getLineHeight(); +		height += fontp->getLineHeight() - 1; // correction factor to match legacy font metrics  		width = llmax(width, llmin(iter->getWidth(fontp), HUD_TEXT_MAX_WIDTH));  		++iter;  	} diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index a856bd0bdc..c4ea8c0d31 100644 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -2458,7 +2458,10 @@ void LLIMMgr::addMessage(  		make_ui_sound("UISndNewIncomingIMSession");  	} -	if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat)) +	bool skip_message = (gSavedSettings.getBOOL("VoiceCallsFriendsOnly") && +		LLAvatarTracker::instance().getBuddyInfo(other_participant_id) == NULL); + +	if (!LLMuteList::getInstance()->isMuted(other_participant_id, LLMute::flagTextChat) && !skip_message)  	{  		LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);  	} @@ -2977,6 +2980,17 @@ bool LLIMMgr::isVoiceCall(const LLUUID& session_id)  	return im_session->mStartedAsIMCall;  } +void LLIMMgr::addNotifiedNonFriendSessionID(const LLUUID& session_id) +{ +	mNotifiedNonFriendSessions.insert(session_id); +} + +bool LLIMMgr::isNonFriendSessionNotified(const LLUUID& session_id) +{ +	return mNotifiedNonFriendSessions.end() != mNotifiedNonFriendSessions.find(session_id); + +} +  void LLIMMgr::noteOfflineUsers(  	const LLUUID& session_id,  	const LLDynamicArray<LLUUID>& ids) diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index b1be26a169..f07a78e2f7 100644 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -438,6 +438,10 @@ public:  	bool isVoiceCall(const LLUUID& session_id); +	void addNotifiedNonFriendSessionID(const LLUUID& session_id); + +	bool isNonFriendSessionNotified(const LLUUID& session_id); +  private:  	/** @@ -465,6 +469,14 @@ private:  	typedef std::list <LLIMSessionObserver *> session_observers_list_t;  	session_observers_list_t mSessionObservers; +	// EXP-901 +	// If "Only friends and groups can IM me" option is ON but the user got message from non-friend, +	// the user should be notified that to be able to see this message the option should be OFF. +	// This set stores session IDs in which user was notified. Need to store this IDs so that the user +	// be notified only one time per session with non-friend. +	typedef std::set<LLUUID> notified_non_friend_sessions_t; +	notified_non_friend_sessions_t mNotifiedNonFriendSessions; +  	LLSD mPendingInvitations;  	LLSD mPendingAgentListUpdates;  }; diff --git a/indra/newview/llinspecttoast.cpp b/indra/newview/llinspecttoast.cpp index d7b82667d1..f4fe5dec01 100644 --- a/indra/newview/llinspecttoast.cpp +++ b/indra/newview/llinspecttoast.cpp @@ -72,6 +72,8 @@ LLInspectToast::LLInspectToast(const LLSD& notification_id) :  LLInspectToast::~LLInspectToast()  {  	LLTransientFloaterMgr::getInstance()->removeControlView(this); + +	mConnection.disconnect();  }  // virtual diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index c0065a94e6..2de2b17373 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -113,6 +113,13 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response  bool confirm_attachment_rez(const LLSD& notification, const LLSD& response);  void teleport_via_landmark(const LLUUID& asset_id);  static BOOL can_move_to_outfit(LLInventoryItem* inv_item, BOOL move_is_into_current_outfit); +static bool check_category(LLInventoryModel* model, +						   const LLUUID& cat_id, +						   LLFolderView* active_folder_view, +						   LLInventoryFilter* filter); +static bool check_item(const LLUUID& item_id, +					   LLFolderView* active_folder_view, +					   LLInventoryFilter* filter);  // Helper functions @@ -148,7 +155,7 @@ LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory,  	mInvType(LLInventoryType::IT_NONE),  	mIsLink(FALSE)  { -	mInventoryPanel = inventory->getHandle(); +	mInventoryPanel = inventory->getInventoryPanelHandle();  	const LLInventoryObject* obj = getInventoryObject();  	mIsLink = obj && obj->getIsLinkType();  } @@ -798,7 +805,7 @@ LLInventoryObject* LLInvFVBridge::getInventoryObject() const  LLInventoryModel* LLInvFVBridge::getInventoryModel() const  { -	LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); +	LLInventoryPanel* panel = mInventoryPanel.get();  	return panel ? panel->getModel() : NULL;  } @@ -1324,8 +1331,8 @@ void LLItemBridge::selectItem()  	LLViewerInventoryItem* item = static_cast<LLViewerInventoryItem*>(getItem());  	if(item && !item->isFinished())  	{ -		item->fetchFromServer(); -		//LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false); +		//item->fetchFromServer(); +		LLInventoryModelBackgroundFetch::instance().start(item->getUUID(), false);  	}  } @@ -1738,7 +1745,7 @@ BOOL LLFolderBridge::isItemRemovable() const  		return FALSE;  	} -	LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); +	LLInventoryPanel* panel = mInventoryPanel.get();  	LLFolderViewFolder* folderp = dynamic_cast<LLFolderViewFolder*>(panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL);  	if (folderp)  	{ @@ -1959,6 +1966,12 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  	if (!isAgentAvatarValid()) return FALSE;  	if (!isAgentInventory()) return FALSE; // cannot drag categories into library +	LLInventoryPanel* destination_panel = mInventoryPanel.get(); +	if (!destination_panel) return false; + +	LLInventoryFilter* filter = destination_panel->getFilter(); +	if (!filter) return false; +  	const LLUUID &cat_id = inv_cat->getUUID();  	const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);  	const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); @@ -2096,7 +2109,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  							// NOTE: The cargo id's count is a total of categories AND items but we err on the side of  							//       prevention rather than letting too many folders into the hierarchy of the outbox,  							//       when we're dragging the item to a new parent -							dragged_folder_count += LLToolDragAndDrop::instance().getCargoIDsCount(); +							dragged_folder_count += LLToolDragAndDrop::instance().getCargoCount();  						}  					} @@ -2146,6 +2159,39 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  			}  		} +		if (is_movable) +		{ +			LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); +			is_movable = active_panel != NULL; + +			// For a folder to pass the filter all its descendants are required to pass. +			// We make this exception to allow reordering folders within an inventory panel, +			// which has a filter applied, like Recent tab for example. +			// There may be folders which are displayed because some of their descendants pass +			// the filter, but other don't, and thus remain hidden. Without this check, +			// such folders would not be allowed to be moved within a panel. +			if (destination_panel == active_panel) +			{ +				is_movable = true; +			} +			else +			{ +				LLFolderView* active_folder_view = NULL; + +				if (is_movable) +				{ +					active_folder_view = active_panel->getRootFolder(); +					is_movable = active_folder_view != NULL; +				} + +				if (is_movable) +				{ +					// Check whether the folder being dragged from active inventory panel +					// passes the filter of the destination panel. +					is_movable = check_category(model, cat_id, active_folder_view, filter); +				} +			} +		}  		//   		//-------------------------------------------------------------------------------- @@ -2240,7 +2286,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,  		}  		else  		{ -			accept = move_inv_category_world_to_agent(cat_id, mUUID, drop); +			accept = move_inv_category_world_to_agent(cat_id, mUUID, drop, NULL, NULL, filter);  		}  	}  	else if (LLToolDragAndDrop::SOURCE_LIBRARY == source) @@ -2285,7 +2331,8 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,  									  const LLUUID& category_id,  									  BOOL drop,  									  void (*callback)(S32, void*), -									  void* user_data) +									  void* user_data, +									  LLInventoryFilter* filter)  {  	// Make sure the object exists. If we allowed dragging from  	// anonymous objects, it would be possible to bypass @@ -2309,7 +2356,7 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,  		return FALSE;  	} -	BOOL accept = TRUE; +	BOOL accept = FALSE;  	BOOL is_move = FALSE;  	// coming from a task. Need to figure out if the person can @@ -2318,9 +2365,16 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,  	LLInventoryObject::object_list_t::iterator end = inventory_objects.end();  	for ( ; it != end; ++it)  	{ +		LLInventoryItem* item = dynamic_cast<LLInventoryItem*>(it->get()); +		if (!item) +		{ +			llwarns << "Invalid inventory item for drop" << llendl; +			continue; +		} +  		// coming from a task. Need to figure out if the person can  		// move/copy this item. -		LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions()); +		LLPermissions perm(item->getPermissions());  		if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())  			&& perm.allowTransferTo(gAgent.getID())))  //			|| gAgent.isGodlike()) @@ -2335,9 +2389,14 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,  			is_move = TRUE;  			accept = TRUE;  		} -		else + +		if (filter && accept) +		{ +			accept = filter->check(item); +		} + +		if (!accept)  		{ -			accept = FALSE;  			break;  		}  	} @@ -2820,18 +2879,62 @@ void LLFolderBridge::pasteFromClipboard()  	if(model && isClipboardPasteable())  	{  		const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); +		const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); +  		const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);  		const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); - -		const LLUUID parent_id(mUUID); +		const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);  		LLDynamicArray<LLUUID> objects;  		LLInventoryClipboard::instance().retrieve(objects); + +		if (move_is_into_outbox) +		{ +			LLFolderViewItem * outbox_itemp = mRoot->getItemByID(mUUID); + +			if (outbox_itemp) +			{ +				LLToolDragAndDrop::instance().setCargoCount(objects.size()); + +				BOOL can_list = TRUE; + +				for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin(); +					(iter != objects.end()) && (can_list == TRUE); +					++iter) +				{ +					const LLUUID& item_id = (*iter); +					LLInventoryItem *item = model->getItem(item_id); + +					if (item) +					{ +						MASK mask = 0x0; +						BOOL drop = FALSE; +						EDragAndDropType cargo_type = LLViewerAssetType::lookupDragAndDropType(item->getActualType()); +						void * cargo_data = (void *) item; +						std::string tooltip_msg; + +						can_list = outbox_itemp->getListener()->dragOrDrop(mask, drop, cargo_type, cargo_data, tooltip_msg); +					} +				} + +				LLToolDragAndDrop::instance().resetCargoCount(); + +				if (can_list == FALSE) +				{ +					// Notify user of failure somehow -- play error sound?  modal dialog? +					return; +				} +			} +		} + +		const LLUUID parent_id(mUUID); +  		for (LLDynamicArray<LLUUID>::const_iterator iter = objects.begin();  			 iter != objects.end();  			 ++iter)  		{  			const LLUUID& item_id = (*iter); +  			LLInventoryItem *item = model->getItem(item_id);  			if (item)  			{ @@ -2874,8 +2977,17 @@ void LLFolderBridge::pasteLinkFromClipboard()  	if(model)  	{  		const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false); +		const LLUUID &outbox_id = model->findCategoryUUIDForType(LLFolderType::FT_OUTBOX, false); +  		const BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);  		const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT); +		const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); + +		if (move_is_into_outbox) +		{ +			// Notify user of failure somehow -- play error sound?  modal dialog? +			return; +		}  		const LLUUID parent_id(mUUID); @@ -3290,7 +3402,7 @@ void LLFolderBridge::createNewCategory(void* user_data)  {  	LLFolderBridge* bridge = (LLFolderBridge*)user_data;  	if(!bridge) return; -	LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get()); +	LLInventoryPanel* panel = bridge->mInventoryPanel.get();  	if (!panel) return;  	LLInventoryModel* model = panel->getModel();  	if(!model) return; @@ -3470,7 +3582,7 @@ void LLFolderBridge::dropToFavorites(LLInventoryItem* inv_item)  	// use callback to rearrange favorite landmarks after adding  	// to have new one placed before target (on which it was dropped). See EXT-4312.  	LLPointer<AddFavoriteLandmarkCallback> cb = new AddFavoriteLandmarkCallback(); -	LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); +	LLInventoryPanel* panel = mInventoryPanel.get();  	LLFolderViewItem* drag_over_item = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;  	if (drag_over_item && drag_over_item->getListener())  	{ @@ -3520,6 +3632,12 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  	if (!isAgentInventory()) return FALSE; // cannot drag into library  	if (!isAgentAvatarValid()) return FALSE; +	LLInventoryPanel* destination_panel = mInventoryPanel.get(); +	if (!destination_panel) return false; + +	LLInventoryFilter* filter = destination_panel->getFilter(); +	if (!filter) return false; +  	const LLUUID ¤t_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT, false);  	const LLUUID &favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE, false);  	const LLUUID &landmarks_id = model->findCategoryUUIDForType(LLFolderType::FT_LANDMARK, false); @@ -3529,7 +3647,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  	const BOOL move_is_into_favorites = (mUUID == favorites_id);  	const BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);  	const BOOL move_is_into_landmarks = (mUUID == landmarks_id) || model->isObjectDescendentOf(mUUID, landmarks_id); -	const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id); //(mUUID == outbox_id); +	const BOOL move_is_into_outbox = model->isObjectDescendentOf(mUUID, outbox_id);  	const BOOL move_is_from_outbox = model->isObjectDescendentOf(inv_item->getUUID(), outbox_id);  	LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource(); @@ -3608,7 +3726,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			{  				const LLViewerInventoryCategory * master_folder = model->getFirstDescendantOf(outbox_id, mUUID); -				int existing_item_count = LLToolDragAndDrop::instance().getCargoIDsCount(); +				int existing_item_count = LLToolDragAndDrop::instance().getCargoCount();  				if (master_folder != NULL)  				{ @@ -3628,6 +3746,21 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			}  		} +		LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + +		// Check whether the item being dragged from active inventory panel +		// passes the filter of the destination panel. +		if (accept && active_panel) +		{ +			LLFolderView* active_folder_view = active_panel->getRootFolder(); +			if (!active_folder_view) return false; + +			LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); +			if (!fv_item) return false; + +			accept = filter->check(fv_item); +		} +  		if (accept && drop)  		{  			if (inv_item->getType() == LLAssetType::AT_GESTURE @@ -3637,15 +3770,10 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			}  			// If an item is being dragged between windows, unselect everything in the active window   			// so that we don't follow the selection to its new location (which is very annoying). -			LLInventoryPanel *active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); -			if (active_panel) -			{ -				LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); -				if (active_panel && (panel != active_panel)) +			if (active_panel && (destination_panel != active_panel))  				{  					active_panel->unSelectAll();  				} -			}  			//--------------------------------------------------------------------------------  			// Destination folder logic @@ -3655,8 +3783,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			// (only reorder the item in Favorites folder)  			if ((mUUID == inv_item->getParentUUID()) && move_is_into_favorites)  			{ -				LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); -				LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL; +				LLFolderViewItem* itemp = destination_panel->getRootFolder()->getDraggingOverItem();  				if (itemp)  				{  					LLUUID srcItemId = inv_item->getUUID(); @@ -3760,6 +3887,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			accept = FALSE;  		} +		// Check whether the item being dragged from in world +		// passes the filter of the destination panel. +		if (accept) +		{ +			accept = filter->check(inv_item); +		} +  		if (accept && drop)  		{  			LLMoveInv* move_inv = new LLMoveInv; @@ -3797,6 +3931,13 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  			accept = !(move_is_into_current_outfit || move_is_into_outfit);  		} +		// Check whether the item being dragged from notecard +		// passes the filter of the destination panel. +		if (accept) +		{ +			accept = filter->check(inv_item); +		} +  		if (accept && drop)  		{  			copy_inventory_from_notecard(mUUID,  // Drop to the chosen destination folder @@ -3828,6 +3969,21 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  				accept = can_move_to_landmarks(inv_item);  			} +			LLInventoryPanel* active_panel = LLInventoryPanel::getActiveInventoryPanel(FALSE); + +			// Check whether the item being dragged from the library +			// passes the filter of the destination panel. +			if (accept && active_panel) +			{ +				LLFolderView* active_folder_view = active_panel->getRootFolder(); +				if (!active_folder_view) return false; + +				LLFolderViewItem* fv_item = active_folder_view->getItemByID(inv_item->getUUID()); +				if (!fv_item) return false; + +				accept = filter->check(fv_item); +			} +  			if (accept && drop)  			{  				// FAVORITES folder @@ -3862,6 +4018,69 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,  	return accept;  } +// static +bool check_category(LLInventoryModel* model, +					const LLUUID& cat_id, +					LLFolderView* active_folder_view, +					LLInventoryFilter* filter) +{ +	if (!model || !active_folder_view || !filter) +		return false; + +	if (!filter->checkFolder(cat_id)) +	{ +		return false; +	} + +	LLInventoryModel::cat_array_t descendent_categories; +	LLInventoryModel::item_array_t descendent_items; +	model->collectDescendents(cat_id, descendent_categories, descendent_items, TRUE); + +	S32 num_descendent_categories = descendent_categories.count(); +	S32 num_descendent_items = descendent_items.count(); + +	if (num_descendent_categories + num_descendent_items == 0) +	{ +		// Empty folder should be checked as any other folder view item. +		// If we are filtering by date the folder should not pass because +		// it doesn't have its own creation date. See LLInvFVBridge::getCreationDate(). +		return check_item(cat_id, active_folder_view, filter); +	} + +	for (S32 i = 0; i < num_descendent_categories; ++i) +	{ +		LLInventoryCategory* category = descendent_categories[i]; +		if(!check_category(model, category->getUUID(), active_folder_view, filter)) +		{ +			return false; +		} +	} + +	for (S32 i = 0; i < num_descendent_items; ++i) +	{ +		LLViewerInventoryItem* item = descendent_items[i]; +		if(!check_item(item->getUUID(), active_folder_view, filter)) +		{ +			return false; +		} +	} + +	return true; +} + +// static +bool check_item(const LLUUID& item_id, +				LLFolderView* active_folder_view, +				LLInventoryFilter* filter) +{ +	if (!active_folder_view || !filter) return false; + +	LLFolderViewItem* fv_item = active_folder_view->getItemByID(item_id); +	if (!fv_item) return false; + +	return filter->check(fv_item); +} +  // +=================================================+  // |        LLTextureBridge                          |  // +=================================================+ @@ -4184,7 +4403,7 @@ LLCallingCardBridge::~LLCallingCardBridge()  void LLCallingCardBridge::refreshFolderViewItem()  { -	LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); +	LLInventoryPanel* panel = mInventoryPanel.get();  	LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL;  	if (itemp)  	{ @@ -4633,14 +4852,14 @@ void LLAnimationBridge::performAction(LLInventoryModel* model, std::string actio  	{  		if (getItem())  		{ -			LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE; -			if ("playworld" == action) activate = LLPreviewAnim::PLAY; -			if ("playlocal" == action) activate = LLPreviewAnim::AUDITION; +			LLSD::String activate = "NONE"; +			if ("playworld" == action) activate = "Inworld"; +			if ("playlocal" == action) activate = "Locally";  			LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));  			if (preview)  			{ -				preview->activate(activate); +				preview->play(activate);  			}  		}  	} diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h index 871657a58a..3b4f845f54 100644 --- a/indra/newview/llinventorybridge.h +++ b/indra/newview/llinventorybridge.h @@ -35,6 +35,7 @@  #include "llviewercontrol.h"  #include "llwearable.h" +class LLInventoryFilter;  class LLInventoryPanel;  class LLInventoryModel;  class LLMenuGL; @@ -161,7 +162,7 @@ protected:  									 BOOL restamp);  	void removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch);  protected: -	LLHandle<LLPanel> mInventoryPanel; +	LLHandle<LLInventoryPanel> mInventoryPanel;  	LLFolderView* mRoot;  	const LLUUID mUUID;	// item id  	LLInventoryType::EType mInvType; @@ -645,7 +646,8 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,  									  const LLUUID& category_id,  									  BOOL drop,  									  void (*callback)(S32, void*) = NULL, -									  void* user_data = NULL); +									  void* user_data = NULL, +									  LLInventoryFilter* filter = NULL);  // Utility function to hide all entries except those in the list  // Can be called multiple times on the same menu (e.g. if multiple items diff --git a/indra/newview/llinventoryfilter.cpp b/indra/newview/llinventoryfilter.cpp index d54bce4619..5496c273f2 100644 --- a/indra/newview/llinventoryfilter.cpp +++ b/indra/newview/llinventoryfilter.cpp @@ -108,16 +108,48 @@ BOOL LLInventoryFilter::check(const LLFolderViewItem* item)  	return passed;  } -bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) +bool LLInventoryFilter::check(const LLInventoryItem* item)  { -	// we're showing all folders, overriding filter -	if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) +	mSubStringMatchOffset = mFilterSubString.size() ? item->getName().find(mFilterSubString) : std::string::npos; + +	const bool passed_filtertype = checkAgainstFilterType(item); +	const bool passed_permissions = checkAgainstPermissions(item); +	const bool passed = (passed_filtertype && +						 passed_permissions && +						 (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)); + +	return passed; +} + +bool LLInventoryFilter::checkFolder(const LLFolderViewFolder* folder) const +{ +	if (!folder)  	{ -		return true; +		llwarns << "The filter can not be checked on an invalid folder." << llendl; +		llassert(false); // crash in development builds +		return false;  	}  	const LLFolderViewEventListener* listener = folder->getListener(); +	if (!listener) +	{ +		llwarns << "Folder view event listener not found." << llendl; +		llassert(false); // crash in development builds +		return false; +	} +  	const LLUUID folder_id = listener->getUUID(); + +	return checkFolder(folder_id); +} + +bool LLInventoryFilter::checkFolder(const LLUUID& folder_id) const +{ +	// we're showing all folders, overriding filter +	if (mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS) +	{ +		return true; +	}  	if (mFilterOps.mFilterTypes & FILTERTYPE_CATEGORY)  	{ @@ -227,6 +259,56 @@ BOOL LLInventoryFilter::checkAgainstFilterType(const LLFolderViewItem* item) con  	return TRUE;  } +bool LLInventoryFilter::checkAgainstFilterType(const LLInventoryItem* item) const +{ +	LLInventoryType::EType object_type = item->getInventoryType(); +	const LLUUID object_id = item->getUUID(); + +	const U32 filterTypes = mFilterOps.mFilterTypes; + +	//////////////////////////////////////////////////////////////////////////////// +	// FILTERTYPE_OBJECT +	// Pass if this item's type is of the correct filter type +	if (filterTypes & FILTERTYPE_OBJECT) +	{ +		// If it has no type, pass it, unless it's a link. +		if (object_type == LLInventoryType::IT_NONE) +		{ +			if (item && item->getIsLinkType()) +			{ +				return false; +			} +		} +		else if ((1LL << object_type & mFilterOps.mFilterObjectTypes) == U64(0)) +		{ +			return false; +		} +	} + +	//////////////////////////////////////////////////////////////////////////////// +	// FILTERTYPE_UUID +	// Pass if this item is the target UUID or if it links to the target UUID +	if (filterTypes & FILTERTYPE_UUID) +	{ +		if (!item) return false; + +		if (item->getLinkedUUID() != mFilterOps.mFilterUUID) +			return false; +	} + +	//////////////////////////////////////////////////////////////////////////////// +	// FILTERTYPE_DATE +	// Pass if this item is within the date range. +	if (filterTypes & FILTERTYPE_DATE) +	{ +		// We don't get the updated item creation date for the task inventory or +		// a notecard embedded item. See LLTaskInvFVBridge::getCreationDate(). +		return false; +	} + +	return true; +} +  BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) const  {  	const LLFolderViewEventListener* listener = item->getListener(); @@ -244,6 +326,17 @@ BOOL LLInventoryFilter::checkAgainstPermissions(const LLFolderViewItem* item) co  	return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions;  } +bool LLInventoryFilter::checkAgainstPermissions(const LLInventoryItem* item) const +{ +	if (!item) return false; + +	LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item); +	PermissionMask perm = new_item->getPermissionMask(); +	new_item = NULL; + +	return (perm & mFilterOps.mPermissions) == mFilterOps.mPermissions; +} +  BOOL LLInventoryFilter::checkAgainstFilterLinks(const LLFolderViewItem* item) const  {  	const LLFolderViewEventListener* listener = item->getListener(); @@ -464,7 +557,9 @@ void LLInventoryFilter::setDateRange(time_t min_date, time_t max_date)  		mFilterOps.mMaxDate = llmax(mFilterOps.mMinDate, max_date);  		setModified();  	} -	mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + +	areDateLimitsSet() ? mFilterOps.mFilterTypes |= FILTERTYPE_DATE +			: mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE;  }  void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl) @@ -476,10 +571,12 @@ void LLInventoryFilter::setDateRangeLastLogoff(BOOL sl)  	}  	if (!sl && isSinceLogoff())  	{ -		setDateRange(0, time_max()); +		setDateRange(time_min(), time_max());  		setModified();  	} -	mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + +	areDateLimitsSet() ? mFilterOps.mFilterTypes |= FILTERTYPE_DATE +			: mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE;  }  BOOL LLInventoryFilter::isSinceLogoff() const @@ -524,7 +621,9 @@ void LLInventoryFilter::setHoursAgo(U32 hours)  			setModified(FILTER_RESTART);  		}  	} -	mFilterOps.mFilterTypes |= FILTERTYPE_DATE; + +	areDateLimitsSet() ? mFilterOps.mFilterTypes |= FILTERTYPE_DATE +			: mFilterOps.mFilterTypes &= ~FILTERTYPE_DATE;  }  void LLInventoryFilter::setFilterLinks(U64 filter_links) @@ -804,7 +903,7 @@ const std::string& LLInventoryFilter::getFilterText()  		filtered_by_all_types = FALSE;  	} -	if (!LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() +	if (!LLInventoryModelBackgroundFetch::instance().folderFetchActive()  		&& filtered_by_type  		&& !filtered_by_all_types)  	{ @@ -974,3 +1073,10 @@ const std::string& LLInventoryFilter::getEmptyLookupMessage() const  	return mEmptyLookupMessage;  } + +bool LLInventoryFilter::areDateLimitsSet() +{ +	return     mFilterOps.mMinDate != time_min() +			|| mFilterOps.mMaxDate != time_max() +			|| mFilterOps.mHoursAgo != 0; +} diff --git a/indra/newview/llinventoryfilter.h b/indra/newview/llinventoryfilter.h index bba24ac652..6be2acfaa3 100644 --- a/indra/newview/llinventoryfilter.h +++ b/indra/newview/llinventoryfilter.h @@ -32,6 +32,7 @@  class LLFolderViewItem;  class LLFolderViewFolder; +class LLInventoryItem;  class LLInventoryFilter  { @@ -115,9 +116,13 @@ public:  	// + Execution And Results  	// +-------------------------------------------------------------------+  	BOOL 				check(const LLFolderViewItem* item); -	bool				checkFolder(const LLFolderViewFolder* folder); +	bool				check(const LLInventoryItem* item); +	bool				checkFolder(const LLFolderViewFolder* folder) const; +	bool				checkFolder(const LLUUID& folder_id) const;  	BOOL 				checkAgainstFilterType(const LLFolderViewItem* item) const; +	bool 				checkAgainstFilterType(const LLInventoryItem* item) const;  	BOOL 				checkAgainstPermissions(const LLFolderViewItem* item) const; +	bool 				checkAgainstPermissions(const LLInventoryItem* item) const;  	BOOL 				checkAgainstFilterLinks(const LLFolderViewItem* item) const;  	std::string::size_type getStringMatchOffset() const; @@ -175,6 +180,8 @@ public:  	void 				fromLLSD(LLSD& data);  private: +	bool				areDateLimitsSet(); +  	struct FilterOps  	{  		FilterOps(); diff --git a/indra/newview/llinventorymodelbackgroundfetch.cpp b/indra/newview/llinventorymodelbackgroundfetch.cpp index 91fdd67806..f4d0110b0f 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.cpp +++ b/indra/newview/llinventorymodelbackgroundfetch.cpp @@ -43,6 +43,7 @@ const S32 MAX_FETCH_RETRIES = 10;  LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() :  	mBackgroundFetchActive(FALSE), +	mFolderFetchActive(false),  	mAllFoldersFetched(FALSE),  	mRecursiveInventoryFetchStarted(FALSE),  	mRecursiveLibraryFetchStarted(FALSE), @@ -50,7 +51,7 @@ LLInventoryModelBackgroundFetch::LLInventoryModelBackgroundFetch() :  	mMinTimeBetweenFetches(0.3f),  	mMaxTimeBetweenFetches(10.f),  	mTimelyFetchPending(FALSE), -	mBulkFetchCount(0) +	mFetchCount(0)  {  } @@ -60,7 +61,7 @@ LLInventoryModelBackgroundFetch::~LLInventoryModelBackgroundFetch()  bool LLInventoryModelBackgroundFetch::isBulkFetchProcessingComplete() const  { -	return mFetchQueue.empty() && mBulkFetchCount<=0; +	return mFetchQueue.empty() && mFetchCount<=0;  }  bool LLInventoryModelBackgroundFetch::libraryFetchStarted() const @@ -98,19 +99,21 @@ bool LLInventoryModelBackgroundFetch::isEverythingFetched() const  	return mAllFoldersFetched;  } -BOOL LLInventoryModelBackgroundFetch::backgroundFetchActive() const +BOOL LLInventoryModelBackgroundFetch::folderFetchActive() const  { -	return mBackgroundFetchActive; +	return mFolderFetchActive;  } -void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive) +void LLInventoryModelBackgroundFetch::start(const LLUUID& id, BOOL recursive)  { -	if (!mAllFoldersFetched || cat_id.notNull()) -	{ -		LL_DEBUGS("InventoryFetch") << "Start fetching category: " << cat_id << ", recursive: " << recursive << LL_ENDL; +	LLViewerInventoryCategory* cat = gInventory.getCategory(id); +	if (cat || (id.isNull() && !isEverythingFetched())) +	{	// it's a folder, do a bulk fetch +		LL_DEBUGS("InventoryFetch") << "Start fetching category: " << id << ", recursive: " << recursive << LL_ENDL;  		mBackgroundFetchActive = TRUE; -		if (cat_id.isNull()) +		mFolderFetchActive = true; +		if (id.isNull())  		{  			if (!mRecursiveInventoryFetchStarted)  			{ @@ -128,41 +131,41 @@ void LLInventoryModelBackgroundFetch::start(const LLUUID& cat_id, BOOL recursive  		else  		{  			// Specific folder requests go to front of queue. -			if (mFetchQueue.empty() || mFetchQueue.front().mCatUUID != cat_id) +			if (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)  			{ -				mFetchQueue.push_front(FetchQueueInfo(cat_id, recursive)); +				mFetchQueue.push_front(FetchQueueInfo(id, recursive));  				gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);  			} -			if (cat_id == gInventory.getLibraryRootFolderID()) +			if (id == gInventory.getLibraryRootFolderID())  			{  				mRecursiveLibraryFetchStarted |= recursive;  			} -			if (cat_id == gInventory.getRootFolderID()) +			if (id == gInventory.getRootFolderID())  			{  				mRecursiveInventoryFetchStarted |= recursive;  			}  		}  	} +	else if (LLViewerInventoryItem* itemp = gInventory.getItem(id)) +	{ +		if (!itemp->mIsComplete && (mFetchQueue.empty() || mFetchQueue.front().mUUID != id)) +		{ +			mBackgroundFetchActive = TRUE; + +			mFetchQueue.push_front(FetchQueueInfo(id, false, false)); +			gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); +		} +	}  }  void LLInventoryModelBackgroundFetch::findLostItems()  {  	mBackgroundFetchActive = TRUE; +	mFolderFetchActive = true;      mFetchQueue.push_back(FetchQueueInfo(LLUUID::null, TRUE));      gIdleCallbacks.addFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL);  } -void LLInventoryModelBackgroundFetch::stopBackgroundFetch() -{ -	if (mBackgroundFetchActive) -	{ -		mBackgroundFetchActive = FALSE; -		gIdleCallbacks.deleteFunction(&LLInventoryModelBackgroundFetch::backgroundFetchCB, NULL); -		mBulkFetchCount=0; -		mMinTimeBetweenFetches=0.0f; -	} -} -  void LLInventoryModelBackgroundFetch::setAllFoldersFetched()  {  	if (mRecursiveInventoryFetchStarted && @@ -170,7 +173,7 @@ void LLInventoryModelBackgroundFetch::setAllFoldersFetched()  	{  		mAllFoldersFetched = TRUE;  	} -	stopBackgroundFetch(); +	mFolderFetchActive = false;  }  void LLInventoryModelBackgroundFetch::backgroundFetchCB(void *) @@ -183,10 +186,9 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  	if (mBackgroundFetchActive && gAgent.getRegion())  	{  		// If we'll be using the capability, we'll be sending batches and the background thing isn't as important. -		std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents2");    -		if (gSavedSettings.getBOOL("UseHTTPInventory") && !url.empty())  +		if (gSavedSettings.getBOOL("UseHTTPInventory"))   		{ -			bulkFetch(url); +			bulkFetch();  			return;  		} @@ -201,6 +203,9 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  			llinfos << "Inventory fetch completed" << llendl;  			setAllFoldersFetched(); +			mBackgroundFetchActive = false; +			mFolderFetchActive = false; +  			return;  		} @@ -230,80 +235,114 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  			}  			const FetchQueueInfo info = mFetchQueue.front(); -			LLViewerInventoryCategory* cat = gInventory.getCategory(info.mCatUUID); -			// Category has been deleted, remove from queue. -			if (!cat) +			if (info.mIsCategory)  			{ -				mFetchQueue.pop_front(); -				continue; -			} + +				LLViewerInventoryCategory* cat = gInventory.getCategory(info.mUUID); + +				// Category has been deleted, remove from queue. +				if (!cat) +				{ +					mFetchQueue.pop_front(); +					continue; +				} -			if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches &&  -				LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) -			{ -				// Category exists but has no children yet, fetch the descendants -				// for now, just request every time and rely on retry timer to throttle. -				if (cat->fetch()) +				if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches &&  +					LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())  				{ -					mFetchTimer.reset(); -					mTimelyFetchPending = TRUE; +					// Category exists but has no children yet, fetch the descendants +					// for now, just request every time and rely on retry timer to throttle. +					if (cat->fetch()) +					{ +						mFetchTimer.reset(); +						mTimelyFetchPending = TRUE; +					} +					else +					{ +						//  The catagory also tracks if it has expired and here it says it hasn't +						//  yet.  Get out of here because nothing is going to happen until we +						//  update the timers. +						break; +					}  				} -				else +				// Do I have all my children? +				else if (gInventory.isCategoryComplete(info.mUUID))  				{ -					//  The catagory also tracks if it has expired and here it says it hasn't -					//  yet.  Get out of here because nothing is going to happen until we -					//  update the timers. +					// Finished with this category, remove from queue. +					mFetchQueue.pop_front(); + +					// Add all children to queue. +					LLInventoryModel::cat_array_t* categories; +					LLInventoryModel::item_array_t* items; +					gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); +					for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); +						 it != categories->end(); +						 ++it) +					{ +						mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive)); +					} + +					// We received a response in less than the fast time. +					if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time) +					{ +						// Shrink timeouts based on success. +						mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f); +						mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f); +						lldebugs << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl; +					} + +					mTimelyFetchPending = FALSE; +					continue; +				} +				else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches) +				{ +					// Received first packet, but our num descendants does not match db's num descendants +					// so try again later. +					mFetchQueue.pop_front(); + +					if (mNumFetchRetries++ < MAX_FETCH_RETRIES) +					{ +						// push on back of queue +						mFetchQueue.push_back(info); +					} +					mTimelyFetchPending = FALSE; +					mFetchTimer.reset();  					break;  				} + +				// Not enough time has elapsed to do a new fetch +				break;  			} -			// Do I have all my children? -			else if (gInventory.isCategoryComplete(info.mCatUUID)) +			else  			{ -				// Finished with this category, remove from queue. -				mFetchQueue.pop_front(); +				LLViewerInventoryItem* itemp = gInventory.getItem(info.mUUID); -				// Add all children to queue. -				LLInventoryModel::cat_array_t* categories; -				LLInventoryModel::item_array_t* items; -				gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); -				for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); -					 it != categories->end(); -					 ++it) +				mFetchQueue.pop_front(); +				if (!itemp)   				{ -					mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(),info.mRecursive)); +					continue;  				} -				// We received a response in less than the fast time. -				if (mTimelyFetchPending && mFetchTimer.getElapsedTimeF32() < fast_fetch_time) +				if (mFetchTimer.getElapsedTimeF32() > mMinTimeBetweenFetches)  				{ -					// Shrink timeouts based on success. -					mMinTimeBetweenFetches = llmax(mMinTimeBetweenFetches * 0.8f, 0.3f); -					mMaxTimeBetweenFetches = llmax(mMaxTimeBetweenFetches * 0.8f, 10.f); -					lldebugs << "Inventory fetch times shrunk to (" << mMinTimeBetweenFetches << ", " << mMaxTimeBetweenFetches << ")" << llendl; +					itemp->fetchFromServer(); +					mFetchTimer.reset(); +					mTimelyFetchPending = TRUE;  				} - -				mTimelyFetchPending = FALSE; -				continue; -			} -			else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches) -			{ -				// Received first packet, but our num descendants does not match db's num descendants -				// so try again later. -				mFetchQueue.pop_front(); - -				if (mNumFetchRetries++ < MAX_FETCH_RETRIES) +				else if (itemp->mIsComplete) +				{ +					mTimelyFetchPending = FALSE; +				} +				else if (mFetchTimer.getElapsedTimeF32() > mMaxTimeBetweenFetches)  				{ -					// push on back of queue  					mFetchQueue.push_back(info); +					mFetchTimer.reset(); +					mTimelyFetchPending = FALSE;  				} -				mTimelyFetchPending = FALSE; -				mFetchTimer.reset(); +				// Not enough time has elapsed to do a new fetch  				break;  			} - -			// Not enough time has elapsed to do a new fetch -			break;  		}  		// @@ -313,15 +352,35 @@ void LLInventoryModelBackgroundFetch::backgroundFetch()  	}  } -void LLInventoryModelBackgroundFetch::incrBulkFetch(S16 fetching)  +void LLInventoryModelBackgroundFetch::incrFetchCount(S16 fetching)   {   -	mBulkFetchCount += fetching;  -	if (mBulkFetchCount < 0) +	mFetchCount += fetching;  +	if (mFetchCount < 0)  	{ -		mBulkFetchCount = 0;  +		mFetchCount = 0;   	}  } +class LLInventoryModelFetchItemResponder : public LLInventoryModel::fetchInventoryResponder +{ +public: +	LLInventoryModelFetchItemResponder(const LLSD& request_sd) : LLInventoryModel::fetchInventoryResponder(request_sd) {}; +	void result(const LLSD& content);			 +	void error(U32 status, const std::string& reason); +}; + +void LLInventoryModelFetchItemResponder::result( const LLSD& content ) +{ +	LLInventoryModel::fetchInventoryResponder::result(content); +	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); +} + +void LLInventoryModelFetchItemResponder::error( U32 status, const std::string& reason ) +{ +	LLInventoryModel::fetchInventoryResponder::error(status, reason); +	LLInventoryModelBackgroundFetch::instance().incrFetchCount(-1); +} +  class LLInventoryModelFetchDescendentsResponder: public LLHTTPClient::Responder  { @@ -458,7 +517,7 @@ void LLInventoryModelFetchDescendentsResponder::result(const LLSD& content)  		}  	} -	fetcher->incrBulkFetch(-1); +	fetcher->incrFetchCount(-1);  	if (fetcher->isBulkFetchProcessingComplete())  	{ @@ -477,7 +536,7 @@ void LLInventoryModelFetchDescendentsResponder::error(U32 status, const std::str  	llinfos << "LLInventoryModelFetchDescendentsResponder::error "  		<< status << ": " << reason << llendl; -	fetcher->incrBulkFetch(-1); +	fetcher->incrFetchCount(-1);  	if (status==499) // timed out  	{ @@ -508,12 +567,13 @@ BOOL LLInventoryModelFetchDescendentsResponder::getIsRecursive(const LLUUID& cat  // Bundle up a bunch of requests to send all at once.  // static    -void LLInventoryModelBackgroundFetch::bulkFetch(std::string url) +void LLInventoryModelBackgroundFetch::bulkFetch()  {  	//Background fetch is called from gIdleCallbacks in a loop until background fetch is stopped.  	//If there are items in mFetchQueue, we want to check the time since the last bulkFetch was   	//sent.  If it exceeds our retry time, go ahead and fire off another batch.   -	//Stopbackgroundfetch will be run from the Responder instead of here.   +	LLViewerRegion* region = gAgent.getRegion(); +	if (!region) return;  	S16 max_concurrent_fetches=8;  	F32 new_min_time = 0.5f;			//HACK!  Clean this up when old code goes away entirely. @@ -523,12 +583,13 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  	}  	if (gDisconnected || -		(mBulkFetchCount > max_concurrent_fetches) || +		(mFetchCount > max_concurrent_fetches) ||  		(mFetchTimer.getElapsedTimeF32() < mMinTimeBetweenFetches))  	{  		return; // just bail if we are disconnected  	}	 +	U32 item_count=0;  	U32 folder_count=0;  	U32 max_batch_size=5; @@ -536,83 +597,159 @@ void LLInventoryModelBackgroundFetch::bulkFetch(std::string url)  	uuid_vec_t recursive_cats; -	LLSD body; -	LLSD body_lib; +	LLSD folder_request_body; +	LLSD folder_request_body_lib; +	LLSD item_request_body; +	LLSD item_request_body_lib; -	while (!(mFetchQueue.empty()) && (folder_count < max_batch_size)) +	while (!mFetchQueue.empty()  +			&& (item_count + folder_count) < max_batch_size)  	{  		const FetchQueueInfo& fetch_info = mFetchQueue.front(); -		const LLUUID &cat_id = fetch_info.mCatUUID; -        if (cat_id.isNull()) //DEV-17797 -        { -			LLSD folder_sd; -			folder_sd["folder_id"]		= LLUUID::null.asString(); -			folder_sd["owner_id"]		= gAgent.getID(); -			folder_sd["sort_order"]		= (LLSD::Integer)sort_order; -			folder_sd["fetch_folders"]	= (LLSD::Boolean)FALSE; -			folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE; -			body["folders"].append(folder_sd); -            folder_count++; -        } -        else -        { -		    const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); +		if (fetch_info.mIsCategory) +		{ +			const LLUUID &cat_id = fetch_info.mUUID; +			if (cat_id.isNull()) //DEV-17797 +			{ +				LLSD folder_sd; +				folder_sd["folder_id"]		= LLUUID::null.asString(); +				folder_sd["owner_id"]		= gAgent.getID(); +				folder_sd["sort_order"]		= (LLSD::Integer)sort_order; +				folder_sd["fetch_folders"]	= (LLSD::Boolean)FALSE; +				folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE; +				folder_request_body["folders"].append(folder_sd); +				folder_count++; +			} +			else +			{ +				const LLViewerInventoryCategory* cat = gInventory.getCategory(cat_id); -		    if (cat) -		    { -			    if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion()) -			    { -				    LLSD folder_sd; -				    folder_sd["folder_id"]		= cat->getUUID(); -				    folder_sd["owner_id"]		= cat->getOwnerID(); -				    folder_sd["sort_order"]		= (LLSD::Integer)sort_order; -				    folder_sd["fetch_folders"]	= TRUE; //(LLSD::Boolean)sFullFetchStarted; -				    folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE; -				     -				    if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) -					    body_lib["folders"].append(folder_sd); -				    else -					    body["folders"].append(folder_sd); -				    folder_count++; -			    } -				// May already have this folder, but append child folders to list. -			    if (fetch_info.mRecursive) -			    {	 -					LLInventoryModel::cat_array_t* categories; -					LLInventoryModel::item_array_t* items; -					gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); -					for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); -						 it != categories->end(); -						 ++it) +				if (cat) +				{ +					if (LLViewerInventoryCategory::VERSION_UNKNOWN == cat->getVersion())  					{ -						mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); -				    } -			    } -		    } -        } -		if (fetch_info.mRecursive) -			recursive_cats.push_back(cat_id); +						LLSD folder_sd; +						folder_sd["folder_id"]		= cat->getUUID(); +						folder_sd["owner_id"]		= cat->getOwnerID(); +						folder_sd["sort_order"]		= (LLSD::Integer)sort_order; +						folder_sd["fetch_folders"]	= TRUE; //(LLSD::Boolean)sFullFetchStarted; +						folder_sd["fetch_items"]	= (LLSD::Boolean)TRUE; +				     +						if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID()) +							folder_request_body_lib["folders"].append(folder_sd); +						else +							folder_request_body["folders"].append(folder_sd); +						folder_count++; +					} +					// May already have this folder, but append child folders to list. +					if (fetch_info.mRecursive) +					{	 +						LLInventoryModel::cat_array_t* categories; +						LLInventoryModel::item_array_t* items; +						gInventory.getDirectDescendentsOf(cat->getUUID(), categories, items); +						for (LLInventoryModel::cat_array_t::const_iterator it = categories->begin(); +							 it != categories->end(); +							 ++it) +						{ +							mFetchQueue.push_back(FetchQueueInfo((*it)->getUUID(), fetch_info.mRecursive)); +						} +					} +				} +			} +			if (fetch_info.mRecursive) +				recursive_cats.push_back(cat_id); +		} +		else +		{ +			LLViewerInventoryItem* itemp = gInventory.getItem(fetch_info.mUUID); +			if (itemp) +			{ +				LLSD item_sd; +				item_sd["owner_id"] = itemp->getPermissions().getOwner(); +				item_sd["item_id"] = itemp->getUUID(); +				if (itemp->getPermissions().getOwner() == gAgent.getID()) +				{ +					item_request_body.append(item_sd); +				} +				else +				{ +					item_request_body_lib.append(item_sd); +				} +				//itemp->fetchFromServer(); +				item_count++; +			} +		}  		mFetchQueue.pop_front();  	} -	if (folder_count > 0) +	if (item_count + folder_count > 0)  	{ -		mBulkFetchCount++; -		if (body["folders"].size()) +		if (folder_count)  		{ -			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body, recursive_cats); -			LLHTTPClient::post(url, body, fetcher, 300.0); +			std::string url = region->getCapability("FetchInventoryDescendents2");    +			mFetchCount++; +			if (folder_request_body["folders"].size()) +			{ +				LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body, recursive_cats); +				LLHTTPClient::post(url, folder_request_body, fetcher, 300.0); +			} +			if (folder_request_body_lib["folders"].size()) +			{ +				std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2"); + +				LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(folder_request_body_lib, recursive_cats); +				LLHTTPClient::post(url_lib, folder_request_body_lib, fetcher, 300.0); +			}  		} -		if (body_lib["folders"].size()) +		if (item_count)  		{ -			std::string url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents2"); -			 -			LLInventoryModelFetchDescendentsResponder *fetcher = new LLInventoryModelFetchDescendentsResponder(body_lib, recursive_cats); -			LLHTTPClient::post(url_lib, body_lib, fetcher, 300.0); +			std::string url; + +			if (item_request_body.size()) +			{ +				mFetchCount++; +				url = region->getCapability("FetchInventory2"); +				if (!url.empty()) +				{ +					LLSD body; +					body["agent_id"]	= gAgent.getID(); +					body["items"] = item_request_body; + +					LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body)); +				} +				//else +				//{ +				//	LLMessageSystem* msg = gMessageSystem; +				//	msg->newMessage("FetchInventory"); +				//	msg->nextBlock("AgentData"); +				//	msg->addUUID("AgentID", gAgent.getID()); +				//	msg->addUUID("SessionID", gAgent.getSessionID()); +				//	msg->nextBlock("InventoryData"); +				//	msg->addUUID("OwnerID", mPermissions.getOwner()); +				//	msg->addUUID("ItemID", mUUID); +				//	gAgent.sendReliableMessage(); +				//} +			} + +			if (item_request_body_lib.size()) +			{ +				mFetchCount++; + +				url = region->getCapability("FetchLib2"); +				if (!url.empty()) +				{ +					LLSD body; +					body["agent_id"]	= gAgent.getID(); +					body["items"] = item_request_body_lib; + +					LLHTTPClient::post(url, body, new LLInventoryModelFetchItemResponder(body)); +				} +			}  		}  		mFetchTimer.reset();  	} +  	else if (isBulkFetchProcessingComplete())  	{  		setAllFoldersFetched(); @@ -624,7 +761,7 @@ bool LLInventoryModelBackgroundFetch::fetchQueueContainsNoDescendentsOf(const LL  	for (fetch_queue_t::const_iterator it = mFetchQueue.begin();  		 it != mFetchQueue.end(); ++it)  	{ -		const LLUUID& fetch_id = (*it).mCatUUID; +		const LLUUID& fetch_id = (*it).mUUID;  		if (gInventory.isObjectDescendentOf(fetch_id, cat_id))  			return false;  	} diff --git a/indra/newview/llinventorymodelbackgroundfetch.h b/indra/newview/llinventorymodelbackgroundfetch.h index c35c785ceb..9dfedddd6d 100644 --- a/indra/newview/llinventorymodelbackgroundfetch.h +++ b/indra/newview/llinventorymodelbackgroundfetch.h @@ -48,7 +48,7 @@ public:  	// This gets triggered when performing a filter-search.  	void start(const LLUUID& cat_id = LLUUID::null, BOOL recursive = TRUE); -	BOOL backgroundFetchActive() const; +	BOOL folderFetchActive() const;  	bool isEverythingFetched() const; // completing the fetch once per session should be sufficient  	bool libraryFetchStarted() const; @@ -60,14 +60,13 @@ public:  	bool inventoryFetchInProgress() const;      void findLostItems();	 +	void incrFetchCount(S16 fetching);  protected: -	void incrBulkFetch(S16 fetching);  	bool isBulkFetchProcessingComplete() const; -	void bulkFetch(std::string url); +	void bulkFetch();  	void backgroundFetch();  	static void backgroundFetchCB(void*); // background fetch idle function -	void stopBackgroundFetch(); // stop fetch process  	void setAllFoldersFetched();  	bool fetchQueueContainsNoDescendentsOf(const LLUUID& cat_id) const; @@ -77,7 +76,8 @@ private:  	BOOL mAllFoldersFetched;  	BOOL mBackgroundFetchActive; -	S16 mBulkFetchCount; +	bool mFolderFetchActive; +	S16 mFetchCount;  	BOOL mTimelyFetchPending;  	S32 mNumFetchRetries; @@ -87,11 +87,11 @@ private:  	struct FetchQueueInfo  	{ -		FetchQueueInfo(const LLUUID& id, BOOL recursive) : -			mCatUUID(id), mRecursive(recursive) -		{ -		} -		LLUUID mCatUUID; +		FetchQueueInfo(const LLUUID& id, BOOL recursive, bool is_category = true) : +			mUUID(id), mRecursive(recursive), mIsCategory(is_category) +		{} +		LLUUID mUUID; +		bool mIsCategory;  		BOOL mRecursive;  	};  	typedef std::deque<FetchQueueInfo> fetch_queue_t; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index 382569fa3a..01a8ecfb5d 100644 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -817,7 +817,7 @@ BOOL LLInventoryPanel::handleHover(S32 x, S32 y, MASK mask)  	if(handled)  	{  		ECursorType cursor = getWindow()->getCursor(); -		if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive() && cursor == UI_CURSOR_ARROW) +		if (LLInventoryModelBackgroundFetch::instance().folderFetchActive() && cursor == UI_CURSOR_ARROW)  		{  			// replace arrow cursor with arrow and hourglass cursor  			getWindow()->setCursor(UI_CURSOR_WORKING); diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h index 8279163762..7d805f6862 100644 --- a/indra/newview/llinventorypanel.h +++ b/indra/newview/llinventorypanel.h @@ -160,6 +160,8 @@ public:  	void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action); +	LLHandle<LLInventoryPanel> getInventoryPanelHandle() const { return getDerivedHandle<LLInventoryPanel>(); } +  	// Callbacks  	void doToSelected(const LLSD& userdata);  	void doCreate(const LLSD& userdata); diff --git a/indra/newview/llmemoryview.cpp b/indra/newview/llmemoryview.cpp index 7e9c3c84a7..c0a323d6cb 100644 --- a/indra/newview/llmemoryview.cpp +++ b/indra/newview/llmemoryview.cpp @@ -220,7 +220,7 @@ void LLMemoryView::draw()  	S32 x, y;  	S32 margin = 10; -	S32 texth = (S32)LLFontGL::getFontMonospace()->getLineHeight(); +	S32 texth = LLFontGL::getFontMonospace()->getLineHeight();  	S32 xleft = margin;  	S32 ytop = height - margin; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index b02bf79a28..bd20210190 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -728,7 +728,7 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id)  			if (!http_url.empty())  			{				  				ret = mCurlRequest->getByteRange(http_url, headers, offset, size, -										   new LLMeshSkinInfoResponder(mesh_id, offset, size)); +												 new LLMeshSkinInfoResponder(mesh_id, offset, size));  				if(ret)  				{  					LLMeshRepository::sHTTPRequestCount++; @@ -805,7 +805,7 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)  			if (!http_url.empty())  			{				  				ret = mCurlRequest->getByteRange(http_url, headers, offset, size, -										   new LLMeshDecompositionResponder(mesh_id, offset, size)); +												 new LLMeshDecompositionResponder(mesh_id, offset, size));  				if(ret)  				{  					LLMeshRepository::sHTTPRequestCount++; @@ -881,7 +881,7 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)  			if (!http_url.empty())  			{				  				ret = mCurlRequest->getByteRange(http_url, headers, offset, size, -										   new LLMeshPhysicsShapeResponder(mesh_id, offset, size)); +												 new LLMeshPhysicsShapeResponder(mesh_id, offset, size));  				if(ret)  				{ @@ -1093,17 +1093,19 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat  bool LLMeshRepoThread::lodReceived(const LLVolumeParams& mesh_params, S32 lod, U8* data, S32 data_size)  { -	LLVolume* volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod)); +	LLPointer<LLVolume> volume = new LLVolume(mesh_params, LLVolumeLODGroup::getVolumeScaleFromDetail(lod));  	std::string mesh_string((char*) data, data_size);  	std::istringstream stream(mesh_string);  	if (volume->unpackVolumeFaces(stream, data_size))  	{ -		LoadedMesh mesh(volume, mesh_params, lod);  		if (volume->getNumFaces() > 0)  		{ -			LLMutexLock lock(mMutex); -			mLoadedQ.push(mesh); +			LoadedMesh mesh(volume, mesh_params, lod); +			{ +				LLMutexLock lock(mMutex); +				mLoadedQ.push(mesh); +			}  			return true;  		}  	} diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h index 04e1570081..7a70370fe3 100644 --- a/indra/newview/llmutelist.h +++ b/indra/newview/llmutelist.h @@ -29,6 +29,7 @@  #include "llstring.h"  #include "lluuid.h" +#include "llextendedstatus.h"  class LLViewerObject;  class LLMessageSystem; diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp index 4512c14b7a..b4224e30e6 100644 --- a/indra/newview/llnearbychatbar.cpp +++ b/indra/newview/llnearbychatbar.cpp @@ -124,7 +124,7 @@ BOOL LLNearbyChatBar::postBuild()  // virtual  void LLNearbyChatBar::onOpen(const LLSD& key)  { -	enableTranslationCheckbox(LLTranslate::isTranslationConfigured()); +	showTranslationCheckbox(LLTranslate::isTranslationConfigured());  }  bool LLNearbyChatBar::applyRectControl() @@ -170,9 +170,9 @@ void LLNearbyChatBar::showHistory()  	}  } -void LLNearbyChatBar::enableTranslationCheckbox(BOOL enable) +void LLNearbyChatBar::showTranslationCheckbox(BOOL show)  { -	getChild<LLUICtrl>("translate_chat_checkbox")->setEnabled(enable); +	getChild<LLUICtrl>("translate_chat_checkbox_lp")->setVisible(show);  }  void LLNearbyChatBar::draw() diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h index baf12a06ea..8547cf0bce 100644 --- a/indra/newview/llnearbychatbar.h +++ b/indra/newview/llnearbychatbar.h @@ -61,7 +61,7 @@ public:  	static void sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL animate);  	void showHistory(); -	void enableTranslationCheckbox(BOOL enable); +	void showTranslationCheckbox(BOOL show);  	/*virtual*/void setMinimized(BOOL b);  protected: diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index 15d5d7c162..1bda7640bd 100644 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -74,6 +74,8 @@ const F32 DOT_SCALE = 0.75f;  const F32 MIN_PICK_SCALE = 2.f;  const S32 MOUSE_DRAG_SLOP = 2;		// How far the mouse needs to move before we think it's a drag +const F64 COARSEUPDATE_MAX_Z = 1020.0f; +  LLNetMap::LLNetMap (const Params & p)  :	LLUICtrl (p),  	mBackgroundColor (p.bg_color()), @@ -300,7 +302,8 @@ void LLNetMap::draw()  		}  		LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal); -		map_center_agent -= gAgentCamera.getCameraPositionAgent(); +		LLVector3 camera_position = gAgentCamera.getCameraPositionAgent(); +		map_center_agent -= camera_position;  		map_center_agent.mV[VX] *= mScale/region_width;  		map_center_agent.mV[VY] *= mScale/region_width; @@ -321,9 +324,6 @@ void LLNetMap::draw()  		gGL.popMatrix(); -		LLVector3d pos_global; -		LLVector3 pos_map; -  		// Mouse pointer in local coordinates  		S32 local_mouse_x;  		S32 local_mouse_y; @@ -333,90 +333,67 @@ void LLNetMap::draw()  		F32 closest_dist_squared = F32_MAX; // value will be overridden in the loop  		F32 min_pick_dist_squared = (mDotRadius * MIN_PICK_SCALE) * (mDotRadius * MIN_PICK_SCALE); +		LLVector3 pos_map; +		uuid_vec_t avatar_ids; +		std::vector<LLVector3d> positions; +		bool unknown_relative_z; + +		LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgentCamera.getCameraPositionGlobal()); +  		// Draw avatars -		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); -			 iter != LLWorld::getInstance()->getRegionList().end(); ++iter) +		for (U32 i = 0; i < avatar_ids.size(); i++)  		{ -			LLViewerRegion* regionp = *iter; -			const LLVector3d& origin_global = regionp->getOriginGlobal(); - -			S32 count = regionp->mMapAvatars.count(); -			S32 i; -			LLVector3 pos_local; -			U32 compact_local; -			U8 bits; -			// TODO: it'd be very cool to draw these in sorted order from lowest Z to highest. -			// just be careful to sort the avatar IDs along with the positions. -MG -			for (i = 0; i < count; i++) -			{ -				compact_local = regionp->mMapAvatars.get(i); +			pos_map = globalPosToView(positions[i]); +			LLUUID uuid = avatar_ids[i]; -				bits = compact_local & 0xFF; -				pos_local.mV[VZ] = F32(bits) * 4.f; -				compact_local >>= 8; +			bool show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL); -				bits = compact_local & 0xFF; -				pos_local.mV[VY] = (F32)bits; -				compact_local >>= 8; +			LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color; -				bits = compact_local & 0xFF; -				pos_local.mV[VX] = (F32)bits; +			unknown_relative_z = positions[i].mdV[VZ] == COARSEUPDATE_MAX_Z && +					camera_position.mV[VZ] >= COARSEUPDATE_MAX_Z; -				pos_global.setVec( pos_local ); -				pos_global += origin_global; +			LLWorldMapView::drawAvatar( +				pos_map.mV[VX], pos_map.mV[VY],  +				color,  +				pos_map.mV[VZ], mDotRadius, +				unknown_relative_z); -				pos_map = globalPosToView(pos_global); - -				LLUUID uuid(NULL); -				BOOL show_as_friend = FALSE; -				if( i < regionp->mMapAvatarIDs.count()) +			if(uuid.notNull()) +			{ +				bool selected = false; +				uuid_vec_t::iterator sel_iter = gmSelected.begin(); +				for (; sel_iter != gmSelected.end(); sel_iter++)  				{ -					uuid = regionp->mMapAvatarIDs.get(i); -					show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL); +					if(*sel_iter == uuid) +					{ +						selected = true; +						break; +					}  				} - -				LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color; -				LLWorldMapView::drawAvatar( -					pos_map.mV[VX], pos_map.mV[VY],  -					color,  -					pos_map.mV[VZ], mDotRadius); - -				if(uuid.notNull()) +				if(selected)  				{ -					bool selected = false; -					uuid_vec_t::iterator sel_iter = gmSelected.begin(); -					for (; sel_iter != gmSelected.end(); sel_iter++) +					if( (pos_map.mV[VX] < 0) || +						(pos_map.mV[VY] < 0) || +						(pos_map.mV[VX] >= getRect().getWidth()) || +						(pos_map.mV[VY] >= getRect().getHeight()) )  					{ -						if(*sel_iter == uuid) -						{ -							selected = true; -							break; -						} -					} -					if(selected) +						S32 x = llround( pos_map.mV[VX] ); +						S32 y = llround( pos_map.mV[VY] ); +						LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10); +					} else  					{ -						if( (pos_map.mV[VX] < 0) || -							(pos_map.mV[VY] < 0) || -							(pos_map.mV[VX] >= getRect().getWidth()) || -							(pos_map.mV[VY] >= getRect().getHeight()) ) -						{ -							S32 x = llround( pos_map.mV[VX] ); -							S32 y = llround( pos_map.mV[VY] ); -							LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10); -						} else -						{ -							LLWorldMapView::drawTrackingDot(pos_map.mV[VX],pos_map.mV[VY],color,0.f); -						} +						LLWorldMapView::drawTrackingDot(pos_map.mV[VX],pos_map.mV[VY],color,0.f);  					}  				} +			} -				F32	dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), -											  LLVector2(local_mouse_x,local_mouse_y)); -				if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared) -				{ -					closest_dist_squared = dist_to_cursor_squared; -					mClosestAgentToCursor = regionp->mMapAvatarIDs.get(i); -				} +			F32	dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), +										  LLVector2(local_mouse_x,local_mouse_y)); +			if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared) +			{ +				closest_dist_squared = dist_to_cursor_squared; +				mClosestAgentToCursor = uuid;  			}  		} @@ -440,7 +417,7 @@ void LLNetMap::draw()  		}  		// Draw dot for self avatar position -		pos_global = gAgent.getPositionGlobal(); +		LLVector3d pos_global = gAgent.getPositionGlobal();  		pos_map = globalPosToView(pos_global);  		S32 dot_width = llround(mDotRadius * 2.f);  		LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage; @@ -514,9 +491,11 @@ void LLNetMap::reshape(S32 width, S32 height, BOOL called_from_parent)  	createObjectImage();  } -LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos ) +LLVector3 LLNetMap::globalPosToView(const LLVector3d& global_pos)  { -	LLVector3d relative_pos_global = global_pos - gAgentCamera.getCameraPositionGlobal(); +	LLVector3d camera_position = gAgentCamera.getCameraPositionGlobal(); + +	LLVector3d relative_pos_global = global_pos - camera_position;  	LLVector3 pos_local;  	pos_local.setVec(relative_pos_global);  // convert to floats from doubles @@ -541,7 +520,7 @@ LLVector3 LLNetMap::globalPosToView( const LLVector3d& global_pos )  void LLNetMap::drawTracking(const LLVector3d& pos_global, const LLColor4& color,   							BOOL draw_arrow )  { -	LLVector3 pos_local = globalPosToView( pos_global ); +	LLVector3 pos_local = globalPosToView(pos_global);  	if( (pos_local.mV[VX] < 0) ||  		(pos_local.mV[VY] < 0) ||  		(pos_local.mV[VX] >= getRect().getWidth()) || diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h index 20fcee0814..1f7e7d68c6 100644 --- a/indra/newview/llnetmap.h +++ b/indra/newview/llnetmap.h @@ -33,9 +33,9 @@  #include "v3dmath.h"  #include "v4color.h"  #include "llpointer.h" +#include "llcoord.h"  class LLColor4U; -class LLCoordGL;  class LLImageRaw;  class LLViewerTexture;  class LLFloaterMap; diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp index 6105eff8ea..f792f53ac5 100644 --- a/indra/newview/llnotificationmanager.cpp +++ b/indra/newview/llnotificationmanager.cpp @@ -35,6 +35,7 @@  #include "llnotifications.h"  #include <boost/bind.hpp> +#include <boost/foreach.hpp>  using namespace LLNotificationsUI; @@ -48,6 +49,10 @@ LLNotificationManager::LLNotificationManager()  //--------------------------------------------------------------------------  LLNotificationManager::~LLNotificationManager()  { +	BOOST_FOREACH(listener_pair_t& pair, mChannelListeners) +	{ +		pair.second.disconnect(); +	}  }  //-------------------------------------------------------------------------- @@ -64,16 +69,16 @@ void LLNotificationManager::init()  	LLNotificationChannel::buildChannel("Browser", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "browser"));  	LLNotificationChannel::buildChannel("Outbox", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "outbox")); -	LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); -	LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); -	LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); -	LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1)); +	mChannelListeners["Notifications"] = LLNotifications::instance().getChannel("Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); +	mChannelListeners["NotificationTips"] = LLNotifications::instance().getChannel("NotificationTips")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); +	mChannelListeners["Group Notifications"] = LLNotifications::instance().getChannel("Group Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); +	mChannelListeners["Alerts"] = LLNotifications::instance().getChannel("Alerts")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); +	mChannelListeners["AlertModal"] = LLNotifications::instance().getChannel("AlertModal")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); +	mChannelListeners["IM Notifications"] = LLNotifications::instance().getChannel("IM Notifications")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); +	mChannelListeners["Offer"] = LLNotifications::instance().getChannel("Offer")->connectChanged(boost::bind(&LLNotificationManager::onNotification, this, _1)); +	mChannelListeners["Hints"] = LLNotifications::instance().getChannel("Hints")->connectChanged(boost::bind(&LLHintHandler::processNotification, LLHintHandler::getInstance(), _1)); +	mChannelListeners["Browser"] = LLNotifications::instance().getChannel("Browser")->connectChanged(boost::bind(&LLBrowserNotification::processNotification, LLBrowserNotification::getInstance(), _1)); +	mChannelListeners["Outbox"] = LLNotifications::instance().getChannel("Outbox")->connectChanged(boost::bind(&LLOutboxNotification::processNotification, LLOutboxNotification::getInstance(), _1));  	mNotifyHandlers["notify"] = boost::shared_ptr<LLEventHandler>(new LLScriptHandler(NT_NOTIFY, LLSD()));  	mNotifyHandlers["notifytip"] =  boost::shared_ptr<LLEventHandler>(new LLTipHandler(NT_NOTIFY, LLSD())); @@ -92,6 +97,9 @@ bool LLNotificationManager::onNotification(const LLSD& notify)  {  	LLSysHandler* handle = NULL; +	if (LLNotifications::destroyed()) +		return false; +  	LLNotificationPtr notification = LLNotifications::instance().find(notify["id"].asUUID());  	if (!notification)  diff --git a/indra/newview/llnotificationmanager.h b/indra/newview/llnotificationmanager.h index 16e82e4cce..27b6ba1c71 100644 --- a/indra/newview/llnotificationmanager.h +++ b/indra/newview/llnotificationmanager.h @@ -28,6 +28,8 @@  #ifndef LL_LLNOTIFICATIONMANAGER_H  #define LL_LLNOTIFICATIONMANAGER_H +#include "llevents.h" +  #include "lluictrl.h"  #include "llnotificationhandler.h" @@ -47,6 +49,7 @@ class LLToast;  class LLNotificationManager : public LLSingleton<LLNotificationManager>  {  	typedef std::pair<std::string, LLEventHandler*> eventhandlers; +	typedef std::pair<const std::string, LLBoundListener> listener_pair_t;  public:	  	LLNotificationManager();	  	virtual ~LLNotificationManager(); @@ -70,6 +73,8 @@ private:  	//TODO (*)  	std::map<std::string, boost::shared_ptr<LLEventHandler> > mNotifyHandlers;  	// cruft std::map<std::string, LLChatHandler*> mChatHandlers; + +	std::map<std::string, LLBoundListener> mChannelListeners;  };  } diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index a4f6921f98..7301b305b2 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -875,8 +875,15 @@ void LLPanelFace::getState()  			{  				getChild<LLUICtrl>("TexScaleU")->setValue(2.0f * getChild<LLUICtrl>("TexScaleU")->getValue().asReal() );  				getChild<LLUICtrl>("TexScaleV")->setValue(2.0f * getChild<LLUICtrl>("TexScaleV")->getValue().asReal() ); -			} +				// EXP-1507 (change label based on the mapping mode) +				getChild<LLUICtrl>("rpt")->setValue(getString("string repeats per meter")); +			} +			else +			if (selected_texgen == 0)  // FIXME: should not be magic numbers +			{ +				getChild<LLUICtrl>("rpt")->setValue(getString("string repeats per face")); +			}  		}  		{ diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp index fbe331c7ab..f825ee3215 100644 --- a/indra/newview/llpanelgrouproles.cpp +++ b/indra/newview/llpanelgrouproles.cpp @@ -749,7 +749,10 @@ LLPanelGroupMembersSubTab::LLPanelGroupMembersSubTab()  LLPanelGroupMembersSubTab::~LLPanelGroupMembersSubTab()  { -	gSavedSettings.setString("GroupMembersSortOrder", mMembersList->getSortColumnName()); +	if (mMembersList) +	{ +		gSavedSettings.setString("GroupMembersSortOrder", mMembersList->getSortColumnName()); +	}  }  BOOL LLPanelGroupMembersSubTab::postBuildSubTab(LLView* root) diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp index 0295ad151f..eda0749cdb 100644 --- a/indra/newview/llpanelimcontrolpanel.cpp +++ b/indra/newview/llpanelimcontrolpanel.cpp @@ -374,7 +374,7 @@ void LLPanelGroupControlPanel::draw()  {  	// Need to resort the participant list if it's in sort by recent speaker order.  	if (mParticipantList) -		mParticipantList->updateRecentSpeakersOrder(); +		mParticipantList->update();  	LLPanelChatControlPanel::draw();  } diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp index 058d1ad6bc..76aadcd913 100644 --- a/indra/newview/llpanellogin.cpp +++ b/indra/newview/llpanellogin.cpp @@ -216,6 +216,7 @@ void LLPanelLogin::addUsersWithFavoritesToUsername()  void LLPanelLogin::addFavoritesToStartLocation()  { +	// Clear the combo.  	LLComboBox* combo = getChild<LLComboBox>("start_location_combo");  	if (!combo) return;  	int num_items = combo->getItemCount(); @@ -223,6 +224,10 @@ void LLPanelLogin::addFavoritesToStartLocation()  	{  		combo->remove(i);  	} + +	// Load favorites into the combo. +	std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple(); +	std::string canonical_user_name = canonicalize_username(user_defined_name);  	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");  	LLSD fav_llsd;  	llifstream file; @@ -232,15 +237,18 @@ void LLPanelLogin::addFavoritesToStartLocation()  	for (LLSD::map_const_iterator iter = fav_llsd.beginMap();  		iter != fav_llsd.endMap(); ++iter)  	{ -		std::string user_defined_name = getChild<LLComboBox>("username_combo")->getSimple(); -  		// The account name in stored_favorites.xml has Resident last name even if user has  		// a single word account name, so it can be compared case-insensitive with the  		// user defined "firstname lastname". -		S32 res = LLStringUtil::compareInsensitive(canonicalize_username(user_defined_name), iter->first); -		if (res != 0) continue; +		S32 res = LLStringUtil::compareInsensitive(canonical_user_name, iter->first); +		if (res != 0) +		{ +			lldebugs << "Skipping favorites for " << iter->first << llendl; +			continue; +		}  		combo->addSeparator(); +		lldebugs << "Loading favorites for " << iter->first << llendl;  		LLSD user_llsd = iter->second;  		for (LLSD::array_const_iterator iter1 = user_llsd.beginArray();  			iter1 != user_llsd.endArray(); ++iter1) diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp index 374afb90be..c3c62920d3 100644 --- a/indra/newview/llpanelmaininventory.cpp +++ b/indra/newview/llpanelmaininventory.cpp @@ -567,7 +567,7 @@ void LLPanelMainInventory::updateItemcountText()  	std::string text = ""; -	if (LLInventoryModelBackgroundFetch::instance().backgroundFetchActive()) +	if (LLInventoryModelBackgroundFetch::instance().folderFetchActive())  	{  		text = getString("ItemcountFetching", string_args);  	} diff --git a/indra/newview/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp index 9c46f04abf..f1380e7a36 100644 --- a/indra/newview/llpanelpeople.cpp +++ b/indra/newview/llpanelpeople.cpp @@ -1162,8 +1162,13 @@ void LLPanelPeople::onAddFriendWizButtonClicked()  {  	// Show add friend wizard.  	LLFloaterAvatarPicker* picker = LLFloaterAvatarPicker::show(boost::bind(&LLPanelPeople::onAvatarPicked, _1, _2), FALSE, TRUE); +	if (!picker) +	{ +		return; +	} +  	// Need to disable 'ok' button when friend occurs in selection -	if (picker)	picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1)); +	picker->setOkBtnEnableCb(boost::bind(&LLPanelPeople::isItemsFreeOfFriends, this, _1));  	LLFloater* root_floater = gFloaterView->getParentFloater(this);  	if (root_floater)  	{ diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index 39c0628cbe..76d38f067d 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -818,7 +818,7 @@ bool LLPanelPrimMediaControls::isMouseOver()  		LLCoordGL cursor_pos_gl;  		S32 x, y;  		getWindow()->getCursorPosition(&cursor_pos_window); -		getWindow()->convertCoords(cursor_pos_window, &cursor_pos_gl); +		cursor_pos_gl = cursor_pos_window.convert();  		if(mMediaControlsStack->getVisible())  		{ diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h index 66956181f2..eeb433e306 100644 --- a/indra/newview/llpanelprimmediacontrols.h +++ b/indra/newview/llpanelprimmediacontrols.h @@ -30,9 +30,9 @@  #include "llpanel.h"  #include "llviewermedia.h"  #include "llnotificationptr.h" +#include "llcoord.h"  class LLButton; -class LLCoordWindow;  class LLIconCtrl;  class LLLayoutStack;  class LLProgressBar; diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp index 4bbfec8ab7..5fec6d967d 100644 --- a/indra/newview/llpanelvoiceeffect.cpp +++ b/indra/newview/llpanelvoiceeffect.cpp @@ -123,7 +123,6 @@ void LLPanelVoiceEffect::update(bool list_updated)  	if (mVoiceEffectCombo)  	{  		LLVoiceEffectInterface* effect_interface = LLVoiceClient::instance().getVoiceEffectInterface(); -		llassert(effect_interface);  		if (!effect_interface) return;  		if (list_updated)  		{ diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp index 5c95e805ce..975a6c67d8 100644 --- a/indra/newview/llparticipantlist.cpp +++ b/indra/newview/llparticipantlist.cpp @@ -390,7 +390,10 @@ void LLParticipantList::onAvatarListRefreshed(LLUICtrl* ctrl, const LLSD& param)  		{  			const LLPointer<LLSpeaker>& speakerp = *it; -			update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); +			if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) +			{ +				update_speaker_indicator(list, speakerp->mID, speakerp->mModeratorMutedVoice); +			}  		}  	}  } @@ -466,12 +469,12 @@ void LLParticipantList::setValidateSpeakerCallback(validate_speaker_callback_t c  	mValidateSpeakerCallback = cb;  } -void LLParticipantList::updateRecentSpeakersOrder() +void LLParticipantList::update()  { +	mSpeakerMgr->update(true); +  	if (E_SORT_BY_RECENT_SPEAKERS == getSortOrder() && !isHovered())  	{ -		// Need to update speakers to sort list correctly -		mSpeakerMgr->update(true);  		// Resort avatar list  		sort();  	} @@ -760,6 +763,7 @@ void LLParticipantList::LLParticipantListMenu::toggleMute(const LLSD& userdata,  	LLPointer<LLSpeaker> speakerp = mParent.mSpeakerMgr->findSpeaker(speaker_id);  	if (speakerp.isNull())  	{ +		LL_WARNS("Speakers") << "Speaker " << speaker_id << " not found" << llendl;  		return;  	}  	LLAvatarListItem* item = dynamic_cast<LLAvatarListItem*>(mParent.mAvatarList->getItemByValue(speaker_id)); diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h index a001d29b67..53966c15fe 100644 --- a/indra/newview/llparticipantlist.h +++ b/indra/newview/llparticipantlist.h @@ -72,9 +72,9 @@ public:  	const EParticipantSortOrder getSortOrder() const;  	/** -	 * Refreshes the participant list if it's in sort by recent speaker order. +	 * Refreshes the participant list.  	 */ -	void updateRecentSpeakersOrder(); +	void update();  	/**  	 * Set a callback to be called before adding a speaker. Invalid speakers will not be added. diff --git a/indra/newview/llplacesinventorybridge.cpp b/indra/newview/llplacesinventorybridge.cpp index 225ac6e224..fe4cc0f55f 100644 --- a/indra/newview/llplacesinventorybridge.cpp +++ b/indra/newview/llplacesinventorybridge.cpp @@ -89,7 +89,7 @@ void LLPlacesFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)  		std::vector<std::string> items;  		std::vector<std::string> disabled_items; -		LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); +		LLInventoryPanel* inv_panel = mInventoryPanel.get();  		bool is_open = false;  		if (inv_panel)  		{ @@ -137,7 +137,7 @@ void LLPlacesFolderBridge::performAction(LLInventoryModel* model, std::string ac  LLFolderViewFolder* LLPlacesFolderBridge::getFolder()  {  	LLFolderViewFolder* folder = NULL; -	LLInventoryPanel* inv_panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get()); +	LLInventoryPanel* inv_panel = mInventoryPanel.get();  	if (inv_panel)  	{  		folder = dynamic_cast<LLFolderViewFolder*>(inv_panel->getRootFolder()->getItemByID(mUUID)); diff --git a/indra/newview/llpopupview.cpp b/indra/newview/llpopupview.cpp index 9fbb67a63a..08829c1184 100644 --- a/indra/newview/llpopupview.cpp +++ b/indra/newview/llpopupview.cpp @@ -83,7 +83,7 @@ void LLPopupView::draw()  			LLUI::pushMatrix();  			{ -				LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f); +				LLUI::translate( (F32) screen_x, (F32) screen_y);  				popup->draw();  			}  			LLUI::popMatrix(); diff --git a/indra/newview/llpreview.h b/indra/newview/llpreview.h index 896e17c3c3..759430c3a5 100644 --- a/indra/newview/llpreview.h +++ b/indra/newview/llpreview.h @@ -32,6 +32,7 @@  #include "llpointer.h"  #include "lluuid.h"  #include "llinventoryobserver.h" +#include "llextendedstatus.h"  #include <map>  class LLInventoryItem; diff --git a/indra/newview/llpreviewanim.cpp b/indra/newview/llpreviewanim.cpp index 8e8b530e13..35ac0537a3 100644 --- a/indra/newview/llpreviewanim.cpp +++ b/indra/newview/llpreviewanim.cpp @@ -43,19 +43,7 @@ extern LLAgent gAgent;  LLPreviewAnim::LLPreviewAnim(const LLSD& key)  	: LLPreview( key )  { -} - -// static -void LLPreviewAnim::endAnimCallback( void *userdata ) -{ -	LLHandle<LLFloater>* handlep = ((LLHandle<LLFloater>*)userdata); -	LLFloater* self = handlep->get(); -	delete handlep; // done with the handle -	if (self) -	{ -		self->getChild<LLUICtrl>("Anim play btn")->setValue(FALSE); -		self->getChild<LLUICtrl>("Anim audition btn")->setValue(FALSE); -	} +	mCommitCallbackRegistrar.add("PreviewAnim.Play", boost::bind(&LLPreviewAnim::play, this, _2));  }  // virtual @@ -68,106 +56,115 @@ BOOL LLPreviewAnim::postBuild()  		getChild<LLUICtrl>("desc")->setValue(item->getDescription());  	} -	childSetAction("Anim play btn",playAnim, this); -	childSetAction("Anim audition btn",auditionAnim, this); -  	childSetCommitCallback("desc", LLPreview::onText, this);  	getChild<LLLineEditor>("desc")->setPrevalidate(&LLTextValidate::validateASCIIPrintableNoPipe); -	 +  	return LLPreview::postBuild();  } -void LLPreviewAnim::activate(e_activation_type type) +// static +// llinventorybridge also calls into here +void LLPreviewAnim::play(const LLSD& param)  { -	switch ( type )  +	const LLInventoryItem *item = getItem(); + +	if(item)  	{ -		case PLAY: +		LLUUID itemID=item->getAssetUUID(); + +		std::string btn_name = param.asString(); +		LLButton* btn_inuse; +		LLButton* btn_other; + +		if ("Inworld" == btn_name)  		{ -			playAnim( (void *) this ); -			break; +			btn_inuse = getChild<LLButton>("Inworld"); +			btn_other = getChild<LLButton>("Locally");  		} -		case AUDITION: +		else if ("Locally" == btn_name)  		{ -			auditionAnim( (void *) this ); -			break; +			btn_inuse = getChild<LLButton>("Locally"); +			btn_other = getChild<LLButton>("Inworld");  		} -		default: +		else  		{ -		//do nothing +			return;  		} -	} -} - -// static -void LLPreviewAnim::playAnim( void *userdata ) -{ -	LLPreviewAnim* self = (LLPreviewAnim*) userdata; -	const LLInventoryItem *item = self->getItem(); -	if(item) -	{ -		LLUUID itemID=item->getAssetUUID(); +		if (btn_inuse) +		{ +			btn_inuse->toggleState(); +		} -		LLButton* btn = self->getChild<LLButton>("Anim play btn"); -		if (btn) +		if (btn_other)  		{ -			btn->toggleState(); +			btn_other->setEnabled(false);  		} -		if (self->getChild<LLUICtrl>("Anim play btn")->getValue().asBoolean() )  +		if (getChild<LLUICtrl>(btn_name)->getValue().asBoolean() )   		{ -			self->mPauseRequest = NULL; -			gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_START); +			if("Inworld" == btn_name) +			{ +				gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_START); +			} +			else +			{ +				gAgentAvatarp->startMotion(item->getAssetUUID()); +			} +  			LLMotion* motion = gAgentAvatarp->findMotion(itemID);  			if (motion)  			{ -				motion->setDeactivateCallback(&endAnimCallback, (void *)(new LLHandle<LLFloater>(self->getHandle()))); +				mItemID = itemID; +				mDidStart = false;  			}  		}  		else  		{  			gAgentAvatarp->stopMotion(itemID);  			gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_STOP); + +			if (btn_other) +			{ +				btn_other->setEnabled(true); +			}  		}  	}  } -// static -void LLPreviewAnim::auditionAnim( void *userdata ) +// virtual +void LLPreviewAnim::draw()  { -	LLPreviewAnim* self = (LLPreviewAnim*) userdata; -	const LLInventoryItem *item = self->getItem(); - -	if(item) +	LLPreview::draw(); +	if (!this->mItemID.isNull())  	{ -		LLUUID itemID=item->getAssetUUID(); - -		LLButton* btn = self->getChild<LLButton>("Anim audition btn"); -		if (btn) -		{ -			btn->toggleState(); -		} -		 -		if (self->getChild<LLUICtrl>("Anim audition btn")->getValue().asBoolean() )  +		LLMotion* motion = gAgentAvatarp->findMotion(this->mItemID); +		if (motion)  		{ -			self->mPauseRequest = NULL; -			gAgentAvatarp->startMotion(item->getAssetUUID()); -			LLMotion* motion = gAgentAvatarp->findMotion(itemID); -			 -			if (motion) +			if (motion->isStopped() && this->mDidStart)  			{ -				motion->setDeactivateCallback(&endAnimCallback, (void *)(new LLHandle<LLFloater>(self->getHandle()))); +				cleanup(); +			} +			if(gAgentAvatarp->isMotionActive(this->mItemID) && !this->mDidStart) +			{ +				this->mDidStart = true;  			} -		} -		else -		{ -			gAgentAvatarp->stopMotion(itemID); -			gAgent.sendAnimationRequest(itemID, ANIM_REQUEST_STOP);  		}  	}  }  // virtual +void LLPreviewAnim::cleanup() +{ +	this->mItemID = LLUUID::null; +	this->mDidStart = false; +	getChild<LLUICtrl>("Inworld")->setValue(FALSE); +	getChild<LLUICtrl>("Locally")->setValue(FALSE); +	getChild<LLUICtrl>("Inworld")->setEnabled(true); +	getChild<LLUICtrl>("Locally")->setEnabled(true); +} + +// virtual  void LLPreviewAnim::onClose(bool app_quitting)  {  	const LLInventoryItem *item = getItem(); @@ -176,12 +173,5 @@ void LLPreviewAnim::onClose(bool app_quitting)  	{  		gAgentAvatarp->stopMotion(item->getAssetUUID());  		gAgent.sendAnimationRequest(item->getAssetUUID(), ANIM_REQUEST_STOP); -		LLMotion* motion = gAgentAvatarp->findMotion(item->getAssetUUID()); -		 -		if (motion) -		{ -			// *TODO: minor memory leak here, user data is never deleted (Use real callbacks) -			motion->setDeactivateCallback(NULL, (void *)NULL); -		}  	}  } diff --git a/indra/newview/llpreviewanim.h b/indra/newview/llpreviewanim.h index 32e07ee33a..8eaed6ca1f 100644 --- a/indra/newview/llpreviewanim.h +++ b/indra/newview/llpreviewanim.h @@ -33,24 +33,18 @@  class LLPreviewAnim : public LLPreview  {  public: -	enum e_activation_type { NONE = 0, PLAY = 1, AUDITION = 2 }; -	LLPreviewAnim(const LLSD& key); -	static void playAnim( void* userdata ); -	static void auditionAnim( void* userdata ); -	static void endAnimCallback( void *userdata ); +	LLPreviewAnim(const LLSD& key);  	/*virtual*/	BOOL postBuild();  	/*virtual*/ void onClose(bool app_quitting); -	void activate(e_activation_type type); +	void draw(); +	void cleanup(); +	void play(const LLSD& param);  protected: -	LLAnimPauseRequest	mPauseRequest; -	LLUUID		mItemID; -	std::string	mTitle; -	LLUUID		mObjectID; -	LLButton*	mPlayBtn; -	LLButton*	mAuditionBtn; +	LLUUID	mItemID; +	bool	mDidStart;  }; -#endif  // LL_LLPREVIEWSOUND_H +#endif  // LL_LLPREVIEWANIM_H diff --git a/indra/newview/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp index 5301955964..d340b304ca 100644 --- a/indra/newview/llscreenchannel.cpp +++ b/indra/newview/llscreenchannel.cpp @@ -195,17 +195,18 @@ LLScreenChannel::~LLScreenChannel()  } -std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher) +std::list<const LLToast*> LLScreenChannel::findToasts(const Matcher& matcher)  { -	std::list<LLToast*> res; +	std::list<const LLToast*> res;  	// collect stored toasts  	for (std::vector<ToastElem>::iterator it = mStoredToastList.begin(); it  			!= mStoredToastList.end(); it++)  	{ -		if (matcher.matches(it->toast->getNotification())) +		const LLToast* toast = it->getToast(); +		if (toast && matcher.matches(toast->getNotification()))  		{ -			res.push_back(it->toast); +			res.push_back(toast);  		}  	} @@ -213,9 +214,10 @@ std::list<LLToast*> LLScreenChannel::findToasts(const Matcher& matcher)  	for (std::vector<ToastElem>::iterator it = mToastList.begin(); it  			!= mToastList.end(); it++)  	{ -		if (matcher.matches(it->toast->getNotification())) +		const LLToast* toast = it->getToast(); +		if (toast && matcher.matches(toast->getNotification()))  		{ -			res.push_back(it->toast); +			res.push_back(toast);  		}  	} @@ -260,15 +262,16 @@ void LLScreenChannel::addToast(const LLToast::Params& p)  		return;  	} -	ToastElem new_toast_elem(p); +	LLToast* toast = new LLToast(p); +	ToastElem new_toast_elem(toast->getHandle()); -	new_toast_elem.toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1)); -	new_toast_elem.toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1)); +	toast->setOnFadeCallback(boost::bind(&LLScreenChannel::onToastFade, this, _1)); +	toast->setOnToastDestroyedCallback(boost::bind(&LLScreenChannel::onToastDestroyed, this, _1));  	if(mControlHovering)  	{ -		new_toast_elem.toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); -		new_toast_elem.toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, new_toast_elem.toast)); -		new_toast_elem.toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, new_toast_elem.toast)); +		toast->setOnToastHoverCallback(boost::bind(&LLScreenChannel::onToastHover, this, _1, _2)); +		toast->setMouseEnterCallback(boost::bind(&LLScreenChannel::stopToastTimer, this, toast)); +		toast->setMouseLeaveCallback(boost::bind(&LLScreenChannel::startToastTimer, this, toast));  	}  	if(show_toast) @@ -340,13 +343,13 @@ void LLScreenChannel::onToastFade(LLToast* toast)  //--------------------------------------------------------------------------  void LLScreenChannel::deleteToast(LLToast* toast)  { -	if (toast->isDead()) +	if (!toast || toast->isDead())  	{  		return;  	}  	// send signal to observers about destroying of a toast -	toast->mOnDeleteToastSignal(toast); +	toast->closeToast();  	// update channel's Hovering state  	// turning hovering off manually because onMouseLeave won't happen if a toast was closed using a keyboard @@ -354,9 +357,6 @@ void LLScreenChannel::deleteToast(LLToast* toast)  	{  		mHoveredToast  = NULL;  	} - -	// close the toast -	toast->closeFloater();  }  //-------------------------------------------------------------------------- @@ -364,12 +364,16 @@ void LLScreenChannel::deleteToast(LLToast* toast)  void LLScreenChannel::storeToast(ToastElem& toast_elem)  {  	// do not store clones -	std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), toast_elem.id); +	std::vector<ToastElem>::iterator it = find(mStoredToastList.begin(), mStoredToastList.end(), toast_elem.getID());  	if( it != mStoredToastList.end() )  		return; -	mStoredToastList.push_back(toast_elem); -	mOnStoreToast(toast_elem.toast->getPanel(), toast_elem.id); +	const LLToast* toast = toast_elem.getToast(); +	if (toast) +	{ +		mStoredToastList.push_back(toast_elem); +		mOnStoreToast(toast->getPanel(), toast->getNotificationID()); +	}  }  //-------------------------------------------------------------------------- @@ -382,9 +386,13 @@ void LLScreenChannel::loadStoredToastsToChannel()  	for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)  	{ -		(*it).toast->setIsHidden(false); -		(*it).toast->startTimer(); -		mToastList.push_back((*it)); +		LLToast* toast = it->getToast(); +		if (toast) +		{ +			toast->setIsHidden(false); +			toast->startTimer(); +			mToastList.push_back(*it); +		}  	}  	mStoredToastList.clear(); @@ -399,17 +407,19 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)  	if( it == mStoredToastList.end() )  		return; -	LLToast* toast = (*it).toast; - -	if(toast->getVisible()) +	LLToast* toast = it->getToast(); +	if (toast)  	{ -		// toast is already in channel -		return; -	} +		if(toast->getVisible()) +		{ +			// toast is already in channel +			return; +		} -	toast->setIsHidden(false); -	toast->startTimer(); -	mToastList.push_back((*it)); +		toast->setIsHidden(false); +		toast->startTimer(); +		mToastList.push_back(*it); +	}  	redrawToasts();  } @@ -423,9 +433,19 @@ void LLScreenChannel::removeStoredToastByNotificationID(LLUUID id)  	if( it == mStoredToastList.end() )  		return; -	LLToast* toast = (*it).toast; -	mStoredToastList.erase(it); -	mRejectToastSignal(toast->getNotificationID()); +	const LLToast* toast = it->getToast(); +	if (toast) +	{ +		mRejectToastSignal(toast->getNotificationID()); +	} + +	// Call find() once more, because the mStoredToastList could have been changed +	// in mRejectToastSignal callback and the iterator could have become invalid. +	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); +	if (it != mStoredToastList.end()) +	{ +		mStoredToastList.erase(it); +	}  }  //-------------------------------------------------------------------------- @@ -436,21 +456,22 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id)  	if( it != mToastList.end())  	{ -		LLToast* toast = (*it).toast; +		LLToast* toast = it->getToast();  		// if it is a notification toast and notification is UnResponded - then respond on it  		// else - simply destroy a toast  		//  		// NOTE:	if a notification is unresponded this function will be called twice for the same toast.  		//			At first, the notification will be discarded, at second (it will be caused by discarding),  		//			the toast will be destroyed. -		if(toast->isNotificationValid()) +		if(toast && toast->isNotificationValid())  		{  			mRejectToastSignal(toast->getNotificationID());  		}  		else  		{ -			mToastList.erase(it); +  			deleteToast(toast); +			mToastList.erase(it);  			redrawToasts();  		}  		return; @@ -459,20 +480,31 @@ void LLScreenChannel::killToastByNotificationID(LLUUID id)  	// searching among stored toasts  	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); -	if( it != mStoredToastList.end() ) +	if (it != mStoredToastList.end()) +	{ +		LLToast* toast = it->getToast(); +		if (toast) +		{ +			// send signal to a listener to let him perform some action on toast rejecting +			mRejectToastSignal(toast->getNotificationID()); +			deleteToast(toast); +		} +	} + +	// Call find() once more, because the mStoredToastList could have been changed +	// in mRejectToastSignal callback and the iterator could have become invalid. +	it = find(mStoredToastList.begin(), mStoredToastList.end(), id); +	if (it != mStoredToastList.end())  	{ -		LLToast* toast = (*it).toast;  		mStoredToastList.erase(it); -		// send signal to a listener to let him perform some action on toast rejecting -		mRejectToastSignal(toast->getNotificationID()); -		deleteToast(toast);  	} +  }  void LLScreenChannel::killMatchedToasts(const Matcher& matcher)  { -	std::list<LLToast*> to_delete = findToasts(matcher); -	for (std::list<LLToast*>::iterator it = to_delete.begin(); it +	std::list<const LLToast*> to_delete = findToasts(matcher); +	for (std::list<const LLToast*>::iterator it = to_delete.begin(); it  			!= to_delete.end(); it++)  	{  		killToastByNotificationID((*it)-> getNotificationID()); @@ -486,12 +518,15 @@ void LLScreenChannel::modifyToastByNotificationID(LLUUID id, LLPanel* panel)  	if( it != mToastList.end() && panel)  	{ -		LLToast* toast = (*it).toast; -		LLPanel* old_panel = toast->getPanel(); -		toast->removeChild(old_panel); -		delete old_panel; -		toast->insertPanel(panel); -		toast->startTimer(); +		LLToast* toast = it->getToast(); +		if (toast) +		{ +			LLPanel* old_panel = toast->getPanel(); +			toast->removeChild(old_panel); +			delete old_panel; +			toast->insertPanel(panel); +			toast->startTimer(); +		}  		redrawToasts();  	}  } @@ -540,16 +575,29 @@ void LLScreenChannel::showToastsBottom()  	{  		if(it != mToastList.rbegin())  		{ -			LLToast* toast = (*(it-1)).toast; +			LLToast* toast = (it-1)->getToast(); +			if (!toast) +			{ +				llwarns << "Attempt to display a deleted toast." << llendl; +				return; +			} +  			bottom = toast->getRect().mTop - toast->getTopPad();  			toast_margin = gSavedSettings.getS32("ToastGap");  		} -		toast_rect = (*it).toast->getRect(); +		LLToast* toast = it->getToast(); +		if(!toast) +		{ +			llwarns << "Attempt to display a deleted toast." << llendl; +			return; +		} + +		toast_rect = toast->getRect();  		toast_rect.setOriginAndSize(getRect().mRight - toast_rect.getWidth(),  				bottom + toast_margin, toast_rect.getWidth(),  				toast_rect.getHeight()); -		(*it).toast->setRect(toast_rect); +		toast->setRect(toast_rect);  		if(floater && floater->overlapsScreenChannel())  		{ @@ -561,7 +609,7 @@ void LLScreenChannel::showToastsBottom()  				{  					shift += floater->getDockControl()->getTongueHeight();  				} -				(*it).toast->translate(0, shift); +				toast->translate(0, shift);  			}  			LLRect channel_rect = getChannelRect(); @@ -572,13 +620,13 @@ void LLScreenChannel::showToastsBottom()  			}  		} -		bool stop_showing_toasts = (*it).toast->getRect().mTop > getRect().mTop; +		bool stop_showing_toasts = toast->getRect().mTop > getRect().mTop;  		if(!stop_showing_toasts)  		{  			if( it != mToastList.rend()-1)  			{ -				S32 toast_top = (*it).toast->getRect().mTop + gSavedSettings.getS32("ToastGap"); +				S32 toast_top = toast->getRect().mTop + gSavedSettings.getS32("ToastGap");  				stop_showing_toasts = toast_top > getRect().mTop;  			}  		}  @@ -592,17 +640,17 @@ void LLScreenChannel::showToastsBottom()  		if(stop_showing_toasts)  			break; -		if( !(*it).toast->getVisible() ) +		if( !toast->getVisible() )  		{  			// HACK  			// EXT-2653: it is necessary to prevent overlapping for secondary showed toasts -			(*it).toast->setVisible(TRUE); +			toast->setVisible(TRUE);  		}		 -		if(!(*it).toast->hasFocus()) +		if(!toast->hasFocus())  		{  			// Fixing Z-order of toasts (EXT-4862)  			// Next toast will be positioned under this one. -			gFloaterView->sendChildToBack((*it).toast); +			gFloaterView->sendChildToBack(toast);  		}  	} @@ -612,7 +660,11 @@ void LLScreenChannel::showToastsBottom()  		mHiddenToastsNum = 0;  		for(; it != mToastList.rend(); it++)  		{ -			(*it).toast->hide(); +			LLToast* toast = it->getToast(); +			if (toast) +			{ +				toast->hide(); +			}  		}  	}  } @@ -620,17 +672,31 @@ void LLScreenChannel::showToastsBottom()  //--------------------------------------------------------------------------  void LLScreenChannel::showToastsCentre()  { -	LLRect	toast_rect;	 -	S32		bottom = (getRect().mTop - getRect().mBottom)/2 + mToastList[0].toast->getRect().getHeight()/2; +	LLToast* toast = mToastList[0].getToast(); +	if (!toast) +	{ +		llwarns << "Attempt to display a deleted toast." << llendl; +		return; +	} + +	LLRect	toast_rect; +	S32		bottom = (getRect().mTop - getRect().mBottom)/2 + toast->getRect().getHeight()/2;  	std::vector<ToastElem>::reverse_iterator it;  	for(it = mToastList.rbegin(); it != mToastList.rend(); ++it)  	{ -		toast_rect = (*it).toast->getRect(); +		LLToast* toast = it->getToast(); +		if (!toast) +		{ +			llwarns << "Attempt to display a deleted toast." << llendl; +			return; +		} + +		toast_rect = toast->getRect();  		toast_rect.setLeftTopAndSize(getRect().mLeft - toast_rect.getWidth() / 2, bottom + toast_rect.getHeight() / 2 + gSavedSettings.getS32("ToastGap"), toast_rect.getWidth() ,toast_rect.getHeight()); -		(*it).toast->setRect(toast_rect); +		toast->setRect(toast_rect); -		(*it).toast->setVisible(TRUE);	 +		toast->setVisible(TRUE);  	}  } @@ -652,16 +718,29 @@ void LLScreenChannel::showToastsTop()  	{  		if(it != mToastList.rbegin())  		{ -			LLToast* toast = (*(it-1)).toast; +			LLToast* toast = (it-1)->getToast(); +			if (!toast) +			{ +				llwarns << "Attempt to display a deleted toast." << llendl; +				return; +			} +  			top = toast->getRect().mBottom - toast->getTopPad();  			toast_margin = gSavedSettings.getS32("ToastGap");  		} -		toast_rect = (*it).toast->getRect(); +		LLToast* toast = it->getToast(); +		if (!toast) +		{ +			llwarns << "Attempt to display a deleted toast." << llendl; +			return; +		} + +		toast_rect = toast->getRect();  		toast_rect.setLeftTopAndSize(channel_rect.mRight - toast_rect.getWidth(),  			top, toast_rect.getWidth(),  			toast_rect.getHeight()); -		(*it).toast->setRect(toast_rect); +		toast->setRect(toast_rect);  		if(floater && floater->overlapsScreenChannel())  		{ @@ -673,7 +752,7 @@ void LLScreenChannel::showToastsTop()  				{  					shift -= floater->getDockControl()->getTongueHeight();  				} -				(*it).toast->translate(0, shift); +				toast->translate(0, shift);  			}  			LLRect channel_rect = getChannelRect(); @@ -684,13 +763,13 @@ void LLScreenChannel::showToastsTop()  			}  		} -		bool stop_showing_toasts = (*it).toast->getRect().mBottom < channel_rect.mBottom; +		bool stop_showing_toasts = toast->getRect().mBottom < channel_rect.mBottom;  		if(!stop_showing_toasts)  		{  			if( it != mToastList.rend()-1)  			{ -				S32 toast_bottom = (*it).toast->getRect().mBottom - gSavedSettings.getS32("ToastGap"); +				S32 toast_bottom = toast->getRect().mBottom - gSavedSettings.getS32("ToastGap");  				stop_showing_toasts = toast_bottom < channel_rect.mBottom;  			}  		}  @@ -704,29 +783,41 @@ void LLScreenChannel::showToastsTop()  		if(stop_showing_toasts)  			break; -		if( !(*it).toast->getVisible() ) +		if (!toast->getVisible())  		{  			// HACK  			// EXT-2653: it is necessary to prevent overlapping for secondary showed toasts -			(*it).toast->setVisible(TRUE); +			toast->setVisible(TRUE);  		}		 -		if(!(*it).toast->hasFocus()) +		if (!toast->hasFocus())  		{  			// Fixing Z-order of toasts (EXT-4862)  			// Next toast will be positioned under this one. -			gFloaterView->sendChildToBack((*it).toast); +			gFloaterView->sendChildToBack(toast);  		}  	}  	// Dismiss toasts we don't have space for (STORM-391). +	std::vector<LLToast*> toasts_to_hide;  	if(it != mToastList.rend())  	{  		mHiddenToastsNum = 0;  		for(; it != mToastList.rend(); it++)  		{ -			(*it).toast->hide(); +			LLToast* toast = it->getToast(); +			if (toast) +			{ +				toasts_to_hide.push_back(toast); +			}  		}  	} + +	for (std::vector<LLToast*>::iterator it = toasts_to_hide.begin(), end_it = toasts_to_hide.end(); +		it != end_it; +		++it) +	{ +		(*it)->hide(); +	}  }  //-------------------------------------------------------------------------- @@ -827,7 +918,17 @@ void LLNotificationsUI::LLScreenChannel::startToastTimer(LLToast* toast)  void LLScreenChannel::hideToastsFromScreen()  {  	for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++) -		(*it).toast->setVisible(FALSE); +	{ +		LLToast* toast = it->getToast(); +		if (toast) +		{ +			toast->setVisible(FALSE); +		} +		else +		{ +			llwarns << "Attempt to hide a deleted toast." << llendl; +		} +	}  }  //-------------------------------------------------------------------------- @@ -836,8 +937,15 @@ void LLScreenChannel::hideToast(const LLUUID& notification_id)  	std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), notification_id);  	if(mToastList.end() != it)  	{ -		ToastElem te = *it; -		te.toast->hide(); +		LLToast* toast = it->getToast(); +		if (toast) +		{ +			toast->hide(); +		} +		else +		{ +			llwarns << "Attempt to hide a deleted toast." << llendl; +		}  	}  } @@ -845,24 +953,25 @@ void LLScreenChannel::closeHiddenToasts(const Matcher& matcher)  {  	// since we can't guarantee that close toast operation doesn't change mToastList  	// we collect matched toasts that should be closed into separate list -	std::list<ToastElem> toasts; +	std::list<LLToast*> toasts;  	for (std::vector<ToastElem>::iterator it = mToastList.begin(); it  			!= mToastList.end(); it++)  	{ -		LLToast * toast = it->toast; +		LLToast* toast = it->getToast();  		// add to list valid toast that match to provided matcher criteria  		if (toast != NULL && !toast->isDead() && toast->getNotification() != NULL  				&& !toast->getVisible() && matcher.matches(toast->getNotification()))  		{ -			toasts.push_back(*it); +			toasts.push_back(toast);  		}  	}  	// close collected toasts -	for (std::list<ToastElem>::iterator it = toasts.begin(); it +	for (std::list<LLToast*>::iterator it = toasts.begin(); it  			!= toasts.end(); it++)  	{ -		it->toast->closeFloater(); +		LLToast* toast = *it; +		toast->closeFloater();  	}  } @@ -872,7 +981,7 @@ void LLScreenChannel::removeToastsFromChannel()  	hideToastsFromScreen();  	for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end(); it++)  	{ -		deleteToast((*it).toast); +		deleteToast(it->getToast());  	}  	mToastList.clear();  } @@ -886,9 +995,10 @@ void LLScreenChannel::removeAndStoreAllStorableToasts()  	hideToastsFromScreen();  	for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();)  	{ -		if((*it).toast->getCanBeStored()) +		LLToast* toast = it->getToast(); +		if(toast && toast->getCanBeStored())  		{ -			storeToast(*(it)); +			storeToast(*it);  			it = mToastList.erase(it);  		}  		else @@ -908,9 +1018,10 @@ void LLScreenChannel::removeToastsBySessionID(LLUUID id)  	hideToastsFromScreen();  	for(std::vector<ToastElem>::iterator it = mToastList.begin(); it != mToastList.end();)  	{ -		if((*it).toast->getSessionID() == id) +		LLToast* toast = it->getToast(); +		if(toast && toast->getSessionID() == id)  		{ -			deleteToast((*it).toast); +			deleteToast(toast);  			it = mToastList.erase(it);  		}  		else @@ -968,5 +1079,5 @@ LLToast* LLScreenChannel::getToastByNotificationID(LLUUID id)  	if (it == mStoredToastList.end())  		return NULL; -	return it->toast; +	return it->getToast();  } diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h index c9f8855fe6..695b6cd44d 100644 --- a/indra/newview/llscreenchannel.h +++ b/indra/newview/llscreenchannel.h @@ -163,7 +163,7 @@ public:  		virtual bool matches(const LLNotificationPtr) const = 0;  	}; -	std::list<LLToast*> findToasts(const Matcher& matcher); +	std::list<const LLToast*> findToasts(const Matcher& matcher);  	// Channel's outfit-functions  	// update channel's size and position in the World View @@ -238,31 +238,39 @@ public:  	reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); }  private: -	struct ToastElem +	class ToastElem  	{ -		LLUUID		id; -		LLToast*	toast; +	public: +		ToastElem(const LLHandle<LLToast>& toast) : mToast(toast) +		{ +		} -		ToastElem(LLToast::Params p) : id(p.notif_id) +		ToastElem(const ToastElem& toast_elem) : mToast(toast_elem.mToast)  		{ -			toast = new LLToast(p);  		} -		ToastElem(const ToastElem& toast_elem) +		LLToast* getToast() const  		{ -			id = toast_elem.id; -			toast = toast_elem.toast; +			return mToast.get(); +		} + +		LLUUID getID() const +		{ +			return mToast.isDead() ? LLUUID() : mToast.get()->getNotificationID();  		}  		bool operator == (const LLUUID &id_op) const  		{ -			return (id == id_op); +			return (getID() == id_op);  		}  		bool operator == (LLPanel* panel_op) const  		{ -			return (toast == panel_op); +			return (mToast.get() == panel_op);  		} + +	private: +		LLHandle<LLToast>	mToast;  	};  	// Channel's handlers diff --git a/indra/newview/llsechandler_basic.cpp b/indra/newview/llsechandler_basic.cpp index 8d64c8c04f..30400a4c6a 100644 --- a/indra/newview/llsechandler_basic.cpp +++ b/indra/newview/llsechandler_basic.cpp @@ -1360,7 +1360,11 @@ void LLSecAPIBasicHandler::_writeProtectedData()  		// (even though this file isn't really secure.  Perhaps in the future  		// it may be, however.  		LLFile::remove(tmp_filename); -		throw LLProtectedDataException("Error writing Protected Data Store"); + +		// EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() +		// Decided throwing an exception here was overkill until we figure out why this happens +		//throw LLProtectedDataException("Error writing Protected Data Store"); +		llinfos << "LLProtectedDataException(Error writing Protected Data Store)" << llendl;  	}  	// move the temporary file to the specified file location. @@ -1369,7 +1373,11 @@ void LLSecAPIBasicHandler::_writeProtectedData()  	   (LLFile::rename(tmp_filename, mProtectedDataFilename)))  	{  		LLFile::remove(tmp_filename); -		throw LLProtectedDataException("Could not overwrite protected data store"); + +		// EXP-1825 crash in LLSecAPIBasicHandler::_writeProtectedData() +		// Decided throwing an exception here was overkill until we figure out why this happens +		//throw LLProtectedDataException("Could not overwrite protected data store"); +		llinfos << "LLProtectedDataException(Could not overwrite protected data store)" << llendl;  	}  } diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp index 038b18afbd..c8b67cc9ec 100644 --- a/indra/newview/llsidepanelinventory.cpp +++ b/indra/newview/llsidepanelinventory.cpp @@ -217,15 +217,17 @@ BOOL LLSidepanelInventory::postBuild()  	{  		LLLayoutStack* inv_stack = getChild<LLLayoutStack>(INVENTORY_LAYOUT_STACK_NAME); -		// Collapse inbox panel -		inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), true); -		  		// Set up button states and callbacks  		LLButton * inbox_button = getChild<LLButton>(INBOX_BUTTON_NAME); -		inbox_button->setToggleState(false);  		inbox_button->setCommitCallback(boost::bind(&LLSidepanelInventory::onToggleInboxBtn, this)); +		// Get the previous inbox state from "InventoryInboxToggleState" setting. +		bool is_inbox_collapsed = !inbox_button->getToggleState(); + +		// Restore the collapsed inbox panel state +		inv_stack->collapsePanel(getChild<LLLayoutPanel>(INBOX_LAYOUT_PANEL_NAME), is_inbox_collapsed); +  		// Set the inbox visible based on debug settings (final setting comes from http request below)  		enableInbox(gSavedSettings.getBOOL("InventoryDisplayInbox")); diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index c588bd8fb4..07d2f1ad6f 100644 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -272,6 +272,7 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin  		speakerp->mStatus = status;  		mSpeakers.insert(std::make_pair(speakerp->mID, speakerp));  		mSpeakersSorted.push_back(speakerp); +		LL_DEBUGS("Speakers") << "Added speaker " << id << llendl;  		fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "add");  	}  	else @@ -290,6 +291,10 @@ LLPointer<LLSpeaker> LLSpeakerMgr::setSpeaker(const LLUUID& id, const std::strin  				speakerp->lookupName();  			}  		} +		else +		{ +			LL_WARNS("Speakers") << "Speaker " << id << " not found" << llendl; +		}  	}  	mSpeakerDelayRemover->unsetActionTimer(speakerp->mID); @@ -354,6 +359,7 @@ void LLSpeakerMgr::update(BOOL resort_ok)  			if (moderator_muted_voice != speakerp->mModeratorMutedVoice)  			{  				speakerp->mModeratorMutedVoice = moderator_muted_voice; +				LL_DEBUGS("Speakers") << (speakerp->mModeratorMutedVoice? "Muted" : "Umuted") << " speaker " << speaker_id<< llendl;  				speakerp->fireEvent(new LLSpeakerVoiceModerationEvent(speakerp));  			} @@ -484,6 +490,7 @@ bool LLSpeakerMgr::removeSpeaker(const LLUUID& speaker_id)  		}  	} +	LL_DEBUGS("Speakers") << "Removed speaker " << speaker_id << llendl;  	fireEvent(new LLSpeakerListChangeEvent(this, speaker_id), "remove");  	update(TRUE); @@ -595,7 +602,10 @@ void LLIMSpeakerMgr::setSpeakers(const LLSD& speakers)  					speaker_it->second["mutes"]["text"];  				// Fire event only if moderator changed  				if ( is_moderator != speakerp->mIsModerator ) +				{ +					LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << llendl;  					fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator"); +				}  			}  		}  	} @@ -665,7 +675,10 @@ void LLIMSpeakerMgr::updateSpeakers(const LLSD& update)  					speakerp->mIsModerator = agent_info["is_moderator"];  					// Fire event only if moderator changed  					if ( is_moderator != speakerp->mIsModerator ) +					{ +						LL_DEBUGS("Speakers") << "Speaker " << agent_id << (is_moderator ? "is now" : "no longer is") << " a moderator" << llendl;  						fireEvent(new LLSpeakerUpdateModeratorEvent(speakerp), "update_moderator"); +					}  				}  				if (agent_info.has("mutes")) @@ -857,6 +870,7 @@ void LLActiveSpeakerMgr::updateSpeakerList()  	// always populate from active voice channel  	if (LLVoiceChannel::getCurrentVoiceChannel() != mVoiceChannel) //MA: seems this is always false  	{ +		LL_DEBUGS("Speakers") << "Removed all speakers" << llendl;  		fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");  		mSpeakers.clear();  		mSpeakersSorted.clear(); diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h index 35f2ee7056..b9358cf37c 100644 --- a/indra/newview/llspeakers.h +++ b/indra/newview/llspeakers.h @@ -208,6 +208,8 @@ private:  class LLSpeakerMgr : public LLOldEvents::LLObservable  { +	LOG_CLASS(LLSpeakerMgr); +  public:  	LLSpeakerMgr(LLVoiceChannel* channelp);  	virtual ~LLSpeakerMgr(); @@ -271,6 +273,8 @@ protected:  class LLIMSpeakerMgr : public LLSpeakerMgr  { +	LOG_CLASS(LLIMSpeakerMgr); +  public:  	LLIMSpeakerMgr(LLVoiceChannel* channel); @@ -320,6 +324,8 @@ protected:  class LLActiveSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLActiveSpeakerMgr>  { +	LOG_CLASS(LLActiveSpeakerMgr); +  public:  	LLActiveSpeakerMgr();  protected: @@ -328,6 +334,7 @@ protected:  class LLLocalSpeakerMgr : public LLSpeakerMgr, public LLSingleton<LLLocalSpeakerMgr>  { +	LOG_CLASS(LLLocalSpeakerMgr);  public:  	LLLocalSpeakerMgr();  	~LLLocalSpeakerMgr (); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 3923b4510a..0ac8c1fe39 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -880,7 +880,6 @@ bool idle_startup()  		LLFile::mkdir(gDirUtilp->getLindenUserDir());  		// Set PerAccountSettingsFile to the default value. -		std::string per_account_settings_file = LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount");  		gSavedSettings.setString("PerAccountSettingsFile",  			gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT,   				LLAppViewer::instance()->getSettingsFilename("Default", "PerAccount"))); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index de22f2ae6b..19a944e88e 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -922,13 +922,20 @@ LLTextureCtrl::LLTextureCtrl(const LLTextureCtrl::Params& p)  	S32 image_top = getRect().getHeight();  	S32 image_bottom = BTN_HEIGHT_SMALL;  	S32 image_middle = (image_top + image_bottom) / 2; -	S32 line_height = llround(LLFontGL::getFontSansSerifSmall()->getLineHeight()); +	S32 line_height = LLFontGL::getFontSansSerifSmall()->getLineHeight();  	LLTextBox::Params tentative_label_p(p.multiselect_text);  	tentative_label_p.name("Multiple");  	tentative_label_p.rect(LLRect (0, image_middle + line_height / 2, getRect().getWidth(), image_middle - line_height / 2 ));  	tentative_label_p.follows.flags(FOLLOWS_ALL);  	mTentativeLabel = LLUICtrlFactory::create<LLTextBox> (tentative_label_p); + +	// It is no longer possible to associate a style with a textbox, so it has to be done in this fashion +	LLStyle::Params style_params; +	style_params.color = LLColor4::white; + +	mTentativeLabel->setText(LLTrans::getString("multiple_textures"), style_params); +	mTentativeLabel->setHAlign(LLFontGL::HCENTER);  	addChild( mTentativeLabel );  	LLRect border_rect = getLocalRect(); diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index 1c89766b26..5b41a05f2a 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -386,7 +386,7 @@ public:  		Params()  		:	texture_view("texture_view")  		{ -			S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); +			S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();  			changeDefault(rect, LLRect(0,0,100,line_height * 4));  		}  	}; @@ -411,7 +411,7 @@ void LLAvatarTexBar::draw()  	LLVOAvatarSelf* avatarp = gAgentAvatarp;  	if (!avatarp) return; -	const S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); +	const S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();  	const S32 v_offset = 0;  	const S32 l_offset = 3; @@ -485,7 +485,7 @@ public:  		Params()  		:	texture_view("texture_view")  		{ -			S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); +			S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();  			changeDefault(rect, LLRect(0,0,100,line_height * 4));  		}  	}; @@ -512,7 +512,7 @@ void LLGLTexMemBar::draw()  	F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;  	F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ;  	F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ; -	S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); +	S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();  	S32 v_offset = (S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f);  	F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024);  	F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024); @@ -1097,7 +1097,7 @@ void LLTextureSizeView::drawTextureSizeGraph()  {  	if(mTextureSizeBar.size() == 0)  	{ -		S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); +		S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();  		mTextureSizeBar.resize(LLImageGL::sTextureLoadedCounter.size()) ;  		mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ; @@ -1140,7 +1140,7 @@ F32 LLTextureSizeView::drawTextureSizeDistributionGraph()  		}  	} -	S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); +	S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();  	S32 left = mTextureSizeBarRect.mLeft ;  	S32 bottom = mTextureSizeBarRect.mBottom ;  	S32 right = mTextureSizeBarRect.mRight ; @@ -1222,7 +1222,7 @@ void LLTextureSizeView::drawTextureCategoryGraph()  {  	if(mTextureSizeBar.size() == 0)  	{ -		S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); +		S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();  		mTextureSizeBar.resize(LLViewerTexture::getTotalNumOfCategories()) ;  		mTextureSizeBarRect.set(700, line_height * 2 + 400, 700 + mTextureSizeBar.size() * mTextureSizeBarWidth, line_height * 2) ; @@ -1267,7 +1267,7 @@ F32 LLTextureSizeView::drawTextureCategoryDistributionGraph()  		}  	} -	S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); +	S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();  	S32 left = mTextureSizeBarRect.mLeft ;  	S32 bottom = mTextureSizeBarRect.mBottom ;  	S32 right = mTextureSizeBarRect.mRight ; diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index da691a2d0c..0eec7f0afd 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -180,11 +180,14 @@ LLToast::~LLToast()  //--------------------------------------------------------------------------  void LLToast::hide()  { -	setVisible(FALSE); -	setFading(false); -	mTimer->stop(); -	mIsHidden = true; -	mOnFadeSignal(this);  +	if (!mIsHidden) +	{ +		setVisible(FALSE); +		setFading(false); +		mTimer->stop(); +		mIsHidden = true; +		mOnFadeSignal(this);  +	}  }  void LLToast::onFocusLost() @@ -215,6 +218,13 @@ void LLToast::setFadingTime(S32 seconds)  	mToastFadingTime = seconds;  } +void LLToast::closeToast() +{ +	mOnDeleteToastSignal(this); + +	closeFloater(); +} +  S32 LLToast::getTopPad()  {  	if(mWrapperPanel) @@ -296,9 +306,7 @@ void LLToast::reshapeToPanel()  	if(!panel)  		return; -	LLRect panel_rect = panel->getRect(); - -	panel_rect.setLeftTopAndSize(0, panel_rect.getHeight(), panel_rect.getWidth(), panel_rect.getHeight()); +	LLRect panel_rect = panel->getLocalRect();  	panel->setShape(panel_rect);  	LLRect toast_rect = getRect(); diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index 0b06728935..e1d99b1bcb 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -75,6 +75,7 @@ class LLToast : public LLModalDialog, public LLInstanceTracker<LLToast>  public:  	typedef boost::function<void (LLToast* toast)> toast_callback_t;  	typedef boost::signals2::signal<void (LLToast* toast)> toast_signal_t; +	typedef boost::signals2::signal<void (LLToast* toast, bool mouse_enter)> toast_hover_check_signal_t;  	struct Params : public LLInitParam::Block<Params>  	{ @@ -131,7 +132,7 @@ public:  	void reshapeToPanel();  	// get toast's panel -	LLPanel* getPanel() { return mPanel; } +	LLPanel* getPanel() const { return mPanel; }  	// enable/disable Toast's Hide button  	void setHideButtonEnabled(bool enabled);  	// @@ -155,6 +156,8 @@ public:  	void setFadingTime(S32 seconds); +	void closeToast(); +  	/**  	 * Returns padding between floater top and wrapper_panel top.  	 * This padding should be taken into account when positioning or reshaping toasts @@ -167,9 +170,9 @@ public:  	// get information whether the notification corresponding to the toast is valid or not  	bool isNotificationValid();  	// get toast's Notification ID -	const LLUUID getNotificationID() { return mNotificationID;} +	const LLUUID getNotificationID() const { return mNotificationID;}  	// get toast's Session ID -	const LLUUID getSessionID() { return mSessionID;} +	const LLUUID getSessionID() const { return mSessionID;}  	//  	void setCanFade(bool can_fade);  	// @@ -179,19 +182,12 @@ public:  	// set whether this toast considered as hidden or not  	void setIsHidden( bool is_toast_hidden ) { mIsHidden = is_toast_hidden; } -	const LLNotificationPtr& getNotification() { return mNotification;} +	const LLNotificationPtr& getNotification() const { return mNotification;}  	// Registers signals/callbacks for events -	toast_signal_t mOnFadeSignal; -	toast_signal_t mOnDeleteToastSignal; -	toast_signal_t mOnToastDestroyedSignal; -	boost::signals2::connection setOnFadeCallback(toast_callback_t cb) { return mOnFadeSignal.connect(cb); } -	boost::signals2::connection setOnToastDestroyedCallback(toast_callback_t cb) { return mOnToastDestroyedSignal.connect(cb); } - -	typedef boost::function<void (LLToast* toast, bool mouse_enter)> toast_hover_check_callback_t; -	typedef boost::signals2::signal<void (LLToast* toast, bool mouse_enter)> toast_hover_check_signal_t; -	toast_hover_check_signal_t mOnToastHoverSignal;	 -	boost::signals2::connection setOnToastHoverCallback(toast_hover_check_callback_t cb) { return mOnToastHoverSignal.connect(cb); } +	boost::signals2::connection setOnFadeCallback(const toast_signal_t::slot_type& cb) { return mOnFadeSignal.connect(cb); } +	boost::signals2::connection setOnToastDestroyedCallback(const toast_signal_t::slot_type& cb) { return mOnToastDestroyedSignal.connect(cb); } +	boost::signals2::connection setOnToastHoverCallback(const toast_hover_check_signal_t::slot_type& cb) { return mOnToastHoverSignal.connect(cb); }  	boost::signals2::connection setMouseEnterCallback( const commit_signal_t::slot_type& cb ) { return mToastMouseEnterSignal.connect(cb); };  	boost::signals2::connection setMouseLeaveCallback( const commit_signal_t::slot_type& cb ) { return mToastMouseLeaveSignal.connect(cb); }; @@ -237,6 +233,11 @@ private:  	bool		mIsFading;  	bool		mIsHovered; +	toast_signal_t mOnFadeSignal; +	toast_signal_t mOnDeleteToastSignal; +	toast_signal_t mOnToastDestroyedSignal; +	toast_hover_check_signal_t mOnToastHoverSignal; +  	commit_signal_t mToastMouseEnterSignal;  	commit_signal_t mToastMouseLeaveSignal;  }; diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 0f337825e9..9ba8431fde 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -69,8 +69,22 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  		mLabel(notification->getName()),  		mLineEditor(NULL)  { +	// EXP-1822 +	// save currently focused view, so that return focus to it +	// on destroying this toast. +	LLView* current_selection = dynamic_cast<LLView*>(gFocusMgr.getKeyboardFocus()); +	while(current_selection) +	{ +		if (current_selection->isFocusRoot()) +		{ +			mPreviouslyFocusedView = current_selection->getHandle(); +			break; +		} +		current_selection = current_selection->getParent(); +	} +  	const LLFontGL* font = LLFontGL::getFontSansSerif(); -	const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); +	const S32 LINE_HEIGHT = font->getLineHeight();  	const S32 EDITOR_HEIGHT = 20;  	LLNotificationFormPtr form = mNotification->getForm(); @@ -365,7 +379,7 @@ bool LLToastAlertPanel::setCheckBox( const std::string& check_title, const std::  	}  	const LLFontGL* font =  mCheck->getFont(); -	const S32 LINE_HEIGHT = llfloor(font->getLineHeight() + 0.99f); +	const S32 LINE_HEIGHT = font->getLineHeight();  	// Extend dialog for "check next time"  	S32 max_msg_width = LLToastPanel::getRect().getWidth() - 2 * HPAD; @@ -408,6 +422,13 @@ LLToastAlertPanel::~LLToastAlertPanel()  {  	LLTransientFloaterMgr::instance().removeControlView(  			LLTransientFloaterMgr::GLOBAL, this); + +	// EXP-1822 +	// return focus to the previously focused view +	if (mPreviouslyFocusedView.get()) +	{ +		mPreviouslyFocusedView.get()->setFocus(TRUE); +	}  }  BOOL LLToastAlertPanel::hasTitleBar() const diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h index 7b157f19bb..d1be5e018e 100644 --- a/indra/newview/lltoastalertpanel.h +++ b/indra/newview/lltoastalertpanel.h @@ -113,6 +113,7 @@ private:  	LLFrameTimer	mDefaultBtnTimer;  	// For Dialogs that take a line as text as input:  	LLLineEditor* mLineEditor; +	LLHandle<LLView>	mPreviouslyFocusedView;  }; diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp index fc69157a40..d2a4ce8745 100644 --- a/indra/newview/lltoastpanel.cpp +++ b/indra/newview/lltoastpanel.cpp @@ -68,7 +68,7 @@ void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)  	if (message->getVisible())  	{  		S32 heightDelta = 0; -		S32 maxTextHeight = (S32)(message->getDefaultFont()->getLineHeight() * maxLineCount); +		S32 maxTextHeight = message->getDefaultFont()->getLineHeight() * maxLineCount;  		LLRect messageRect = message->getRect();  		S32 oldTextHeight = messageRect.getHeight(); diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 8c32dfcb4d..c7ab934f9e 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -333,14 +333,15 @@ LLToolDragAndDrop::LLDragAndDropDictionary::LLDragAndDropDictionary()  };  LLToolDragAndDrop::LLToolDragAndDrop() -:	 LLTool(std::string("draganddrop"), NULL), -	 mDragStartX(0), -	 mDragStartY(0), -	 mSource(SOURCE_AGENT), -	 mCursor(UI_CURSOR_NO), -	 mLastAccept(ACCEPT_NO), -	 mDrop(FALSE), -	 mCurItemIndex(0) +:	LLTool(std::string("draganddrop"), NULL), +	mCargoCount(0), +	mDragStartX(0), +	mDragStartY(0), +	mSource(SOURCE_AGENT), +	mCursor(UI_CURSOR_NO), +	mLastAccept(ACCEPT_NO), +	mDrop(FALSE), +	mCurItemIndex(0)  {  } diff --git a/indra/newview/lltooldraganddrop.h b/indra/newview/lltooldraganddrop.h index 188d36cd1b..245c2a23e6 100644 --- a/indra/newview/lltooldraganddrop.h +++ b/indra/newview/lltooldraganddrop.h @@ -86,8 +86,11 @@ public:  	EAcceptance getLastAccept() { return mLastAccept; }  	boost::signals2::connection setEndDragCallback( const enddrag_signal_t::slot_type& cb ) { return mEndDragSignal.connect(cb); } -	 -	uuid_vec_t::size_type getCargoIDsCount() const { return mCargoIDs.size(); } + +	void setCargoCount(U32 count) { mCargoCount = count; } +	void resetCargoCount() { mCargoCount = 0; } +	U32 getCargoCount() const { return (mCargoCount > 0) ? mCargoCount : mCargoIDs.size(); } +  	static S32 getOperationId() { return sOperationId; }  protected: @@ -118,6 +121,8 @@ protected:  protected: +	U32				mCargoCount; +  	S32				mDragStartX;  	S32				mDragStartY; diff --git a/indra/newview/lltoolmgr.cpp b/indra/newview/lltoolmgr.cpp index 6bc7c6de11..ac01316462 100644 --- a/indra/newview/lltoolmgr.cpp +++ b/indra/newview/lltoolmgr.cpp @@ -81,7 +81,7 @@ LLToolMgr::LLToolMgr()  	// Not a panel, register these callbacks globally.  	LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Active", boost::bind(&LLToolMgr::inEdit, this));  	LLUICtrl::EnableCallbackRegistry::currentRegistrar().add("Build.Enabled", boost::bind(&LLToolMgr::canEdit, this)); -	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this)); +	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Build.Toggle", boost::bind(&LLToolMgr::toggleBuildMode, this, _2));  	gToolNull = new LLTool(LLStringUtil::null);  // Does nothing  	setCurrentTool(gToolNull); @@ -245,8 +245,15 @@ bool LLToolMgr::canEdit()  	return LLViewerParcelMgr::getInstance()->allowAgentBuild();  } -void LLToolMgr::toggleBuildMode() +void LLToolMgr::toggleBuildMode(const LLSD& sdname)  { +	const std::string& param = sdname.asString(); + +	if (param == "build" && !canEdit()) +	{ +		return; +	} +  	LLFloaterReg::toggleInstanceOrBringToFront("build");  	bool build_visible = LLFloaterReg::instanceVisible("build"); diff --git a/indra/newview/lltoolmgr.h b/indra/newview/lltoolmgr.h index d489c4c829..12649cfba2 100644 --- a/indra/newview/lltoolmgr.h +++ b/indra/newview/lltoolmgr.h @@ -54,7 +54,7 @@ public:  	bool			inEdit();  	bool			canEdit(); -	void			toggleBuildMode(); +	void			toggleBuildMode(const LLSD& sdname);  	/* Determines if we are in Build mode or not. */  	bool			inBuildMode(); diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp index c1cc9c7bc4..f3d8de1904 100755 --- a/indra/newview/lltranslate.cpp +++ b/indra/newview/lltranslate.cpp @@ -162,10 +162,10 @@ void LLBingTranslationHandler::getTranslateURL(  	const std::string &text) const  {  	url = std::string("http://api.microsofttranslator.com/v2/Http.svc/Translate?appId=") -		+ getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + to_lang; +		+ getAPIKey() + "&text=" + LLURI::escape(text) + "&to=" + getAPILanguageCode(to_lang);  	if (!from_lang.empty())  	{ -		url += "&from=" + from_lang; +		url += "&from=" + getAPILanguageCode(from_lang);  	}  } @@ -236,6 +236,12 @@ std::string LLBingTranslationHandler::getAPIKey()  	return gSavedSettings.getString("BingTranslateAPIKey");  } +// static +std::string LLBingTranslationHandler::getAPILanguageCode(const std::string& lang) +{ +	return lang == "zh" ? "zh-CHT" : lang; // treat Chinese as Traditional Chinese +} +  LLTranslate::TranslationReceiver::TranslationReceiver(const std::string& from_lang, const std::string& to_lang)  :	mFromLang(from_lang)  ,	mToLang(to_lang) diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h index 424bc14587..c58e1adb8c 100755 --- a/indra/newview/lltranslate.h +++ b/indra/newview/lltranslate.h @@ -157,6 +157,7 @@ public:  	/*virtual*/ bool isConfigured() const;  private:  	static std::string getAPIKey(); +	static std::string getAPILanguageCode(const std::string& lang);  };  /** diff --git a/indra/newview/lluploaddialog.cpp b/indra/newview/lluploaddialog.cpp index df7c5be0d6..e59064c074 100644 --- a/indra/newview/lluploaddialog.cpp +++ b/indra/newview/lluploaddialog.cpp @@ -115,7 +115,7 @@ void LLUploadDialog::setMessage( const std::string& msg)  		token = strtok( NULL, "\n" );  	} -	S32 line_height = S32( font->getLineHeight() + 0.99f ); +	S32 line_height = font->getLineHeight();  	S32 dialog_width = max_msg_width + 2 * HPAD;  	S32 dialog_height = line_height * msg_lines.size() + 2 * VPAD; diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index cc3395115b..184033de42 100644 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -32,8 +32,8 @@  #include "llstat.h"  #include "lltimer.h"  #include "m4math.h" +#include "llcoord.h" -class LLCoordGL;  class LLViewerObject;  // This rotation matrix moves the default OpenGL reference frame  diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index d7ef038e4e..42309349b0 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -1,889 +1,892 @@ -/**  - * @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); -		} -		 +/** 
 + * @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();
 +	
 +	//reset vertex buffers if needed
 +	gPipeline.doResetVertexBuffers();
 +
 +	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);
 +		}
 +		
  			if (!(LLAppViewer::instance()->logoutRequestSent() && LLAppViewer::instance()->hasSavedFinalSnapshot())
  				&& !gRestoreGL)
  		{
 @@ -911,655 +914,655 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)  				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; -} +		}
 +
 +		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/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index d396219bf8..12f802b29a 100644 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -35,7 +35,6 @@  #include "llcallfloater.h"  #include "llfasttimerview.h"  #include "llfloaterabout.h" -#include "llfloateranimpreview.h"  #include "llfloaterauction.h"  #include "llfloateravatar.h"  #include "llfloateravatarpicker.h" @@ -49,6 +48,7 @@  #include "llfloaterbuyland.h"  #include "llfloaterbulkpermission.h"  #include "llfloaterbump.h" +#include "llfloaterbvhpreview.h"  #include "llfloatercamera.h"  #include "llfloaterdeleteenvpreset.h"  #include "llfloaterdisplayname.h" @@ -302,7 +302,8 @@ void LLViewerFloaterReg::registerFloaters()  	LLFloaterUIPreviewUtil::registerFloater(); -	LLFloaterReg::add("upload_anim", "floater_animation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload"); +	LLFloaterReg::add("upload_anim_bvh", "floater_animation_bvh_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBvhPreview>, "upload"); +	LLFloaterReg::add("upload_anim_anim", "floater_animation_anim_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");  	LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload");  	LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelPreview>, "upload");  	LLFloaterReg::add("upload_model_wizard", "floater_model_wizard.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelWizard>); diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp index 163581ea7f..45ca23cdfe 100644 --- a/indra/newview/llviewerinventory.cpp +++ b/indra/newview/llviewerinventory.cpp @@ -436,11 +436,6 @@ void LLViewerInventoryItem::fetchFromServer(void) const  			gAgent.sendReliableMessage();  		}  	} -	else -	{ -		// *FIX: this can be removed after a bit. -		llwarns << "request to fetch complete item" << llendl; -	}  }  // virtual @@ -1462,6 +1457,7 @@ const std::string& LLViewerInventoryItem::getName() const  class LLFavoritesOrderStorage : public LLSingleton<LLFavoritesOrderStorage>  	, public LLDestroyClass<LLFavoritesOrderStorage>  { +	LOG_CLASS(LLFavoritesOrderStorage);  public:  	/**  	 * Sets sort index for specified with LLUUID favorite landmark @@ -1620,10 +1616,18 @@ void LLFavoritesOrderStorage::load()  void LLFavoritesOrderStorage::saveFavoritesSLURLs()  {  	// Do not change the file if we are not logged in yet. -	if (!LLLoginInstance::getInstance()->authSuccess()) return; +	if (!LLLoginInstance::getInstance()->authSuccess()) +	{ +		llwarns << "Cannot save favorites: not logged in" << llendl; +		return; +	}  	std::string user_dir = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, ""); -	if (user_dir.empty()) return; +	if (user_dir.empty()) +	{ +		llwarns << "Cannot save favorites: empty user dir name" << llendl; +		return; +	}  	std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "stored_favorites.xml");  	llifstream in_file; @@ -1649,13 +1653,19 @@ void LLFavoritesOrderStorage::saveFavoritesSLURLs()  		slurls_map_t::iterator slurl_iter = mSLURLs.find(value["asset_id"]);  		if (slurl_iter != mSLURLs.end())  		{ +			lldebugs << "Saving favorite: idx=" << (*it)->getSortField() << ", SLURL=" <<  slurl_iter->second << ", value=" << value << llendl;  			value["slurl"] = slurl_iter->second;  			user_llsd[(*it)->getSortField()] = value;  		} +		else +		{ +			llwarns << "Not saving favorite " << value["name"] << ": no matching SLURL" << llendl; +		}  	}  	LLAvatarName av_name;  	LLAvatarNameCache::get( gAgentID, &av_name ); +	lldebugs << "Saved favorites for " << av_name.getLegacyName() << llendl;  	fav_llsd[av_name.getLegacyName()] = user_llsd;  	llofstream file; @@ -1674,6 +1684,7 @@ void LLFavoritesOrderStorage::removeFavoritesRecordOfUser()  	LLAvatarName av_name;  	LLAvatarNameCache::get( gAgentID, &av_name ); +	lldebugs << "Removed favorites for " << av_name.getLegacyName() << llendl;  	if (fav_llsd.has(av_name.getLegacyName()))  	{  		fav_llsd.erase(av_name.getLegacyName()); @@ -1706,6 +1717,7 @@ void LLFavoritesOrderStorage::onLandmarkLoaded(const LLUUID& asset_id, LLLandmar  void LLFavoritesOrderStorage::storeFavoriteSLURL(const LLUUID& asset_id, std::string& slurl)  { +	lldebugs << "Saving landmark SLURL: " << slurl << llendl;  	mSLURLs[asset_id] = slurl;  } diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp index 76f4e18c27..e052e37393 100644 --- a/indra/newview/llviewerjointmesh.cpp +++ b/indra/newview/llviewerjointmesh.cpp @@ -63,7 +63,6 @@ extern PFNGLWEIGHTFVARBPROC glWeightfvARB;  extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB;  #endif -static LLPointer<LLVertexBuffer> sRenderBuffer = NULL;  static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX |  							   LLVertexBuffer::MAP_NORMAL |  							   LLVertexBuffer::MAP_TEXCOORD0; diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp index 046360e9e9..1eb4bedfaf 100644 --- a/indra/newview/llviewermedia.cpp +++ b/indra/newview/llviewermedia.cpp @@ -387,7 +387,6 @@ class LLViewerMediaMuteListObserver : public LLMuteListObserver  static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver;  static bool sViewerMediaMuteListObserverInitialized = false; -static bool sInWorldMediaDisabled = false;  ////////////////////////////////////////////////////////////////////////////////////////// @@ -654,20 +653,6 @@ void LLViewerMedia::muteListChanged()  //////////////////////////////////////////////////////////////////////////////////////////  // static -void LLViewerMedia::setInWorldMediaDisabled(bool disabled) -{ -	sInWorldMediaDisabled = disabled; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// static -bool LLViewerMedia::getInWorldMediaDisabled() -{ -	return sInWorldMediaDisabled; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// static  bool LLViewerMedia::isInterestingEnough(const LLVOVolume *object, const F64 &object_interest)  {  	bool result = false; @@ -1568,7 +1553,6 @@ LLPluginClassMedia* LLViewerMedia::getSpareBrowserMediaSource()  bool LLViewerMedia::hasInWorldMedia()  { -	if (sInWorldMediaDisabled) return false;  	impl_list::iterator iter = sViewerMediaImplList.begin();  	impl_list::iterator end = sViewerMediaImplList.end();  	// This should be quick, because there should be very few non-in-world-media impls @@ -1901,7 +1885,7 @@ LLPluginClassMedia* LLViewerMediaImpl::newSourceFromMediaType(std::string media_  		}  	} -	LL_WARNS_ONCE("Plugin") << "plugin intialization failed for mime type: " << media_type << LL_ENDL; +	LL_WARNS_ONCE("Plugin") << "plugin initialization failed for mime type: " << media_type << LL_ENDL;  	LLSD args;  	args["MIME_TYPE"] = media_type;  	LLNotificationsUtil::add("NoPlugin", args); @@ -3107,15 +3091,6 @@ bool LLViewerMediaImpl::isForcedUnloaded() const  		return true;  	} -	if(sInWorldMediaDisabled) -	{ -		// When inworld media is disabled, all instances that aren't marked as "used in UI" will not be loaded. -		if(!mUsedInUI) -		{ -			return true; -		} -	} -	  	// If this media's class is not supposed to be shown, unload  	if (!shouldShowBasedOnClass())  	{ @@ -3783,12 +3758,22 @@ bool LLViewerMediaImpl::shouldShowBasedOnClass() const  	// If it is attached to an avatar and the pref is off, we shouldn't show it  	if (attached_to_another_avatar) -		return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING); -	 +	{ +		static LLCachedControl<bool> show_media_on_others(gSavedSettings, LLViewerMedia::SHOW_MEDIA_ON_OTHERS_SETTING); +		return show_media_on_others; +	}  	if (inside_parcel) -		return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING); +	{ +		static LLCachedControl<bool> show_media_within_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_WITHIN_PARCEL_SETTING); + +		return show_media_within_parcel; +	}  	else  -		return gSavedSettings.getBOOL(LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING); +	{ +		static LLCachedControl<bool> show_media_outside_parcel(gSavedSettings, LLViewerMedia::SHOW_MEDIA_OUTSIDE_PARCEL_SETTING); + +		return show_media_outside_parcel; +	}  }  ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h index 15dcda59cf..fff5b3fc08 100644 --- a/indra/newview/llviewermedia.h +++ b/indra/newview/llviewermedia.h @@ -112,9 +112,6 @@ public:  	static F32 getVolume();	  	static void muteListChanged(); -	static void setInWorldMediaDisabled(bool disabled); -	static bool getInWorldMediaDisabled(); -	  	static bool isInterestingEnough(const LLVOVolume* object, const F64 &object_interest);  	// Returns the priority-sorted list of all media impls. diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 06f9d931f8..e91a1d6afa 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -7338,12 +7338,6 @@ class LLToolsUseSelectionForGrid : public view_listener_t  		} func;  		LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func);  		LLSelectMgr::getInstance()->setGridMode(GRID_MODE_REF_OBJECT); - -		LLFloaterBuildOptions* build_options_floater = LLFloaterReg::getTypedInstance<LLFloaterBuildOptions>("build_options"); -		if (build_options_floater && build_options_floater->getVisible()) -		{ -			build_options_floater->setGridMode(GRID_MODE_REF_OBJECT); -		}  		return true;  	}  }; diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index 99d08087d4..e2f9b1f1a0 100644 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -183,7 +183,7 @@ void LLFilePickerThread::clearDead()  #if LL_WINDOWS
  static std::string SOUND_EXTENSIONS = "wav";
  static std::string IMAGE_EXTENSIONS = "tga bmp jpg jpeg png";
 -static std::string ANIM_EXTENSIONS =  "bvh";
 +static std::string ANIM_EXTENSIONS =  "bvh anim";
  #ifdef _CORY_TESTING
  static std::string GEOMETRY_EXTENSIONS = "slg";
  #endif
 @@ -385,7 +385,14 @@ class LLFileUploadAnim : public view_listener_t  		const std::string filename = upload_pick((void*)LLFilePicker::FFLOAD_ANIM);
  		if (!filename.empty())
  		{
 -			LLFloaterReg::showInstance("upload_anim", LLSD(filename));
 +			if (filename.rfind(".anim") != std::string::npos)
 +			{
 +				LLFloaterReg::showInstance("upload_anim_anim", LLSD(filename));
 +			}
 +			else
 +			{
 +				LLFloaterReg::showInstance("upload_anim_bvh", LLSD(filename));
 +			}
  		}
  		return true;
  	}
 @@ -527,8 +534,22 @@ class LLFileTakeSnapshotToDisk : public view_listener_t  									   FALSE))
  		{
  			gViewerWindow->playSnapshotAnimAndSound();
 -			
 -			LLPointer<LLImageFormatted> formatted = new LLImagePNG;
 +			LLPointer<LLImageFormatted> formatted;
 +			LLFloaterSnapshot::ESnapshotFormat fmt = (LLFloaterSnapshot::ESnapshotFormat) gSavedSettings.getS32("SnapshotFormat");
 +			switch (fmt)
 +			{
 +			case LLFloaterSnapshot::SNAPSHOT_FORMAT_JPEG:
 +				formatted = new LLImageJPEG(gSavedSettings.getS32("SnapshotQuality"));
 +				break;
 +			default:
 +				llwarns << "Unknown local snapshot format: " << fmt << llendl;
 +			case LLFloaterSnapshot::SNAPSHOT_FORMAT_PNG:
 +				formatted = new LLImagePNG;
 +				break;
 +			case LLFloaterSnapshot::SNAPSHOT_FORMAT_BMP:
 +				formatted = new LLImageBMP;
 +				break;
 +			}
  			formatted->enableOverSize() ;
  			formatted->encode(raw, 0);
  			formatted->disableOverSize() ;
 @@ -785,6 +806,11 @@ LLUUID upload_new_resource(  		upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args);
  		return LLUUID();
  	}
 +	else if (exten == "anim")
 +	{
 +		asset_type = LLAssetType::AT_ANIMATION;
 +		filename = src_filename;
 +	}
  	else
  	{
  		// Unknown extension
 diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index 8905efed75..05f1be5de5 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -135,6 +135,7 @@ extern BOOL gDebugClicks;  // function prototypes  bool check_offer_throttle(const std::string& from_name, bool check_only); +bool check_asset_previewable(const LLAssetType::EType asset_type);  static void process_money_balance_reply_extended(LLMessageSystem* msg);  //inventory offer throttle globals @@ -1147,7 +1148,18 @@ bool check_offer_throttle(const std::string& from_name, bool check_only)  		}  	}  } -  + +// Return "true" if we have a preview method for that asset type, "false" otherwise +bool check_asset_previewable(const LLAssetType::EType asset_type) +{ +	return	(asset_type == LLAssetType::AT_NOTECARD)  ||  +			(asset_type == LLAssetType::AT_LANDMARK)  || +			(asset_type == LLAssetType::AT_TEXTURE)   || +			(asset_type == LLAssetType::AT_ANIMATION) || +			(asset_type == LLAssetType::AT_SCRIPT)    || +			(asset_type == LLAssetType::AT_SOUND); +} +  void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_name)  {  	for (uuid_vec_t::const_iterator obj_iter = objects.begin(); @@ -1171,7 +1183,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam  		// Either an inventory item or a category.  		const LLInventoryItem* item = dynamic_cast<const LLInventoryItem*>(obj); -		if (item) +		if (item && check_asset_previewable(asset_type))  		{  			////////////////////////////////////////////////////////////////////////////////  			// Special handling for various types. @@ -1246,6 +1258,7 @@ void open_inventory_offer(const uuid_vec_t& objects, const std::string& from_nam  						LLFloaterReg::showInstance("preview_sound", LLSD(obj_id), take_focus);  						break;  					default: +						LL_DEBUGS("Messaging") << "No preview method for previewable asset type : " << LLAssetType::lookupHumanReadable(asset_type)  << LL_ENDL;  						break;  				}  			} @@ -2360,8 +2373,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)  			LL_INFOS("Messaging") << "process_improved_im: session_id( " << session_id << " ), from_id( " << from_id << " )" << LL_ENDL;  			bool mute_im = is_muted; -			if(accept_im_from_only_friend&&!is_friend) +			if (accept_im_from_only_friend && !is_friend)  			{ +				if (!gIMMgr->isNonFriendSessionNotified(session_id)) +				{ +					std::string message = LLTrans::getString("IM_unblock_only_groups_friends"); +					gIMMgr->addMessage(session_id, from_id, name, message); +					gIMMgr->addNotifiedNonFriendSessionID(session_id); +				} +  				mute_im = true;  			}  			if (!mute_im || is_linden)  @@ -5816,6 +5836,16 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)  	S32 orig = notification["payload"]["questions"].asInteger();  	S32 new_questions = orig; +	if (response["Details"]) +	{ +		// respawn notification... +		LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]); + +		// ...with description on top +		LLNotificationsUtil::add("DebitPermissionDetails"); +		return false; +	} +  	// check whether permissions were granted or denied  	BOOL allowed = TRUE;  	// the "yes/accept" button is the first button in the template, making it button 0 @@ -5873,14 +5903,6 @@ bool script_question_cb(const LLSD& notification, const LLSD& response)  				gSavedSettings.getString("NotificationChannelUUID")), OfferMatcher(item_id));  	} -	if (response["Details"]) -	{ -		// respawn notification... -		LLNotificationsUtil::add(notification["name"], notification["substitutions"], notification["payload"]); - -		// ...with description on top -		LLNotificationsUtil::add("DebitPermissionDetails"); -	}  	return false;  }  static LLNotificationFunctorRegistration script_question_cb_reg_1("ScriptQuestion", script_question_cb); diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h index d8acd99953..46bfb2dad0 100644 --- a/indra/newview/llviewermessage.h +++ b/indra/newview/llviewermessage.h @@ -35,6 +35,7 @@  #include "message.h"  #include "stdenums.h"  #include "llnotifications.h" +#include "llextendedstatus.h"  //  // Forward declarations diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 5de363e03c..6db2138688 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -730,7 +730,7 @@ BOOL LLViewerShaderMgr::loadBasicShaders()  	vector< pair<string, S32> > shaders;  	shaders.push_back( make_pair( "windlight/atmosphericsVarsV.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) ); -	shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl",		mVertexShaderLevel[SHADER_WINDLIGHT] ) ); +	shaders.push_back( make_pair( "windlight/atmosphericsVarsWaterV.glsl",	mVertexShaderLevel[SHADER_WINDLIGHT] ) );  	shaders.push_back( make_pair( "windlight/atmosphericsHelpersV.glsl",	mVertexShaderLevel[SHADER_WINDLIGHT] ) );  	shaders.push_back( make_pair( "lighting/lightFuncV.glsl",				mVertexShaderLevel[SHADER_LIGHTING] ) );  	shaders.push_back( make_pair( "lighting/sumLightsV.glsl",				sum_lights_class ) ); @@ -1102,19 +1102,25 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  	if (success)  	{  		gDeferredSkinnedAlphaProgram.mName = "Deferred Skinned Alpha Shader"; +		gDeferredSkinnedAlphaProgram.mFeatures.atmosphericHelpers = true;  		gDeferredSkinnedAlphaProgram.mFeatures.hasObjectSkinning = true;  		gDeferredSkinnedAlphaProgram.mFeatures.calculatesAtmospherics = true;  		gDeferredSkinnedAlphaProgram.mFeatures.hasGamma = true;  		gDeferredSkinnedAlphaProgram.mFeatures.hasAtmospherics = true; -		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true; -		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true; +		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = false; +		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = false;  		gDeferredSkinnedAlphaProgram.mFeatures.isAlphaLighting = true;  		gDeferredSkinnedAlphaProgram.mFeatures.disableTextureIndex = true;  		gDeferredSkinnedAlphaProgram.mShaderFiles.clear();  		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaSkinnedV.glsl", GL_VERTEX_SHADER_ARB));  		gDeferredSkinnedAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredSkinnedAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; +		  		success = gDeferredSkinnedAlphaProgram.createShader(NULL, NULL); +		 +		// Hack to include uniforms for lighting without linking in lighting file +		gDeferredSkinnedAlphaProgram.mFeatures.calculatesLighting = true; +		gDeferredSkinnedAlphaProgram.mFeatures.hasLighting = true;  	}  	if (success) @@ -1231,11 +1237,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  	if (success)  	{  		gDeferredAlphaProgram.mName = "Deferred Alpha Shader"; -		gDeferredAlphaProgram.mFeatures.calculatesLighting = true; +		gDeferredAlphaProgram.mFeatures.atmosphericHelpers = true; +		gDeferredAlphaProgram.mFeatures.calculatesLighting = false;  		gDeferredAlphaProgram.mFeatures.calculatesAtmospherics = true;  		gDeferredAlphaProgram.mFeatures.hasGamma = true;  		gDeferredAlphaProgram.mFeatures.hasAtmospherics = true; -		gDeferredAlphaProgram.mFeatures.hasLighting = true; +		gDeferredAlphaProgram.mFeatures.hasLighting = false;  		gDeferredAlphaProgram.mFeatures.isAlphaLighting = true;  		gDeferredAlphaProgram.mFeatures.disableTextureIndex = true; //hack to disable auto-setup of texture channels  		if (mVertexShaderLevel[SHADER_DEFERRED] < 1) @@ -1251,7 +1258,12 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaV.glsl", GL_VERTEX_SHADER_ARB));  		gDeferredAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; +  		success = gDeferredAlphaProgram.createShader(NULL, NULL); + +		// Hack +		gDeferredAlphaProgram.mFeatures.calculatesLighting = true; +		gDeferredAlphaProgram.mFeatures.hasLighting = true;  	}  	if (success) @@ -1394,19 +1406,24 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  	if (success)  	{  		gDeferredAvatarAlphaProgram.mName = "Avatar Alpha Shader"; +		gDeferredAvatarAlphaProgram.mFeatures.atmosphericHelpers = true;  		gDeferredAvatarAlphaProgram.mFeatures.hasSkinning = true; -		gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true; +		gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = false;  		gDeferredAvatarAlphaProgram.mFeatures.calculatesAtmospherics = true;  		gDeferredAvatarAlphaProgram.mFeatures.hasGamma = true;  		gDeferredAvatarAlphaProgram.mFeatures.hasAtmospherics = true; -		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; +		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = false;  		gDeferredAvatarAlphaProgram.mFeatures.isAlphaLighting = true;  		gDeferredAvatarAlphaProgram.mFeatures.disableTextureIndex = true;  		gDeferredAvatarAlphaProgram.mShaderFiles.clear();  		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB));  		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedNoColorF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; +  		success = gDeferredAvatarAlphaProgram.createShader(NULL, &mAvatarUniforms); + +		gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true; +		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;  	}  	if (success) diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp index b41ed00f17..99102309a1 100644 --- a/indra/newview/llviewertexteditor.cpp +++ b/indra/newview/llviewertexteditor.cpp @@ -187,7 +187,7 @@ public:  		else  		{  			width = EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidth(mLabel.c_str()); -			height = llmax(mImage->getHeight(), llceil(mStyle->getFont()->getLineHeight())); +			height = llmax(mImage->getHeight(), mStyle->getFont()->getLineHeight());  		}  		return false;  	} diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 2d837b3df8..8750b3b1f2 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -27,9 +27,6 @@  #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> @@ -49,7 +46,6 @@  #include "llviewquery.h"  #include "llxmltree.h"  #include "llslurl.h" -//#include "llviewercamera.h"  #include "llrender.h"  #include "llvoiceclient.h"	// for push-to-talk button handling @@ -616,7 +612,7 @@ public:  				addText(xpos, ypos, llformat("%d/%d Mesh HTTP Requests/Retries", LLMeshRepository::sHTTPRequestCount,  					LLMeshRepository::sHTTPRetryCount));  				ypos += y_inc; - +				  				addText(xpos, ypos, llformat("%d/%d Mesh LOD Pending/Processing", LLMeshRepository::sLODPending, LLMeshRepository::sLODProcessing));  				ypos += y_inc; @@ -1556,14 +1552,14 @@ LLViewerWindow::LLViewerWindow(const Params& p)  	mResDirty(false),  	mStatesDirty(false),  	mCurrResolutionIndex(0), +	mProgressView(NULL) +{  	// 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) -{ +	mWindowListener.reset(new LLWindowListener(this, boost::lambda::var(gKeyboard))); +	mViewerWindowListener.reset(new LLViewerWindowListener(this));  	LLNotificationChannel::buildChannel("VW_alerts", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alert"));  	LLNotificationChannel::buildChannel("VW_alertmodal", "Visible", LLNotificationFilters::filterBy<std::string>(&LLNotification::getType, "alertmodal")); @@ -1989,12 +1985,12 @@ void LLViewerWindow::shutdownViews()  		gMorphView->setVisible(FALSE);  	}  	llinfos << "Global views cleaned." << llendl ; -	 +  	// DEV-40930: Clear sModalStack. Otherwise, any LLModalDialog left open  	// will crump with LL_ERRS.  	LLModalDialog::shutdownModals();  	llinfos << "LLModalDialog shut down." << llendl;  - +	  	// destroy the nav bar, not currently part of gViewerWindow  	// *TODO: Make LLNavigationBar part of gViewerWindow  	if (LLNavigationBar::instanceExists()) @@ -2002,17 +1998,17 @@ void LLViewerWindow::shutdownViews()  		delete LLNavigationBar::getInstance();  	}  	llinfos << "LLNavigationBar destroyed." << llendl ; -	 +  	// destroy menus after instantiating navbar above, as it needs  	// access to gMenuHolder  	cleanup_menus();  	llinfos << "menus destroyed." << llendl ; -	 +  	// Delete all child views.  	delete mRootView;  	mRootView = NULL;  	llinfos << "RootView deleted." << llendl ; -	 +  	// Automatically deleted as children of mRootView.  Fix the globals.  	gStatusBar = NULL;  	gIMMgr = NULL; @@ -2391,7 +2387,7 @@ void LLViewerWindow::draw()  			gGL.matrixMode(LLRender::MM_MODELVIEW);  			LLUI::pushMatrix(); -			LLUI::translate( (F32) screen_x, (F32) screen_y, 0.f); +			LLUI::translate( (F32) screen_x, (F32) screen_y);  			top_ctrl->draw();	  			LLUI::popMatrix();  		} @@ -3199,12 +3195,6 @@ void LLViewerWindow::updateLayout()  		//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)  	{ @@ -4122,14 +4112,11 @@ void LLViewerWindow::resetSnapshotLoc()  void LLViewerWindow::movieSize(S32 new_width, S32 new_height)  {  	LLCoordWindow size; +	LLCoordWindow new_size(new_width, new_height);  	gViewerWindow->getWindow()->getSize(&size); -	if ( size.mX != new_width -		|| size.mY != new_height) +	if ( size != new_size )  	{ -		LLCoordWindow new_size(new_width, new_height); -		LLCoordScreen screen_size; -		gViewerWindow->getWindow()->convertCoords(new_size, &screen_size); -		gViewerWindow->getWindow()->setSize(screen_size); +		gViewerWindow->getWindow()->setSize(new_size.convert());  	}  } diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 15786b5dd0..c505936097 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -366,9 +366,9 @@ BOOL LLVOAvatarSelf::buildMenus()  						item_params.label = sub_piemenu_name;  					}  					item_params.name =(item_params.label ); -					item_params.on_click.function_name = "Attachment.Detach"; +					item_params.on_click.function_name = "Attachment.DetachFromPoint";  					item_params.on_click.parameter = iter->first; -					item_params.on_enable.function_name = "Attachment.EnableDetach"; +					item_params.on_enable.function_name = "Attachment.PointFilled";  					item_params.on_enable.parameter = iter->first;  					LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params); diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index e9db37821b..312034022e 100644 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -342,7 +342,7 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)  	blue_density = LLColor3();  	blue_horizon = LLColor3();  	haze_density = 0.f; -	haze_horizon = LLColor3(); +	haze_horizon = 1.f;  	density_multiplier = 0.f;  	max_y = 0.f;  	glow = LLColor3(); @@ -651,17 +651,17 @@ void LLVOSky::initAtmospherics(void)  	sunlight_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("sunlight_color", error));  	ambient = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("ambient", error));  	//lightnorm = LLWLParamManager::getInstance()->mCurParams.getVector("lightnorm", error); -	gamma = LLWLParamManager::getInstance()->mCurParams.getVector("gamma", error)[0]; +	gamma = LLWLParamManager::getInstance()->mCurParams.getFloat("gamma", error);  	blue_density = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_density", error));  	blue_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("blue_horizon", error)); -	haze_density = LLWLParamManager::getInstance()->mCurParams.getVector("haze_density", error)[0]; -	haze_horizon = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("haze_horizon", error)); -	density_multiplier = LLWLParamManager::getInstance()->mCurParams.getVector("density_multiplier", error)[0]; -	max_y = LLWLParamManager::getInstance()->mCurParams.getVector("max_y", error)[0]; +	haze_density = LLWLParamManager::getInstance()->mCurParams.getFloat("haze_density", error); +	haze_horizon = LLWLParamManager::getInstance()->mCurParams.getFloat("haze_horizon", error); +	density_multiplier = LLWLParamManager::getInstance()->mCurParams.getFloat("density_multiplier", error); +	max_y = LLWLParamManager::getInstance()->mCurParams.getFloat("max_y", error);  	glow = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("glow", error)); -	cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_shadow", error)[0]; +	cloud_shadow = LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_shadow", error);  	cloud_color = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_color", error)); -	cloud_scale = LLWLParamManager::getInstance()->mCurParams.getVector("cloud_scale", error)[0]; +	cloud_scale = LLWLParamManager::getInstance()->mCurParams.getFloat("cloud_scale", error);  	cloud_pos_density1 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density1", error));  	cloud_pos_density2 = LLColor3(LLWLParamManager::getInstance()->mCurParams.getVector("cloud_pos_density2", error)); @@ -825,7 +825,7 @@ void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLCo  	// Haze color above cloud  	vary_HazeColor = (blue_horizon * blue_weight * (sunlight + ambient) -				+ componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + ambient) +				+ componentMult(haze_horizon * haze_weight, sunlight * temp2.mV[0] + ambient)  			 );	  	// Increase ambient when there are more clouds @@ -836,7 +836,7 @@ void LLVOSky::calcSkyColorWLVert(LLVector3 & Pn, LLColor3 & vary_HazeColor, LLCo  	// Haze color below cloud  	LLColor3 additiveColorBelowCloud = (blue_horizon * blue_weight * (sunlight + tmpAmbient) -				+ componentMult(haze_horizon.mV[0] * haze_weight, sunlight * temp2.mV[0] + tmpAmbient) +				+ componentMult(haze_horizon * haze_weight, sunlight * temp2.mV[0] + tmpAmbient)  			 );	  	// Final atmosphere additive @@ -1002,7 +1002,7 @@ void LLVOSky::calcAtmospherics(void)  		//haze color  		vary_HazeColor =  			(blue_horizon * blue_weight * (sunlight*(1.f - cloud_shadow) + tmpAmbient)	 -			+ componentMult(haze_horizon.mV[0] * haze_weight, sunlight*(1.f - cloud_shadow) * temp2.mV[0] + tmpAmbient) +			+ componentMult(haze_horizon * haze_weight, sunlight*(1.f - cloud_shadow) * temp2.mV[0] + tmpAmbient)  				 );	  		//brightness of surface both sunlight and ambient diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h index d3a42583ea..6e6898d80a 100644 --- a/indra/newview/llvosky.h +++ b/indra/newview/llvosky.h @@ -410,7 +410,7 @@ public:  	LLColor3 blue_density;  	LLColor3 blue_horizon;  	F32 haze_density; -	LLColor3 haze_horizon; +	F32 haze_horizon;  	F32 density_multiplier;  	F32 max_y;  	LLColor3 glow; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 03d4c51aff..438d578ac5 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -4939,6 +4939,11 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  				fullbright = TRUE;  			} +			if (hud_group) +			{ //all hud attachments are fullbright +				fullbright = TRUE; +			} +  			const LLTextureEntry* te = facep->getTextureEntry();  			tex = facep->getTexture(); @@ -4968,7 +4973,6 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  				}  			}  			else if (gPipeline.canUseVertexShaders() -				&& group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD   				&& LLPipeline::sRenderBump   				&& te->getShiny())  			{ //shiny @@ -5033,9 +5037,12 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  					}  				} -				//not sure why this is here -- shiny HUD attachments maybe?  -- davep 5/11/2010 -				if (!is_alpha && te->getShiny() && LLPipeline::sRenderBump) -				{ +				 +				if (!gPipeline.canUseVertexShaders() &&  +					!is_alpha &&  +					te->getShiny() &&  +					LLPipeline::sRenderBump) +				{ //shiny as an extra pass when shaders are disabled  					registerFace(group, facep, LLRenderPass::PASS_SHINY);  				}  			} diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index 20b34637b8..e386112334 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -194,7 +194,7 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)  		shader->uniform4fv("waterPlane", 1, mWaterPlane.mV);  		shader->uniform1f("waterFogDensity", getFogDensity());  		shader->uniform1f("waterFogKS", mWaterFogKS); -		shader->uniform4f("distance_multiplier", 0, 0, 0, 0); +		shader->uniform1f("distance_multiplier", 0);  	}  } diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index 55608a059f..49d9d44d74 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -64,7 +64,6 @@  LLWLParamManager::LLWLParamManager() :  	//set the defaults for the controls -	// index is from sWLUniforms in pipeline.cpp line 979  	/// Sun Delta Terrain tweak variables.  	mSunDeltaYaw(180.0f), @@ -72,10 +71,10 @@ LLWLParamManager::LLWLParamManager() :  	mWLGamma(1.0f, "gamma"),  	mBlueHorizon(0.25f, 0.25f, 1.0f, 1.0f, "blue_horizon", "WLBlueHorizon"), -	mHazeDensity(1.0f, 1.0f, 1.0f, 0.5f, "haze_density"), +	mHazeDensity(1.0f, "haze_density"),  	mBlueDensity(0.25f, 0.25f, 0.25f, 1.0f, "blue_density", "WLBlueDensity"),  	mDensityMult(1.0f, "density_multiplier", 1000), -	mHazeHorizon(1.0f, 1.0f, 1.0f, 0.5f, "haze_horizon"), +	mHazeHorizon(1.0f, "haze_horizon"),  	mMaxAlt(4000.0f, "max_y"),  	// Lighting diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h index bc984b9126..72422500fc 100644 --- a/indra/newview/llwlparammanager.h +++ b/indra/newview/llwlparammanager.h @@ -102,9 +102,8 @@ struct WLFloatControl {  	{  	} -	inline WLFloatControl & operator = (LLVector4 const & val) { -		x = val.mV[0]; - +	inline WLFloatControl & operator = (F32 val) { +		x = val;  		return *this;  	} @@ -340,10 +339,10 @@ public:  	/// Atmospherics  	WLColorControl mBlueHorizon; -	WLColorControl mHazeDensity; +	WLFloatControl mHazeDensity;  	WLColorControl mBlueDensity;  	WLFloatControl mDensityMult; -	WLColorControl mHazeHorizon; +	WLFloatControl mHazeHorizon;  	WLFloatControl mMaxAlt;  	/// Lighting diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp index 5bb7025031..b04d30db55 100644 --- a/indra/newview/llwlparamset.cpp +++ b/indra/newview/llwlparamset.cpp @@ -41,33 +41,7 @@  LLWLParamSet::LLWLParamSet(void) :  	mName("Unnamed Preset"),  	mCloudScrollXOffset(0.f), mCloudScrollYOffset(0.f)	 -{ -/* REMOVE or init the LLSD -	const std::map<std::string, LLVector4>::value_type hardcodedPreset[] = { -		std::make_pair("lightnorm",				LLVector4(0.f, 0.707f, -0.707f, 0.f)), -		std::make_pair("sunlight_color",		LLVector4(0.6f, 0.6f, 2.83f, 2.27f)), -		std::make_pair("ambient",				LLVector4(0.27f, 0.33f, 0.44f, 1.19f)), -		std::make_pair("blue_horizon",			LLVector4(0.3f, 0.4f, 0.9f, 1.f)), -		std::make_pair("blue_density",			LLVector4(0.3f, 0.4f, 0.8f, 1.f)), -		std::make_pair("haze_horizon",			LLVector4(0.6f, 0.6f, 0.6f, 1.f)), -		std::make_pair("haze_density",			LLVector4(0.3f, 0.3f, 0.3f, 1.f)), -		std::make_pair("cloud_shadow",			LLVector4(0.f, 0.f, 0.f, 0.f)), -		std::make_pair("density_multiplier",	LLVector4(0.001f, 0.001f, 0.001f, 0.001f)), -		std::make_pair("distance_multiplier",	LLVector4(1.f, 1.f, 1.f, 1.f)), -		std::make_pair("max_y",					LLVector4(600.f, 600.f, 600.f, 0.f)), -		std::make_pair("glow",					LLVector4(15.f, 0.001f, -0.03125f, 0.f)), -		std::make_pair("cloud_color",			LLVector4(0.0f, 0.0f, 0.0f, 0.0f)), -		std::make_pair("cloud_pos_density1",	LLVector4(0.f, 0.f, 0.f, 1.f)), -		std::make_pair("cloud_pos_density2",	LLVector4(0.f, 0.f, 0.f, 1.f)), -		std::make_pair("cloud_scale",			LLVector4(0.42f, 0.f, 0.f, 1.f)), -		std::make_pair("gamma",					LLVector4(2.0f, 2.0f, 2.0f, 0.0f)), -	}; -	std::map<std::string, LLVector4>::value_type const * endHardcodedPreset =  -		hardcodedPreset + LL_ARRAY_SIZE(hardcodedPreset); - -	mParamValues.insert(hardcodedPreset, endHardcodedPreset); -*/ -} +{}  static LLFastTimer::DeclareTimer FTM_WL_PARAM_UPDATE("WL Param Update"); @@ -79,55 +53,78 @@ void LLWLParamSet::update(LLGLSLShader * shader) const  		i != mParamValues.endMap();  		++i)  	{ -		 -  		const std::string& param = i->first; -		if(	param == "star_brightness" || param == "preset_num" || param == "sun_angle" || +		if (param == "star_brightness" || param == "preset_num" || param == "sun_angle" ||  			param == "east_angle" || param == "enable_cloud_scroll" ||  			param == "cloud_scroll_rate" || param == "lightnorm" )   		{  			continue;  		} -		if(param == "cloud_pos_density1")  +		if (param == "cloud_pos_density1")  		{  			LLVector4 val;  			val.mV[0] = F32(i->second[0].asReal()) + mCloudScrollXOffset;  			val.mV[1] = F32(i->second[1].asReal()) + mCloudScrollYOffset;  			val.mV[2] = (F32) i->second[2].asReal();  			val.mV[3] = (F32) i->second[3].asReal(); +  			stop_glerror();  			shader->uniform4fv(param, 1, val.mV);  			stop_glerror(); -		}  +		} +		else if (param == "cloud_scale" || param == "cloud_shadow" || +				 param == "density_multiplier" || param == "distance_multiplier" || +				 param == "haze_density" || param == "haze_horizon" || +				 param == "max_y" ) +		{ +			F32 val = (F32) i->second[0].asReal(); + +			stop_glerror(); +			shader->uniform1f(param, val); +			stop_glerror(); +		}  		else // param is the uniform name  		{ -			LLVector4 val; -			  			// handle all the different cases -			if(i->second.isArray() && i->second.size() == 4)  +			if (i->second.isArray() && i->second.size() == 4)  			{ +				LLVector4 val; +  				val.mV[0] = (F32) i->second[0].asReal();  				val.mV[1] = (F32) i->second[1].asReal();  				val.mV[2] = (F32) i->second[2].asReal();  				val.mV[3] = (F32) i->second[3].asReal();															 + +				stop_glerror(); +				shader->uniform4fv(param, 1, val.mV); +				stop_glerror();  			}  -			else if(i->second.isReal())  +			else if (i->second.isReal())  			{ -				val.mV[0] = (F32) i->second.asReal(); +				F32 val = (F32) i->second.asReal(); + +				stop_glerror(); +				shader->uniform1f(param, val); +				stop_glerror();  			}  -			else if(i->second.isInteger())  +			else if (i->second.isInteger())  			{ -				val.mV[0] = (F32) i->second.asReal(); +				S32 val = (S32) i->second.asInteger(); + +				stop_glerror(); +				shader->uniform1i(param, val); +				stop_glerror();  			}  -			else if(i->second.isBoolean()) +			else if (i->second.isBoolean())  			{ -				val.mV[0] = i->second.asBoolean(); +				S32 val = (i->second.asBoolean() ? 1 : 0); + +				stop_glerror(); +				shader->uniform1i(param, val); +				stop_glerror();  			} -			stop_glerror(); -			shader->uniform4fv(param, 1, val.mV); -			stop_glerror();  		}  	}  } @@ -148,7 +145,8 @@ void LLWLParamSet::set(const std::string& paramName, float x)  	}  } -void LLWLParamSet::set(const std::string& paramName, float x, float y) { +void LLWLParamSet::set(const std::string& paramName, float x, float y) +{  	mParamValues[paramName][0] = x;  	mParamValues[paramName][1] = y;  } @@ -194,7 +192,6 @@ void LLWLParamSet::set(const std::string& paramName, const LLColor4 & val)  LLVector4 LLWLParamSet::getVector(const std::string& paramName, bool& error)   { -	  	// test to see if right type  	LLSD cur_val = mParamValues.get(paramName);  	if (!cur_val.isArray())  @@ -215,7 +212,6 @@ LLVector4 LLWLParamSet::getVector(const std::string& paramName, bool& error)  F32 LLWLParamSet::getFloat(const std::string& paramName, bool& error)   { -	  	// test to see if right type  	LLSD cur_val = mParamValues.get(paramName);  	if (cur_val.isArray() && cur_val.size() != 0)  @@ -234,8 +230,6 @@ F32 LLWLParamSet::getFloat(const std::string& paramName, bool& error)  	return 0;  } - -  void LLWLParamSet::setSunAngle(float val)   {  	// keep range 0 - 2pi @@ -263,7 +257,6 @@ void LLWLParamSet::setEastAngle(float val)  	mParamValues["east_angle"] = val;  } -  void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight)  {  	// set up the iterators @@ -282,7 +275,6 @@ void LLWLParamSet::mix(LLWLParamSet& src, LLWLParamSet& dest, F32 weight)  	// Iterate through values  	for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter)  	{ -  		// If param exists in both src and dest, set the holder variables, otherwise skip  		if(src.mParamValues.has(iter->first) && dest.mParamValues.has(iter->first))  		{ diff --git a/indra/newview/llwlparamset.h b/indra/newview/llwlparamset.h index 3c44ed3bb8..b087119dd5 100644 --- a/indra/newview/llwlparamset.h +++ b/indra/newview/llwlparamset.h @@ -110,7 +110,7 @@ public:  	/// \param error		A flag to set if it's not the proper return type  	LLVector4 getVector(const std::string& paramName, bool& error); -	/// Get an integer parameter +	/// Get a float parameter  	/// \param paramName	The name of the parameter to set.  	/// \param error		A flag to set if it's not the proper return type	  	F32 getFloat(const std::string& paramName, bool& error); diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 9fd77546eb..e508f768b4 100644 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -1,1097 +1,1097 @@ -/**  - * @file llworld.cpp - * @brief Initial test structure to organize viewer regions - * - * $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 "llworld.h" -#include "llrender.h" - -#include "indra_constants.h" -#include "llstl.h" - -#include "llagent.h" -#include "llviewercontrol.h" -#include "lldrawpool.h" -#include "llglheaders.h" -#include "llhttpnode.h" -#include "llregionhandle.h" -#include "llsurface.h" -#include "lltrans.h" -#include "llviewercamera.h" -#include "llviewertexture.h" -#include "llviewertexturelist.h" -#include "llviewernetwork.h" -#include "llviewerobjectlist.h" -#include "llviewerparceloverlay.h" -#include "llviewerregion.h" -#include "llviewerstats.h" -#include "llvlcomposition.h" -#include "llvoavatar.h" -#include "llvocache.h" -#include "llvowater.h" -#include "message.h" -#include "pipeline.h" -#include "llappviewer.h"		// for do_disconnect() -#include "llfloaterpathfindingconsole.h" - -#include <deque> -#include <queue> -#include <map> -#include <cstring> - - -// -// Globals -// -U32			gAgentPauseSerialNum = 0; - -// -// Constants -// -const S32 MAX_NUMBER_OF_CLOUDS	= 750; -const S32 WORLD_PATCH_SIZE = 16; - -extern LLColor4U MAX_WATER_COLOR; - -const U32 LLWorld::mWidth = 256; - -// meters/point, therefore mWidth * mScale = meters per edge -const F32 LLWorld::mScale = 1.f; - -const F32 LLWorld::mWidthInMeters = mWidth * mScale; - -// -// Functions -// - -// allocate the stack -LLWorld::LLWorld() : -	mLandFarClip(DEFAULT_FAR_PLANE), -	mLastPacketsIn(0), -	mLastPacketsOut(0), -	mLastPacketsLost(0), -	mSpaceTimeUSec(0) -{ -	for (S32 i = 0; i < 8; i++) -	{ -		mEdgeWaterObjects[i] = NULL; -	} - -	LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,4); -	U8 *default_texture = raw->getData(); -	*(default_texture++) = MAX_WATER_COLOR.mV[0]; -	*(default_texture++) = MAX_WATER_COLOR.mV[1]; -	*(default_texture++) = MAX_WATER_COLOR.mV[2]; -	*(default_texture++) = MAX_WATER_COLOR.mV[3]; -	 -	mDefaultWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE); -	gGL.getTexUnit(0)->bind(mDefaultWaterTexturep); -	mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - -} - - -void LLWorld::destroyClass() -{ -	mHoleWaterObjects.clear(); -	gObjectList.destroy(); -	for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); ) -	{ -		LLViewerRegion* region_to_delete = *region_it++; -		removeRegion(region_to_delete->getHost()); -	} -	if(LLVOCache::hasInstance()) -	{ -		LLVOCache::getInstance()->destroyClass() ; -	} -	LLViewerPartSim::getInstance()->destroyClass(); - -	mDefaultWaterTexturep = NULL ; -	for (S32 i = 0; i < 8; i++) -	{ -		mEdgeWaterObjects[i] = NULL; -	} -} - - -LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host) -{ -	LLMemType mt(LLMemType::MTYPE_REGIONS); -	llinfos << "Add region with handle: " << region_handle << " on host " << host << llendl; -	LLViewerRegion *regionp = getRegionFromHandle(region_handle); -	if (regionp) -	{ -		llinfos << "Region exists, removing it " << llendl; -		LLHost old_host = regionp->getHost(); -		// region already exists! -		if (host == old_host && regionp->isAlive()) -		{ -			// This is a duplicate for the same host and it's alive, don't bother. -			return regionp; -		} - -		if (host != old_host) -		{ -			llwarns << "LLWorld::addRegion exists, but old host " << old_host -					<< " does not match new host " << host << llendl; -		} -		if (!regionp->isAlive()) -		{ -			llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl; -		} - -		// Kill the old host, and then we can continue on and add the new host.  We have to kill even if the host -		// matches, because all the agent state for the new camera is completely different. -		removeRegion(old_host); -	} - -	U32 iindex = 0; -	U32 jindex = 0; -	from_region_handle(region_handle, &iindex, &jindex); -	S32 x = (S32)(iindex/mWidth); -	S32 y = (S32)(jindex/mWidth); -	llinfos << "Adding new region (" << x << ":" << y << ")" << llendl; -	llinfos << "Host: " << host << llendl; - -	LLVector3d origin_global; - -	origin_global = from_region_handle(region_handle); - -	regionp = new LLViewerRegion(region_handle, -								    host, -									mWidth, -									WORLD_PATCH_SIZE, -									getRegionWidthInMeters() ); -	if (!regionp) -	{ -		llerrs << "Unable to create new region!" << llendl; -	} - -	mRegionList.push_back(regionp); -	mActiveRegionList.push_back(regionp); -	mCulledRegionList.push_back(regionp); - - -	// Find all the adjacent regions, and attach them. -	// Generate handles for all of the adjacent regions, and attach them in the correct way. -	// connect the edges -	F32 adj_x = 0.f; -	F32 adj_y = 0.f; -	F32 region_x = 0.f; -	F32 region_y = 0.f; -	U64 adj_handle = 0; - -	F32 width = getRegionWidthInMeters(); - -	LLViewerRegion *neighborp; -	from_region_handle(region_handle, ®ion_x, ®ion_y); - -	// Iterate through all directions, and connect neighbors if there. -	S32 dir; -	for (dir = 0; dir < 8; dir++) -	{ -		adj_x = region_x + width * gDirAxes[dir][0]; -		adj_y = region_y + width * gDirAxes[dir][1]; -		to_region_handle(adj_x, adj_y, &adj_handle); - -		neighborp = getRegionFromHandle(adj_handle); -		if (neighborp) -		{ -			//llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl; -			regionp->connectNeighbor(neighborp, dir); -		} -	} - -	updateWaterObjects(); - -	return regionp; -} - - -void LLWorld::removeRegion(const LLHost &host) -{ -	F32 x, y; - -	LLViewerRegion *regionp = getRegion(host); -	if (!regionp) -	{ -		llwarns << "Trying to remove region that doesn't exist!" << llendl; -		return; -	} -	 -	if (regionp == gAgent.getRegion()) -	{ -		for (region_list_t::iterator iter = mRegionList.begin(); -			 iter != mRegionList.end(); ++iter) -		{ -			LLViewerRegion* reg = *iter; -			llwarns << "RegionDump: " << reg->getName() -				<< " " << reg->getHost() -				<< " " << reg->getOriginGlobal() -				<< llendl; -		} - -		llwarns << "Agent position global " << gAgent.getPositionGlobal()  -			<< " agent " << gAgent.getPositionAgent() -			<< llendl; - -		llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl; - -		llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl; - -		llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl; -		LLAppViewer::instance()->forceDisconnect(LLTrans::getString("YouHaveBeenDisconnected")); - -		regionp->saveObjectCache() ; //force to save objects here in case that the object cache is about to be destroyed. -		return; -	} - -	from_region_handle(regionp->getHandle(), &x, &y); -	llinfos << "Removing region " << x << ":" << y << llendl; - -	mRegionList.remove(regionp); -	mActiveRegionList.remove(regionp); -	mCulledRegionList.remove(regionp); -	mVisibleRegionList.remove(regionp); -	 -	delete regionp; - -	updateWaterObjects(); - -	//double check all objects of this region are removed. -	gObjectList.clearAllMapObjectsInRegion(regionp) ; -	//llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ; -} - - -LLViewerRegion* LLWorld::getRegion(const LLHost &host) -{ -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		if (regionp->getHost() == host) -		{ -			return regionp; -		} -	} -	return NULL; -} - -LLViewerRegion* LLWorld::getRegionFromPosAgent(const LLVector3 &pos) -{ -	return getRegionFromPosGlobal(gAgent.getPosGlobalFromAgent(pos)); -} - -LLViewerRegion* LLWorld::getRegionFromPosGlobal(const LLVector3d &pos) -{ -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		if (regionp->pointInRegionGlobal(pos)) -		{ -			return regionp; -		} -	} -	return NULL; -} - - -LLVector3d	LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos) -{ -	if (positionRegionValidGlobal(end_pos)) -	{ -		return end_pos; -	} - -	LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos); -	if (!regionp)  -	{ -		return start_pos; -	} - -	LLVector3d delta_pos = end_pos - start_pos; -	LLVector3d delta_pos_abs; -	delta_pos_abs.setVec(delta_pos); -	delta_pos_abs.abs(); - -	LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos); -	F64 clip_factor = 1.0; -	F32 region_width = regionp->getWidth(); -	if (region_coord.mV[VX] < 0.f) -	{ -		if (region_coord.mV[VY] < region_coord.mV[VX]) -		{ -			// clip along y - -			clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); -		} -		else -		{ -			// clip along x - -			clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]); -		} -	} -	else if (region_coord.mV[VX] > region_width) -	{ -		if (region_coord.mV[VY] > region_coord.mV[VX]) -		{ -			// clip along y + -			clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; -		} -		else -		{ -			//clip along x + -			clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX]; -		} -	} -	else if (region_coord.mV[VY] < 0.f) -	{ -		// clip along y - -		clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); -	} -	else if (region_coord.mV[VY] > region_width) -	{  -		// clip along y + -		clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; -	} - -	// clamp to within region dimensions -	LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor); -	final_region_pos.mdV[VX] = llclamp(final_region_pos.mdV[VX], 0.0, -									   (F64)(region_width - F_ALMOST_ZERO)); -	final_region_pos.mdV[VY] = llclamp(final_region_pos.mdV[VY], 0.0, -									   (F64)(region_width - F_ALMOST_ZERO)); -	final_region_pos.mdV[VZ] = llclamp(final_region_pos.mdV[VZ], 0.0, -									   (F64)(LLWorld::getInstance()->getRegionMaxHeight() - F_ALMOST_ZERO)); -	return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos)); -} - -LLViewerRegion* LLWorld::getRegionFromHandle(const U64 &handle) -{ -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		if (regionp->getHandle() == handle) -		{ -			return regionp; -		} -	} -	return NULL; -} - - -void LLWorld::updateAgentOffset(const LLVector3d &offset_global) -{ -#if 0 -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		regionp->setAgentOffset(offset_global); -	} -#endif -} - - -BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global) -{ -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		if (regionp->pointInRegionGlobal(pos_global)) -		{ -			return TRUE; -		} -	} -	return FALSE; -} - - -// Allow objects to go up to their radius underground. -F32 LLWorld::getMinAllowedZ(LLViewerObject* object, const LLVector3d &global_pos) -{ -	F32 land_height = resolveLandHeightGlobal(global_pos); -	F32 radius = 0.5f * object->getScale().length(); -	return land_height - radius; -} - - - -LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global) -{ -	LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); - -	if (regionp) -	{ -		pos_region = regionp->getPosRegionFromGlobal(pos_global); -		return regionp; -	} - -	return NULL; -} - - -LLViewerRegion* LLWorld::resolveRegionAgent(LLVector3 &pos_region, const LLVector3 &pos_agent) -{ -	LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); -	LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); - -	if (regionp) -	{ -		pos_region = regionp->getPosRegionFromGlobal(pos_global); -		return regionp; -	} - -	return NULL; -} - - -F32 LLWorld::resolveLandHeightAgent(const LLVector3 &pos_agent) -{ -	LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent); -	return resolveLandHeightGlobal(pos_global); -} - - -F32 LLWorld::resolveLandHeightGlobal(const LLVector3d &pos_global) -{ -	LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); -	if (regionp) -	{ -		return regionp->getLand().resolveHeightGlobal(pos_global); -	} -	return 0.0f; -} - - -// Takes a line defined by "point_a" and "point_b" and determines the closest (to point_a)  -// point where the the line intersects an object or the land surface.  Stores the results -// in "intersection" and "intersection_normal" and returns a scalar value that represents -// the normalized distance along the line from "point_a" to "intersection". -// -// Currently assumes point_a and point_b only differ in z-direction,  -// but it may eventually become more general. -F32 LLWorld::resolveStepHeightGlobal(const LLVOAvatar* avatarp, const LLVector3d &point_a, const LLVector3d &point_b,  -							   LLVector3d &intersection, LLVector3 &intersection_normal, -							   LLViewerObject **viewerObjectPtr) -{ -	// initialize return value to null -	if (viewerObjectPtr) -	{ -		*viewerObjectPtr = NULL; -	} - -	LLViewerRegion *regionp = getRegionFromPosGlobal(point_a); -	if (!regionp) -	{ -		// We're outside the world  -		intersection = 0.5f * (point_a + point_b); -		intersection_normal.setVec(0.0f, 0.0f, 1.0f); -		return 0.5f; -	} -	 -	// calculate the length of the segment -	F32 segment_length = (F32)((point_a - point_b).length()); -	if (0.0f == segment_length) -	{ -		intersection = point_a; -		intersection_normal.setVec(0.0f, 0.0f, 1.0f); -		return segment_length; -	} - -	// get land height	 -	// Note: we assume that the line is parallel to z-axis here -	LLVector3d land_intersection = point_a; -	F32 normalized_land_distance; - -	land_intersection.mdV[VZ] = regionp->getLand().resolveHeightGlobal(point_a); -	normalized_land_distance = (F32)(point_a.mdV[VZ] - land_intersection.mdV[VZ]) / segment_length; -	intersection = land_intersection; -	intersection_normal = resolveLandNormalGlobal(land_intersection); - -	if (avatarp && !avatarp->mFootPlane.isExactlyClear()) -	{ -		LLVector3 foot_plane_normal(avatarp->mFootPlane.mV); -		LLVector3 start_pt = avatarp->getRegion()->getPosRegionFromGlobal(point_a); -		// added 0.05 meters to compensate for error in foot plane reported by Havok -		F32 norm_dist_from_plane = ((start_pt * foot_plane_normal) - avatarp->mFootPlane.mV[VW]) + 0.05f; -		norm_dist_from_plane = llclamp(norm_dist_from_plane / segment_length, 0.f, 1.f); -		if (norm_dist_from_plane < normalized_land_distance) -		{ -			// collided with object before land -			normalized_land_distance = norm_dist_from_plane; -			intersection = point_a; -			intersection.mdV[VZ] -= norm_dist_from_plane * segment_length; -			intersection_normal = foot_plane_normal; -		} -		else -		{ -			intersection = land_intersection; -			intersection_normal = resolveLandNormalGlobal(land_intersection); -		} -	} - -	return normalized_land_distance; -} - - -LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global) -{ -	//  returns a pointer to the patch at this location -	LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); -	if (!regionp) -	{ -		return NULL; -	} - -	return regionp->getLand().resolvePatchGlobal(pos_global); -} - - -LLVector3 LLWorld::resolveLandNormalGlobal(const LLVector3d &pos_global) -{ -	LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global); -	if (!regionp) -	{ -		return LLVector3::z_axis; -	} - -	return regionp->getLand().resolveNormalGlobal(pos_global); -} - - -void LLWorld::updateVisibilities() -{ -	F32 cur_far_clip = LLViewerCamera::getInstance()->getFar(); - -	// Go through the culled list and check for visible regions (region is visible if land is visible) -	for (region_list_t::iterator iter = mCulledRegionList.begin(); -		 iter != mCulledRegionList.end(); ) -	{ -		region_list_t::iterator curiter = iter++; -		LLViewerRegion* regionp = *curiter; -		 -		LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN); -		if (part) -		{ -			LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); -			if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1])) -			{ -				mCulledRegionList.erase(curiter); -				mVisibleRegionList.push_back(regionp); -			} -		} -	} -	 -	// Update all of the visible regions  -	for (region_list_t::iterator iter = mVisibleRegionList.begin(); -		 iter != mVisibleRegionList.end(); ) -	{ -		region_list_t::iterator curiter = iter++; -		LLViewerRegion* regionp = *curiter; -		if (!regionp->getLand().hasZData()) -		{ -			continue; -		} - -		LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN); -		if (part) -		{ -			LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); -			if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1])) -			{ -				regionp->calculateCameraDistance(); -				regionp->getLand().updatePatchVisibilities(gAgent); -			} -			else -			{ -				mVisibleRegionList.erase(curiter); -				mCulledRegionList.push_back(regionp); -			} -		} -	} - -	// Sort visible regions -	mVisibleRegionList.sort(LLViewerRegion::CompareDistance()); -	 -	LLViewerCamera::getInstance()->setFar(cur_far_clip); -} - -void LLWorld::updateRegions(F32 max_update_time) -{ -	LLMemType mt_ur(LLMemType::MTYPE_IDLE_UPDATE_REGIONS); -	LLTimer update_timer; -	BOOL did_one = FALSE; -	 -	// Perform idle time updates for the regions (and associated surfaces) -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		F32 max_time = max_update_time - update_timer.getElapsedTimeF32(); -		if (did_one && max_time <= 0.f) -			break; -		max_time = llmin(max_time, max_update_time*.1f); -		did_one |= regionp->idleUpdate(max_update_time); -	} -} - -void LLWorld::updateParticles() -{ -	LLViewerPartSim::getInstance()->updateSimulation(); -} - -void LLWorld::renderPropertyLines() -{ -	S32 region_count = 0; -	S32 vertex_count = 0; - -	for (region_list_t::iterator iter = mVisibleRegionList.begin(); -		 iter != mVisibleRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		region_count++; -		vertex_count += regionp->renderPropertyLines(); -	} -} - - -void LLWorld::updateNetStats() -{ -	F32 bits = 0.f; -	U32 packets = 0; - -	for (region_list_t::iterator iter = mActiveRegionList.begin(); -		 iter != mActiveRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		regionp->updateNetStats(); -		bits += regionp->mBitStat.getCurrent(); -		packets += llfloor( regionp->mPacketsStat.getCurrent() ); -	} - -	S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn; -	S32 packets_out = gMessageSystem->mPacketsOut - mLastPacketsOut; -	S32 packets_lost = gMessageSystem->mDroppedPackets - mLastPacketsLost; - -	S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits(); -	S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits(); -	LLViewerStats::getInstance()->mActualInKBitStat.addValue(actual_in_bits/1024.f); -	LLViewerStats::getInstance()->mActualOutKBitStat.addValue(actual_out_bits/1024.f); -	LLViewerStats::getInstance()->mKBitStat.addValue(bits/1024.f); -	LLViewerStats::getInstance()->mPacketsInStat.addValue(packets_in); -	LLViewerStats::getInstance()->mPacketsOutStat.addValue(packets_out); -	LLViewerStats::getInstance()->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets); -	if (packets_in) -	{ -		LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in)); -	} -	else -	{ -		LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(0.f); -	} - -	mLastPacketsIn = gMessageSystem->mPacketsIn; -	mLastPacketsOut = gMessageSystem->mPacketsOut; -	mLastPacketsLost = gMessageSystem->mDroppedPackets; -} - - -void LLWorld::printPacketsLost() -{ -	llinfos << "Simulators:" << llendl; -	llinfos << "----------" << llendl; - -	LLCircuitData *cdp = NULL; -	for (region_list_t::iterator iter = mActiveRegionList.begin(); -		 iter != mActiveRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost()); -		if (cdp) -		{ -			LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal(); -				 -			llinfos << regionp->getHost() << ", range: " << range.length() -					<< " packets lost: " << cdp->getPacketsLost() << llendl; -		} -	} -} - -void LLWorld::processCoarseUpdate(LLMessageSystem* msg, void** user_data) -{ -	LLViewerRegion* region = LLWorld::getInstance()->getRegion(msg->getSender()); -	if( region ) -	{ -		region->updateCoarseLocations(msg); -	} -} - -F32 LLWorld::getLandFarClip() const -{ -	return mLandFarClip; -} - -void LLWorld::setLandFarClip(const F32 far_clip) -{ -	static S32 const rwidth = (S32)REGION_WIDTH_U32; -	S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth; -	S32 const n2 = (llceil(far_clip) - 1) / rwidth; -	bool need_water_objects_update = n1 != n2; - -	mLandFarClip = far_clip; - -	if (need_water_objects_update) -	{ -		updateWaterObjects(); -	} -} - -// Some region that we're connected to, but not the one we're in, gave us -// a (possibly) new water height. Update it in our local copy. -void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_height) -{ -	for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter) -	{ -		if ((*iter)->getName() == sim_name) -		{ -			(*iter)->setWaterHeight(water_height); -			break; -		} -	} -} - -void LLWorld::updateWaterObjects() -{ -	if (!gAgent.getRegion()) -	{ -		return; -	} -	if (mRegionList.empty()) -	{ -		llwarns << "No regions!" << llendl; -		return; -	} - -	// First, determine the min and max "box" of water objects -	S32 min_x = 0; -	S32 min_y = 0; -	S32 max_x = 0; -	S32 max_y = 0; -	U32 region_x, region_y; - -	S32 rwidth = 256; - -	// We only want to fill in water for stuff that's near us, say, within 256 or 512m -	S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256; - -	LLViewerRegion* regionp = gAgent.getRegion(); -	from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y); - -	min_x = (S32)region_x - range; -	min_y = (S32)region_y - range; -	max_x = (S32)region_x + range; -	max_y = (S32)region_y + range; - -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		LLVOWater* waterp = regionp->getLand().getWaterObj(); -		if (waterp) -		{ -			gObjectList.updateActive(waterp); -		} -	} - -	for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin(); -		 iter != mHoleWaterObjects.end(); ++ iter) -	{ -		LLVOWater* waterp = *iter; -		gObjectList.killObject(waterp); -	} -	mHoleWaterObjects.clear(); - -	// Now, get a list of the holes -	S32 x, y; -	F32 water_height = gAgent.getRegion()->getWaterHeight() + 256.f; -	for (x = min_x; x <= max_x; x += rwidth) -	{ -		for (y = min_y; y <= max_y; y += rwidth) -		{ -			U64 region_handle = to_region_handle(x, y); -			if (!getRegionFromHandle(region_handle)) -			{ -				LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion()); -				waterp->setUseTexture(FALSE); -				waterp->setPositionGlobal(LLVector3d(x + rwidth/2, -													 y + rwidth/2, -													 water_height)); -				waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f)); -				gPipeline.createObject(waterp); -				mHoleWaterObjects.push_back(waterp); -			} -		} -	} - -	// Update edge water objects -	S32 wx, wy; -	S32 center_x, center_y; -	wx = (max_x - min_x) + rwidth; -	wy = (max_y - min_y) + rwidth; -	center_x = min_x + (wx >> 1); -	center_y = min_y + (wy >> 1); - -	S32 add_boundary[4] = { -		512 - (max_x - region_x), -		512 - (max_y - region_y), -		512 - (region_x - min_x), -		512 - (region_y - min_y) }; -		 -	S32 dir; -	for (dir = 0; dir < 8; dir++) -	{ -		S32 dim[2] = { 0 }; -		switch (gDirAxes[dir][0]) -		{ -		case -1: dim[0] = add_boundary[2]; break; -		case  0: dim[0] = wx; break; -		default: dim[0] = add_boundary[0]; break; -		} -		switch (gDirAxes[dir][1]) -		{ -		case -1: dim[1] = add_boundary[3]; break; -		case  0: dim[1] = wy; break; -		default: dim[1] = add_boundary[1]; break; -		} - -		// Resize and reshape the water objects -		const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]); -		const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]); -		 -		LLVOWater* waterp = mEdgeWaterObjects[dir]; -		if (!waterp || waterp->isDead()) -		{ -			// The edge water objects can be dead because they're attached to the region that the -			// agent was in when they were originally created. -			mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER, -																				 gAgent.getRegion()); -			waterp = mEdgeWaterObjects[dir]; -			waterp->setUseTexture(FALSE); -			waterp->setIsEdgePatch(TRUE); -			gPipeline.createObject(waterp); -		} - -		waterp->setRegion(gAgent.getRegion()); -		LLVector3d water_pos(water_center_x, water_center_y, water_height) ; -		LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f); - -		//stretch out to horizon -		water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]); -		water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]); - -		water_pos.mdV[0] += 1024.f * gDirAxes[dir][0]; -		water_pos.mdV[1] += 1024.f * gDirAxes[dir][1]; - -		waterp->setPositionGlobal(water_pos); -		waterp->setScale(water_scale); - -		gObjectList.updateActive(waterp); -	} -} - - -void LLWorld::shiftRegions(const LLVector3& offset) -{ -	for (region_list_t::const_iterator i = getRegionList().begin(); i != getRegionList().end(); ++i) -	{ -		LLViewerRegion* region = *i; -		region->updateRenderMatrix(); -	} - -	LLViewerPartSim::getInstance()->shift(offset); -} - -LLViewerTexture* LLWorld::getDefaultWaterTexture() -{ -	return mDefaultWaterTexturep; -} - -void LLWorld::setSpaceTimeUSec(const U64 space_time_usec) -{ -	mSpaceTimeUSec = space_time_usec; -} - -U64 LLWorld::getSpaceTimeUSec() const -{ -	return mSpaceTimeUSec; -} - -void LLWorld::requestCacheMisses() -{ -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		regionp->requestCacheMisses(); -	} -} - -void LLWorld::getInfo(LLSD& info) -{ -	LLSD region_info; -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) -	{	 -		LLViewerRegion* regionp = *iter; -		regionp->getInfo(region_info); -		info["World"].append(region_info); -	} -} - -void LLWorld::disconnectRegions() -{ -	LLMessageSystem* msg = gMessageSystem; -	for (region_list_t::iterator iter = mRegionList.begin(); -		 iter != mRegionList.end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		if (regionp == gAgent.getRegion()) -		{ -			// Skip the main agent -			continue; -		} - -		llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl; -		msg->newMessageFast(_PREHASH_AgentQuitCopy); -		msg->nextBlockFast(_PREHASH_AgentData); -		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); -		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -		msg->nextBlockFast(_PREHASH_FuseBlock); -		msg->addU32Fast(_PREHASH_ViewerCircuitCode, gMessageSystem->mOurCircuitCode); -		msg->sendMessage(regionp->getHost()); -	} -} - -static LLFastTimer::DeclareTimer FTM_ENABLE_SIMULATOR("Enable Sim"); - -void process_enable_simulator(LLMessageSystem *msg, void **user_data) -{ -	LLFastTimer t(FTM_ENABLE_SIMULATOR); -	// enable the appropriate circuit for this simulator and  -	// add its values into the gSimulator structure -	U64		handle; -	U32		ip_u32; -	U16		port; - -	msg->getU64Fast(_PREHASH_SimulatorInfo, _PREHASH_Handle, handle); -	msg->getIPAddrFast(_PREHASH_SimulatorInfo, _PREHASH_IP, ip_u32); -	msg->getIPPortFast(_PREHASH_SimulatorInfo, _PREHASH_Port, port); - -	// which simulator should we modify? -	LLHost sim(ip_u32, port); - -	// Viewer trusts the simulator. -	msg->enableCircuit(sim, TRUE); -	LLWorld::getInstance()->addRegion(handle, sim); - -	// give the simulator a message it can use to get ip and port -	llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl; -	msg->newMessageFast(_PREHASH_UseCircuitCode); -	msg->nextBlockFast(_PREHASH_CircuitCode); -	msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode()); -	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -	msg->addUUIDFast(_PREHASH_ID, gAgent.getID()); -	msg->sendReliable(sim); -} - -class LLEstablishAgentCommunication : public LLHTTPNode -{ -	LOG_CLASS(LLEstablishAgentCommunication); -public: - 	virtual void describe(Description& desc) const -	{ -		desc.shortInfo("seed capability info for a region"); -		desc.postAPI(); -		desc.input( -			"{ seed-capability: ..., sim-ip: ..., sim-port }"); -		desc.source(__FILE__, __LINE__); -	} - -	virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const -	{ -		if (!input["body"].has("agent-id") || -			!input["body"].has("sim-ip-and-port") || -			!input["body"].has("seed-capability")) -		{ -			llwarns << "invalid parameters" << llendl; -            return; -		} - -		LLHost sim(input["body"]["sim-ip-and-port"].asString()); -	 -		LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim); -		if (!regionp) -		{ -			llwarns << "Got EstablishAgentCommunication for unknown region " -					<< sim << llendl; -			return; -		} -		regionp->setSeedCapability(input["body"]["seed-capability"]); -	} -}; - -// disable the circuit to this simulator -// Called in response to "DisableSimulator" message. -void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data) -{	 -	LLHost host = mesgsys->getSender(); - -	//llinfos << "Disabling simulator with message from " << host << llendl; -	LLWorld::getInstance()->removeRegion(host); - -	mesgsys->disableCircuit(host); -} - - -void process_region_handshake(LLMessageSystem* msg, void** user_data) -{ -	LLHost host = msg->getSender(); -	LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(host); -	if (!regionp) -	{ -		llwarns << "Got region handshake for unknown region " -			<< host << llendl; -		return; -	} - -	regionp->unpackRegionHandshake(); +/** 
 + * @file llworld.cpp
 + * @brief Initial test structure to organize viewer regions
 + *
 + * $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 "llworld.h"
 +#include "llrender.h"
 +
 +#include "indra_constants.h"
 +#include "llstl.h"
 +
 +#include "llagent.h"
 +#include "llviewercontrol.h"
 +#include "lldrawpool.h"
 +#include "llglheaders.h"
 +#include "llhttpnode.h"
 +#include "llregionhandle.h"
 +#include "llsurface.h"
 +#include "lltrans.h"
 +#include "llviewercamera.h"
 +#include "llviewertexture.h"
 +#include "llviewertexturelist.h"
 +#include "llviewernetwork.h"
 +#include "llviewerobjectlist.h"
 +#include "llviewerparceloverlay.h"
 +#include "llviewerregion.h"
 +#include "llviewerstats.h"
 +#include "llvlcomposition.h"
 +#include "llvoavatar.h"
 +#include "llvocache.h"
 +#include "llvowater.h"
 +#include "message.h"
 +#include "pipeline.h"
 +#include "llappviewer.h"		// for do_disconnect()
 +#include "llfloaterpathfindingconsole.h"
 +
 +#include <deque>
 +#include <queue>
 +#include <map>
 +#include <cstring>
 +
 +
 +//
 +// Globals
 +//
 +U32			gAgentPauseSerialNum = 0;
 +
 +//
 +// Constants
 +//
 +const S32 MAX_NUMBER_OF_CLOUDS	= 750;
 +const S32 WORLD_PATCH_SIZE = 16;
 +
 +extern LLColor4U MAX_WATER_COLOR;
 +
 +const U32 LLWorld::mWidth = 256;
 +
 +// meters/point, therefore mWidth * mScale = meters per edge
 +const F32 LLWorld::mScale = 1.f;
 +
 +const F32 LLWorld::mWidthInMeters = mWidth * mScale;
 +
 +//
 +// Functions
 +//
 +
 +// allocate the stack
 +LLWorld::LLWorld() :
 +	mLandFarClip(DEFAULT_FAR_PLANE),
 +	mLastPacketsIn(0),
 +	mLastPacketsOut(0),
 +	mLastPacketsLost(0),
 +	mSpaceTimeUSec(0)
 +{
 +	for (S32 i = 0; i < 8; i++)
 +	{
 +		mEdgeWaterObjects[i] = NULL;
 +	}
 +
 +	LLPointer<LLImageRaw> raw = new LLImageRaw(1,1,4);
 +	U8 *default_texture = raw->getData();
 +	*(default_texture++) = MAX_WATER_COLOR.mV[0];
 +	*(default_texture++) = MAX_WATER_COLOR.mV[1];
 +	*(default_texture++) = MAX_WATER_COLOR.mV[2];
 +	*(default_texture++) = MAX_WATER_COLOR.mV[3];
 +	
 +	mDefaultWaterTexturep = LLViewerTextureManager::getLocalTexture(raw.get(), FALSE);
 +	gGL.getTexUnit(0)->bind(mDefaultWaterTexturep);
 +	mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
 +
 +}
 +
 +
 +void LLWorld::destroyClass()
 +{
 +	mHoleWaterObjects.clear();
 +	gObjectList.destroy();
 +	for(region_list_t::iterator region_it = mRegionList.begin(); region_it != mRegionList.end(); )
 +	{
 +		LLViewerRegion* region_to_delete = *region_it++;
 +		removeRegion(region_to_delete->getHost());
 +	}
 +	if(LLVOCache::hasInstance())
 +	{
 +		LLVOCache::getInstance()->destroyClass() ;
 +	}
 +	LLViewerPartSim::getInstance()->destroyClass();
 +
 +	mDefaultWaterTexturep = NULL ;
 +	for (S32 i = 0; i < 8; i++)
 +	{
 +		mEdgeWaterObjects[i] = NULL;
 +	}
 +}
 +
 +
 +LLViewerRegion* LLWorld::addRegion(const U64 ®ion_handle, const LLHost &host)
 +{
 +	LLMemType mt(LLMemType::MTYPE_REGIONS);
 +	llinfos << "Add region with handle: " << region_handle << " on host " << host << llendl;
 +	LLViewerRegion *regionp = getRegionFromHandle(region_handle);
 +	if (regionp)
 +	{
 +		llinfos << "Region exists, removing it " << llendl;
 +		LLHost old_host = regionp->getHost();
 +		// region already exists!
 +		if (host == old_host && regionp->isAlive())
 +		{
 +			// This is a duplicate for the same host and it's alive, don't bother.
 +			return regionp;
 +		}
 +
 +		if (host != old_host)
 +		{
 +			llwarns << "LLWorld::addRegion exists, but old host " << old_host
 +					<< " does not match new host " << host << llendl;
 +		}
 +		if (!regionp->isAlive())
 +		{
 +			llwarns << "LLWorld::addRegion exists, but isn't alive" << llendl;
 +		}
 +
 +		// Kill the old host, and then we can continue on and add the new host.  We have to kill even if the host
 +		// matches, because all the agent state for the new camera is completely different.
 +		removeRegion(old_host);
 +	}
 +
 +	U32 iindex = 0;
 +	U32 jindex = 0;
 +	from_region_handle(region_handle, &iindex, &jindex);
 +	S32 x = (S32)(iindex/mWidth);
 +	S32 y = (S32)(jindex/mWidth);
 +	llinfos << "Adding new region (" << x << ":" << y << ")" << llendl;
 +	llinfos << "Host: " << host << llendl;
 +
 +	LLVector3d origin_global;
 +
 +	origin_global = from_region_handle(region_handle);
 +
 +	regionp = new LLViewerRegion(region_handle,
 +								    host,
 +									mWidth,
 +									WORLD_PATCH_SIZE,
 +									getRegionWidthInMeters() );
 +	if (!regionp)
 +	{
 +		llerrs << "Unable to create new region!" << llendl;
 +	}
 +
 +	mRegionList.push_back(regionp);
 +	mActiveRegionList.push_back(regionp);
 +	mCulledRegionList.push_back(regionp);
 +
 +
 +	// Find all the adjacent regions, and attach them.
 +	// Generate handles for all of the adjacent regions, and attach them in the correct way.
 +	// connect the edges
 +	F32 adj_x = 0.f;
 +	F32 adj_y = 0.f;
 +	F32 region_x = 0.f;
 +	F32 region_y = 0.f;
 +	U64 adj_handle = 0;
 +
 +	F32 width = getRegionWidthInMeters();
 +
 +	LLViewerRegion *neighborp;
 +	from_region_handle(region_handle, ®ion_x, ®ion_y);
 +
 +	// Iterate through all directions, and connect neighbors if there.
 +	S32 dir;
 +	for (dir = 0; dir < 8; dir++)
 +	{
 +		adj_x = region_x + width * gDirAxes[dir][0];
 +		adj_y = region_y + width * gDirAxes[dir][1];
 +		to_region_handle(adj_x, adj_y, &adj_handle);
 +
 +		neighborp = getRegionFromHandle(adj_handle);
 +		if (neighborp)
 +		{
 +			//llinfos << "Connecting " << region_x << ":" << region_y << " -> " << adj_x << ":" << adj_y << llendl;
 +			regionp->connectNeighbor(neighborp, dir);
 +		}
 +	}
 +
 +	updateWaterObjects();
 +
 +	return regionp;
 +}
 +
 +
 +void LLWorld::removeRegion(const LLHost &host)
 +{
 +	F32 x, y;
 +
 +	LLViewerRegion *regionp = getRegion(host);
 +	if (!regionp)
 +	{
 +		llwarns << "Trying to remove region that doesn't exist!" << llendl;
 +		return;
 +	}
 +	
 +	if (regionp == gAgent.getRegion())
 +	{
 +		for (region_list_t::iterator iter = mRegionList.begin();
 +			 iter != mRegionList.end(); ++iter)
 +		{
 +			LLViewerRegion* reg = *iter;
 +			llwarns << "RegionDump: " << reg->getName()
 +				<< " " << reg->getHost()
 +				<< " " << reg->getOriginGlobal()
 +				<< llendl;
 +		}
 +
 +		llwarns << "Agent position global " << gAgent.getPositionGlobal() 
 +			<< " agent " << gAgent.getPositionAgent()
 +			<< llendl;
 +
 +		llwarns << "Regions visited " << gAgent.getRegionsVisited() << llendl;
 +
 +		llwarns << "gFrameTimeSeconds " << gFrameTimeSeconds << llendl;
 +
 +		llwarns << "Disabling region " << regionp->getName() << " that agent is in!" << llendl;
 +		LLAppViewer::instance()->forceDisconnect(LLTrans::getString("YouHaveBeenDisconnected"));
 +
 +		regionp->saveObjectCache() ; //force to save objects here in case that the object cache is about to be destroyed.
 +		return;
 +	}
 +
 +	from_region_handle(regionp->getHandle(), &x, &y);
 +	llinfos << "Removing region " << x << ":" << y << llendl;
 +
 +	mRegionList.remove(regionp);
 +	mActiveRegionList.remove(regionp);
 +	mCulledRegionList.remove(regionp);
 +	mVisibleRegionList.remove(regionp);
 +	
 +	delete regionp;
 +
 +	updateWaterObjects();
 +
 +	//double check all objects of this region are removed.
 +	gObjectList.clearAllMapObjectsInRegion(regionp) ;
 +	//llassert_always(!gObjectList.hasMapObjectInRegion(regionp)) ;
 +}
 +
 +
 +LLViewerRegion* LLWorld::getRegion(const LLHost &host)
 +{
 +	for (region_list_t::iterator iter = mRegionList.begin();
 +		 iter != mRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		if (regionp->getHost() == host)
 +		{
 +			return regionp;
 +		}
 +	}
 +	return NULL;
 +}
 +
 +LLViewerRegion* LLWorld::getRegionFromPosAgent(const LLVector3 &pos)
 +{
 +	return getRegionFromPosGlobal(gAgent.getPosGlobalFromAgent(pos));
 +}
 +
 +LLViewerRegion* LLWorld::getRegionFromPosGlobal(const LLVector3d &pos)
 +{
 +	for (region_list_t::iterator iter = mRegionList.begin();
 +		 iter != mRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		if (regionp->pointInRegionGlobal(pos))
 +		{
 +			return regionp;
 +		}
 +	}
 +	return NULL;
 +}
 +
 +
 +LLVector3d	LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos)
 +{
 +	if (positionRegionValidGlobal(end_pos))
 +	{
 +		return end_pos;
 +	}
 +
 +	LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos);
 +	if (!regionp) 
 +	{
 +		return start_pos;
 +	}
 +
 +	LLVector3d delta_pos = end_pos - start_pos;
 +	LLVector3d delta_pos_abs;
 +	delta_pos_abs.setVec(delta_pos);
 +	delta_pos_abs.abs();
 +
 +	LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos);
 +	F64 clip_factor = 1.0;
 +	F32 region_width = regionp->getWidth();
 +	if (region_coord.mV[VX] < 0.f)
 +	{
 +		if (region_coord.mV[VY] < region_coord.mV[VX])
 +		{
 +			// clip along y -
 +			clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]);
 +		}
 +		else
 +		{
 +			// clip along x -
 +			clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]);
 +		}
 +	}
 +	else if (region_coord.mV[VX] > region_width)
 +	{
 +		if (region_coord.mV[VY] > region_coord.mV[VX])
 +		{
 +			// clip along y +
 +			clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY];
 +		}
 +		else
 +		{
 +			//clip along x +
 +			clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX];
 +		}
 +	}
 +	else if (region_coord.mV[VY] < 0.f)
 +	{
 +		// clip along y -
 +		clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]);
 +	}
 +	else if (region_coord.mV[VY] > region_width)
 +	{ 
 +		// clip along y +
 +		clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY];
 +	}
 +
 +	// clamp to within region dimensions
 +	LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor);
 +	final_region_pos.mdV[VX] = llclamp(final_region_pos.mdV[VX], 0.0,
 +									   (F64)(region_width - F_ALMOST_ZERO));
 +	final_region_pos.mdV[VY] = llclamp(final_region_pos.mdV[VY], 0.0,
 +									   (F64)(region_width - F_ALMOST_ZERO));
 +	final_region_pos.mdV[VZ] = llclamp(final_region_pos.mdV[VZ], 0.0,
 +									   (F64)(LLWorld::getInstance()->getRegionMaxHeight() - F_ALMOST_ZERO));
 +	return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos));
 +}
 +
 +LLViewerRegion* LLWorld::getRegionFromHandle(const U64 &handle)
 +{
 +	for (region_list_t::iterator iter = mRegionList.begin();
 +		 iter != mRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		if (regionp->getHandle() == handle)
 +		{
 +			return regionp;
 +		}
 +	}
 +	return NULL;
 +}
 +
 +
 +void LLWorld::updateAgentOffset(const LLVector3d &offset_global)
 +{
 +#if 0
 +	for (region_list_t::iterator iter = mRegionList.begin();
 +		 iter != mRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		regionp->setAgentOffset(offset_global);
 +	}
 +#endif
 +}
 +
 +
 +BOOL LLWorld::positionRegionValidGlobal(const LLVector3d &pos_global)
 +{
 +	for (region_list_t::iterator iter = mRegionList.begin();
 +		 iter != mRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		if (regionp->pointInRegionGlobal(pos_global))
 +		{
 +			return TRUE;
 +		}
 +	}
 +	return FALSE;
 +}
 +
 +
 +// Allow objects to go up to their radius underground.
 +F32 LLWorld::getMinAllowedZ(LLViewerObject* object, const LLVector3d &global_pos)
 +{
 +	F32 land_height = resolveLandHeightGlobal(global_pos);
 +	F32 radius = 0.5f * object->getScale().length();
 +	return land_height - radius;
 +}
 +
 +
 +
 +LLViewerRegion* LLWorld::resolveRegionGlobal(LLVector3 &pos_region, const LLVector3d &pos_global)
 +{
 +	LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
 +
 +	if (regionp)
 +	{
 +		pos_region = regionp->getPosRegionFromGlobal(pos_global);
 +		return regionp;
 +	}
 +
 +	return NULL;
 +}
 +
 +
 +LLViewerRegion* LLWorld::resolveRegionAgent(LLVector3 &pos_region, const LLVector3 &pos_agent)
 +{
 +	LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
 +	LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
 +
 +	if (regionp)
 +	{
 +		pos_region = regionp->getPosRegionFromGlobal(pos_global);
 +		return regionp;
 +	}
 +
 +	return NULL;
 +}
 +
 +
 +F32 LLWorld::resolveLandHeightAgent(const LLVector3 &pos_agent)
 +{
 +	LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
 +	return resolveLandHeightGlobal(pos_global);
 +}
 +
 +
 +F32 LLWorld::resolveLandHeightGlobal(const LLVector3d &pos_global)
 +{
 +	LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
 +	if (regionp)
 +	{
 +		return regionp->getLand().resolveHeightGlobal(pos_global);
 +	}
 +	return 0.0f;
 +}
 +
 +
 +// Takes a line defined by "point_a" and "point_b" and determines the closest (to point_a) 
 +// point where the the line intersects an object or the land surface.  Stores the results
 +// in "intersection" and "intersection_normal" and returns a scalar value that represents
 +// the normalized distance along the line from "point_a" to "intersection".
 +//
 +// Currently assumes point_a and point_b only differ in z-direction, 
 +// but it may eventually become more general.
 +F32 LLWorld::resolveStepHeightGlobal(const LLVOAvatar* avatarp, const LLVector3d &point_a, const LLVector3d &point_b, 
 +							   LLVector3d &intersection, LLVector3 &intersection_normal,
 +							   LLViewerObject **viewerObjectPtr)
 +{
 +	// initialize return value to null
 +	if (viewerObjectPtr)
 +	{
 +		*viewerObjectPtr = NULL;
 +	}
 +
 +	LLViewerRegion *regionp = getRegionFromPosGlobal(point_a);
 +	if (!regionp)
 +	{
 +		// We're outside the world 
 +		intersection = 0.5f * (point_a + point_b);
 +		intersection_normal.setVec(0.0f, 0.0f, 1.0f);
 +		return 0.5f;
 +	}
 +	
 +	// calculate the length of the segment
 +	F32 segment_length = (F32)((point_a - point_b).length());
 +	if (0.0f == segment_length)
 +	{
 +		intersection = point_a;
 +		intersection_normal.setVec(0.0f, 0.0f, 1.0f);
 +		return segment_length;
 +	}
 +
 +	// get land height	
 +	// Note: we assume that the line is parallel to z-axis here
 +	LLVector3d land_intersection = point_a;
 +	F32 normalized_land_distance;
 +
 +	land_intersection.mdV[VZ] = regionp->getLand().resolveHeightGlobal(point_a);
 +	normalized_land_distance = (F32)(point_a.mdV[VZ] - land_intersection.mdV[VZ]) / segment_length;
 +	intersection = land_intersection;
 +	intersection_normal = resolveLandNormalGlobal(land_intersection);
 +
 +	if (avatarp && !avatarp->mFootPlane.isExactlyClear())
 +	{
 +		LLVector3 foot_plane_normal(avatarp->mFootPlane.mV);
 +		LLVector3 start_pt = avatarp->getRegion()->getPosRegionFromGlobal(point_a);
 +		// added 0.05 meters to compensate for error in foot plane reported by Havok
 +		F32 norm_dist_from_plane = ((start_pt * foot_plane_normal) - avatarp->mFootPlane.mV[VW]) + 0.05f;
 +		norm_dist_from_plane = llclamp(norm_dist_from_plane / segment_length, 0.f, 1.f);
 +		if (norm_dist_from_plane < normalized_land_distance)
 +		{
 +			// collided with object before land
 +			normalized_land_distance = norm_dist_from_plane;
 +			intersection = point_a;
 +			intersection.mdV[VZ] -= norm_dist_from_plane * segment_length;
 +			intersection_normal = foot_plane_normal;
 +		}
 +		else
 +		{
 +			intersection = land_intersection;
 +			intersection_normal = resolveLandNormalGlobal(land_intersection);
 +		}
 +	}
 +
 +	return normalized_land_distance;
 +}
 +
 +
 +LLSurfacePatch * LLWorld::resolveLandPatchGlobal(const LLVector3d &pos_global)
 +{
 +	//  returns a pointer to the patch at this location
 +	LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
 +	if (!regionp)
 +	{
 +		return NULL;
 +	}
 +
 +	return regionp->getLand().resolvePatchGlobal(pos_global);
 +}
 +
 +
 +LLVector3 LLWorld::resolveLandNormalGlobal(const LLVector3d &pos_global)
 +{
 +	LLViewerRegion *regionp = getRegionFromPosGlobal(pos_global);
 +	if (!regionp)
 +	{
 +		return LLVector3::z_axis;
 +	}
 +
 +	return regionp->getLand().resolveNormalGlobal(pos_global);
 +}
 +
 +
 +void LLWorld::updateVisibilities()
 +{
 +	F32 cur_far_clip = LLViewerCamera::getInstance()->getFar();
 +
 +	// Go through the culled list and check for visible regions (region is visible if land is visible)
 +	for (region_list_t::iterator iter = mCulledRegionList.begin();
 +		 iter != mCulledRegionList.end(); )
 +	{
 +		region_list_t::iterator curiter = iter++;
 +		LLViewerRegion* regionp = *curiter;
 +		
 +		LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN);
 +		if (part)
 +		{
 +			LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
 +			if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1]))
 +			{
 +				mCulledRegionList.erase(curiter);
 +				mVisibleRegionList.push_back(regionp);
 +			}
 +		}
 +	}
 +	
 +	// Update all of the visible regions 
 +	for (region_list_t::iterator iter = mVisibleRegionList.begin();
 +		 iter != mVisibleRegionList.end(); )
 +	{
 +		region_list_t::iterator curiter = iter++;
 +		LLViewerRegion* regionp = *curiter;
 +		if (!regionp->getLand().hasZData())
 +		{
 +			continue;
 +		}
 +
 +		LLSpatialPartition* part = regionp->getSpatialPartition(LLViewerRegion::PARTITION_TERRAIN);
 +		if (part)
 +		{
 +			LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0);
 +			if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1]))
 +			{
 +				regionp->calculateCameraDistance();
 +				regionp->getLand().updatePatchVisibilities(gAgent);
 +			}
 +			else
 +			{
 +				mVisibleRegionList.erase(curiter);
 +				mCulledRegionList.push_back(regionp);
 +			}
 +		}
 +	}
 +
 +	// Sort visible regions
 +	mVisibleRegionList.sort(LLViewerRegion::CompareDistance());
 +	
 +	LLViewerCamera::getInstance()->setFar(cur_far_clip);
 +}
 +
 +void LLWorld::updateRegions(F32 max_update_time)
 +{
 +	LLMemType mt_ur(LLMemType::MTYPE_IDLE_UPDATE_REGIONS);
 +	LLTimer update_timer;
 +	BOOL did_one = FALSE;
 +	
 +	// Perform idle time updates for the regions (and associated surfaces)
 +	for (region_list_t::iterator iter = mRegionList.begin();
 +		 iter != mRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		F32 max_time = max_update_time - update_timer.getElapsedTimeF32();
 +		if (did_one && max_time <= 0.f)
 +			break;
 +		max_time = llmin(max_time, max_update_time*.1f);
 +		did_one |= regionp->idleUpdate(max_update_time);
 +	}
 +}
 +
 +void LLWorld::updateParticles()
 +{
 +	LLViewerPartSim::getInstance()->updateSimulation();
 +}
 +
 +void LLWorld::renderPropertyLines()
 +{
 +	S32 region_count = 0;
 +	S32 vertex_count = 0;
 +
 +	for (region_list_t::iterator iter = mVisibleRegionList.begin();
 +		 iter != mVisibleRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		region_count++;
 +		vertex_count += regionp->renderPropertyLines();
 +	}
 +}
 +
 +
 +void LLWorld::updateNetStats()
 +{
 +	F32 bits = 0.f;
 +	U32 packets = 0;
 +
 +	for (region_list_t::iterator iter = mActiveRegionList.begin();
 +		 iter != mActiveRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		regionp->updateNetStats();
 +		bits += regionp->mBitStat.getCurrent();
 +		packets += llfloor( regionp->mPacketsStat.getCurrent() );
 +	}
 +
 +	S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn;
 +	S32 packets_out = gMessageSystem->mPacketsOut - mLastPacketsOut;
 +	S32 packets_lost = gMessageSystem->mDroppedPackets - mLastPacketsLost;
 +
 +	S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits();
 +	S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits();
 +	LLViewerStats::getInstance()->mActualInKBitStat.addValue(actual_in_bits/1024.f);
 +	LLViewerStats::getInstance()->mActualOutKBitStat.addValue(actual_out_bits/1024.f);
 +	LLViewerStats::getInstance()->mKBitStat.addValue(bits/1024.f);
 +	LLViewerStats::getInstance()->mPacketsInStat.addValue(packets_in);
 +	LLViewerStats::getInstance()->mPacketsOutStat.addValue(packets_out);
 +	LLViewerStats::getInstance()->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets);
 +	if (packets_in)
 +	{
 +		LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in));
 +	}
 +	else
 +	{
 +		LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(0.f);
 +	}
 +
 +	mLastPacketsIn = gMessageSystem->mPacketsIn;
 +	mLastPacketsOut = gMessageSystem->mPacketsOut;
 +	mLastPacketsLost = gMessageSystem->mDroppedPackets;
 +}
 +
 +
 +void LLWorld::printPacketsLost()
 +{
 +	llinfos << "Simulators:" << llendl;
 +	llinfos << "----------" << llendl;
 +
 +	LLCircuitData *cdp = NULL;
 +	for (region_list_t::iterator iter = mActiveRegionList.begin();
 +		 iter != mActiveRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		cdp = gMessageSystem->mCircuitInfo.findCircuit(regionp->getHost());
 +		if (cdp)
 +		{
 +			LLVector3d range = regionp->getCenterGlobal() - gAgent.getPositionGlobal();
 +				
 +			llinfos << regionp->getHost() << ", range: " << range.length()
 +					<< " packets lost: " << cdp->getPacketsLost() << llendl;
 +		}
 +	}
 +}
 +
 +void LLWorld::processCoarseUpdate(LLMessageSystem* msg, void** user_data)
 +{
 +	LLViewerRegion* region = LLWorld::getInstance()->getRegion(msg->getSender());
 +	if( region )
 +	{
 +		region->updateCoarseLocations(msg);
 +	}
 +}
 +
 +F32 LLWorld::getLandFarClip() const
 +{
 +	return mLandFarClip;
 +}
 +
 +void LLWorld::setLandFarClip(const F32 far_clip)
 +{
 +	static S32 const rwidth = (S32)REGION_WIDTH_U32;
 +	S32 const n1 = (llceil(mLandFarClip) - 1) / rwidth;
 +	S32 const n2 = (llceil(far_clip) - 1) / rwidth;
 +	bool need_water_objects_update = n1 != n2;
 +
 +	mLandFarClip = far_clip;
 +
 +	if (need_water_objects_update)
 +	{
 +		updateWaterObjects();
 +	}
 +}
 +
 +// Some region that we're connected to, but not the one we're in, gave us
 +// a (possibly) new water height. Update it in our local copy.
 +void LLWorld::waterHeightRegionInfo(std::string const& sim_name, F32 water_height)
 +{
 +	for (region_list_t::iterator iter = mRegionList.begin(); iter != mRegionList.end(); ++iter)
 +	{
 +		if ((*iter)->getName() == sim_name)
 +		{
 +			(*iter)->setWaterHeight(water_height);
 +			break;
 +		}
 +	}
 +}
 +
 +void LLWorld::updateWaterObjects()
 +{
 +	if (!gAgent.getRegion())
 +	{
 +		return;
 +	}
 +	if (mRegionList.empty())
 +	{
 +		llwarns << "No regions!" << llendl;
 +		return;
 +	}
 +
 +	// First, determine the min and max "box" of water objects
 +	S32 min_x = 0;
 +	S32 min_y = 0;
 +	S32 max_x = 0;
 +	S32 max_y = 0;
 +	U32 region_x, region_y;
 +
 +	S32 rwidth = 256;
 +
 +	// We only want to fill in water for stuff that's near us, say, within 256 or 512m
 +	S32 range = LLViewerCamera::getInstance()->getFar() > 256.f ? 512 : 256;
 +
 +	LLViewerRegion* regionp = gAgent.getRegion();
 +	from_region_handle(regionp->getHandle(), ®ion_x, ®ion_y);
 +
 +	min_x = (S32)region_x - range;
 +	min_y = (S32)region_y - range;
 +	max_x = (S32)region_x + range;
 +	max_y = (S32)region_y + range;
 +
 +	for (region_list_t::iterator iter = mRegionList.begin();
 +		 iter != mRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		LLVOWater* waterp = regionp->getLand().getWaterObj();
 +		if (waterp)
 +		{
 +			gObjectList.updateActive(waterp);
 +		}
 +	}
 +
 +	for (std::list<LLVOWater*>::iterator iter = mHoleWaterObjects.begin();
 +		 iter != mHoleWaterObjects.end(); ++ iter)
 +	{
 +		LLVOWater* waterp = *iter;
 +		gObjectList.killObject(waterp);
 +	}
 +	mHoleWaterObjects.clear();
 +
 +	// Now, get a list of the holes
 +	S32 x, y;
 +	F32 water_height = gAgent.getRegion()->getWaterHeight() + 256.f;
 +	for (x = min_x; x <= max_x; x += rwidth)
 +	{
 +		for (y = min_y; y <= max_y; y += rwidth)
 +		{
 +			U64 region_handle = to_region_handle(x, y);
 +			if (!getRegionFromHandle(region_handle))
 +			{
 +				LLVOWater* waterp = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_WATER, gAgent.getRegion());
 +				waterp->setUseTexture(FALSE);
 +				waterp->setPositionGlobal(LLVector3d(x + rwidth/2,
 +													 y + rwidth/2,
 +													 water_height));
 +				waterp->setScale(LLVector3((F32)rwidth, (F32)rwidth, 512.f));
 +				gPipeline.createObject(waterp);
 +				mHoleWaterObjects.push_back(waterp);
 +			}
 +		}
 +	}
 +
 +	// Update edge water objects
 +	S32 wx, wy;
 +	S32 center_x, center_y;
 +	wx = (max_x - min_x) + rwidth;
 +	wy = (max_y - min_y) + rwidth;
 +	center_x = min_x + (wx >> 1);
 +	center_y = min_y + (wy >> 1);
 +
 +	S32 add_boundary[4] = {
 +		512 - (max_x - region_x),
 +		512 - (max_y - region_y),
 +		512 - (region_x - min_x),
 +		512 - (region_y - min_y) };
 +		
 +	S32 dir;
 +	for (dir = 0; dir < 8; dir++)
 +	{
 +		S32 dim[2] = { 0 };
 +		switch (gDirAxes[dir][0])
 +		{
 +		case -1: dim[0] = add_boundary[2]; break;
 +		case  0: dim[0] = wx; break;
 +		default: dim[0] = add_boundary[0]; break;
 +		}
 +		switch (gDirAxes[dir][1])
 +		{
 +		case -1: dim[1] = add_boundary[3]; break;
 +		case  0: dim[1] = wy; break;
 +		default: dim[1] = add_boundary[1]; break;
 +		}
 +
 +		// Resize and reshape the water objects
 +		const S32 water_center_x = center_x + llround((wx + dim[0]) * 0.5f * gDirAxes[dir][0]);
 +		const S32 water_center_y = center_y + llround((wy + dim[1]) * 0.5f * gDirAxes[dir][1]);
 +		
 +		LLVOWater* waterp = mEdgeWaterObjects[dir];
 +		if (!waterp || waterp->isDead())
 +		{
 +			// The edge water objects can be dead because they're attached to the region that the
 +			// agent was in when they were originally created.
 +			mEdgeWaterObjects[dir] = (LLVOWater *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_VOID_WATER,
 +																				 gAgent.getRegion());
 +			waterp = mEdgeWaterObjects[dir];
 +			waterp->setUseTexture(FALSE);
 +			waterp->setIsEdgePatch(TRUE);
 +			gPipeline.createObject(waterp);
 +		}
 +
 +		waterp->setRegion(gAgent.getRegion());
 +		LLVector3d water_pos(water_center_x, water_center_y, water_height) ;
 +		LLVector3 water_scale((F32) dim[0], (F32) dim[1], 512.f);
 +
 +		//stretch out to horizon
 +		water_scale.mV[0] += fabsf(2048.f * gDirAxes[dir][0]);
 +		water_scale.mV[1] += fabsf(2048.f * gDirAxes[dir][1]);
 +
 +		water_pos.mdV[0] += 1024.f * gDirAxes[dir][0];
 +		water_pos.mdV[1] += 1024.f * gDirAxes[dir][1];
 +
 +		waterp->setPositionGlobal(water_pos);
 +		waterp->setScale(water_scale);
 +
 +		gObjectList.updateActive(waterp);
 +	}
 +}
 +
 +
 +void LLWorld::shiftRegions(const LLVector3& offset)
 +{
 +	for (region_list_t::const_iterator i = getRegionList().begin(); i != getRegionList().end(); ++i)
 +	{
 +		LLViewerRegion* region = *i;
 +		region->updateRenderMatrix();
 +	}
 +
 +	LLViewerPartSim::getInstance()->shift(offset);
 +}
 +
 +LLViewerTexture* LLWorld::getDefaultWaterTexture()
 +{
 +	return mDefaultWaterTexturep;
 +}
 +
 +void LLWorld::setSpaceTimeUSec(const U64 space_time_usec)
 +{
 +	mSpaceTimeUSec = space_time_usec;
 +}
 +
 +U64 LLWorld::getSpaceTimeUSec() const
 +{
 +	return mSpaceTimeUSec;
 +}
 +
 +void LLWorld::requestCacheMisses()
 +{
 +	for (region_list_t::iterator iter = mRegionList.begin();
 +		 iter != mRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		regionp->requestCacheMisses();
 +	}
 +}
 +
 +void LLWorld::getInfo(LLSD& info)
 +{
 +	LLSD region_info;
 +	for (region_list_t::iterator iter = mRegionList.begin();
 +		 iter != mRegionList.end(); ++iter)
 +	{	
 +		LLViewerRegion* regionp = *iter;
 +		regionp->getInfo(region_info);
 +		info["World"].append(region_info);
 +	}
 +}
 +
 +void LLWorld::disconnectRegions()
 +{
 +	LLMessageSystem* msg = gMessageSystem;
 +	for (region_list_t::iterator iter = mRegionList.begin();
 +		 iter != mRegionList.end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		if (regionp == gAgent.getRegion())
 +		{
 +			// Skip the main agent
 +			continue;
 +		}
 +
 +		llinfos << "Sending AgentQuitCopy to: " << regionp->getHost() << llendl;
 +		msg->newMessageFast(_PREHASH_AgentQuitCopy);
 +		msg->nextBlockFast(_PREHASH_AgentData);
 +		msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
 +		msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 +		msg->nextBlockFast(_PREHASH_FuseBlock);
 +		msg->addU32Fast(_PREHASH_ViewerCircuitCode, gMessageSystem->mOurCircuitCode);
 +		msg->sendMessage(regionp->getHost());
 +	}
 +}
 +
 +static LLFastTimer::DeclareTimer FTM_ENABLE_SIMULATOR("Enable Sim");
 +
 +void process_enable_simulator(LLMessageSystem *msg, void **user_data)
 +{
 +	LLFastTimer t(FTM_ENABLE_SIMULATOR);
 +	// enable the appropriate circuit for this simulator and 
 +	// add its values into the gSimulator structure
 +	U64		handle;
 +	U32		ip_u32;
 +	U16		port;
 +
 +	msg->getU64Fast(_PREHASH_SimulatorInfo, _PREHASH_Handle, handle);
 +	msg->getIPAddrFast(_PREHASH_SimulatorInfo, _PREHASH_IP, ip_u32);
 +	msg->getIPPortFast(_PREHASH_SimulatorInfo, _PREHASH_Port, port);
 +
 +	// which simulator should we modify?
 +	LLHost sim(ip_u32, port);
 +
 +	// Viewer trusts the simulator.
 +	msg->enableCircuit(sim, TRUE);
 +	LLWorld::getInstance()->addRegion(handle, sim);
 +
 +	// give the simulator a message it can use to get ip and port
 +	llinfos << "simulator_enable() Enabling " << sim << " with code " << msg->getOurCircuitCode() << llendl;
 +	msg->newMessageFast(_PREHASH_UseCircuitCode);
 +	msg->nextBlockFast(_PREHASH_CircuitCode);
 +	msg->addU32Fast(_PREHASH_Code, msg->getOurCircuitCode());
 +	msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
 +	msg->addUUIDFast(_PREHASH_ID, gAgent.getID());
 +	msg->sendReliable(sim);
 +}
 +
 +class LLEstablishAgentCommunication : public LLHTTPNode
 +{
 +	LOG_CLASS(LLEstablishAgentCommunication);
 +public:
 + 	virtual void describe(Description& desc) const
 +	{
 +		desc.shortInfo("seed capability info for a region");
 +		desc.postAPI();
 +		desc.input(
 +			"{ seed-capability: ..., sim-ip: ..., sim-port }");
 +		desc.source(__FILE__, __LINE__);
 +	}
 +
 +	virtual void post(ResponsePtr response, const LLSD& context, const LLSD& input) const
 +	{
 +		if (!input["body"].has("agent-id") ||
 +			!input["body"].has("sim-ip-and-port") ||
 +			!input["body"].has("seed-capability"))
 +		{
 +			llwarns << "invalid parameters" << llendl;
 +            return;
 +		}
 +
 +		LLHost sim(input["body"]["sim-ip-and-port"].asString());
 +	
 +		LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(sim);
 +		if (!regionp)
 +		{
 +			llwarns << "Got EstablishAgentCommunication for unknown region "
 +					<< sim << llendl;
 +			return;
 +		}
 +		regionp->setSeedCapability(input["body"]["seed-capability"]);
 +	}
 +};
 +
 +// disable the circuit to this simulator
 +// Called in response to "DisableSimulator" message.
 +void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data)
 +{	
 +	LLHost host = mesgsys->getSender();
 +
 +	//llinfos << "Disabling simulator with message from " << host << llendl;
 +	LLWorld::getInstance()->removeRegion(host);
 +
 +	mesgsys->disableCircuit(host);
 +}
 +
 +
 +void process_region_handshake(LLMessageSystem* msg, void** user_data)
 +{
 +	LLHost host = msg->getSender();
 +	LLViewerRegion* regionp = LLWorld::getInstance()->getRegion(host);
 +	if (!regionp)
 +	{
 +		llwarns << "Got region handshake for unknown region "
 +			<< host << llendl;
 +		return;
 +	}
 +
 +	regionp->unpackRegionHandshake();
  	LLFloaterPathfindingConsole* pWindow = LLFloaterPathfindingConsole::getInstanceHandle().get();
  	if ( pWindow && pWindow->getHeartBeat() )
 @@ -1099,163 +1099,149 @@ void process_region_handshake(LLMessageSystem* msg, void** user_data)  		pWindow->regionCrossingOccured();
  		return;
  	}
 - -} - - -void send_agent_pause() -{ -	// *NOTE:Mani Pausing the mainloop timeout. Otherwise a long modal event may cause -	// the thread monitor to timeout. -	LLAppViewer::instance()->pauseMainloopTimeout(); -	 -	// Note: used to check for LLWorld initialization before it became a singleton. -	// Rather than just remove this check I'm changing it to assure that the message  -	// system has been initialized. -MG -	if (!gMessageSystem) -	{ -		return; -	} -	 -	gMessageSystem->newMessageFast(_PREHASH_AgentPause); -	gMessageSystem->nextBlockFast(_PREHASH_AgentData); -	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); -	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); - -	gAgentPauseSerialNum++; -	gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum); - -	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); -		 iter != LLWorld::getInstance()->getRegionList().end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		gMessageSystem->sendReliable(regionp->getHost()); -	} - -	gObjectList.mWasPaused = TRUE; -} - - -void send_agent_resume() -{ -	// Note: used to check for LLWorld initialization before it became a singleton. -	// Rather than just remove this check I'm changing it to assure that the message  -	// system has been initialized. -MG -	if (!gMessageSystem) -	{ -		return; -	} - -	gMessageSystem->newMessageFast(_PREHASH_AgentResume); -	gMessageSystem->nextBlockFast(_PREHASH_AgentData); -	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID); -	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID); - -	gAgentPauseSerialNum++; -	gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum); -	 - -	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); -		 iter != LLWorld::getInstance()->getRegionList().end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		gMessageSystem->sendReliable(regionp->getHost()); -	} - -	// Reset the FPS counter to avoid an invalid fps -	LLViewerStats::getInstance()->mFPSStat.start(); - -	LLAppViewer::instance()->resumeMainloopTimeout(); -} - -static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3d& region_origin) -{ -	LLVector3d pos_global; -	LLVector3 pos_local; -	U8 bits; - -	bits = compact_local & 0xFF; -	pos_local.mV[VZ] = F32(bits) * 4.f; -	compact_local >>= 8; - -	bits = compact_local & 0xFF; -	pos_local.mV[VY] = (F32)bits; -	compact_local >>= 8; - -	bits = compact_local & 0xFF; -	pos_local.mV[VX] = (F32)bits; - -	pos_global.setVec( pos_local ); -	pos_global += region_origin; -	return pos_global; -} - -void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positions, const LLVector3d& relative_to, F32 radius) const -{ -	F32 radius_squared = radius * radius; -	 -	if(avatar_ids != NULL) -	{ -		avatar_ids->clear(); -	} -	if(positions != NULL) -	{ -		positions->clear(); -	} -	// get the list of avatars from the character list first, so distances are correct -	// when agent is above 1020m and other avatars are nearby -	for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); -		iter != LLCharacter::sInstances.end(); ++iter) -	{ -		LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter; -		if(!pVOAvatar->isDead() && !pVOAvatar->isSelf()) -		{ -			LLUUID uuid = pVOAvatar->getID(); -			if(!uuid.isNull()) -			{ -				LLVector3d pos_global = pVOAvatar->getPositionGlobal(); -				if(dist_vec_squared(pos_global, relative_to) <= radius_squared) -				{ -					if(positions != NULL) -					{ -						positions->push_back(pos_global); -					} -					if(avatar_ids !=NULL) -					{ -						avatar_ids->push_back(uuid); -					} -				} -			} -		} -	} -	// region avatars added for situations where radius is greater than RenderFarClip -	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); -		iter != LLWorld::getInstance()->getRegionList().end(); ++iter) -	{ -		LLViewerRegion* regionp = *iter; -		const LLVector3d& origin_global = regionp->getOriginGlobal(); -		S32 count = regionp->mMapAvatars.count(); -		for (S32 i = 0; i < count; i++) -		{ -			LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.get(i), origin_global); -			if(dist_vec_squared(pos_global, relative_to) <= radius_squared) -			{ -				LLUUID uuid = regionp->mMapAvatarIDs.get(i); -				// if this avatar doesn't already exist in the list, add it -				if(uuid.notNull() && avatar_ids!=NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end()) -				{ -					if(positions != NULL) -					{ -						positions->push_back(pos_global); -					} -					avatar_ids->push_back(uuid); -				} -			} -		} -	} -} - - -LLHTTPRegistration<LLEstablishAgentCommunication> -	gHTTPRegistrationEstablishAgentCommunication( -							"/message/EstablishAgentCommunication"); +
 +}
 +
 +
 +void send_agent_pause()
 +{
 +	// *NOTE:Mani Pausing the mainloop timeout. Otherwise a long modal event may cause
 +	// the thread monitor to timeout.
 +	LLAppViewer::instance()->pauseMainloopTimeout();
 +	
 +	// Note: used to check for LLWorld initialization before it became a singleton.
 +	// Rather than just remove this check I'm changing it to assure that the message 
 +	// system has been initialized. -MG
 +	if (!gMessageSystem)
 +	{
 +		return;
 +	}
 +	
 +	gMessageSystem->newMessageFast(_PREHASH_AgentPause);
 +	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
 +	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
 +	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
 +
 +	gAgentPauseSerialNum++;
 +	gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum);
 +
 +	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
 +		 iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		gMessageSystem->sendReliable(regionp->getHost());
 +	}
 +
 +	gObjectList.mWasPaused = TRUE;
 +}
 +
 +
 +void send_agent_resume()
 +{
 +	// Note: used to check for LLWorld initialization before it became a singleton.
 +	// Rather than just remove this check I'm changing it to assure that the message 
 +	// system has been initialized. -MG
 +	if (!gMessageSystem)
 +	{
 +		return;
 +	}
 +
 +	gMessageSystem->newMessageFast(_PREHASH_AgentResume);
 +	gMessageSystem->nextBlockFast(_PREHASH_AgentData);
 +	gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgentID);
 +	gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
 +
 +	gAgentPauseSerialNum++;
 +	gMessageSystem->addU32Fast(_PREHASH_SerialNum, gAgentPauseSerialNum);
 +	
 +
 +	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
 +		 iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		gMessageSystem->sendReliable(regionp->getHost());
 +	}
 +
 +	// Reset the FPS counter to avoid an invalid fps
 +	LLViewerStats::getInstance()->mFPSStat.start();
 +
 +	LLAppViewer::instance()->resumeMainloopTimeout();
 +}
 +
 +static LLVector3d unpackLocalToGlobalPosition(U32 compact_local, const LLVector3d& region_origin)
 +{
 +	LLVector3d pos_local;
 +
 +	pos_local.mdV[VZ] = (compact_local & 0xFFU) * 4;
 +	pos_local.mdV[VY] = (compact_local >> 8) & 0xFFU;
 +	pos_local.mdV[VX] = (compact_local >> 16) & 0xFFU;
 +
 +	return region_origin + pos_local;
 +}
 +
 +void LLWorld::getAvatars(uuid_vec_t* avatar_ids, std::vector<LLVector3d>* positions, const LLVector3d& relative_to, F32 radius) const
 +{
 +	F32 radius_squared = radius * radius;
 +	
 +	if(avatar_ids != NULL)
 +	{
 +		avatar_ids->clear();
 +	}
 +	if(positions != NULL)
 +	{
 +		positions->clear();
 +	}
 +	// get the list of avatars from the character list first, so distances are correct
 +	// when agent is above 1020m and other avatars are nearby
 +	for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
 +		iter != LLCharacter::sInstances.end(); ++iter)
 +	{
 +		LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter;
 +		LLVector3d pos_global = pVOAvatar->getPositionGlobal();
 +		LLUUID uuid = pVOAvatar->getID();
 +		if( !pVOAvatar->isDead()
 +			&& !pVOAvatar->isSelf()
 +			&& !uuid.isNull() &&
 +			dist_vec_squared(pos_global, relative_to) <= radius_squared)
 +		{
 +			if(positions != NULL)
 +			{
 +				positions->push_back(pos_global);
 +			}
 +			if(avatar_ids !=NULL)
 +			{
 +				avatar_ids->push_back(uuid);
 +			}
 +		}
 +	}
 +	// region avatars added for situations where radius is greater than RenderFarClip
 +	for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
 +		iter != LLWorld::getInstance()->getRegionList().end(); ++iter)
 +	{
 +		LLViewerRegion* regionp = *iter;
 +		const LLVector3d& origin_global = regionp->getOriginGlobal();
 +		S32 count = regionp->mMapAvatars.count();
 +		for (S32 i = 0; i < count; i++)
 +		{
 +			LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.get(i), origin_global);
 +			if(dist_vec_squared(pos_global, relative_to) <= radius_squared)
 +			{
 +				LLUUID uuid = regionp->mMapAvatarIDs.get(i);
 +				// if this avatar doesn't already exist in the list, add it
 +				if(uuid.notNull() && avatar_ids != NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end())
 +				{
 +					if (positions != NULL)
 +					{
 +						positions->push_back(pos_global);
 +					}
 +					avatar_ids->push_back(uuid);
 +				}
 +			}
 +		}
 +	}
 +}
 +
 +
 +LLHTTPRegistration<LLEstablishAgentCommunication>
 +	gHTTPRegistrationEstablishAgentCommunication(
 +							"/message/EstablishAgentCommunication");
 diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index e50851b8e7..a3ccf87cfc 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -77,6 +77,7 @@ LLUIImagePtr LLWorldMapView::sAvatarYouLargeImage = NULL;  LLUIImagePtr LLWorldMapView::sAvatarLevelImage = NULL;  LLUIImagePtr LLWorldMapView::sAvatarAboveImage = NULL;  LLUIImagePtr LLWorldMapView::sAvatarBelowImage = NULL; +LLUIImagePtr LLWorldMapView::sAvatarUnknownImage = NULL;  LLUIImagePtr LLWorldMapView::sTelehubImage = NULL;  LLUIImagePtr LLWorldMapView::sInfohubImage = NULL; @@ -120,6 +121,7 @@ void LLWorldMapView::initClass()  	sAvatarLevelImage =		LLUI::getUIImage("map_avatar_32.tga");  	sAvatarAboveImage =		LLUI::getUIImage("map_avatar_above_32.tga");  	sAvatarBelowImage =		LLUI::getUIImage("map_avatar_below_32.tga"); +	sAvatarUnknownImage =	LLUI::getUIImage("map_avatar_unknown_32.tga");  	sHomeImage =			LLUI::getUIImage("map_home.tga");  	sTelehubImage = 		LLUI::getUIImage("map_telehub.tga"); @@ -149,6 +151,7 @@ void LLWorldMapView::cleanupClass()  	sAvatarLevelImage = NULL;  	sAvatarAboveImage = NULL;  	sAvatarBelowImage = NULL; +	sAvatarUnknownImage = NULL;  	sTelehubImage = NULL;  	sInfohubImage = NULL; @@ -513,7 +516,7 @@ void LLWorldMapView::draw()  					 TRUE,  					 "You are here",  					 "", -					 llround(LLFontGL::getFontSansSerifSmall()->getLineHeight())); // offset vertically by one line, to avoid overlap with target tracking +					 LLFontGL::getFontSansSerifSmall()->getLineHeight()); // offset vertically by one line, to avoid overlap with target tracking  	}  	// Draw the current agent viewing angle @@ -992,7 +995,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&  	const S32 TEXT_PADDING = DEFAULT_TRACKING_ARROW_SIZE + 2;  	S32 half_text_width = llfloor(font->getWidthF32(label) * 0.5f);  	text_x = llclamp(text_x, half_text_width + TEXT_PADDING, getRect().getWidth() - half_text_width - TEXT_PADDING); -	text_y = llclamp(text_y + vert_offset, TEXT_PADDING + vert_offset, getRect().getHeight() - llround(font->getLineHeight()) - TEXT_PADDING - vert_offset); +	text_y = llclamp(text_y + vert_offset, TEXT_PADDING + vert_offset, getRect().getHeight() - font->getLineHeight() - TEXT_PADDING - vert_offset);  	if (label != "")  	{ @@ -1005,7 +1008,7 @@ void LLWorldMapView::drawTracking(const LLVector3d& pos_global, const LLColor4&  		if (tooltip != "")  		{ -			text_y -= (S32)font->getLineHeight(); +			text_y -= font->getLineHeight();  			font->renderUTF8(  				tooltip, 0, @@ -1147,17 +1150,25 @@ void LLWorldMapView::drawAvatar(F32 x_pixels,  								F32 y_pixels,  								const LLColor4& color,  								F32 relative_z, -								F32 dot_radius) +								F32 dot_radius, +								bool unknown_relative_z)  {  	const F32 HEIGHT_THRESHOLD = 7.f;  	LLUIImagePtr dot_image = sAvatarLevelImage; -	if(relative_z < -HEIGHT_THRESHOLD)  +	if (unknown_relative_z)  	{ -		dot_image = sAvatarBelowImage;  +		dot_image = sAvatarUnknownImage;  	} -	else if(relative_z > HEIGHT_THRESHOLD)  -	{  -		dot_image = sAvatarAboveImage; +	else +	{ +		if(relative_z < -HEIGHT_THRESHOLD) +		{ +			dot_image = sAvatarBelowImage;  +		} +		else if(relative_z > HEIGHT_THRESHOLD)  +		{  +			dot_image = sAvatarAboveImage; +		}  	}  	S32 dot_width = llround(dot_radius * 2.f);  	dot_image->draw(llround(x_pixels - dot_radius), @@ -1203,7 +1214,7 @@ void LLWorldMapView::drawIconName(F32 x_pixels,  		LLFontGL::NORMAL,   		LLFontGL::DROP_SHADOW); -	text_y -= llround(LLFontGL::getFontSansSerif()->getLineHeight()); +	text_y -= LLFontGL::getFontSansSerif()->getLineHeight();  	// render text  	LLFontGL::getFontSansSerif()->renderUTF8(second_line, 0, diff --git a/indra/newview/llworldmapview.h b/indra/newview/llworldmapview.h index 9ab53b1ba3..a2a6dc53fb 100644 --- a/indra/newview/llworldmapview.h +++ b/indra/newview/llworldmapview.h @@ -112,7 +112,8 @@ public:  								F32 y_pixels,   								const LLColor4& color,  								F32 relative_z = 0.f, -								F32 dot_radius = 3.f); +								F32 dot_radius = 3.f, +								bool reached_max_z = false);  	static void		drawIconName(F32 x_pixels,   									F32 y_pixels,   									const LLColor4& color, @@ -138,6 +139,7 @@ public:  	static LLUIImagePtr	sAvatarLevelImage;  	static LLUIImagePtr	sAvatarAboveImage;  	static LLUIImagePtr	sAvatarBelowImage; +	static LLUIImagePtr	sAvatarUnknownImage;  	static LLUIImagePtr	sTelehubImage;  	static LLUIImagePtr	sInfohubImage; diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 9548263843..28d59785d3 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -1,4342 +1,4328 @@ -/**  - * @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" -#include "llfloaterpathfindingconsole.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() -{ -	static const std::string vertex_shader_enable_feature_string = "VertexShaderEnable"; - -	if (sDisableShaders || -		!gGLManager.mHasVertexShader || -		!gGLManager.mHasFragmentShader || -		!LLFeatureManager::getInstance()->isFeatureAvailable(vertex_shader_enable_feature_string) || -		(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->flagUsePhysics()) -	{ -		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.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); -	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(); -	 -	if (LLGLSLShader::sNoFixedFunction) -	{ -		gUIProgram.bind(); -	}
 -
 -
 -	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);	 -	gPipeline.disableLights(); +/** 
 + * @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"
 +#include "llfloaterpathfindingconsole.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;
 +
 +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),
 +	mResetVertexBuffers(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)
 +	{
 +		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()
 +{
 +	static const std::string vertex_shader_enable_feature_string = "VertexShaderEnable";
 +
 +	if (sDisableShaders ||
 +		!gGLManager.mHasVertexShader ||
 +		!gGLManager.mHasFragmentShader ||
 +		!LLFeatureManager::getInstance()->isFeatureAvailable(vertex_shader_enable_feature_string) ||
 +		(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();
 +
 +	// 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->flagUsePhysics())
 +	{
 +		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.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 +	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();
 +	
 +	if (LLGLSLShader::sNoFixedFunction)
 +	{
 +		gUIProgram.bind();
 +	}
 +
 +
 +	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);	
 +	gPipeline.disableLights();
  	//Render any navmesh geometry	
  	LLPathingLib *llPathingLibInstance = LLPathingLib::getInstance();
 @@ -4386,5490 +4372,5500 @@ void LLPipeline::renderDebug()  			}
  		}
  	}
 -	gGL.flush(); -	if (LLGLSLShader::sNoFixedFunction) -	{ -		gUIProgram.unbind(); -	} - -	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) -			{ -				F32 size = light_radius*1.5f; -				light_state->setLinearAttenuation(size*size); -				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); -	 -				const LLColor4 specular(0.f, 0.f, 0.f, 0.f); -				light_state->setSpecular(specular); -			} -			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 = avatar->isVisuallyMuted();		 - -	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); -} - +	gGL.flush();
 +	if (LLGLSLShader::sNoFixedFunction)
 +	{
 +		gUIProgram.unbind();
 +	}
 +
 +	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)
 +			{
 +				F32 size = light_radius*1.5f;
 +				light_state->setLinearAttenuation(size*size);
 +				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);
 +	
 +				const LLColor4 specular(0.f, 0.f, 0.f, 0.f);
 +				light_state->setSpecular(specular);
 +			}
 +			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)
 +	{
 +		return;
 +	}
 +
 +	for (S32 i = 0; i < drawable->getNumFaces(); i++)
 +	{
 +		LLFace* facep = drawable->getFace(i);
 +		facep->clearVertexBuffer();
 +	}
 +}
 +
 +void LLPipeline::resetVertexBuffers()
 +{
 +	mResetVertexBuffers = true;
 +}
 +
 +void LLPipeline::doResetVertexBuffers()
 +{
 +	if (!mResetVertexBuffers)
 +	{
 +		return;
 +	}
 +	
 +	mResetVertexBuffers = false;
 +
 +	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 -- " << LLVertexBuffer::sGLCount << " buffers remaining." << llendl;
 +	}
 +
 +	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 = avatar->isVisuallyMuted();		
 +
 +	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);
 +}
 +
 diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index 9c78048c46..3c4e389ce0 100644 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -111,6 +111,7 @@ public:  	void destroyGL();  	void restoreGL();  	void resetVertexBuffers(); +	void doResetVertexBuffers();  	void resizeScreenTexture();  	void releaseGLBuffers();  	void releaseScreenBuffers(); @@ -653,6 +654,8 @@ protected:  	bool mGroupQ2Locked;  	bool mGroupQ1Locked; +	bool mResetVertexBuffers; //if true, clear vertex buffers on next update +  	LLViewerObject::vobj_list_t		mCreateQ;  	LLDrawable::drawable_set_t		mRetexturedList; diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml index 8baaa14595..b616e2327b 100644 --- a/indra/newview/skins/default/colors.xml +++ b/indra/newview/skins/default/colors.xml @@ -615,6 +615,9 @@       name="PanelFocusBackgroundColor"       reference="DkGray2" />      <color +     name="PanelNotificationBackground" +     value="1 0.3 0.3 0" /> +    <color       name="ParcelHoverColor"       reference="White" />      <color @@ -747,6 +750,9 @@       name="TitleBarFocusColor"       reference="White_10" />      <color +     name="ToastBackground" +     value="0.3 0.3 0.3 0" /> +    <color       name="ToolTipBgColor"       value="0.937 0.89 0.655 1" />      <color diff --git a/indra/newview/skins/default/textures/checker.png b/indra/newview/skins/default/textures/checker.png Binary files differnew file mode 100644 index 0000000000..1ab87e3f02 --- /dev/null +++ b/indra/newview/skins/default/textures/checker.png diff --git a/indra/newview/skins/default/textures/map_avatar_unknown_32.tga b/indra/newview/skins/default/textures/map_avatar_unknown_32.tga Binary files differnew file mode 100644 index 0000000000..d1192478c6 --- /dev/null +++ b/indra/newview/skins/default/textures/map_avatar_unknown_32.tga diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index ee8b7ba082..d5d58235a4 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -122,6 +122,8 @@ with the same filename but different name    <texture name="Checkbox_Press" file_name="widgets/Checkbox_Press.png" preload="true" />    <texture name="Check_Mark" file_name="icons/check_mark.png" preload="true" /> +  <texture name="Checker" file_name="checker.png" preload="false" /> +      <texture name="Command_AboutLand_Icon"    file_name="toolbar_icons/land.png"         preload="true" />    <texture name="Command_Appearance_Icon"   file_name="toolbar_icons/appearance.png"   preload="true" />    <texture name="Command_Avatar_Icon"       file_name="toolbar_icons/avatars.png"      preload="true" /> diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml index 930bbaa8cb..d11373ce1d 100644 --- a/indra/newview/skins/default/xui/en/floater_aaa.xml +++ b/indra/newview/skins/default/xui/en/floater_aaa.xml @@ -1,6 +1,5 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <floater - legacy_header_height="18"   can_minimize="false"   can_tear_off="false"   can_resize="true" @@ -16,67 +15,98 @@   save_dock_state="true"   save_visibility="true"   single_instance="true"  - width="320"> -  <string name="nudge_parabuild" translate="false">Nudge 1</string> -  <string name="test_the_vlt">This string CHANGE2 is extracted.</string> -  <string name="testing_eli">Just a test. changes.</string> -  <text_editor -   parse_urls="true" -   bg_readonly_color="ChatHistoryBgColor" -   bg_writeable_color="ChatHistoryBgColor"  -   border_visible="false" -   follows="all" -   font="SansSerif"  -	 left="1" -   top="20" -   layout="topleft" -	 height="260" -   name="chat_history" -   max_length="200000"  -   parse_highlights="true" -   text_color="ChatHistoryTextColor" -   text_readonly_color="ChatHistoryTextColor" -   translate="false" -   track_end="true"  -   wrap="true"  -   width="320"> -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    Really long line that is long enough to wrap once with jyg descenders. -    </text_editor> + width="650"> +  <text left="0" +        follows="left|top|bottom" +        top="5" +        clip_partial="true"         +        bottom="-5" +        width="100" +        valign="top"> +this +is +some +text +that +is +top +aligned</text> +  <text left_pad="5" +        follows="left|top|bottom" +        top="5" +        bottom="-5" +        clip_partial="true" +        width="100" +        valign="center"> +this +is +some +text +that +is +center +aligned</text> +  <text left_pad="5" +        follows="left|top|bottom" +        top="5" +        clip_partial="true"         +        bottom="-5" +        width="100" +        valign="bottom"> +this +is +some +text +that +is +bottom +aligned</text> +  <text_editor left_pad="5" +        follows="left|top|bottom" +        top="5" +        clip_partial="true" +        bottom="-5" +        width="100" +        valign="top"> +this +is +some +text +that +is +top +aligned +  </text_editor> +  <text_editor left_pad="5" +        follows="left|top|bottom" +        top="5" +        bottom="-5" +        clip_partial="true" +        width="100" +        valign="center"> +this +is +some +text +that +is +center +aligned +  </text_editor> +  <text_editor left_pad="5" +        follows="left|top|bottom" +        top="5" +        clip_partial="true" +        bottom="-5" +        width="100" +        valign="bottom"> +this +is +some +text +that +is +bottom +aligned +  </text_editor>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml index 1d5a6740b7..3a6c2678c1 100644 --- a/indra/newview/skins/default/xui/en/floater_about_land.xml +++ b/indra/newview/skins/default/xui/en/floater_about_land.xml @@ -192,12 +192,12 @@               type="string"               length="1"               follows="left|top" -             height="20" +             height="18"               layout="topleft"               left_pad="2"               valign="center"                name="ContentRatingText" -             top_delta="0" +             top_delta="-2"               width="250">                  Adult              </text> @@ -209,7 +209,7 @@               layout="topleft"               left="10"               name="Owner:" -             top_pad="1" +             top_pad="3"               width="100">                  Owner:              </text> @@ -736,7 +736,7 @@               height="16"               layout="topleft"               left_pad="10" -             top_delta="-3"  +             top_delta="-1"                mouse_opaque="false"               name="region_maturity_text"               valign="center"  @@ -1210,7 +1210,7 @@ Only large parcels can be listed in search.               type="string"               length="1"               follows="left|top" -             text_color="white" +             text_color="White"               height="16"               layout="topleft"               left="10" @@ -1500,7 +1500,7 @@ Only large parcels can be listed in search.               layout="topleft"               left="20"               name="Snapshot:" -             text_color="white" +             text_color="White"               top="225"               width="200">                  Snapshot: @@ -1546,7 +1546,7 @@ Only large parcels can be listed in search.               layout="topleft"               left="255"               top="282" -             text_color="white" +             text_color="White"               name="landing_point"               word_wrap="true"               width="200"> @@ -1576,7 +1576,7 @@ Only large parcels can be listed in search.              <text               type="string"               length="1" -             text_color="white" +             text_color="White"               follows="left|top"               height="16"               layout="topleft" @@ -1951,7 +1951,7 @@ Only large parcels can be listed in search.  			 name="access_estate_defined">  				(Defined by the Estate)  			</panel.string> -            <panel.string +      <panel.string               name="estate_override">                  One or more of these options is set at the estate level              </panel.string> @@ -2085,7 +2085,7 @@ Only large parcels can be listed in search.               column_padding="0"               follows="top|bottom"               heading_height="14" -             height="120" +             height="125"               layout="topleft"               left="0"               multi_select="true" @@ -2134,7 +2134,7 @@ Only large parcels can be listed in search.               column_padding="0"               follows="top|bottom"               heading_height="14" -             height="120" +             height="125"               layout="topleft"               left="0"               multi_select="true" diff --git a/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml new file mode 100644 index 0000000000..b5538a511c --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_animation_anim_preview.xml @@ -0,0 +1,76 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + legacy_header_height="18" + height="190" + layout="topleft" + name="Anim Preview" + help_topic="animation_anim_preview" + title="ANIMATION.ANIM" + width="300"> +    <text +     type="string" +     length="1" +     follows="left|top" +     height="15" +     layout="topleft" +     left="10" +     mouse_opaque="false" +     name="name_label" +     top="20" +     width="275"> +        Name: +    </text> +    <line_editor +     border_style="line" +     border_thickness="1" +     follows="left|top|right" +     height="19" +     layout="topleft" +     left_delta="0" +     max_length_bytes="63" +     name="name_form" +     top_pad="0" +     width="280" /> +    <text +     type="string" +     length="1" +     follows="left|top" +     height="15" +     layout="topleft" +     left_delta="0" +     mouse_opaque="false" +     name="description_label" +     top_pad="10" +     width="270"> +        Description: +    </text> +    <line_editor +     border_style="line" +     border_thickness="1" +     follows="left|top|right" +     height="19" +     layout="topleft" +     left_delta="0" +     max_length_bytes="127" +     name="description_form" +     top_pad="0" +     width="280" /> +    <button +     follows="left|bottom" +     height="22" +     label="Upload (L$[AMOUNT])" +     layout="topleft" +     left="45" +     name="ok_btn" +     top_pad="60" +     width="150" /> +    <button +     follows="right|bottom" +     height="22" +     label="Cancel" +     label_selected="Cancel" +     layout="topleft" +     name="cancel_btn" +     left_pad="5" +     width="90" /> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_animation_preview.xml b/indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml index cb6b2f6ebc..cb6b2f6ebc 100644 --- a/indra/newview/skins/default/xui/en/floater_animation_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_animation_bvh_preview.xml diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml index 35918e9705..38428b36fc 100644 --- a/indra/newview/skins/default/xui/en/floater_build_options.xml +++ b/indra/newview/skins/default/xui/en/floater_build_options.xml @@ -1,70 +1,13 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <floater   legacy_header_height="18" - height="198" + height="170"   layout="topleft"   name="build options floater"   help_topic="build_options_floater"   save_rect="true"   title="GRID OPTIONS"   width="264"> - 	<floater.string -     name="grid_screen_text"> -        Screen -    </floater.string> -    <floater.string -     name="grid_local_text"> -        Local -    </floater.string> -    <floater.string -     name="grid_world_text"> -        World -    </floater.string> -    <floater.string -     name="grid_reference_text"> -        Reference -    </floater.string> -    <floater.string -     name="grid_attachment_text"> -        Attachment -    </floater.string> -    <text -     type="string" -     length="1" -     follows="left|top" -     height="16" -     layout="topleft" -     left="10" -     tool_tip="Grid opacity" -     name="grid_mode_label" -     top_pad="30" -     width="123"> -        Mode -    </text> -    <combo_box -     height="23" -     layout="topleft" -     left_pad="9" -     follows="left|top" -     name="combobox grid mode" -     tool_tip="Choose the type of grid ruler for positioning the object" -     top_delta="-3" -     width="108"> -      <combo_box.item -       label="World grid" -       name="World" -       value="World" /> -      <combo_box.item -       label="Local grid" -       name="Local" -       value="Local" /> -      <combo_box.item -       label="Reference grid" -       name="Reference" -       value="Reference" /> -       <combo_box.commit_callback -      function="GridOptions.gridMode"/> -    </combo_box>      <spinner       control_name="GridResolution"       follows="left|top" @@ -77,7 +20,7 @@       max_val="5"       min_val="0.01"       name="GridResolution" -     top_pad="4" +     top_pad="30"       width="200" />      <spinner       control_name="GridDrawSize" diff --git a/indra/newview/skins/default/xui/en/floater_buy_contents.xml b/indra/newview/skins/default/xui/en/floater_buy_contents.xml index 92001534e7..ac96a70805 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_contents.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_contents.xml @@ -62,7 +62,7 @@       layout="topleft"       left="10"       name="buy_text" -     text_color="white" +     text_color="White"       top="220"       use_ellipses="true"        width="260"> diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml index 6afa24d04a..553c5d51d0 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml @@ -215,7 +215,7 @@      <text       type="string"       length="1" -     text_color="0.7 0.7 0.7 0.5" +     text_color="LtGray_50"       follows="top|left"       layout="topleft"       halign="right" @@ -229,7 +229,7 @@      <text       type="string"       length="1" -     text_color="0.7 0.7 0.7 0.5" +     text_color="LtGray_50"       follows="top|left"       layout="topleft"       halign="right" @@ -243,7 +243,7 @@ Re-enter amount to see the latest exchange rate.      <text       type="string"       length="1" -     text_color="0.7 0.7 0.7 0.5" +     text_color="LtGray_50"       follows="top|left"       layout="topleft"       halign="right" @@ -257,7 +257,7 @@ Re-enter amount to see the latest exchange rate.      <text       type="string"       length="1" -     text_color="0.7 0.7 0.7 0.5" +     text_color="LtGray_50"       follows="top|left"       layout="topleft"       halign="right" diff --git a/indra/newview/skins/default/xui/en/floater_buy_object.xml b/indra/newview/skins/default/xui/en/floater_buy_object.xml index 8dfb6ba00c..5fdd4aa49d 100644 --- a/indra/newview/skins/default/xui/en/floater_buy_object.xml +++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml @@ -89,7 +89,7 @@       left_delta="0"  	 line_spacing.pixels="7"       name="buy_text" -     text_color="white" +     text_color="White"       top_pad="5"       use_ellipses="true"       width="260" @@ -106,7 +106,7 @@ Buy for L$[AMOUNT] from:       left_delta="0"  	 line_spacing.pixels="7"       name="buy_name_text" -     text_color="white" +     text_color="White"       top_pad="5"       use_ellipses="true"       width="260"> diff --git a/indra/newview/skins/default/xui/en/floater_choose_group.xml b/indra/newview/skins/default/xui/en/floater_choose_group.xml index dc1ee5f24e..2cf6e682fd 100644 --- a/indra/newview/skins/default/xui/en/floater_choose_group.xml +++ b/indra/newview/skins/default/xui/en/floater_choose_group.xml @@ -20,7 +20,7 @@          Choose a group:      </text>      <scroll_list -     height="160" +     height="165"       layout="topleft"       left_delta="0"       name="group list" diff --git a/indra/newview/skins/default/xui/en/floater_fast_timers.xml b/indra/newview/skins/default/xui/en/floater_fast_timers.xml index 49aa8f3840..77adb5524e 100644 --- a/indra/newview/skins/default/xui/en/floater_fast_timers.xml +++ b/indra/newview/skins/default/xui/en/floater_fast_timers.xml @@ -22,7 +22,6 @@            top="5"            width="180"            height="40" -          pad_bottom="-5"            label="Pause"            font="SansSerifHuge"/>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml index 6f387f4800..3d33d19de5 100644 --- a/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml +++ b/indra/newview/skins/default/xui/en/floater_merchant_outbox.xml @@ -99,7 +99,7 @@              halign="center"              font="SansSerifMedium"              font_shadow="hard" -            valign="bottom"> +            valign="top">            Drag items here to create folders          </text>        </panel> @@ -114,8 +114,8 @@            height="20"            wrap="true"            halign="left" -          valign="bottom" -          font="SansSerif" /> +          valign="center" +          font="SansSerif"/>        <button            label="Send to Marketplace"            tool_tip="Push to my Marketplace Storefront" diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index eebc5ddc72..0e211551e6 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -117,18 +117,18 @@               name="lod_tab_border"               top_pad="0"               width="619" /> -            <text -             follows="left|top" -             height="18" -             initial_value="Source" -             layout="topleft" -             left="75" -             name="source" -             text_color="ModelUploaderLabels" -             top="15" -             valign="center" -             value="Source" -             width="335" /> +          <text +           follows="left|top" +           height="18" +           initial_value="Source" +           layout="topleft" +           left="75" +           name="source" +           text_color="ModelUploaderLabels" +           top="15" +           valign="center" +           value="Source" +           width="335"/>              <text               follows="left|top"               halign="right" @@ -163,7 +163,7 @@               name="high_label"               text_color="ModelUploaderLabels"               top_pad="10" -             valign="center" +             valign="top"               value="High"               width="65" />              <combo_box @@ -240,34 +240,34 @@              <text               follows="left|top"               halign="right" -             height="18" +             height="15"               initial_value="0"               layout="topleft"               left_pad="0"               name="high_triangles" -             valign="center" +             valign="top"               value="0"               width="65" />              <text               follows="left|top"               halign="right" -             height="18" +             height="15"               initial_value="0"               layout="topleft"               left_pad="0"               name="high_vertices" -             valign="center" +             valign="top"               value="0"               width="65" />              <text               follows="left|top"               halign="center" -             height="18" +             height="15"               initial_value=""               layout="topleft"               left_pad="0"               name="high_status" -             valign="center" +             valign="top"               value=""               width="65" />              <icon @@ -277,7 +277,7 @@               left_delta="20"               mouse_opaque="true"               name="status_icon_high" -             top_delta="0" +             top_delta="-2"               width="16" />              <text               follows="left|top" @@ -288,7 +288,7 @@               name="medium_label"               text_color="ModelUploaderLabels"               top_pad="15" -             valign="center" +             valign="top"               value="Medium"               width="65" />              <combo_box @@ -368,34 +368,34 @@              <text               follows="left|top"               halign="right" -             height="18" +             height="15"               initial_value="0"               layout="topleft"               left_pad="0"               name="medium_triangles" -             valign="center" +             valign="top"               value="0"               width="65" />              <text               follows="left|top"               halign="right" -             height="18" +             height="15"               initial_value="0"               layout="topleft"               left_pad="0"               name="medium_vertices" -             valign="center" +             valign="top"               value="0"               width="65" />              <text               follows="left|top"               halign="center" -             height="18" +             height="15"               initial_value=""               layout="topleft"               left_pad="0"               name="medium_status" -             valign="center" +             valign="top"               value=""               width="65" />              <icon @@ -405,7 +405,7 @@               left_delta="20"               mouse_opaque="true"               name="status_icon_medium" -             top_delta="0" +             top_delta="-2"               width="16" />              <text               follows="left|top" @@ -416,7 +416,7 @@               name="low_label"               text_color="ModelUploaderLabels"               top_pad="15" -             valign="center" +             valign="top"               value="Low"               width="65" />              <combo_box @@ -496,34 +496,34 @@              <text               follows="left|top"               halign="right" -             height="18" +             height="15"               initial_value="0"               layout="topleft"               left_pad="0"               name="low_triangles" -             valign="center" +             valign="top"               value="0"               width="65" />              <text               follows="left|top"               halign="right" -             height="18" +             height="15"               initial_value="0"               layout="topleft"               left_pad="0"               name="low_vertices" -             valign="center" +             valign="top"               value="0"               width="65" />              <text               follows="left|top"               halign="center" -             height="18" +             height="15"               initial_value=""               layout="topleft"               left_pad="0"               name="low_status" -             valign="center" +             valign="top"               value=""               width="65" />              <icon @@ -533,7 +533,7 @@               left_delta="20"               mouse_opaque="true"               name="status_icon_low" -             top_delta="0" +             top_delta="-2"               width="16" />              <text               follows="left|top" @@ -544,7 +544,7 @@               name="lowest_label"               text_color="ModelUploaderLabels"               top_pad="15" -             valign="center" +             valign="top"               value="Lowest"               width="65" />              <combo_box @@ -624,34 +624,34 @@              <text               follows="left|top"               halign="right" -             height="18" +             height="15"               initial_value="0"               layout="topleft"               left_pad="0"               name="lowest_triangles" -             valign="center" +             valign="top"               value="0"               width="65" />              <text               follows="left|top"               halign="right" -             height="18" +             height="15"               initial_value="0"               layout="topleft"               left_pad="0"               name="lowest_vertices" -             valign="center" +             valign="top"               value="0"               width="65" />              <text               follows="left|top"               halign="center" -             height="18" +             height="15"               initial_value=""               layout="topleft"               left_pad="0"               name="lowest_status" -             valign="center" +             valign="top"               value=""               width="65" />              <icon diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml index 402868bb97..b2662331b0 100644 --- a/indra/newview/skins/default/xui/en/floater_preferences.xml +++ b/indra/newview/skins/default/xui/en/floater_preferences.xml @@ -100,7 +100,7 @@           help_topic="preferences_colors_tab"           name="colors" />          <panel -		 class="panel_preference" +         class="panel_preference_privacy"           filename="panel_preferences_privacy.xml"           label="Privacy"           layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_preview_animation.xml b/indra/newview/skins/default/xui/en/floater_preview_animation.xml index 8427c7b06f..3ea5f54f2c 100644 --- a/indra/newview/skins/default/xui/en/floater_preview_animation.xml +++ b/indra/newview/skins/default/xui/en/floater_preview_animation.xml @@ -41,18 +41,26 @@       label_selected="Stop"       layout="topleft"       left="10" -     name="Anim play btn" +     name="Inworld"       tool_tip="Play this animation so that others can see it"       top="47" -     width="125" /> +     width="125"> +       <button.commit_callback +        function="PreviewAnim.Play" +        parameter="Inworld" />  +    </button>      <button       height="20"       label="Play Locally"       label_selected="Stop"       layout="topleft"       left_pad="5" -     name="Anim audition btn" +     name="Locally"       tool_tip="Play this animation so that only you can see it"       top_delta="0" -     width="125" /> +     width="125"> +       <button.commit_callback +        function="PreviewAnim.Play" +        parameter="Locally" />  +    </button>  </floater> diff --git a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml index f95f21e63a..a04050e7eb 100644 --- a/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml +++ b/indra/newview/skins/default/xui/en/floater_test_layout_stacks.xml @@ -32,6 +32,26 @@                    bg_alpha_color="blue"                    height="11"                    min_height="0" +                  visible="false" +                  background_visible="true"> +      <text follows="top|left|right" halign="center" text_color="white">flex</text> +    </layout_panel> +    <layout_panel name="flex" +                  auto_resize="true" +                  user_resize="true" +                  bg_alpha_color="blue" +                  height="11" +                  min_height="0" +                  visible="true" +                  background_visible="true"> +      <text follows="top|left|right" halign="center" text_color="white">flex</text> +    </layout_panel> +    <layout_panel name="flex" +                  auto_resize="true" +                  user_resize="true" +                  bg_alpha_color="blue" +                  height="11" +                  min_height="0"                    background_visible="true">        <text follows="top|left|right" halign="center" text_color="white">flex</text>      </layout_panel> diff --git a/indra/newview/skins/default/xui/en/floater_test_text_vertical_aligment.xml b/indra/newview/skins/default/xui/en/floater_test_text_vertical_aligment.xml new file mode 100644 index 0000000000..d11373ce1d --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_test_text_vertical_aligment.xml @@ -0,0 +1,112 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater + can_minimize="false" + can_tear_off="false" + can_resize="true" + can_drag_on_left="false" + can_close="true" + can_dock="true" + bevel_style="in" + height="300" + layout="topleft" + name="Test Floater" + save_rect="true" + title="TEST FLOATER" + save_dock_state="true" + save_visibility="true" + single_instance="true"  + width="650"> +  <text left="0" +        follows="left|top|bottom" +        top="5" +        clip_partial="true"         +        bottom="-5" +        width="100" +        valign="top"> +this +is +some +text +that +is +top +aligned</text> +  <text left_pad="5" +        follows="left|top|bottom" +        top="5" +        bottom="-5" +        clip_partial="true" +        width="100" +        valign="center"> +this +is +some +text +that +is +center +aligned</text> +  <text left_pad="5" +        follows="left|top|bottom" +        top="5" +        clip_partial="true"         +        bottom="-5" +        width="100" +        valign="bottom"> +this +is +some +text +that +is +bottom +aligned</text> +  <text_editor left_pad="5" +        follows="left|top|bottom" +        top="5" +        clip_partial="true" +        bottom="-5" +        width="100" +        valign="top"> +this +is +some +text +that +is +top +aligned +  </text_editor> +  <text_editor left_pad="5" +        follows="left|top|bottom" +        top="5" +        bottom="-5" +        clip_partial="true" +        width="100" +        valign="center"> +this +is +some +text +that +is +center +aligned +  </text_editor> +  <text_editor left_pad="5" +        follows="left|top|bottom" +        top="5" +        clip_partial="true" +        bottom="-5" +        width="100" +        valign="bottom"> +this +is +some +text +that +is +bottom +aligned +  </text_editor> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml index 2df9bb35fe..1d31fbd6dc 100644 --- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml +++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml @@ -8,21 +8,7 @@   help_topic="floater_test_textbox"   translate="false"   width="800"> -    <text -     type="string" -     length="1" -     height="90" -     layout="topleft" -     left="10" -     top_pad="30" -     width="300"> -        First line of multiple lines -Second line of multiple lines -Third line of multiple lines -Fourth line of multiple lines -Fifth line of multiple lines -    </text> -  <text + <text      clip_partial="true"      top_pad="10"      left="10" diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index f9147ea650..2d63c94fe1 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -14,7 +14,27 @@   save_visibility="true"   sound_flags="0"   width="295"> -    <floater.string +  <floater.string +     name="grid_screen_text"> +    Screen +  </floater.string> +  <floater.string +   name="grid_local_text"> +    Local +  </floater.string> +  <floater.string +   name="grid_world_text"> +    World +  </floater.string> +  <floater.string +   name="grid_reference_text"> +    Reference +  </floater.string> +  <floater.string +   name="grid_attachment_text"> +    Attachment +  </floater.string> +  <floater.string       name="status_rotate">          Drag colored bands to rotate object      </floater.string> @@ -312,20 +332,48 @@       top_pad="0"       name="checkbox snap to grid"       width="134" /> -    <button -     left_pad="0" -     label="Options..." +    <combo_box +      height="20" +      layout="topleft" +      follows="left|top" +      name="combobox grid mode" +      tool_tip="Choose the type of grid ruler for positioning the object" +      top="83" +      left="195" +      top_pad="0" +      width="60"> +      <combo_box.item +      label="World" +      name="World" +      value="World" /> +      <combo_box.item +      label="Local" +      name="Local" +      value="Local" /> +      <combo_box.item +      label="Reference" +      name="Reference" +      value="Reference" /> +      <combo_box.commit_callback +      function="BuildTool.gridMode"/> +    </combo_box>   +   +  <button +     left="259" +     label="" +     image_selected="ForwardArrow_Press" +     image_unselected="ForwardArrow_Off"       layout="topleft"       follows="top|left"       name="Options..."       tool_tip="See more grid options"       top="83" -     right="-35" -     width="65" -     height="21" > +     width="25" +     height="20" >  	 <button.commit_callback  	     function="BuildTool.gridOptions"/>  	</button> +       <button       follows="left|top"       height="20" diff --git a/indra/newview/skins/default/xui/en/floater_toybox.xml b/indra/newview/skins/default/xui/en/floater_toybox.xml index 72e6187a14..fcaae9d172 100644 --- a/indra/newview/skins/default/xui/en/floater_toybox.xml +++ b/indra/newview/skins/default/xui/en/floater_toybox.xml @@ -18,7 +18,7 @@    <text      follows="left|top"      font="SansSerifMedium" -    valign="bottom" +    valign="top"      halign="left"      height="20"      layout="topleft" @@ -33,7 +33,7 @@    <text      follows="left|top"      font="SansSerifMedium" -    valign="bottom" +    valign="top"      halign="left"      height="20"      layout="topleft" diff --git a/indra/newview/skins/default/xui/en/floater_voice_controls.xml b/indra/newview/skins/default/xui/en/floater_voice_controls.xml index cea19ec75c..d99b29f324 100644 --- a/indra/newview/skins/default/xui/en/floater_voice_controls.xml +++ b/indra/newview/skins/default/xui/en/floater_voice_controls.xml @@ -71,7 +71,7 @@               layout="topleft"               left_pad="10"               name="user_text" -             text_color="white" +             text_color="White"               top="4"               use_ellipses="true"               value="My Avatar:" diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml index 8d14c974b4..bfeb8fc470 100644 --- a/indra/newview/skins/default/xui/en/inspect_object.xml +++ b/indra/newview/skins/default/xui/en/inspect_object.xml @@ -56,7 +56,7 @@ owner secondlife:///app/agent/0e346d8b-4433-4d66-a6b0-fd37083abc4c/about     halign="right"     right="-5"     name="price_text" -   text_color="white" +   text_color="White"     top="60"     font_shadow="none"     width="60"> @@ -90,6 +90,7 @@ L$30,000     follows="all"     font="SansSerifSmall"     height="13" +   clip="false"     name="object_media_url"     width="207"     left_pad="2" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index f70d4db0f2..5faafecef7 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -1667,7 +1667,7 @@ Unable to create output file: [FILE]     icon="alertmodal.tga"     name="DoNotSupportBulkAnimationUpload"     type="alertmodal"> -[APP_NAME] does not currently support bulk upload of animation files. +[APP_NAME] does not currently support bulk upload of BVH format animation files.    <tag>fail</tag>    </notification> @@ -6409,11 +6409,11 @@ Grant this request?      <form name="form">        <button         index="-2" -       name="Mute" +       name="Client_Side_Mute"         text="Block"/>        <button         index="-1" -       name="Ignore" +       name="Client_Side_Ignore"         text="Ignore"/>      </form>    </notification> @@ -6428,11 +6428,11 @@ Grant this request?      <form name="form">        <button         index="-2" -       name="Mute" +       name="Client_Side_Mute"         text="Block"/>        <button         index="-1" -       name="Ignore" +       name="Client_Side_Ignore"         text="Ignore"/>      </form>    </notification> diff --git a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml index 1e6a31d388..7c67fd7f83 100644 --- a/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml +++ b/indra/newview/skins/default/xui/en/panel_block_list_sidetray.xml @@ -28,7 +28,7 @@       layout="topleft"       left_pad="10"       name="title_text" -     text_color="white" +     text_color="White"       top="5"       width="250">          Block List diff --git a/indra/newview/skins/default/xui/en/panel_chat_header.xml b/indra/newview/skins/default/xui/en/panel_chat_header.xml index 2645d472f9..5c5c718bdf 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_header.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml @@ -23,7 +23,7 @@      <text        parse_urls="false"        allow_scroll="false" -      v_pad = "7" +      v_pad = "6"        read_only = "true"        follows="left|right"        font.style="BOLD" @@ -37,7 +37,7 @@        top="0"        translate="false"        use_ellipses="true" -      valign="bottom"  +      valign="top"         value="TestString PleaseIgnore" />    <text      allow_scroll="false" @@ -49,7 +49,7 @@      left_pad="5"      name="time_box"      right="-5" -    top="8" +    top="7"      value="23:30"      width="110" />  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_chat_item.xml b/indra/newview/skins/default/xui/en/panel_chat_item.xml index 6af1105400..1b97de2b05 100644 --- a/indra/newview/skins/default/xui/en/panel_chat_item.xml +++ b/indra/newview/skins/default/xui/en/panel_chat_item.xml @@ -16,13 +16,13 @@          top="3"          width="18" />  	<text_chat -      top="5" +      top="3"        left="30"        height="120"        text_color="white"        word_wrap="true"        mouse_opaque="true" -      valign="bottom" +      valign="top"        name="msg_text">  	</text_chat>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml index df459b4083..4b05ab27e4 100644 --- a/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/panel_dummy_clothing_list_item.xml @@ -29,7 +29,7 @@       width="380" />      <icon       height="16" -     color="0.75 0.75 0.75 1" +     color="LtGray"       follows="top|left"       image_name="Inv_Object"       layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml index 69a692e2c4..f34b913218 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_wearable.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_wearable.xml @@ -164,7 +164,7 @@       layout="topleft"       left_pad="8"       name="edit_wearable_title" -     text_color="white" +     text_color="White"       top="3"       value="Editing Shape"       use_ellipses="true" @@ -190,7 +190,7 @@           layout="topleft"           left="10"           name="description_text" -         text_color="white" +         text_color="White"           top="10"           value="Shape:"           width="150" /> @@ -254,7 +254,7 @@           name="description"           prevalidate_callback="ascii"           select_on_focus="true" -         text_color="black" +         text_color="Black"           top_pad="3"           width="290" />      </panel> diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml index a7178dc288..eea2606125 100644 --- a/indra/newview/skins/default/xui/en/panel_group_roles.xml +++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml @@ -172,7 +172,7 @@ including the Everyone and Owner Roles.               draw_heading="true"               draw_stripes="false"               heading_height="23" -             height="130" +             height="132"               layout="topleft"               search_column="1"               left="0" diff --git a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml index 383e637ace..413e22e444 100644 --- a/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_inbox_inventory.xml @@ -1,5 +1,6 @@  <?xml version="1.0" encoding="utf-8" standalone="yes" ?>  <inbox_inventory_panel +    accepts_drag_and_drop="false"      name="inventory_inbox"      start_folder="Received Items"      follows="all" layout="topleft" diff --git a/indra/newview/skins/default/xui/en/panel_instant_message.xml b/indra/newview/skins/default/xui/en/panel_instant_message.xml index 4251128714..2e5d650902 100644 --- a/indra/newview/skins/default/xui/en/panel_instant_message.xml +++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml @@ -15,7 +15,7 @@      <panel       background_visible="true"       bevel_style="in" -     bg_alpha_color="black" +     bg_alpha_color="Black"       follows="top"       height="24"       label="im_header" @@ -64,7 +64,7 @@           left_pad="5"           name="user_name"           parse_urls="false" -         text_color="white" +         text_color="White"           top="8"           translate="false"           use_ellipses="true" @@ -90,7 +90,7 @@       layout="topleft"       left="10"       name="message" -     text_color="white" +     text_color="White"       top="33"       use_ellipses="true"       value="" diff --git a/indra/newview/skins/default/xui/en/panel_landmark_info.xml b/indra/newview/skins/default/xui/en/panel_landmark_info.xml index d2088594dd..fd6e96b9a7 100644 --- a/indra/newview/skins/default/xui/en/panel_landmark_info.xml +++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml @@ -271,7 +271,7 @@                  <text_editor                   bg_readonly_color="DkGray2"                   follows="all" -                 height="70" +                 height="75"                   layout="topleft"                   left="0"                   max_length="127" @@ -288,7 +288,7 @@                   layout="topleft"                   left="0"                   name="folder_label" -                 top_pad="15" +                 top_pad="10"                   value="Landmark location:"                   width="290" />                  <combo_box diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml index d6d8b2a83e..1c882bb099 100644 --- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml +++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml @@ -80,7 +80,6 @@       top="16"       width="288" />      <recent_inventory_panel -     accepts_drag_and_drop="false"       bg_opaque_color="DkGray2"       bg_alpha_color="DkGray2"       background_visible="true" diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml index 4bf420b79f..3edeb9aa36 100644 --- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml @@ -70,7 +70,7 @@             layout="topleft"             auto_resize="true"             user_resize="true" -           min_width="480" +           min_width="410"             name="navigation_layout_panel"             width="480">  	        <panel @@ -148,15 +148,15 @@  	         layout="topleft"             auto_resize="true"             user_resize="true" -           min_width="315" +           min_width="185"             name="favorites_layout_panel" -           width="315"> +           width="320">             <icon               follows="top|left"               height="25"               image_name="ChatBarHandle"               layout="topleft" -             left="-318" +             left="-323"               name="resize_handle"               top="4"               width="5" /> @@ -171,16 +171,17 @@               name="favorite"               image_drag_indication="Accordion_ArrowOpened_Off"               tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!" -             width="311"> +             width="320">              <label               follows="left|top" -             height="15" +             height="13"               layout="topleft"               left="10"               name="favorites_bar_label"               text_color="LtGray"               tool_tip="Drag Landmarks here for quick access to your favorite places in Second Life!" -             top="12" +             top="13" +	     valign="bottom"               width="102">                Favorites Bar              </label> diff --git a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml index d492f9bd68..d683116eb8 100644 --- a/indra/newview/skins/default/xui/en/panel_nearby_chat.xml +++ b/indra/newview/skins/default/xui/en/panel_nearby_chat.xml @@ -1,35 +1,63 @@  <?xml version="1.0" encoding="utf-8" standalone="yes"?>  <panel - height="300"   follows="all" + height="300" + help_topic="nearby_chat"   layout="topleft"   name="nearby_chat" - help_topic="nearby_chat"   width="320"> -            <check_box -             bottom_delta="36" -             control_name="TranslateChat" -             enabled="true" -             height="16" -             label="Translate chat" -             layout="topleft" -             left="5" -             name="translate_chat_checkbox" -             width="230" /> -  <chat_history -    parse_urls="true" -    bg_readonly_color="ChatHistoryBgColor" -    bg_writeable_color="ChatHistoryBgColor" -    follows="all" -    left="5" -    top_delta="17" -    layout="topleft" -    height="260" -    name="chat_history" -    parse_highlights="true" -    text_color="ChatHistoryTextColor" -    text_readonly_color="ChatHistoryTextColor" -    right_widget_pad="5" -    left_widget_pad="0" -    width="315" /> +  <layout_stack +   follows="all" +   height="295" +   layout="topleft" +   left="0" +   name="stack" +   top="5" +   orientation="vertical" +   width="320"> +    <layout_panel +     auto_resize="false" +     height="26" +     layout="topleft" +     left_delta="0" +     name="translate_chat_checkbox_lp" +     top_delta="0" +     visible="true" +     width="313"> +      <check_box +       top="10" +       control_name="TranslateChat" +       enabled="true" +       height="16" +       label="Translate chat" +       layout="topleft" +       left="5" +       name="translate_chat_checkbox" +       width="300" /> +    </layout_panel> +    <layout_panel +     auto_resize="true" +     height="277" +     left_delta="0" +     layout="topleft" +     name="chat_history_lp" +     width="318"> +      <chat_history +       bg_readonly_color="ChatHistoryBgColor" +       bg_writeable_color="ChatHistoryBgColor" +       follows="all" +       layout="topleft" +       left="5" +       left_widget_pad="0" +       height="272" +       name="chat_history" +       parse_highlights="true" +       parse_urls="true" +       right_widget_pad="5" +       text_color="ChatHistoryTextColor" +       text_readonly_color="ChatHistoryTextColor" +       top="0" +       width="313" /> +    </layout_panel> +  </layout_stack>  </panel> diff --git a/indra/newview/skins/default/xui/en/panel_notification.xml b/indra/newview/skins/default/xui/en/panel_notification.xml index f6f62ac54e..94c468e1bb 100644 --- a/indra/newview/skins/default/xui/en/panel_notification.xml +++ b/indra/newview/skins/default/xui/en/panel_notification.xml @@ -3,8 +3,8 @@    background_opaque="false"        border_visible="false"    background_visible="true" -  bg_alpha_color="1 0.3 0.3 0" -  bg_opaque_color="1 0.3 0.3 0" +  bg_alpha_color="PanelNotificationBackground" +  bg_opaque_color="PanelNotificationBackground"    label="notification_panel"    layout="topleft"    left="0" @@ -20,8 +20,8 @@        border_visible="false"   bevel_style="none"      background_visible="true" -  bg_alpha_color="0.3 0.3 0.3 0" -  bg_opaque_color="0.3 0.3 0.3 0" +  bg_alpha_color="ToastBackground" +  bg_opaque_color="ToastBackground"      follows="left|right|top"      height="100"      label="info_panel" @@ -39,7 +39,7 @@        left="10"        name="text_box"        read_only="true" -      text_color="white" +      text_color="White"        top="10"        visible="false"         width="285" @@ -52,7 +52,7 @@        layout="topleft"        left="10"        name="caution_text_box" -      text_color="1 0.82 0.46 1" +      text_color="NotifyCautionBoxColor"        top="10"        visible="false"        width="285" @@ -60,7 +60,7 @@      <text_editor      	h_pad="0"  	v_pad="0" -      bg_readonly_color="0.0 0.0 0.0 0" +      bg_readonly_color="Transparent"        border_visible="false"        embedded_items="false"        enabled="false" @@ -73,8 +73,8 @@        name="text_editor_box"        read_only="true"        tab_stop="false" -      text_color="white" -      text_readonly_color="white" +      text_color="White" +      text_readonly_color="White"        top="10"        visible="false"        width="285" diff --git a/indra/newview/skins/default/xui/en/panel_online_status_toast.xml b/indra/newview/skins/default/xui/en/panel_online_status_toast.xml index b1a7697e83..dadbd9c9ab 100644 --- a/indra/newview/skins/default/xui/en/panel_online_status_toast.xml +++ b/indra/newview/skins/default/xui/en/panel_online_status_toast.xml @@ -25,7 +25,7 @@       layout="topleft"       left_pad="5"       name="message" -     text_color="white" +     text_color="White"       top="15"       use_ellipses="true"       value="" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml index 9827180aa7..24882988b0 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml @@ -331,7 +331,7 @@     </text>     <radio_group       control_name="LetterKeysFocusChatBar"  -     height="20" +     height="34"       layout="topleft"       left="35"       top_pad="0"  @@ -339,7 +339,7 @@          <radio_item           label="Starts local chat"           name="radio_start_chat" -         top_delta="20"  +         top="0"            layout="topleft"           height="16"            left="0"  @@ -364,7 +364,7 @@       layout="topleft"       left="30"       name="title_afk_text" -     top_pad="15"  +     top_pad="5"        width="190">      	Away timeout:      </text> diff --git a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml index 1f92244eb9..b71586aab1 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_sound.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml @@ -63,7 +63,7 @@        layout="topleft"        left_pad="0"        name="mute_chb_label" -      top_delta="0" +      top_delta="-1"        width="150"        wrap="true">        Mute when minimized diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml index d453a970e7..22c1139cdb 100644 --- a/indra/newview/skins/default/xui/en/panel_status_bar.xml +++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml @@ -67,7 +67,6 @@       label_shadow="true"       name="buyL"       pad_right="0" -     pad_bottom="2"       tool_tip="Click to buy more L$"       top="0"       width="80" /> @@ -87,7 +86,6 @@       left_pad="0"       label_shadow="true"       name="goShop" -     pad_bottom="2"       tool_tip="Open Second Life Marketplace"       top="0"       width="65" /> diff --git a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml index 5e74689c5a..007b73a4bc 100644 --- a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml +++ b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml @@ -13,7 +13,7 @@    follows="left|right"    background_opaque="false"    background_visible="true" -  bg_alpha_color="0.0 0.0 0.0 0.0" > +  bg_alpha_color="SysWellItemUnselected" >    <text      clip_partial="true"       top="2" @@ -22,7 +22,7 @@      height="28"      layout="topleft"      follows="right|left" -    text_color="white" +    text_color="White"      use_ellipses="true"      word_wrap="true"      mouse_opaque="false" diff --git a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml index c89e1dc215..c5b0be0616 100644 --- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml +++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml @@ -44,7 +44,7 @@       parse_urls="false"       use_ellipses="true"       name="region" -     text_color="white" +     text_color="White"       top="4"       value="..."       width="330" /> diff --git a/indra/newview/skins/default/xui/en/panel_toast.xml b/indra/newview/skins/default/xui/en/panel_toast.xml index 062c403a26..0b5aff54ca 100644 --- a/indra/newview/skins/default/xui/en/panel_toast.xml +++ b/indra/newview/skins/default/xui/en/panel_toast.xml @@ -59,7 +59,7 @@     left="20"     name="toast_text"     word_wrap="true" -   text_color="white" +   text_color="White"     top="5"     translate="false"     use_ellipses="true" diff --git a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml index 29aa6d1039..ee790e8dd4 100644 --- a/indra/newview/skins/default/xui/en/sidepanel_inventory.xml +++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml @@ -48,7 +48,7 @@                        height="300"                        width="330" />               </layout_panel> -			 <layout_panel +			    <layout_panel                   width="330"                   layout="topleft"                   auto_resize="true" @@ -73,6 +73,7 @@                       <string name="InboxLabelWithArg">Received items ([NUM])</string>                       <string name="InboxLabelNoArg">Received items</string>                       <button +                        control_name="InventoryInboxToggleState"                          label="Received items"  						font="SansSerifMedium"                          name="inbox_btn" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index d6b5f3559f..749f0e9ad9 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -369,6 +369,9 @@ Please try logging in again in a minute.</string>  	<string name="anim_yes_happy">Yes (Happy)</string>  	<string name="anim_yes_head">Yes</string> +	<!-- build floater --> +	<string name="multiple_textures">Multiple</string> +  	<!-- world map -->  	<string name="texture_loading">Loading...</string>  	<string name="worldmap_offline">Offline</string> @@ -3238,6 +3241,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].  	<string name="IM_to_label">To</string>  	<string name="IM_moderator_label">(Moderator)</string>  	<string name="Saved_message">(Saved [LONG_TIMESTAMP])</string> +	<string name="IM_unblock_only_groups_friends">To see this message, you must uncheck 'Only friends and groups can call or IM me' in Preferences/Privacy.</string>  	<!-- voice calls -->  	<string name="answered_call">Your call has been answered</string> diff --git a/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml b/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml index 1bb3188cc8..8a4ccb19f9 100644 --- a/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/avatar_list_item.xml @@ -17,13 +17,13 @@    <voice_call_invited_style     font="SansSerifSmall"     font.style="NORMAL" -   color="0.5 0.5 0.5 0.5"/> +   color="AvatarListItemIconVoiceInvitedColor"/>    <!-- styles for avatar item JOINED to voice call -->    <voice_call_joined_style     font="SansSerifSmall"     font.style="NORMAL" -   color="white"/> +   color="White"/>    <!-- styles for avatar item which HAS LEFT voice call -->    <voice_call_left_style @@ -35,11 +35,11 @@    <online_style     font="SansSerifSmall"     font.style="NORMAL" -   color="white"/> +   color="White"/>    <!-- styles for OFFLINE avatar item -->    <offline_style     font="SansSerifSmall"     font.style="NORMAL" -   color="0.5 0.5 0.5 1.0"/> +   color="Gray"/>  </avatar_list_item> diff --git a/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml b/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml index 0eec002006..0016a8cf53 100644 --- a/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/bodyparts_list_item.xml @@ -24,7 +24,7 @@     parse_urls="false"     use_ellipses="true"     name="item_name" -   text_color="white" +   text_color="White"     top="5"     value="..."     width="359" /> diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml index e2baba92a3..2b2c3faf91 100644 --- a/indra/newview/skins/default/xui/en/widgets/button.xml +++ b/indra/newview/skins/default/xui/en/widgets/button.xml @@ -21,7 +21,7 @@          font="SansSerifSmall"          hover_glow_amount="0.15"          halign="center" -        pad_bottom="3"  +        pad_bottom="1"          height="23"          scale_image="true"          handle_right_mouse="true" diff --git a/indra/newview/skins/default/xui/en/widgets/check_box.xml b/indra/newview/skins/default/xui/en/widgets/check_box.xml index cca64fad2a..8947024e45 100644 --- a/indra/newview/skins/default/xui/en/widgets/check_box.xml +++ b/indra/newview/skins/default/xui/en/widgets/check_box.xml @@ -10,7 +10,7 @@                          text_readonly_color="LabelDisabledColor"/>    <check_box.check_button name="CheckboxCtrl Button"                            left="2" -                          bottom="2" +                          bottom="1"                            width="13"                            height="13"                             commit_on_return="false" diff --git a/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml b/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml index 96d72c78a6..d83f44737e 100644 --- a/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/clothing_list_item.xml @@ -24,7 +24,7 @@     parse_urls="false"     use_ellipses="true"     name="item_name" -   text_color="white" +   text_color="White"     top="5"     value="..."     width="359" /> diff --git a/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml b/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml index 6c60624805..8c805da048 100644 --- a/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml +++ b/indra/newview/skins/default/xui/en/widgets/dummy_clothing_list_item.xml @@ -9,7 +9,7 @@   width="380">    <item_icon      height="16" -    color="0.75 0.75 0.75 1" +    color="LtGray"      follows="top|left"      image_name="Inv_Object"      layout="topleft" diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml index 3e2202b20f..0586119681 100644 --- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml +++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml @@ -11,7 +11,7 @@ label_pad_left - padding to the left of tab button labels                 halign="center"                 font="SansSerifSmall"                  tab_height="21" -               label_pad_bottom="2" +               label_pad_bottom="1"                 label_pad_left="4">    <!--    Possible additional attributes for tabs: diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp index 4c0959d1a9..e7ef017760 100644 --- a/indra/newview/tests/llworldmipmap_test.cpp +++ b/indra/newview/tests/llworldmipmap_test.cpp @@ -100,9 +100,9 @@ namespace tut  	{  		S32 level = mMap->scaleToLevel(0.0);  		ensure("scaleToLevel() test 1 failed", level == LLWorldMipmap::MAP_LEVELS); -		level = mMap->scaleToLevel(LLWorldMipmap::MAP_TILE_SIZE); +		level = mMap->scaleToLevel((F32)LLWorldMipmap::MAP_TILE_SIZE);  		ensure("scaleToLevel() test 2 failed", level == 1); -		level = mMap->scaleToLevel(10 * LLWorldMipmap::MAP_TILE_SIZE); +		level = mMap->scaleToLevel(10.f * LLWorldMipmap::MAP_TILE_SIZE);  		ensure("scaleToLevel() test 3 failed", level == 1);  	}  	// Test 2 : globalToMipmap() diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py index 0931c4ec9b..9bf755c8f8 100644 --- a/indra/newview/viewer_manifest.py +++ b/indra/newview/viewer_manifest.py @@ -1047,9 +1047,13 @@ class Linux_i686Manifest(LinuxManifest):              self.path("libuuid.so.16")              self.path("libuuid.so.16.0.22")              self.path("libSDL-1.2.so.0.11.3") +            self.path("libSDL-1.2.so.0")              self.path("libdirectfb-1.4.so.5.0.4") +            self.path("libdirectfb-1.4.so.5")              self.path("libfusion-1.4.so.5.0.4") +            self.path("libfusion-1.4.so.5")              self.path("libdirect-1.4.so.5.0.4") +            self.path("libdirect-1.4.so.5")              self.path("libopenjpeg.so.1.4.0")              self.path("libopenjpeg.so.1")              self.path("libopenjpeg.so") diff --git a/indra/test/test.cpp b/indra/test/test.cpp index ffdb0cb976..e58e7293fb 100644 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -37,6 +37,7 @@  #include "linden_common.h"  #include "llerrorcontrol.h"  #include "lltut.h" +#include "stringize.h"  #include "apr_pools.h"  #include "apr_getopt.h" @@ -53,6 +54,22 @@  #include <gtest/gtest.h>  #endif +#if LL_MSVC +#pragma warning (push) +#pragma warning (disable : 4702) // warning C4702: unreachable code +#endif +#include <boost/iostreams/tee.hpp> +#include <boost/iostreams/stream.hpp> +#if LL_MSVC +#pragma warning (pop) +#endif + +#include <boost/scoped_ptr.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/make_shared.hpp> +#include <boost/foreach.hpp> +#include <boost/lambda/lambda.hpp> +  namespace tut  {  	std::string sSourceDir; @@ -69,8 +86,24 @@ public:  	mPassedTests(0),  	mFailedTests(0),  	mSkippedTests(0), -	mStream(stream) +	// By default, capture a shared_ptr to std::cout, with a no-op "deleter" +	// so that destroying the shared_ptr makes no attempt to delete std::cout. +	mStream(boost::shared_ptr<std::ostream>(&std::cout, boost::lambda::_1))  	{ +		if (stream) +		{ +			// We want a boost::iostreams::tee_device that will stream to two +			// std::ostreams. +			typedef boost::iostreams::tee_device<std::ostream, std::ostream> TeeDevice; +			// More than that, though, we want an actual stream using that +			// device. +			typedef boost::iostreams::stream<TeeDevice> TeeStream; +			// Allocate and assign in two separate steps, per Herb Sutter. +			// (Until we turn on C++11 support, have to wrap *stream with +			// boost::ref() due to lack of perfect forwarding.) +			boost::shared_ptr<std::ostream> pstream(new TeeStream(std::cout, boost::ref(*stream))); +			mStream = pstream; +		}  	}  	~LLTestCallback() @@ -83,18 +116,21 @@ public:  	}  	virtual void group_started(const std::string& name) { -		std::cout << "Unit test group_started name=" << name << std::endl; +		*mStream << "Unit test group_started name=" << name << std::endl;  	}  	virtual void group_completed(const std::string& name) { -		std::cout << "Unit test group_completed name=" << name << std::endl; +		*mStream << "Unit test group_completed name=" << name << std::endl;  	}  	virtual void test_completed(const tut::test_result& tr)  	{  		++mTotalTests;  		std::ostringstream out; -		out << "[" << tr.group << ", " << tr.test << "] "; +		out << "[" << tr.group << ", " << tr.test; +		if (! tr.name.empty()) +			out << ": " << tr.name; +		out << "] ";  		switch(tr.result)  		{  			case tut::test_result::ok: @@ -123,56 +159,43 @@ public:  				break;  			default:  				++mFailedTests; -				out << "unknown"; +				out << "unknown (tr.result == " << tr.result << ")";  		}  		if(mVerboseMode || (tr.result != tut::test_result::ok))  		{ +			*mStream << out.str();  			if(!tr.message.empty())  			{ -				out << ": '" << tr.message << "'"; -			} -			if (mStream) -			{ -				*mStream << out.str() << std::endl; +				*mStream << ": '" << tr.message << "'";  			} -			 -			std::cout << out.str() << std::endl; -		} -	} - -	virtual void run_completed() -	{ -		if (mStream) -		{ -			run_completed_(*mStream); +			*mStream << std::endl;  		} -		run_completed_(std::cout);  	}  	virtual int getFailedTests() const { return mFailedTests; } -	virtual void run_completed_(std::ostream &stream) +	virtual void run_completed()  	{ -		stream << "\tTotal Tests:\t" << mTotalTests << std::endl; -		stream << "\tPassed Tests:\t" << mPassedTests; +		*mStream << "\tTotal Tests:\t" << mTotalTests << std::endl; +		*mStream << "\tPassed Tests:\t" << mPassedTests;  		if (mPassedTests == mTotalTests)  		{ -			stream << "\tYAY!! \\o/"; +			*mStream << "\tYAY!! \\o/";  		} -		stream << std::endl; +		*mStream << std::endl;  		if (mSkippedTests > 0)  		{ -			stream << "\tSkipped known failures:\t" << mSkippedTests +			*mStream << "\tSkipped known failures:\t" << mSkippedTests  			<< std::endl;  		}  		if(mFailedTests > 0)  		{ -			stream << "*********************************" << std::endl; -			stream << "Failed Tests:\t" << mFailedTests << std::endl; -			stream << "Please report or fix the problem." << std::endl; -			stream << "*********************************" << std::endl; +			*mStream << "*********************************" << std::endl; +			*mStream << "Failed Tests:\t" << mFailedTests << std::endl; +			*mStream << "Please report or fix the problem." << std::endl; +			*mStream << "*********************************" << std::endl;  		}  	} @@ -182,7 +205,7 @@ protected:  	int mPassedTests;  	int mFailedTests;  	int mSkippedTests; -	std::ostream *mStream; +	boost::shared_ptr<std::ostream> mStream;  };  // TeamCity specific class which emits service messages @@ -192,84 +215,111 @@ class LLTCTestCallback : public LLTestCallback  {  public:  	LLTCTestCallback(bool verbose_mode, std::ostream *stream) : -		LLTestCallback(verbose_mode, stream), -		mTCStream() +		LLTestCallback(verbose_mode, stream)  	{  	}  	~LLTCTestCallback()  	{ -	}	 +	}  	virtual void group_started(const std::string& name) {  		LLTestCallback::group_started(name); -		mTCStream << "\n##teamcity[testSuiteStarted name='" << name << "']" << std::endl; +		std::cout << "\n##teamcity[testSuiteStarted name='" << escape(name) << "']" << std::endl;  	}  	virtual void group_completed(const std::string& name) {  		LLTestCallback::group_completed(name); -		mTCStream << "##teamcity[testSuiteFinished name='" << name << "']" << std::endl; +		std::cout << "##teamcity[testSuiteFinished name='" << escape(name) << "']" << std::endl;  	}  	virtual void test_completed(const tut::test_result& tr)  	{ +		std::string testname(STRINGIZE(tr.group << "." << tr.test)); +		if (! tr.name.empty()) +		{ +			testname.append(":"); +			testname.append(tr.name); +		} +		testname = escape(testname); + +		// Sadly, tut::callback doesn't give us control at test start; have to +		// backfill start message into TC output. +		std::cout << "##teamcity[testStarted name='" << testname << "']" << std::endl; + +		// now forward call to base class so any output produced there is in +		// the right TC context  		LLTestCallback::test_completed(tr);  		switch(tr.result)  		{  			case tut::test_result::ok: -				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; -				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl;  				break; +  			case tut::test_result::fail: -				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; -				mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl; -				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; -				break;  			case tut::test_result::ex: -				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; -				mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl; -				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; -				break;  			case tut::test_result::warn: -				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; -				mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl; -				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; -				break;  			case tut::test_result::term: -				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; -				mTCStream << "##teamcity[testFailed name='" << tr.group << "." << tr.test << "' message='" << tr.message << "']" << std::endl; -				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; +				std::cout << "##teamcity[testFailed name='" << testname +						  << "' message='" << escape(tr.message) << "']" << std::endl;  				break; +  			case tut::test_result::skip: -				mTCStream << "##teamcity[testStarted name='" << tr.group << "." << tr.test << "']" << std::endl; -				mTCStream << "##teamcity[testIgnored name='" << tr.group << "." << tr.test << "']" << std::endl; -				mTCStream << "##teamcity[testFinished name='" << tr.group << "." << tr.test << "']" << std::endl; +				std::cout << "##teamcity[testIgnored name='" << testname << "']" << std::endl;  				break; +  			default:  				break;  		} +		std::cout << "##teamcity[testFinished name='" << testname << "']" << std::endl;  	} -	virtual void run_completed() +	static std::string escape(const std::string& str)  	{ -		LLTestCallback::run_completed(); - -		// dump the TC reporting results to cout -		tc_run_completed_(std::cout); -	} - -	virtual void tc_run_completed_(std::ostream &stream) -	{ -		 -		// dump the TC reporting results to cout -		stream << mTCStream.str() << std::endl; +		// Per http://confluence.jetbrains.net/display/TCD65/Build+Script+Interaction+with+TeamCity#BuildScriptInteractionwithTeamCity-ServiceMessages +		std::string result; +		BOOST_FOREACH(char c, str) +		{ +			switch (c) +			{ +			case '\'': +				result.append("|'"); +				break; +			case '\n': +				result.append("|n"); +				break; +			case '\r': +				result.append("|r"); +				break; +/*==========================================================================*| +			// These are not possible 'char' values from a std::string. +			case '\u0085':			// next line +				result.append("|x"); +				break; +			case '\u2028':			// line separator +				result.append("|l"); +				break; +			case '\u2029':			// paragraph separator +				result.append("|p"); +				break; +|*==========================================================================*/ +			case '|': +				result.append("||"); +				break; +			case '[': +				result.append("|["); +				break; +			case ']': +				result.append("|]"); +				break; +			default: +				result.push_back(c); +				break; +			} +		} +		return result;  	} -	 -protected: -	std::ostringstream mTCStream; -  }; @@ -359,7 +409,7 @@ int main(int argc, char **argv)  	apr_getopt_t* os = NULL;  	if(APR_SUCCESS != apr_getopt_init(&os, pool, argc, argv))  	{ -		std::cerr << "Unable to  pool" << std::endl; +		std::cerr << "apr_getopt_init() failed" << std::endl;  		return 1;  	} @@ -373,7 +423,7 @@ int main(int argc, char **argv)  	apr_status_t apr_err;  	const char* opt_arg = NULL;  	int opt_id = 0; -	std::ofstream *output = NULL; +	boost::scoped_ptr<std::ofstream> output;  	const char *touch = NULL;  	while(true) @@ -403,7 +453,7 @@ int main(int argc, char **argv)  				verbose_mode = true;  				break;  			case 'o': -				output = new std::ofstream; +				output.reset(new std::ofstream);  				output->open(opt_arg);  				break;  			case 's':	// --sourcedir @@ -437,11 +487,11 @@ int main(int argc, char **argv)  	LLTestCallback* mycallback;  	if (getenv("TEAMCITY_PROJECT_NAME"))  	{ -		mycallback = new LLTCTestCallback(verbose_mode, output);		 +		mycallback = new LLTCTestCallback(verbose_mode, output.get());		  	}  	else  	{ -		mycallback = new LLTestCallback(verbose_mode, output); +		mycallback = new LLTestCallback(verbose_mode, output.get());  	}  	tut::runner.get().set_callback(mycallback); @@ -463,12 +513,6 @@ int main(int argc, char **argv)  		std::cin.get();  	} -	if (output) -	{ -		output->close(); -		delete output; -	} -  	if (touch && success)  	{  		std::ofstream s; diff --git a/indra/viewer_components/updater/llupdaterservice.cpp b/indra/viewer_components/updater/llupdaterservice.cpp index 1888f191e2..2e18218667 100644 --- a/indra/viewer_components/updater/llupdaterservice.cpp +++ b/indra/viewer_components/updater/llupdaterservice.cpp @@ -447,7 +447,7 @@ void LLUpdaterServiceImpl::restartTimer(unsigned int seconds)  	LL_INFOS("UpdaterService") << "will check for update again in " <<   	seconds << " seconds" << LL_ENDL;   	mTimer.start(); -	mTimer.setTimerExpirySec(seconds); +	mTimer.setTimerExpirySec((F32)seconds);  	LLEventPumps::instance().obtain("mainloop").listen(  		sListenerName, boost::bind(&LLUpdaterServiceImpl::onMainLoop, this, _1));  }  | 
