diff options
189 files changed, 4941 insertions, 3460 deletions
diff --git a/autobuild.xml b/autobuild.xml index 80a44ec75d..f6f23f6c1c 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -138,9 +138,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>e6caaeea16131e1f2343ecd7765e3147</string> +              <string>4dd93da518dc00319cadac43dce2676b</string>                <key>url</key> -              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/ares-1.7.1-darwin-20110217.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-ares/rev/239515/arch/Darwin/installer/ares-1.7.5-darwin-20110825.tar.bz2</string>              </map>              <key>name</key>              <string>darwin</string> @@ -150,9 +150,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>0745872db83d45f4ab3bdc697d98e264</string> +              <string>c223c0df8ebdab02a5bd785c21459875</string>                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-ares/rev/223275/arch/Linux/installer/ares-1.7.1-linux-20110310.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-ares/rev/239515/arch/Linux/installer/ares-1.7.5-linux-20110825.tar.bz2</string>              </map>              <key>name</key>              <string>linux</string> @@ -162,9 +162,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>1dcec6babd249a2597114d4ac226c461</string> +              <string>a0a002359e44a9c68f897b45217abf7e</string>                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-ares/rev/220963/arch/CYGWIN/installer/ares-1.7.1-windows-20110211.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-ares/rev/239515/arch/CYGWIN/installer/ares-1.7.5-windows-20110825.tar.bz2</string>              </map>              <key>name</key>              <string>windows</string> @@ -282,9 +282,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>aaea644191807f51051cefa2fac11069</string> +              <string>6f6b4fc6268e7935e82e694ed3f5912a</string>                <key>url</key> -              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/curl-7.21.1-darwin-20110316.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-curl/rev/249347/arch/Darwin/installer/curl-7.24.0-darwin-20120213.tar.bz2</string>              </map>              <key>name</key>              <string>darwin</string> @@ -294,9 +294,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>2d9377951d99a1aa4735cea8d4b5aa71</string> +              <string>384e6d46f2f4228117cda7eea396df06</string>                <key>url</key> -              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/curl-7.21.1-linux-20110316.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-curl/rev/263749/arch/Linux/installer/curl-7.24.0-linux-20120820.tar.bz2</string>              </map>              <key>name</key>              <string>linux</string> @@ -306,9 +306,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>fea96aa2a7d513397317194f3d6c979b</string> +              <string>56c72a3b4d6faab81a4d66a630a67c83</string>                <key>url</key> -              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/curl-7.21.1-windows-20110211.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-curl/rev/249347/arch/CYGWIN/installer/curl-7.24.0-windows-20120213.tar.bz2</string>              </map>              <key>name</key>              <string>windows</string> @@ -606,9 +606,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>ca95bbdabd2bed612af79a3704fdbe79</string> +              <string>bd6f84f9fb3c2e68850676d06935373f</string>                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-freetype/rev/265843/arch/Linux/installer/freetype-2.3.9-linux-20121013.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-freetype/rev/271684/arch/Linux/installer/freetype-2.4.4-linux-20130312.tar.bz2</string>              </map>              <key>name</key>              <string>linux</string> @@ -1612,9 +1612,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>facee34b8bd57ad602157e65a5af1a49</string> +              <string>38ea083fe1204ee106b4d44d9811af19</string>                <key>url</key> -              <string>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/openssl-0.9.8q-darwin-20110211.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-openssl/rev/249044/arch/Darwin/installer/openssl-1.0.0g-darwin-20120207.tar.bz2</string>              </map>              <key>name</key>              <string>darwin</string> @@ -1624,9 +1624,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>3d40be8566fa4b9df9a38e2a0f9ea467</string> +	      <string>7dc5191a3d95074a6ed3bd53f57420e5</string>                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-openssl/rev/226882/arch/Linux/installer/openssl-1.0.0d-linux-20110418.tar.bz2</string> +		   <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-openssl/rev/249044/arch/Linux/installer/openssl-1.0.0g-linux-20120207.tar.bz2</string>              </map>              <key>name</key>              <string>linux</string> @@ -1636,9 +1636,9 @@              <key>archive</key>              <map>                <key>hash</key> -              <string>774c7f0a0312bee3054757a623e227bc</string> +              <string>ed6cbaf9860a03bc99ac301277f1452a</string>                <key>url</key> -              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-openssl/rev/220986/arch/CYGWIN/installer/openssl-0.9.8q-windows-20110211.tar.bz2</string> +              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/3p-openssl/rev/249044/arch/CYGWIN/installer/openssl-1.0.0g-windows-20120207.tar.bz2</string>              </map>              <key>name</key>              <string>windows</string> diff --git a/doc/contributions.txt b/doc/contributions.txt index 5f1445dfc5..3abf32b8b1 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -900,6 +900,9 @@ NickyD  Nicky Dasmijn  	VWR-29228  	MAINT-873 +	STORM-1935 +	STORM-1936 +	STORM-1937  Nicky Perian  	OPEN-1  	STORM-1087 diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index fb5c759493..a820cd39d0 100644 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -131,6 +131,17 @@ if (LINUX)    # Let's actually get a numerical version of gxx's version    STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION_NUMBER ${CXX_VERSION}) +  # Hacks to work around gcc 4.1 TC build pool machines which can't process pragma warning disables +  # This is pure rubbish; I wish there was another way. +  # +  if(${CXX_VERSION_NUMBER} LESS 420) +    set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-uninitialized -Wno-unused-variable -Wno-unused-function ${CMAKE_CXX_FLAGS}") +  endif (${CXX_VERSION_NUMBER} LESS 420) + +  if(${CXX_VERSION_NUMBER} GREATER 459) +    set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-unused-but-set-variable -Wno-unused-variable ${CMAKE_CXX_FLAGS}") +  endif (${CXX_VERSION_NUMBER} GREATER 459) +    # gcc 4.3 and above don't like the LL boost and also    # cause warnings due to our use of deprecated headers    if(${CXX_VERSION_NUMBER} GREATER 429) @@ -201,7 +212,7 @@ if (LINUX OR DARWIN)    set(GCC_WARNINGS "-Wall -Wno-sign-compare -Wno-trigraphs")    if (NOT GCC_DISABLE_FATAL_WARNINGS) -    set(GCC_WARNINGS "${GCC_WARNINGS} -Werror") +#    set(GCC_WARNINGS "${GCC_WARNINGS} -Werror")    endif (NOT GCC_DISABLE_FATAL_WARNINGS)    set(GCC_CXX_WARNINGS "${GCC_WARNINGS} -Wno-reorder -Wno-non-virtual-dtor") diff --git a/indra/cmake/Copy3rdPartyLibs.cmake b/indra/cmake/Copy3rdPartyLibs.cmake index 338da4743e..b83aec4e69 100644 --- a/indra/cmake/Copy3rdPartyLibs.cmake +++ b/indra/cmake/Copy3rdPartyLibs.cmake @@ -266,6 +266,7 @@ elseif(LINUX)          libdb-5.1.so          libexpat.so          libexpat.so.1 +        libfreetype.so.6          libGLOD.so          libgmock_main.so          libgmock.so.0 diff --git a/indra/cmake/FreeType.cmake b/indra/cmake/FreeType.cmake index 43a9d282d0..c9a90a9a8d 100644 --- a/indra/cmake/FreeType.cmake +++ b/indra/cmake/FreeType.cmake @@ -7,13 +7,7 @@ if (STANDALONE)    pkg_check_modules(FREETYPE REQUIRED freetype2)  else (STANDALONE)    use_prebuilt_binary(freetype) -  if (LINUX) -    set(FREETYPE_INCLUDE_DIRS -        ${LIBS_PREBUILT_DIR}/include) -  else (LINUX) -    set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include) -  endif (LINUX) - +  set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)    set(FREETYPE_LIBRARIES freetype)  endif (STANDALONE) diff --git a/indra/linux_crash_logger/CMakeLists.txt b/indra/linux_crash_logger/CMakeLists.txt index e0d0c9fc69..9e8c9a1ac6 100644 --- a/indra/linux_crash_logger/CMakeLists.txt +++ b/indra/linux_crash_logger/CMakeLists.txt @@ -12,6 +12,7 @@ include(LLVFS)  include(LLXML)  include(Linking)  include(UI) +include(FreeType)  include_directories(      ${LLCOMMON_INCLUDE_DIRS} @@ -57,6 +58,7 @@ target_link_libraries(linux-crash-logger      ${LLCOMMON_LIBRARIES}      ${UI_LIBRARIES}      ${DB_LIBRARIES} +    ${FREETYPE_LIBRARIES}      )  add_custom_target(linux-crash-logger-target ALL diff --git a/indra/llcharacter/lleditingmotion.cpp b/indra/llcharacter/lleditingmotion.cpp index 0d0b85ba60..4e8c3268c5 100644 --- a/indra/llcharacter/lleditingmotion.cpp +++ b/indra/llcharacter/lleditingmotion.cpp @@ -258,3 +258,4 @@ void LLEditingMotion::onDeactivate()  // End + diff --git a/indra/llcharacter/llheadrotmotion.cpp b/indra/llcharacter/llheadrotmotion.cpp index 15a58a8389..2b1aa194a9 100644 --- a/indra/llcharacter/llheadrotmotion.cpp +++ b/indra/llcharacter/llheadrotmotion.cpp @@ -530,3 +530,4 @@ void LLEyeMotion::onDeactivate()  }  // End + diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index c6f45bffa2..07ef52228e 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -672,7 +672,8 @@ BOOL LLKeyframeMotion::onActivate()  //-----------------------------------------------------------------------------  BOOL LLKeyframeMotion::onUpdate(F32 time, U8* joint_mask)  { -	llassert(time >= 0.f); +	// llassert(time >= 0.f);		// This will fire +	time = llmax(0.f, time);  	if (mJointMotionList->mLoop)  	{ @@ -2304,3 +2305,4 @@ LLKeyframeMotion::JointConstraint::~JointConstraint()  }  // End + diff --git a/indra/llcharacter/llkeyframewalkmotion.cpp b/indra/llcharacter/llkeyframewalkmotion.cpp index d52eb89a5c..69f064b615 100644 --- a/indra/llcharacter/llkeyframewalkmotion.cpp +++ b/indra/llcharacter/llkeyframewalkmotion.cpp @@ -390,3 +390,4 @@ BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask)  	return TRUE;  } + diff --git a/indra/llcharacter/llmotion.cpp b/indra/llcharacter/llmotion.cpp index 2551f125d0..a07f9f4d2e 100644 --- a/indra/llcharacter/llmotion.cpp +++ b/indra/llcharacter/llmotion.cpp @@ -169,3 +169,4 @@ BOOL LLMotion::canDeprecate()  }  // End + diff --git a/indra/llcharacter/lltargetingmotion.cpp b/indra/llcharacter/lltargetingmotion.cpp index 489aef923c..fa5f06328e 100644 --- a/indra/llcharacter/lltargetingmotion.cpp +++ b/indra/llcharacter/lltargetingmotion.cpp @@ -169,3 +169,4 @@ void LLTargetingMotion::onDeactivate()  // End + diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 5cce8ff2c4..0c2ceebb52 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -121,6 +121,7 @@ set(llcommon_HEADER_FILES      linden_common.h      linked_lists.h      llaccountingcost.h +    llalignedarray.h      llallocator.h      llallocator_heap_profile.h      llagentconstants.h @@ -236,6 +237,7 @@ set(llcommon_HEADER_FILES      llstrider.h      llstring.h      llstringtable.h +    llstaticstringtable.h      llsys.h      llthread.h      llthreadsafequeue.h diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h new file mode 100644 index 0000000000..ed8fd31205 --- /dev/null +++ b/indra/llcommon/llalignedarray.h @@ -0,0 +1,139 @@ +/**  + * @file llalignedarray.h + * @brief A static array which obeys alignment restrictions and mimics std::vector accessors. + * + * $LicenseInfo:firstyear=2002&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2010, Linden Research, Inc. + *  + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + *  + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU + * Lesser General Public License for more details. + *  + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA + *  + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA + * $/LicenseInfo$ + */ + +#ifndef LL_LLALIGNEDARRAY_H +#define LL_LLALIGNEDARRAY_H + +#include "llmemory.h" + +template <class T, U32 alignment> +class LLAlignedArray +{ +public: +	T* mArray; +	U32 mElementCount; +	U32 mCapacity; + +	LLAlignedArray(); +	~LLAlignedArray(); + +	void push_back(const T& elem); +	U32 size() const { return mElementCount; } +	void resize(U32 size); +	T* append(S32 N); +	T& operator[](int idx); +	const T& operator[](int idx) const; +}; + +template <class T, U32 alignment> +LLAlignedArray<T, alignment>::LLAlignedArray() +{ +	llassert(alignment >= 16); +	mArray = NULL; +	mElementCount = 0; +	mCapacity = 0; +} + +template <class T, U32 alignment> +LLAlignedArray<T, alignment>::~LLAlignedArray() +{ +	ll_aligned_free(mArray); +	mArray = NULL; +	mElementCount = 0; +	mCapacity = 0; +} + +template <class T, U32 alignment> +void LLAlignedArray<T, alignment>::push_back(const T& elem) +{ +	T* old_buf = NULL; +	if (mCapacity <= mElementCount) +	{ +		mCapacity++; +		mCapacity *= 2; +		T* new_buf = (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment); +		if (mArray) +		{ +			ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount); +		} +		old_buf = mArray; +		mArray = new_buf; +	} + +	mArray[mElementCount++] = elem; + +	//delete old array here to prevent error on a.push_back(a[0]) +	ll_aligned_free(old_buf); +} + +template <class T, U32 alignment> +void LLAlignedArray<T, alignment>::resize(U32 size) +{ +	if (mCapacity < size) +	{ +		mCapacity = size+mCapacity*2; +		T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment) : NULL; +		if (mArray) +		{ +			ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount); +			ll_aligned_free(mArray); +		} + +		/*for (U32 i = mElementCount; i < mCapacity; ++i) +		{ +			new(new_buf+i) T(); +		}*/ +		mArray = new_buf; +	} + +	mElementCount = size; +} + + +template <class T, U32 alignment> +T& LLAlignedArray<T, alignment>::operator[](int idx) +{ +	llassert(idx < mElementCount); +	return mArray[idx]; +} + +template <class T, U32 alignment> +const T& LLAlignedArray<T, alignment>::operator[](int idx) const +{ +	llassert(idx < mElementCount); +	return mArray[idx]; +} + +template <class T, U32 alignment> +T* LLAlignedArray<T, alignment>::append(S32 N) +{ +	U32 sz = size(); +	resize(sz+N); +	return &((*this)[sz]); +} + +#endif + diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index a536a06ea5..afa06df23e 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -38,7 +38,7 @@ typedef LLAtomic32<U32> LLAtomicU32;  class LLErrorThread;  class LLLiveFile;  #if LL_LINUX -typedef struct siginfo siginfo_t; +#include <signal.h>  #endif  typedef void (*LLAppErrorHandler)(); diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 034546c3f3..8042fe2502 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -164,14 +164,20 @@ public:  	~LLAtomic32<Type>() {};  	operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); } +	 +	Type	CurrentValue() const { apr_uint32_t data = apr_atomic_read32(const_cast< volatile apr_uint32_t* >(&mData)); return Type(data); } +  	Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }  	void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }  	void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }  	Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++  	Type operator --(int) { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise) + +	Type operator ++() { return apr_atomic_inc32(&mData); } // Type++ +	Type operator --() { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)  private: -	apr_uint32_t mData; +	volatile apr_uint32_t mData;  };  typedef LLAtomic32<U32> LLAtomicU32; diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp index 87d79b1ee0..49aac9ce75 100644 --- a/indra/llcommon/llcriticaldamp.cpp +++ b/indra/llcommon/llcriticaldamp.cpp @@ -87,3 +87,4 @@ F32 LLCriticalDamp::getInterpolant(const F32 time_constant, BOOL use_cache)  	return interpolant;  } + diff --git a/indra/llcommon/lleventapi.h b/indra/llcommon/lleventapi.h index 1a37d780b6..10c7e7a23f 100644 --- a/indra/llcommon/lleventapi.h +++ b/indra/llcommon/lleventapi.h @@ -41,12 +41,13 @@   * Deriving from LLInstanceTracker lets us enumerate instances.   */  class LL_COMMON_API LLEventAPI: public LLDispatchListener, -                  public LLInstanceTracker<LLEventAPI, std::string> +                  public INSTANCE_TRACKER_KEYED(LLEventAPI, std::string)  {      typedef LLDispatchListener lbase; -    typedef LLInstanceTracker<LLEventAPI, std::string> ibase; +    typedef INSTANCE_TRACKER_KEYED(LLEventAPI, std::string) ibase;  public: +      /**       * @param name LLEventPump name on which this LLEventAPI will listen. This       * also serves as the LLInstanceTracker instance key. diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h index 7f42623d01..e55f851758 100644 --- a/indra/llcommon/lleventtimer.h +++ b/indra/llcommon/lleventtimer.h @@ -33,9 +33,10 @@  #include "lltimer.h"  // class for scheduling a function to be called at a given frequency (approximate, inprecise) -class LL_COMMON_API LLEventTimer : public LLInstanceTracker<LLEventTimer> +class LL_COMMON_API LLEventTimer : public INSTANCE_TRACKER(LLEventTimer)  {  public: +  	LLEventTimer(F32 period);	// period is the amount of time between each call to tick() in seconds  	LLEventTimer(const LLDate& time);  	virtual ~LLEventTimer(); diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 81c4b78775..a6b34bdc69 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -63,7 +63,7 @@ public:  	// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances  	class LL_COMMON_API NamedTimer -	:	public LLInstanceTracker<NamedTimer> +	:	public LLInstanceTracker<NamedTimer, InstanceTrackType_NamedTimer >  	{  		friend class DeclareTimer;  	public: @@ -139,10 +139,11 @@ public:  	// used to statically declare a new named timer  	class LL_COMMON_API DeclareTimer -	:	public LLInstanceTracker<DeclareTimer> +	:	public LLInstanceTracker< DeclareTimer, InstanceTrackType_DeclareTimer >  	{  		friend class LLFastTimer;  	public: +  		DeclareTimer(const std::string& name, bool open);  		DeclareTimer(const std::string& name); diff --git a/indra/llcommon/llfoldertype.h b/indra/llcommon/llfoldertype.h index a0c847914f..a0c847914f 100755..100644 --- a/indra/llcommon/llfoldertype.h +++ b/indra/llcommon/llfoldertype.h diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp index 5dc3ea5d7b..65ef4322f6 100644 --- a/indra/llcommon/llinstancetracker.cpp +++ b/indra/llcommon/llinstancetracker.cpp @@ -32,18 +32,15 @@  // external library headers  // other Linden headers -//static  -void * & LLInstanceTrackerBase::getInstances(std::type_info const & info) -{ -	typedef std::map<std::string, void *> InstancesMap; -	static InstancesMap instances; +static void* sInstanceTrackerData[ kInstanceTrackTypeCount ] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +void * & LLInstanceTrackerBase::getInstances(InstanceTrackType t) +{  	// std::map::insert() is just what we want here. You attempt to insert a  	// (key, value) pair. If the specified key doesn't yet exist, it inserts  	// the pair and returns a std::pair of (iterator, true). If the specified  	// key DOES exist, insert() simply returns (iterator, false). One lookup  	// handles both cases. -	return instances.insert(InstancesMap::value_type(info.name(), -													 InstancesMap::mapped_type())) -		.first->second; +	return sInstanceTrackerData[t];  } + diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 1eab270e3c..0f952f56ac 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -38,6 +38,33 @@  #include <boost/iterator/transform_iterator.hpp>  #include <boost/iterator/indirect_iterator.hpp> +enum InstanceTrackType +{ +	InstanceTrackType_LLEventAPI, +	InstanceTrackType_LLEventTimer, +	InstanceTrackType_NamedTimer, +	InstanceTrackType_DeclareTimer, +	InstanceTrackType_LLLeap, +	InstanceTrackType_LLGLNamePool, +	InstanceTrackType_LLConsole, +	InstanceTrackType_LLFloater, +	InstanceTrackType_LLFloaterWebContent, +	InstanceTrackType_LLLayoutStack, +	InstanceTrackType_LLNotificationContext, +	InstanceTrackType_LLWindow, +	InstanceTrackType_LLControlGroup, +	InstanceTrackType_LLControlCache, +	InstanceTrackType_LLMediaCtrl, +	InstanceTrackType_LLNameListCtrl, +	InstanceTrackType_LLToast, +	InstanceTrackType_Keyed,	// for integ tests +	InstanceTrackType_Unkeyed,	// for integ tests +	kInstanceTrackTypeCount +}; + +#define INSTANCE_TRACKER(T)			LLInstanceTracker< T, InstanceTrackType_##T > +#define INSTANCE_TRACKER_KEYED(T,K)	LLInstanceTracker< T, InstanceTrackType_##T, K > +  /**   * Base class manages "class-static" data that must actually have singleton   * semantics: one instance per process, rather than one instance per module as @@ -47,14 +74,15 @@ class LL_COMMON_API LLInstanceTrackerBase  {  protected:  	/// Get a process-unique void* pointer slot for the specified type_info -	static void * & getInstances(std::type_info const & info); +	//static void * & getInstances(std::type_info const & info); +	static void * & getInstances(InstanceTrackType t);  	/// Find or create a STATICDATA instance for the specified TRACKED class.  	/// STATICDATA must be default-constructible. -	template<typename STATICDATA, class TRACKED> +	template<typename STATICDATA, class TRACKED, class INST, InstanceTrackType TRACKEDTYPE>  	static STATICDATA& getStatic()  	{ -		void *& instances = getInstances(typeid(TRACKED)); +		void *& instances = getInstances(TRACKEDTYPE);  		if (! instances)  		{  			instances = new STATICDATA; @@ -78,16 +106,16 @@ protected:  /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup  /// If KEY is not provided, then instances are stored in a simple set  /// @NOTE: see explicit specialization below for default KEY==T* case -template<typename T, typename KEY = T*> +template<typename T, enum InstanceTrackType TRACKED, typename KEY = T*>  class LLInstanceTracker : public LLInstanceTrackerBase  { -	typedef LLInstanceTracker<T, KEY> MyT; +	typedef LLInstanceTracker<T, TRACKED, KEY> MyT;  	typedef typename std::map<KEY, T*> InstanceMap;  	struct StaticData: public StaticBase  	{  		InstanceMap sMap;  	}; -	static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); } +	static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT, T, TRACKED>(); }  	static InstanceMap& getMap_() { return getStatic().sMap; }  public: @@ -229,16 +257,16 @@ private:  /// explicit specialization for default case where KEY is T*  /// use a simple std::set<T*> -template<typename T> -class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase +template<typename T, enum InstanceTrackType TRACKED> +class LLInstanceTracker<T, TRACKED, T*> : public LLInstanceTrackerBase  { -	typedef LLInstanceTracker<T, T*> MyT; +	typedef LLInstanceTracker<T, TRACKED, T*> MyT;  	typedef typename std::set<T*> InstanceSet;  	struct StaticData: public StaticBase  	{  		InstanceSet sSet;  	}; -	static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); } +	static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT, T, TRACKED>(); }  	static InstanceSet& getSet_() { return getStatic().sSet; }  public: diff --git a/indra/llcommon/llleap.h b/indra/llcommon/llleap.h index 1a1ad23d39..d4e138f4be 100644 --- a/indra/llcommon/llleap.h +++ b/indra/llcommon/llleap.h @@ -29,9 +29,10 @@   * LLLeap* pointer should be validated before use by   * LLLeap::getInstance(LLLeap*) (see LLInstanceTracker).   */ -class LL_COMMON_API LLLeap: public LLInstanceTracker<LLLeap> +class LL_COMMON_API LLLeap: public INSTANCE_TRACKER(LLLeap)  {  public: +      /**       * Pass a brief string description, mostly for logging purposes. The desc       * need not be unique, but obviously the clearer we can make it, the diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index e725bdd9fa..61e30f11cc 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -36,19 +36,68 @@ class LLMutex ;  #define LL_CHECK_MEMORY  #endif +LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); + +#ifdef SHOW_ASSERT +#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment)) +#else +#define ll_assert_aligned(ptr,alignment) +#endif + +#include <xmmintrin.h> + +template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address)  +{  +	return reinterpret_cast<T*>( +		(reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF); +} + +template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)  +{  +	return reinterpret_cast<T*>( +		(reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F); +} + +#if LL_LINUX || LL_DARWIN + +#define			LL_ALIGN_PREFIX(x) +#define			LL_ALIGN_POSTFIX(x)		__attribute__((aligned(x))) + +#elif LL_WINDOWS + +#define			LL_ALIGN_PREFIX(x)		__declspec(align(x)) +#define			LL_ALIGN_POSTFIX(x) + +#else +#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined" +#endif + +#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) +  inline void* ll_aligned_malloc( size_t size, int align )  { +#if defined(LL_WINDOWS) +	return _aligned_malloc(size, align); +#else  	void* mem = malloc( size + (align - 1) + sizeof(void*) );  	char* aligned = ((char*)mem) + sizeof(void*);  	aligned += align - ((uintptr_t)aligned & (align - 1));  	((void**)aligned)[-1] = mem;  	return aligned; +#endif  }  inline void ll_aligned_free( void* ptr )  { -	free( ((void**)ptr)[-1] ); +#if defined(LL_WINDOWS) +	_aligned_free(ptr); +#else +	if (ptr) +	{ +		free( ((void**)ptr)[-1] ); +	} +#endif  }  #if !LL_USE_TCMALLOC @@ -133,6 +182,78 @@ inline void ll_aligned_free_32(void *p)  #endif  } + +// Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP.  +// Source and dest must be 16-byte aligned and size must be multiple of 16. +// +inline void ll_memcpy_nonaliased_aligned_16(char* __restrict dst, const char* __restrict src, size_t bytes) +{ +	assert(src != NULL); +	assert(dst != NULL); +	assert(bytes > 0); +	assert((bytes % sizeof(F32))== 0);  +	ll_assert_aligned(src,16); +	ll_assert_aligned(dst,16); +	assert((src < dst) ? ((src + bytes) < dst) : ((dst + bytes) < src)); +	assert(bytes%16==0); + +	char* end = dst + bytes; + +	if (bytes > 64) +	{ + +		// Find start of 64b aligned area within block +		// +		void* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst); +		 +		//at least 64 bytes before the end of the destination, switch to 16 byte copies +		void* end_64 = end-64; +	 +		// Prefetch the head of the 64b area now +		// +		_mm_prefetch((char*)begin_64, _MM_HINT_NTA); +		_mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA); +		_mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA); +		_mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA); +	 +		// Copy 16b chunks until we're 64b aligned +		// +		while (dst < begin_64) +		{ + +			_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src)); +			dst += 16; +			src += 16; +		} +	 +		// Copy 64b chunks up to your tail +		// +		// might be good to shmoo the 512b prefetch offset +		// (characterize performance for various values) +		// +		while (dst < end_64) +		{ +			_mm_prefetch((char*)src + 512, _MM_HINT_NTA); +			_mm_prefetch((char*)dst + 512, _MM_HINT_NTA); +			_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src)); +			_mm_store_ps((F32*)(dst + 16), _mm_load_ps((F32*)(src + 16))); +			_mm_store_ps((F32*)(dst + 32), _mm_load_ps((F32*)(src + 32))); +			_mm_store_ps((F32*)(dst + 48), _mm_load_ps((F32*)(src + 48))); +			dst += 64; +			src += 64; +		} +	} + +	// Copy remainder 16b tail chunks (or ALL 16b chunks for sub-64b copies) +	// +	while (dst < end) +	{ +		_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src)); +		dst += 16; +		src += 16; +	} +} +  #ifndef __DEBUG_PRIVATE_MEM__  #define __DEBUG_PRIVATE_MEM__  0  #endif @@ -541,13 +662,7 @@ void  LLPrivateMemoryPoolTester::operator delete[](void* addr)  // LLSingleton moved to llsingleton.h -LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment); -#ifdef SHOW_ASSERT -#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment)) -#else -#define ll_assert_aligned(ptr,alignment) -#endif  #endif diff --git a/indra/llcommon/llstaticstringtable.h b/indra/llcommon/llstaticstringtable.h new file mode 100644 index 0000000000..d7e0e8a08d --- /dev/null +++ b/indra/llcommon/llstaticstringtable.h @@ -0,0 +1,82 @@ +/**  + * @file llstringtable.h + * @brief The LLStringTable class provides a _fast_ method for finding + * unique copies of strings. + * + * $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$ + */ + +#ifndef LL_STATIC_STRING_TABLE_H +#define LL_STATIC_STRING_TABLE_H + +#include "lldefs.h" +#include <boost/unordered_map.hpp> +#include "llstl.h" + +class LLStaticHashedString +{ +public: + +	LLStaticHashedString(const std::string& s) +	{ +		string_hash = makehash(s); +		string		= s; +	} + +	const std::string&	String() const { return string;		} +	size_t				Hash()	 const { return string_hash;  } + +	bool operator==(const LLStaticHashedString& b) const { return Hash() == b.Hash(); } + +protected: + +	size_t makehash(const std::string& s) +	{ +		size_t len = s.size(); +		const char* c = s.c_str(); +		size_t hashval = 0; +		for (size_t i=0; i<len; i++) +		{ +			hashval = ((hashval<<5) + hashval) + *c++; +		} +		return hashval; +	} + +	std::string string; +	size_t		string_hash; +}; + +struct LLStaticStringHasher +{ +	enum { bucket_size = 8 }; +	size_t operator()(const LLStaticHashedString& key_value) const { return key_value.Hash(); } +	bool   operator()(const LLStaticHashedString& left, const LLStaticHashedString& right) const { return left.Hash() < right.Hash(); } +}; + +template< typename MappedObject > +class LL_COMMON_API LLStaticStringTable +	: public boost::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher > +{ +}; + +#endif + diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h index 59d7372ed4..787a046741 100644 --- a/indra/llcommon/llstringtable.h +++ b/indra/llcommon/llstringtable.h @@ -1,217 +1,209 @@ -/**  - * @file llstringtable.h - * @brief The LLStringTable class provides a _fast_ method for finding - * unique copies of strings. - * - * $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$ - */ - -#ifndef LL_STRING_TABLE_H -#define LL_STRING_TABLE_H - -#include "lldefs.h" -#include "llformat.h" -#include "llstl.h" -#include <list> -#include <set> - -#if LL_WINDOWS -# if (_MSC_VER >= 1300 && _MSC_VER < 1400) -#  define STRING_TABLE_HASH_MAP 1 -# endif -#else -//# define STRING_TABLE_HASH_MAP 1 -#endif - -#if STRING_TABLE_HASH_MAP -# if LL_WINDOWS -#  include <hash_map> -# else -#  include <ext/hash_map> -# endif -#endif - -const U32 MAX_STRINGS_LENGTH = 256; - -class LL_COMMON_API LLStringTableEntry -{ -public: -	LLStringTableEntry(const char *str); -	~LLStringTableEntry(); - -	void incCount()		{ mCount++; } -	BOOL decCount()		{ return --mCount; } - -	char *mString; -	S32  mCount; -}; - -class LL_COMMON_API LLStringTable -{ -public: -	LLStringTable(int tablesize); -	~LLStringTable(); - -	char *checkString(const char *str); -	char *checkString(const std::string& str); -	LLStringTableEntry *checkStringEntry(const char *str); -	LLStringTableEntry *checkStringEntry(const std::string& str); - -	char *addString(const char *str); -	char *addString(const std::string& str); -	LLStringTableEntry *addStringEntry(const char *str); -	LLStringTableEntry *addStringEntry(const std::string& str); -	void  removeString(const char *str); - -	S32 mMaxEntries; -	S32 mUniqueEntries; -	 -#if STRING_TABLE_HASH_MAP -#if LL_WINDOWS -	typedef std::hash_multimap<U32, LLStringTableEntry *> string_hash_t; -#else -	typedef __gnu_cxx::hash_multimap<U32, LLStringTableEntry *> string_hash_t; -#endif -	string_hash_t mStringHash; -#else -	typedef std::list<LLStringTableEntry *> string_list_t; -	typedef string_list_t * string_list_ptr_t; -	string_list_ptr_t	*mStringList; -#endif	 -}; - -extern LL_COMMON_API LLStringTable gStringTable; - -//============================================================================ - -// This class is designed to be used locally, -// e.g. as a member of an LLXmlTree -// Strings can be inserted only, then quickly looked up - -typedef const std::string* LLStdStringHandle; - -class LL_COMMON_API LLStdStringTable -{ -public: -	LLStdStringTable(S32 tablesize = 0) -	{ -		if (tablesize == 0) -		{ -			tablesize = 256; // default -		} -		// Make sure tablesize is power of 2 -		for (S32 i = 31; i>0; i--) -		{ -			if (tablesize & (1<<i)) -			{ -				if (tablesize >= (3<<(i-1))) -					tablesize = (1<<(i+1)); -				else -					tablesize = (1<<i); -				break; -			} -		} -		mTableSize = tablesize; -		mStringList = new string_set_t[tablesize]; -	} -	~LLStdStringTable() -	{ -		cleanup(); -		delete[] mStringList; -	} -	void cleanup() -	{ -		// remove strings -		for (S32 i = 0; i<mTableSize; i++) -		{ -			string_set_t& stringset = mStringList[i]; -			for (string_set_t::iterator iter = stringset.begin(); iter != stringset.end(); iter++) -			{ -				delete *iter; -			} -			stringset.clear(); -		} -	} - -	LLStdStringHandle lookup(const std::string& s) -	{ -		U32 hashval = makehash(s); -		return lookup(hashval, s); -	} -	 -	LLStdStringHandle checkString(const std::string& s) -	{ -		U32 hashval = makehash(s); -		return lookup(hashval, s); -	} - -	LLStdStringHandle insert(const std::string& s) -	{ -		U32 hashval = makehash(s); -		LLStdStringHandle result = lookup(hashval, s); -		if (result == NULL) -		{ -			result = new std::string(s); -			mStringList[hashval].insert(result); -		} -		return result; -	} -	LLStdStringHandle addString(const std::string& s) -	{ -		return insert(s); -	} -	 -private: -	U32 makehash(const std::string& s) -	{ -		S32 len = (S32)s.size(); -		const char* c = s.c_str(); -		U32 hashval = 0; -		for (S32 i=0; i<len; i++) -		{ -			hashval = ((hashval<<5) + hashval) + *c++; -		} -		return hashval & (mTableSize-1); -	} -	LLStdStringHandle lookup(U32 hashval, const std::string& s) -	{ -		string_set_t& stringset = mStringList[hashval]; -		LLStdStringHandle handle = &s; -		string_set_t::iterator iter = stringset.find(handle); // compares actual strings -		if (iter != stringset.end()) -		{ -			return *iter; -		} -		else -		{ -			return NULL; -		} -	} -	 -private: -	S32 mTableSize; -	typedef std::set<LLStdStringHandle, compare_pointer_contents<std::string> > string_set_t; -	string_set_t* mStringList; // [mTableSize] -}; - - -#endif +/** 
 + * @file llstringtable.h
 + * @brief The LLStringTable class provides a _fast_ method for finding
 + * unique copies of strings.
 + *
 + * $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$
 + */
 +
 +#ifndef LL_STRING_TABLE_H
 +#define LL_STRING_TABLE_H
 +
 +#include "lldefs.h"
 +#include "llformat.h"
 +#include "llstl.h"
 +#include <list>
 +#include <set>
 +
 +#if LL_WINDOWS
 +# if (_MSC_VER >= 1300 && _MSC_VER < 1400)
 +#  define STRING_TABLE_HASH_MAP 1
 +# endif
 +#else
 +//# define STRING_TABLE_HASH_MAP 1
 +#endif
 +
 +const U32 MAX_STRINGS_LENGTH = 256;
 +
 +class LL_COMMON_API LLStringTableEntry
 +{
 +public:
 +	LLStringTableEntry(const char *str);
 +	~LLStringTableEntry();
 +
 +	void incCount()		{ mCount++; }
 +	BOOL decCount()		{ return --mCount; }
 +
 +	char *mString;
 +	S32  mCount;
 +};
 +
 +class LL_COMMON_API LLStringTable
 +{
 +public:
 +	LLStringTable(int tablesize);
 +	~LLStringTable();
 +
 +	char *checkString(const char *str);
 +	char *checkString(const std::string& str);
 +	LLStringTableEntry *checkStringEntry(const char *str);
 +	LLStringTableEntry *checkStringEntry(const std::string& str);
 +
 +	char *addString(const char *str);
 +	char *addString(const std::string& str);
 +	LLStringTableEntry *addStringEntry(const char *str);
 +	LLStringTableEntry *addStringEntry(const std::string& str);
 +	void  removeString(const char *str);
 +
 +	S32 mMaxEntries;
 +	S32 mUniqueEntries;
 +	
 +#if STRING_TABLE_HASH_MAP
 +#if LL_WINDOWS
 +	typedef std::hash_multimap<U32, LLStringTableEntry *> string_hash_t;
 +#else
 +	typedef __gnu_cxx::hash_multimap<U32, LLStringTableEntry *> string_hash_t;
 +#endif
 +	string_hash_t mStringHash;
 +#else
 +	typedef std::list<LLStringTableEntry *> string_list_t;
 +	typedef string_list_t * string_list_ptr_t;
 +	string_list_ptr_t	*mStringList;
 +#endif	
 +};
 +
 +extern LL_COMMON_API LLStringTable gStringTable;
 +
 +//============================================================================
 +
 +// This class is designed to be used locally,
 +// e.g. as a member of an LLXmlTree
 +// Strings can be inserted only, then quickly looked up
 +
 +typedef const std::string* LLStdStringHandle;
 +
 +class LL_COMMON_API LLStdStringTable
 +{
 +public:
 +	LLStdStringTable(S32 tablesize = 0)
 +	{
 +		if (tablesize == 0)
 +		{
 +			tablesize = 256; // default
 +		}
 +		// Make sure tablesize is power of 2
 +		for (S32 i = 31; i>0; i--)
 +		{
 +			if (tablesize & (1<<i))
 +			{
 +				if (tablesize >= (3<<(i-1)))
 +					tablesize = (1<<(i+1));
 +				else
 +					tablesize = (1<<i);
 +				break;
 +			}
 +		}
 +		mTableSize = tablesize;
 +		mStringList = new string_set_t[tablesize];
 +	}
 +	~LLStdStringTable()
 +	{
 +		cleanup();
 +		delete[] mStringList;
 +	}
 +	void cleanup()
 +	{
 +		// remove strings
 +		for (S32 i = 0; i<mTableSize; i++)
 +		{
 +			string_set_t& stringset = mStringList[i];
 +			for (string_set_t::iterator iter = stringset.begin(); iter != stringset.end(); iter++)
 +			{
 +				delete *iter;
 +			}
 +			stringset.clear();
 +		}
 +	}
 +
 +	LLStdStringHandle lookup(const std::string& s)
 +	{
 +		U32 hashval = makehash(s);
 +		return lookup(hashval, s);
 +	}
 +	
 +	LLStdStringHandle checkString(const std::string& s)
 +	{
 +		U32 hashval = makehash(s);
 +		return lookup(hashval, s);
 +	}
 +
 +	LLStdStringHandle insert(const std::string& s)
 +	{
 +		U32 hashval = makehash(s);
 +		LLStdStringHandle result = lookup(hashval, s);
 +		if (result == NULL)
 +		{
 +			result = new std::string(s);
 +			mStringList[hashval].insert(result);
 +		}
 +		return result;
 +	}
 +	LLStdStringHandle addString(const std::string& s)
 +	{
 +		return insert(s);
 +	}
 +	
 +private:
 +	U32 makehash(const std::string& s)
 +	{
 +		S32 len = (S32)s.size();
 +		const char* c = s.c_str();
 +		U32 hashval = 0;
 +		for (S32 i=0; i<len; i++)
 +		{
 +			hashval = ((hashval<<5) + hashval) + *c++;
 +		}
 +		return hashval & (mTableSize-1);
 +	}
 +	LLStdStringHandle lookup(U32 hashval, const std::string& s)
 +	{
 +		string_set_t& stringset = mStringList[hashval];
 +		LLStdStringHandle handle = &s;
 +		string_set_t::iterator iter = stringset.find(handle); // compares actual strings
 +		if (iter != stringset.end())
 +		{
 +			return *iter;
 +		}
 +		else
 +		{
 +			return NULL;
 +		}
 +	}
 +	
 +private:
 +	S32 mTableSize;
 +	typedef std::set<LLStdStringHandle, compare_pointer_contents<std::string> > string_set_t;
 +	string_set_t* mStringList; // [mTableSize]
 +};
 +
 +
 +#endif
 diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 1d56a52c32..6c117f7daf 100644 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -495,15 +495,7 @@ LLThreadSafeRefCount::LLThreadSafeRefCount() :  LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)  { -	if (sMutex) -	{ -		sMutex->lock(); -	}  	mRef = 0; -	if (sMutex) -	{ -		sMutex->unlock(); -	}  }  LLThreadSafeRefCount::~LLThreadSafeRefCount() diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 0fb89c5613..8c95b1c0e5 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -242,47 +242,43 @@ public:  	LLThreadSafeRefCount(const LLThreadSafeRefCount&);  	LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)   	{ -		if (sMutex) -		{ -			sMutex->lock(); -		}  		mRef = 0; -		if (sMutex) -		{ -			sMutex->unlock(); -		}  		return *this;  	} - -	  	void ref()  	{ -		if (sMutex) sMutex->lock();  		mRef++;  -		if (sMutex) sMutex->unlock();  	}   	S32 unref()  	{ -		llassert(mRef >= 1); -		if (sMutex) sMutex->lock(); -		S32 res = --mRef; -		if (sMutex) sMutex->unlock(); -		if (0 == res)  +		llassert(mRef >= 1);		 +		bool time_to_die = (mRef == 1);		 +		if (time_to_die)  		{ -			delete this;  +			if (sMutex) sMutex->lock(); +			// Looks redundant, but is very much not +			// We need to check again once we've acquired the lock +			// so that two threads who get into the if in parallel +			// don't both attempt to the delete. +			// +			mRef--; +			if (mRef == 0) +				delete this; 			 +			if (sMutex) sMutex->unlock();  			return 0;  		} -		return res; -	}	 +		return --mRef;		 +	}  	S32 getNumRefs() const  	{ -		return mRef; +		const S32 currentVal = mRef.CurrentValue(); +		return currentVal;  	}  private:  -	S32	mRef;  +	LLAtomic32< S32	> mRef;   };  /** diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index e769c3e22c..b2d82d1843 100644 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -48,16 +48,16 @@ struct Badness: public std::runtime_error      Badness(const std::string& what): std::runtime_error(what) {}  }; -struct Keyed: public LLInstanceTracker<Keyed, std::string> +struct Keyed: public INSTANCE_TRACKER_KEYED(Keyed, std::string)  {      Keyed(const std::string& name): -        LLInstanceTracker<Keyed, std::string>(name), +        INSTANCE_TRACKER_KEYED(Keyed, std::string)(name),          mName(name)      {}      std::string mName;  }; -struct Unkeyed: public LLInstanceTracker<Unkeyed> +struct Unkeyed: public INSTANCE_TRACKER(Unkeyed)  {      Unkeyed(const std::string& thrw="")      { diff --git a/indra/llcorehttp/_httpoprequest.cpp b/indra/llcorehttp/_httpoprequest.cpp index 51a8eaf998..469ce75434 100644 --- a/indra/llcorehttp/_httpoprequest.cpp +++ b/indra/llcorehttp/_httpoprequest.cpp @@ -339,7 +339,6 @@ void HttpOpRequest::setupCommon(HttpRequest::policy_t policy_id,  	}  } -  // Sets all libcurl options and data for a request.  //  // Used both for initial requests and to 'reload' for @@ -381,13 +380,7 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  	// Get policy options  	HttpPolicyGlobal & policy(service->getPolicy().getGlobalOptions()); -	mCurlHandle = curl_easy_init(); -	curl_easy_setopt(mCurlHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); -	curl_easy_setopt(mCurlHandle, CURLOPT_NOSIGNAL, 1); -	curl_easy_setopt(mCurlHandle, CURLOPT_NOPROGRESS, 1); -	curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str()); -	curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this); -	curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, ""); +	mCurlHandle = LLCurlHandleHandler::getInstance()->CreateCurlHandle();  	if (HTTP_ENABLE_LINKSYS_WRT54G_V5_DNS_FIX)  	{ @@ -399,23 +392,14 @@ HttpStatus HttpOpRequest::prepareRequest(HttpService * service)  		// seconds and no RSTs.  		curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);  	} -	else -	{ -		// *TODO:  Revisit this old DNS timeout setting - may no longer be valid -		// I don't think this is valid anymore, the Multi shared DNS -		// cache is working well.  For the case of naked easy handles, -		// consider using a shared DNS object. -		curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0); -	} -	curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1); -	curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1); -	curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT); +  	curl_easy_setopt(mCurlHandle, CURLOPT_WRITEFUNCTION, writeCallback); -	curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, this); -	curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION, readCallback); +	curl_easy_setopt(mCurlHandle, CURLOPT_READFUNCTION,  readCallback);	  	curl_easy_setopt(mCurlHandle, CURLOPT_READDATA, this); -	curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYPEER, 1); -	curl_easy_setopt(mCurlHandle, CURLOPT_SSL_VERIFYHOST, 0); +	curl_easy_setopt(mCurlHandle, CURLOPT_WRITEDATA, this); +	curl_easy_setopt(mCurlHandle, CURLOPT_URL, mReqURL.c_str()); +	curl_easy_setopt(mCurlHandle, CURLOPT_PRIVATE, this); +	curl_easy_setopt(mCurlHandle, CURLOPT_MAXREDIRS, HTTP_REDIRECTS_DEFAULT);	  	const std::string * opt_value(NULL);  	long opt_long(0L); diff --git a/indra/llcorehttp/_httpoprequest.h b/indra/llcorehttp/_httpoprequest.h index 7b65d17783..e819f74079 100644 --- a/indra/llcorehttp/_httpoprequest.h +++ b/indra/llcorehttp/_httpoprequest.h @@ -29,6 +29,7 @@  #include "linden_common.h"		// Modifies curl/curl.h interfaces +#include "llsingleton.h"  #include <string>  #include <curl/curl.h> @@ -60,12 +61,13 @@ class HttpOptions;  /// the information needed to make a working request which can  /// then be enqueued to a request queue.  /// -  class HttpOpRequest : public HttpOperation  {  public:  	HttpOpRequest(); +	friend class CurlHandleHandler; +  protected:  	virtual ~HttpOpRequest();							// Use release() diff --git a/indra/llmath/llmatrix4a.h b/indra/llmath/llmatrix4a.h index c4cefdb4fa..d141298f69 100644 --- a/indra/llmath/llmatrix4a.h +++ b/indra/llmath/llmatrix4a.h @@ -107,15 +107,14 @@ public:  	inline void rotate(const LLVector4a& v, LLVector4a& res)  	{ +		LLVector4a y,z; +  		res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0)); -		res.mul(mMatrix[0]); -		 -		LLVector4a y;  		y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1)); -		y.mul(mMatrix[1]); - -		LLVector4a z;  		z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2)); +		 +		res.mul(mMatrix[0]); +		y.mul(mMatrix[1]);  		z.mul(mMatrix[2]);  		res.add(y); diff --git a/indra/llmath/llsimdmath.h b/indra/llmath/llsimdmath.h index 01458521ec..cebd2ace7d 100644 --- a/indra/llmath/llsimdmath.h +++ b/indra/llmath/llsimdmath.h @@ -39,34 +39,6 @@  #include <stdint.h>  #endif -template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address)  -{  -	return reinterpret_cast<T*>( -		(reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF); -} - -template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)  -{  -	return reinterpret_cast<T*>( -		(reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F); -} - -#if LL_LINUX || LL_DARWIN - -#define			LL_ALIGN_PREFIX(x) -#define			LL_ALIGN_POSTFIX(x)		__attribute__((aligned(x))) - -#elif LL_WINDOWS - -#define			LL_ALIGN_PREFIX(x)		__declspec(align(x)) -#define			LL_ALIGN_POSTFIX(x) - -#else -#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined" -#endif - -#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16) -  #include <xmmintrin.h>  #include <emmintrin.h> diff --git a/indra/llmath/llvector4a.cpp b/indra/llmath/llvector4a.cpp index 6edeb0fefe..570fa41a43 100644 --- a/indra/llmath/llvector4a.cpp +++ b/indra/llmath/llvector4a.cpp @@ -41,55 +41,7 @@ extern const LLVector4a LL_V4A_EPSILON = reinterpret_cast<const LLVector4a&> ( F  /*static */void LLVector4a::memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes)  { -	assert(src != NULL); -	assert(dst != NULL); -	assert(bytes > 0); -	assert((bytes % sizeof(F32))== 0);  -	ll_assert_aligned(src,16); -	ll_assert_aligned(dst,16); -	assert(bytes%16==0); - -	F32* end = dst + (bytes / sizeof(F32) ); - -	if (bytes > 64) -	{ -		F32* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst); -		 -		//at least 64 (16*4) bytes before the end of the destination, switch to 16 byte copies -		F32* end_64 = end-16; -		 -		_mm_prefetch((char*)begin_64, _MM_HINT_NTA); -		_mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA); -		_mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA); -		_mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA); -		 -		while (dst < begin_64) -		{ -			copy4a(dst, src); -			dst += 4; -			src += 4; -		} -		 -		while (dst < end_64) -		{ -			_mm_prefetch((char*)src + 512, _MM_HINT_NTA); -			_mm_prefetch((char*)dst + 512, _MM_HINT_NTA); -			copy4a(dst, src); -			copy4a(dst+4, src+4); -			copy4a(dst+8, src+8); -			copy4a(dst+12, src+12); -			 -			dst += 16; -			src += 16; -		} -	} - -	while (dst < end) -	{ -		copy4a(dst, src); -		dst += 4; -		src += 4; -	} +        ll_memcpy_nonaliased_aligned_16((char*)dst, (char*)src, bytes);  }  void LLVector4a::setRotated( const LLRotation& rot, const LLVector4a& vec ) diff --git a/indra/llmath/llvector4a.inl b/indra/llmath/llvector4a.inl index 7c52ffef21..35a67204ec 100644 --- a/indra/llmath/llvector4a.inl +++ b/indra/llmath/llvector4a.inl @@ -460,16 +460,13 @@ inline void LLVector4a::setMax(const LLVector4a& lhs, const LLVector4a& rhs)  	mQ = _mm_max_ps(lhs.mQ, rhs.mQ);  } -// Set this to  (c * lhs) + rhs * ( 1 - c) +// Set this to  lhs + (rhs-lhs)*c  inline void LLVector4a::setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c)  { -	LLVector4a a = lhs; -	a.mul(c); -	 -	LLVector4a b = rhs; -	b.mul(1.f-c); -	 -	setAdd(a, b); +	LLVector4a t; +	t.setSub(rhs,lhs); +	t.mul(c); +	setAdd(lhs, t);  }  inline LLBool32 LLVector4a::isFinite3() const diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 3f06e6b99e..602f2c29e5 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -94,6 +94,8 @@ const S32 SCULPT_MIN_AREA_DETAIL = 1;  extern BOOL gDebugGL; +bool less_than_max_mag(const LLVector4a& vec); +  BOOL check_same_clock_dir( const LLVector3& pt1, const LLVector3& pt2, const LLVector3& pt3, const LLVector3& norm)  {      	LLVector3 test = (pt2-pt1)%(pt3-pt2); @@ -474,7 +476,7 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  	const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };  	F32 scale = 0.5f;  	F32 t, t_step, t_first, t_fraction, ang, ang_step; -	LLVector3 pt1,pt2; +	LLVector4a pt1,pt2;  	F32 begin  = params.getBegin();  	F32 end    = params.getEnd(); @@ -497,20 +499,21 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  	// Starting t and ang values for the first face  	t = t_first;  	ang = 2.0f*F_PI*(t*ang_scale + offset); -	pt1.setVec(cos(ang)*scale,sin(ang)*scale, t); +	pt1.set(cos(ang)*scale,sin(ang)*scale, t);  	// Increment to the next point.  	// pt2 is the end point on the fractional face  	t += t_step;  	ang += ang_step; -	pt2.setVec(cos(ang)*scale,sin(ang)*scale,t); +	pt2.set(cos(ang)*scale,sin(ang)*scale,t);  	t_fraction = (begin - t_first)*sides;  	// Only use if it's not almost exactly on an edge.  	if (t_fraction < 0.9999f)  	{ -		LLVector3 new_pt = lerp(pt1, pt2, t_fraction); +		LLVector4a new_pt; +		new_pt.setLerp(pt1, pt2, t_fraction);  		mProfile.push_back(new_pt);  	} @@ -518,12 +521,17 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  	while (t < end)  	{  		// Iterate through all the integer steps of t. -		pt1.setVec(cos(ang)*scale,sin(ang)*scale,t); +		pt1.set(cos(ang)*scale,sin(ang)*scale,t);  		if (mProfile.size() > 0) { -			LLVector3 p = mProfile[mProfile.size()-1]; +			LLVector4a p = mProfile[mProfile.size()-1];  			for (S32 i = 0; i < split && mProfile.size() > 0; i++) { -				mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1)); +				//mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1)); +				LLVector4a new_pt; +				new_pt.setSub(pt1, p); +				new_pt.mul(1.0f/(float)(split+1) * (float)(i+1)); +				new_pt.add(p); +				mProfile.push_back(new_pt);  			}  		}  		mProfile.push_back(pt1); @@ -536,18 +544,25 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  	// pt1 is the first point on the fractional face  	// pt2 is the end point on the fractional face -	pt2.setVec(cos(ang)*scale,sin(ang)*scale,t); +	pt2.set(cos(ang)*scale,sin(ang)*scale,t);  	// Find the fraction that we need to add to the end point.  	t_fraction = (end - (t - t_step))*sides;  	if (t_fraction > 0.0001f)  	{ -		LLVector3 new_pt = lerp(pt1, pt2, t_fraction); +		LLVector4a new_pt; +		new_pt.setLerp(pt1, pt2, t_fraction);  		if (mProfile.size() > 0) { -			LLVector3 p = mProfile[mProfile.size()-1]; +			LLVector4a p = mProfile[mProfile.size()-1];  			for (S32 i = 0; i < split && mProfile.size() > 0; i++) { -				mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1)); +				//mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1)); + +				LLVector4a pt1; +				pt1.setSub(new_pt, p); +				pt1.mul(1.0f/(float)(split+1) * (float)(i+1)); +				pt1.add(p); +				mProfile.push_back(pt1);  			}  		}  		mProfile.push_back(new_pt); @@ -568,7 +583,7 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  		if (params.getHollow() <= 0)  		{  			// put center point if not hollow. -			mProfile.push_back(LLVector3(0,0,0)); +			mProfile.push_back(LLVector4a(0,0,0));  		}  	}  	else @@ -581,103 +596,6 @@ void LLProfile::genNGon(const LLProfileParams& params, S32 sides, F32 offset, F3  	mTotal = mProfile.size();  } -void LLProfile::genNormals(const LLProfileParams& params) -{ -	S32 count = mProfile.size(); - -	S32 outer_count; -	if (mTotalOut) -	{ -		outer_count = mTotalOut; -	} -	else -	{ -		outer_count = mTotal / 2; -	} - -	mEdgeNormals.resize(count * 2); -	mEdgeCenters.resize(count * 2); -	mNormals.resize(count); - -	LLVector2 pt0,pt1; - -	BOOL hollow = (params.getHollow() > 0); - -	S32 i0, i1, i2, i3, i4; - -	// Parametrically generate normal -	for (i2 = 0; i2 < count; i2++) -	{ -		mNormals[i2].mV[0] = mProfile[i2].mV[0]; -		mNormals[i2].mV[1] = mProfile[i2].mV[1]; -		if (hollow && (i2 >= outer_count)) -		{ -			mNormals[i2] *= -1.f; -		} -		if (mNormals[i2].magVec() < 0.001) -		{ -			// Special case for point at center, get adjacent points. -			i1 = (i2 - 1) >= 0 ? i2 - 1 : count - 1; -			i0 = (i1 - 1) >= 0 ? i1 - 1 : count - 1; -			i3 = (i2 + 1) < count ? i2 + 1 : 0; -			i4 = (i3 + 1) < count ? i3 + 1 : 0; - -			pt0.setVec(mProfile[i1].mV[VX] + mProfile[i1].mV[VX] - mProfile[i0].mV[VX],  -				mProfile[i1].mV[VY] + mProfile[i1].mV[VY] - mProfile[i0].mV[VY]); -			pt1.setVec(mProfile[i3].mV[VX] + mProfile[i3].mV[VX] - mProfile[i4].mV[VX],  -				mProfile[i3].mV[VY] + mProfile[i3].mV[VY] - mProfile[i4].mV[VY]); - -			mNormals[i2] = pt0 + pt1; -			mNormals[i2] *= 0.5f; -		} -		mNormals[i2].normVec(); -	} - -	S32 num_normal_sets = isConcave() ? 2 : 1; -	for (S32 normal_set = 0; normal_set < num_normal_sets; normal_set++) -	{ -		S32 point_num; -		for (point_num = 0; point_num < mTotal; point_num++) -		{ -			LLVector3 point_1 = mProfile[point_num]; -			point_1.mV[VZ] = 0.f; - -			LLVector3 point_2; -			 -			if (isConcave() && normal_set == 0 && point_num == (mTotal - 1) / 2) -			{ -				point_2 = mProfile[mTotal - 1]; -			} -			else if (isConcave() && normal_set == 1 && point_num == mTotal - 1) -			{ -				point_2 = mProfile[(mTotal - 1) / 2]; -			} -			else -			{ -				LLVector3 delta_pos; -				S32 neighbor_point = (point_num + 1) % mTotal; -				while(delta_pos.magVecSquared() < 0.01f * 0.01f) -				{ -					point_2 = mProfile[neighbor_point]; -					delta_pos = point_2 - point_1; -					neighbor_point = (neighbor_point + 1) % mTotal; -					if (neighbor_point == point_num) -					{ -						break; -					} -				} -			} - -			point_2.mV[VZ] = 0.f; -			LLVector3 face_normal = (point_2 - point_1) % LLVector3::z_axis; -			face_normal.normVec(); -			mEdgeNormals[normal_set * count + point_num] = face_normal; -			mEdgeCenters[normal_set * count + point_num] = lerp(point_1, point_2, 0.5f); -		} -	} -} - -  // Hollow is percent of the original bounding box, not of this particular  // profile's geometry.  Thus, a swept triangle needs lower hollow values than  // a swept square. @@ -693,12 +611,13 @@ LLProfile::Face* LLProfile::addHole(const LLProfileParams& params, BOOL flat, F3  	Face *face = addFace(mTotalOut, mTotal-mTotalOut,0,LL_FACE_INNER_SIDE, flat); -	std::vector<LLVector3> pt; +	static LLAlignedArray<LLVector4a,64> pt;  	pt.resize(mTotal) ;  	for (S32 i=mTotalOut;i<mTotal;i++)  	{ -		pt[i] = mProfile[i] * box_hollow; +		pt[i] = mProfile[i]; +		pt[i].mul(box_hollow);  	}  	S32 j=mTotal-1; @@ -844,8 +763,8 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai  		detail = MIN_LOD;  	} -	mProfile.clear(); -	mFaces.clear(); +	mProfile.resize(0); +	mFaces.resize(0);  	// Generate the face data  	S32 i; @@ -877,10 +796,12 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai  				addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE);  			} +			LLVector4a scale(1,1,4,1); +  			for (i = 0; i <(S32) mProfile.size(); i++)  			{  				// Scale by 4 to generate proper tex coords. -				mProfile[i].mV[2] *= 4.f; +				mProfile[i].mul(scale);  			}  			if (hollow) @@ -913,10 +834,11 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai  	case  LL_PCODE_PROFILE_EQUALTRI:  		{  			genNGon(params, 3,0, 0, 1, split); +			LLVector4a scale(1,1,3,1);  			for (i = 0; i <(S32) mProfile.size(); i++)  			{  				// Scale by 3 to generate proper tex coords. -				mProfile[i].mV[2] *= 3.f; +				mProfile[i].mul(scale);  			}  			if (path_open) @@ -1094,8 +1016,6 @@ BOOL LLProfile::generate(const LLProfileParams& params, BOOL path_open,F32 detai  			addFace(mTotal-2, 2,0.5,LL_FACE_PROFILE_END, TRUE);  		}  	} -	 -	//genNormals(params);  	return TRUE;  } @@ -1379,25 +1299,29 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en  	// the path begins at the correct cut.  	F32 step= 1.0f / sides;  	F32 t	= params.getBegin(); -	pt		= vector_append(mPath, 1); +	pt		= mPath.append(1);  	ang		= 2.0f*F_PI*revolutions * t;  	s		= sin(ang)*lerp(radius_start, radius_end, t);	  	c		= cos(ang)*lerp(radius_start, radius_end, t); -	pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) +	pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)  					  + lerp(-skew ,skew, t) * 0.5f,  					c + lerp(0,params.getShear().mV[1],s),   					s); -	pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); -	pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); +	pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), +		hole_y * lerp(taper_y_begin, taper_y_end, t), +		0,1);  	pt->mTexT  = t;  	// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02  	twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);  	// Rotate the point around the circle's center.  	qang.setQuat   (ang,path_axis); -	pt->mRot   = twist * qang; + +	LLMatrix3 rot(twist * qang); + +	pt->mRot.loadu(rot);  	t+=step; @@ -1408,51 +1332,55 @@ void LLPath::genNGon(const LLPathParams& params, S32 sides, F32 startOff, F32 en  	// Run through the non-cut dependent points.  	while (t < params.getEnd())  	{ -		pt		= vector_append(mPath, 1); +		pt		= mPath.append(1);  		ang = 2.0f*F_PI*revolutions * t;  		c   = cos(ang)*lerp(radius_start, radius_end, t);  		s   = sin(ang)*lerp(radius_start, radius_end, t); -		pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) +		pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)  					      + lerp(-skew ,skew, t) * 0.5f,  						c + lerp(0,params.getShear().mV[1],s),   						s); -		pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); -		pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); +		pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), +					hole_y * lerp(taper_y_begin, taper_y_end, t), +					0,1);  		pt->mTexT  = t;  		// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02  		twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);  		// Rotate the point around the circle's center.  		qang.setQuat   (ang,path_axis); -		pt->mRot	= twist * qang; - +		LLMatrix3 tmp(twist*qang); +		pt->mRot.loadu(tmp); +		  		t+=step;  	}  	// Make one final pass for the end cut.  	t = params.getEnd(); -	pt		= vector_append(mPath, 1); +	pt		= mPath.append(1);  	ang = 2.0f*F_PI*revolutions * t;  	c   = cos(ang)*lerp(radius_start, radius_end, t);  	s   = sin(ang)*lerp(radius_start, radius_end, t); -	pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s) +	pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)  					  + lerp(-skew ,skew, t) * 0.5f,  					c + lerp(0,params.getShear().mV[1],s),   					s); -	pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t); -	pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t); +	pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t), +				   hole_y * lerp(taper_y_begin, taper_y_end, t), +				   0,1);  	pt->mTexT  = t;  	// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02  	twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);  	// Rotate the point around the circle's center.  	qang.setQuat   (ang,path_axis); -	pt->mRot   = twist * qang; - +	LLMatrix3 tmp(twist*qang); +	pt->mRot.loadu(tmp); +	  	mTotal = mPath.size();  } @@ -1549,7 +1477,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  	mDirty = FALSE;  	S32 np = 2; // hardcode for line -	mPath.clear(); +	mPath.resize(0);  	mOpen = TRUE;  	// Is this 0xf0 mask really necessary?  DK 03/02/05 @@ -1575,12 +1503,16 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  			for (S32 i=0;i<np;i++)  			{  				F32 t = lerp(params.getBegin(),params.getEnd(),(F32)i * mStep); -				mPath[i].mPos.setVec(lerp(0,params.getShear().mV[0],t), +				mPath[i].mPos.set(lerp(0,params.getShear().mV[0],t),  									 lerp(0,params.getShear().mV[1],t),  									 t - 0.5f); -				mPath[i].mRot.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1); -				mPath[i].mScale.mV[0] = lerp(start_scale.mV[0],end_scale.mV[0],t); -				mPath[i].mScale.mV[1] = lerp(start_scale.mV[1],end_scale.mV[1],t); +				LLQuaternion quat; +				quat.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1); +				LLMatrix3 tmp(quat); +				mPath[i].mRot.loadu(tmp); +				mPath[i].mScale.set(lerp(start_scale.mV[0],end_scale.mV[0],t), +									lerp(start_scale.mV[1],end_scale.mV[1],t), +									0,1);  				mPath[i].mTexT        = t;  			}  		} @@ -1617,7 +1549,7 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  			F32 toggle = 0.5f;  			for (S32 i=0;i<(S32)mPath.size();i++)  			{ -				mPath[i].mPos.mV[0] = toggle; +				mPath[i].mPos.getF32ptr()[0] = toggle;  				if (toggle == 0.5f)  					toggle = -0.5f;  				else @@ -1638,13 +1570,16 @@ BOOL LLPath::generate(const LLPathParams& params, F32 detail, S32 split,  		for (S32 i=0;i<np;i++)  		{  			F32 t = (F32)i * mStep; -			mPath[i].mPos.setVec(0, +			mPath[i].mPos.set(0,  								lerp(0,   -sin(F_PI*params.getTwist()*t)*0.5f,t),  								lerp(-0.5, cos(F_PI*params.getTwist()*t)*0.5f,t)); -			mPath[i].mScale.mV[0] = lerp(1,params.getScale().mV[0],t); -			mPath[i].mScale.mV[1] = lerp(1,params.getScale().mV[1],t); +			mPath[i].mScale.set(lerp(1,params.getScale().mV[0],t), +								lerp(1,params.getScale().mV[1],t), 0,1);  			mPath[i].mTexT  = t; -			mPath[i].mRot.setQuat(F_PI * params.getTwist() * t,1,0,0); +			LLQuaternion quat; +			quat.setQuat(F_PI * params.getTwist() * t,1,0,0); +			LLMatrix3 tmp(quat); +			mPath[i].mRot.loadu(tmp);  		}  		break; @@ -1668,11 +1603,15 @@ BOOL LLDynamicPath::generate(const LLPathParams& params, F32 detail, S32 split,  		// Path hasn't been generated yet.  		// Some algorithms later assume at least TWO path points.  		resizePath(2); +		LLQuaternion quat; +		quat.setQuat(0,0,0); +		LLMatrix3 tmp(quat); +  		for (U32 i = 0; i < 2; i++)  		{ -			mPath[i].mPos.setVec(0, 0, 0); -			mPath[i].mRot.setQuat(0, 0, 0); -			mPath[i].mScale.setVec(1, 1); +			mPath[i].mPos.set(0, 0, 0); +			mPath[i].mRot.loadu(tmp); +			mPath[i].mScale.set(1, 1, 0, 1);  			mPath[i].mTexT = 0;  		}  	} @@ -2045,7 +1984,7 @@ LLVolume::LLVolume(const LLVolumeParams ¶ms, const F32 detail, const BOOL ge  	mHullIndices = NULL;  	mNumHullPoints = 0;  	mNumHullIndices = 0; - +	  	// set defaults  	if (mParams.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE)  	{ @@ -2105,6 +2044,7 @@ LLVolume::~LLVolume()  BOOL LLVolume::generate()  { +	LL_CHECK_MEMORY  	llassert_always(mProfilep);  	//Added 10.03.05 Dave Parks @@ -2141,20 +2081,6 @@ BOOL LLVolume::generate()  		mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);  	} -	//******************************************************************** -	//debug info, to be removed -	if((U32)(mPathp->mPath.size() * mProfilep->mProfile.size()) > (1u << 20)) -	{ -		llinfos << "sizeS: " << mPathp->mPath.size() << " sizeT: " << mProfilep->mProfile.size() << llendl ; -		llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ; -		llinfos << mParams << llendl ; -		llinfos << "more info to check if mProfilep is deleted or not." << llendl ; -		llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ; - -		llerrs << "LLVolume corrupted!" << llendl ; -	} -	//******************************************************************** -  	BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split);  	BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split); @@ -2163,21 +2089,6 @@ BOOL LLVolume::generate()  		S32 sizeS = mPathp->mPath.size();  		S32 sizeT = mProfilep->mProfile.size(); -		//******************************************************************** -		//debug info, to be removed -		if((U32)(sizeS * sizeT) > (1u << 20)) -		{ -			llinfos << "regenPath: " << (S32)regenPath << " regenProf: " << (S32)regenProf << llendl ; -			llinfos << "sizeS: " << sizeS << " sizeT: " << sizeT << llendl ; -			llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ; -			llinfos << mParams << llendl ; -			llinfos << "more info to check if mProfilep is deleted or not." << llendl ; -			llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ; - -			llerrs << "LLVolume corrupted!" << llendl ; -		} -		//******************************************************************** -  		sNumMeshPoints -= mMesh.size();  		mMesh.resize(sizeT * sizeS);  		sNumMeshPoints += mMesh.size();		 @@ -2185,22 +2096,39 @@ BOOL LLVolume::generate()  		//generate vertex positions  		// Run along the path. +		LLVector4a* dst = mMesh.mArray; +  		for (S32 s = 0; s < sizeS; ++s)  		{ -			LLVector2  scale = mPathp->mPath[s].mScale; -			LLQuaternion rot = mPathp->mPath[s].mRot; +			F32* scale = mPathp->mPath[s].mScale.getF32ptr(); +			 +			F32 sc [] =  +			{ scale[0], 0, 0, 0, +				0, scale[1], 0, 0, +				0, 0, scale[2], 0, +					0, 0, 0, 1 }; +			 +			LLMatrix4 rot((F32*) mPathp->mPath[s].mRot.mMatrix); +			LLMatrix4 scale_mat(sc); +			 +			scale_mat *= rot; +			 +			LLMatrix4a rot_mat; +			rot_mat.loadu(scale_mat); +			 +			LLVector4a* profile = mProfilep->mProfile.mArray; +			LLVector4a* end_profile = profile+sizeT; +			LLVector4a offset = mPathp->mPath[s].mPos; + +			LLVector4a tmp;  			// Run along the profile. -			for (S32 t = 0; t < sizeT; ++t) +			while (profile < end_profile)  			{ -				S32 m = s*sizeT + t; -				Point& pt = mMesh[m]; -				 -				pt.mPos.mV[0] = mProfilep->mProfile[t].mV[0] * scale.mV[0]; -				pt.mPos.mV[1] = mProfilep->mProfile[t].mV[1] * scale.mV[1]; -				pt.mPos.mV[2] = 0.0f; -				pt.mPos       = pt.mPos * rot; -				pt.mPos      += mPathp->mPath[s].mPos; +				rot_mat.rotate(*profile++, tmp); +				dst->setAdd(tmp,offset); +				llassert(less_than_max_mag(*dst)); +				++dst;  			}  		} @@ -2210,9 +2138,11 @@ BOOL LLVolume::generate()  			LLFaceID id = iter->mFaceID;  			mFaceMask |= id;  		} -		 +		LL_CHECK_MEMORY  		return TRUE;  	} + +	LL_CHECK_MEMORY  	return FALSE;  } @@ -2790,14 +2720,16 @@ void LLVolume::createVolumeFaces()  } -inline LLVector3 sculpt_rgb_to_vector(U8 r, U8 g, U8 b) +inline LLVector4a sculpt_rgb_to_vector(U8 r, U8 g, U8 b)  {  	// maps RGB values to vector values [0..255] -> [-0.5..0.5] -	LLVector3 value; -	value.mV[VX] = r / 255.f - 0.5f; -	value.mV[VY] = g / 255.f - 0.5f; -	value.mV[VZ] = b / 255.f - 0.5f; +	LLVector4a value; +	LLVector4a sub(0.5f, 0.5f, 0.5f); +	value.set(r,g,b); +	value.mul(1.f/255.f); +	value.sub(sub); +	  	return value;  } @@ -2817,21 +2749,21 @@ inline U32 sculpt_st_to_index(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_w  } -inline LLVector3 sculpt_index_to_vector(U32 index, const U8* sculpt_data) +inline LLVector4a sculpt_index_to_vector(U32 index, const U8* sculpt_data)  { -	LLVector3 v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]); +	LLVector4a v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]);  	return v;  } -inline LLVector3 sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) +inline LLVector4a sculpt_st_to_vector(S32 s, S32 t, S32 size_s, S32 size_t, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)  {  	U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components);  	return sculpt_index_to_vector(index, sculpt_data);  } -inline LLVector3 sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data) +inline LLVector4a sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)  {  	U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components); @@ -2853,15 +2785,26 @@ F32 LLVolume::sculptGetSurfaceArea()  		for (S32 t = 0; t < sizeT-1; t++)  		{  			// get four corners of quad -			LLVector3 p1 = mMesh[(s  )*sizeT + (t  )].mPos; -			LLVector3 p2 = mMesh[(s+1)*sizeT + (t  )].mPos; -			LLVector3 p3 = mMesh[(s  )*sizeT + (t+1)].mPos; -			LLVector3 p4 = mMesh[(s+1)*sizeT + (t+1)].mPos; +			LLVector4a& p1 = mMesh[(s  )*sizeT + (t  )]; +			LLVector4a& p2 = mMesh[(s+1)*sizeT + (t  )]; +			LLVector4a& p3 = mMesh[(s  )*sizeT + (t+1)]; +			LLVector4a& p4 = mMesh[(s+1)*sizeT + (t+1)];  			// 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.f; +			LLVector4a v0,v1,v2,v3; +			v0.setSub(p1,p2); +			v1.setSub(p1,p3); +			v2.setSub(p4,p2); +			v3.setSub(p4,p3); + +			LLVector4a cross1, cross2; +			cross1.setCross3(v0,v1); +			cross2.setCross3(v2,v3); + +			//LLVector3 cross1 = (p1 - p2) % (p1 - p3); +			//LLVector3 cross2 = (p4 - p2) % (p4 - p3); +			 +			area += (cross1.getLength3() + cross2.getLength3()).getF32() / 2.f;  		}  	} @@ -2882,17 +2825,19 @@ void LLVolume::sculptGeneratePlaceholder()  		for (S32 t = 0; t < sizeT; t++)  		{  			S32 i = t + line; -			Point& pt = mMesh[i]; +			LLVector4a& pt = mMesh[i];  			F32 u = (F32)s/(sizeS-1);  			F32 v = (F32)t/(sizeT-1);  			const F32 RADIUS = (F32) 0.3; -					 -			pt.mPos.mV[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); -			pt.mPos.mV[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); -			pt.mPos.mV[2] = (F32)(cos(F_PI * v) * RADIUS); +			 +			F32* p = pt.getF32ptr(); + +			p[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS); +			p[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS); +			p[2] = (F32)(cos(F_PI * v) * RADIUS);  		}  		line += sizeT; @@ -2917,7 +2862,7 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8  		for (S32 t = 0; t < sizeT; t++)  		{  			S32 i = t + line; -			Point& pt = mMesh[i]; +			LLVector4a& pt = mMesh[i];  			S32 reversed_t = t; @@ -2974,11 +2919,12 @@ void LLVolume::sculptGenerateMapVertices(U16 sculpt_width, U16 sculpt_height, S8  				}  			} -			pt.mPos = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data); +			pt = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data);  			if (sculpt_mirror)  			{ -				pt.mPos.mV[VX] *= -1.f; +				LLVector4a scale(-1.f,1,1,1); +				pt.mul(scale);  			}  		} @@ -3560,627 +3506,6 @@ bool LLVolumeParams::validate(U8 prof_curve, F32 prof_begin, F32 prof_end, F32 h  	return true;  } -S32 *LLVolume::getTriangleIndices(U32 &num_indices) const -{ -	S32 expected_num_triangle_indices = getNumTriangleIndices(); -	if (expected_num_triangle_indices > MAX_VOLUME_TRIANGLE_INDICES) -	{ -		// we don't allow LLVolumes with this many vertices -		llwarns << "Couldn't allocate triangle indices" << llendl; -		num_indices = 0; -		return NULL; -	} - -	S32* index = new S32[expected_num_triangle_indices]; -	S32 count = 0; - -	// Let's do this totally diffently, as we don't care about faces... -	// Counter-clockwise triangles are forward facing... - -	BOOL open = getProfile().isOpen(); -	BOOL hollow = (mParams.getProfileParams().getHollow() > 0); -	BOOL path_open = getPath().isOpen(); -	S32 size_s, size_s_out, size_t; -	S32 s, t, i; -	size_s = getProfile().getTotal(); -	size_s_out = getProfile().getTotalOut(); -	size_t = getPath().mPath.size(); - -	// NOTE -- if the construction of the triangles below ever changes -	// then getNumTriangleIndices() method may also have to be updated. - -	if (open)		/* Flawfinder: ignore */ -	{ -		if (hollow) -		{ -			// Open hollow -- much like the closed solid, except we  -			// we need to stitch up the gap between s=0 and s=size_s-1 - -			for (t = 0; t < size_t - 1; t++) -			{ -				// The outer face, first cut, and inner face -				for (s = 0; s < size_s - 1; s++) -				{ -					i  = s + t*size_s; -					index[count++]  = i;				// x,y -					index[count++]  = i + 1;			// x+1,y -					index[count++]  = i + size_s;		// x,y+1 -	 -					index[count++]  = i + size_s;		// x,y+1 -					index[count++]  = i + 1;			// x+1,y -					index[count++]  = i + size_s + 1;	// x+1,y+1 -				} - -				// The other cut face -				index[count++]  = s + t*size_s;		// x,y -				index[count++]  = 0 + t*size_s;		// x+1,y -				index[count++]  = s + (t+1)*size_s;	// x,y+1 -	 -				index[count++]  = s + (t+1)*size_s;	// x,y+1 -				index[count++]  = 0 + t*size_s;		// x+1,y -				index[count++]  = 0 + (t+1)*size_s;	// x+1,y+1 -			} - -			// Do the top and bottom caps, if necessary -			if (path_open) -			{ -				// Top cap -				S32 pt1 = 0; -				S32 pt2 = size_s-1; -				S32 i   = (size_t - 1)*size_s; - -				while (pt2 - pt1 > 1) -				{ -					// Use the profile points instead of the mesh, since you want -					// the un-transformed profile distances. -					LLVector3 p1 = getProfile().mProfile[pt1]; -					LLVector3 p2 = getProfile().mProfile[pt2]; -					LLVector3 pa = getProfile().mProfile[pt1+1]; -					LLVector3 pb = getProfile().mProfile[pt2-1]; - -					p1.mV[VZ] = 0.f; -					p2.mV[VZ] = 0.f; -					pa.mV[VZ] = 0.f; -					pb.mV[VZ] = 0.f; - -					// Use area of triangle to determine backfacing -					F32 area_1a2, area_1ba, area_21b, area_2ab; -					area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -								(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -								(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - -					area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -								(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -								(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - -					area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -								(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -					area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -								(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -					BOOL use_tri1a2 = TRUE; -					BOOL tri_1a2 = TRUE; -					BOOL tri_21b = TRUE; - -					if (area_1a2 < 0) -					{ -						tri_1a2 = FALSE; -					} -					if (area_2ab < 0) -					{ -						// Can't use, because it contains point b -						tri_1a2 = FALSE; -					} -					if (area_21b < 0) -					{ -						tri_21b = FALSE; -					} -					if (area_1ba < 0) -					{ -						// Can't use, because it contains point b -						tri_21b = FALSE; -					} - -					if (!tri_1a2) -					{ -						use_tri1a2 = FALSE; -					} -					else if (!tri_21b) -					{ -						use_tri1a2 = TRUE; -					} -					else -					{ -						LLVector3 d1 = p1 - pa; -						LLVector3 d2 = p2 - pb; - -						if (d1.magVecSquared() < d2.magVecSquared()) -						{ -							use_tri1a2 = TRUE; -						} -						else -						{ -							use_tri1a2 = FALSE; -						} -					} - -					if (use_tri1a2) -					{ -						index[count++] = pt1 + i; -						index[count++] = pt1 + 1 + i; -						index[count++] = pt2 + i; -						pt1++; -					} -					else -					{ -						index[count++] = pt1 + i; -						index[count++] = pt2 - 1 + i; -						index[count++] = pt2 + i; -						pt2--; -					} -				} - -				// Bottom cap -				pt1          = 0; -				pt2          = size_s-1; -				while (pt2 - pt1 > 1) -				{ -					// Use the profile points instead of the mesh, since you want -					// the un-transformed profile distances. -					LLVector3 p1 = getProfile().mProfile[pt1]; -					LLVector3 p2 = getProfile().mProfile[pt2]; -					LLVector3 pa = getProfile().mProfile[pt1+1]; -					LLVector3 pb = getProfile().mProfile[pt2-1]; - -					p1.mV[VZ] = 0.f; -					p2.mV[VZ] = 0.f; -					pa.mV[VZ] = 0.f; -					pb.mV[VZ] = 0.f; - -					// Use area of triangle to determine backfacing -					F32 area_1a2, area_1ba, area_21b, area_2ab; -					area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -								(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -								(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - -					area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -								(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -								(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - -					area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -								(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -					area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -								(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -					BOOL use_tri1a2 = TRUE; -					BOOL tri_1a2 = TRUE; -					BOOL tri_21b = TRUE; - -					if (area_1a2 < 0) -					{ -						tri_1a2 = FALSE; -					} -					if (area_2ab < 0) -					{ -						// Can't use, because it contains point b -						tri_1a2 = FALSE; -					} -					if (area_21b < 0) -					{ -						tri_21b = FALSE; -					} -					if (area_1ba < 0) -					{ -						// Can't use, because it contains point b -						tri_21b = FALSE; -					} - -					if (!tri_1a2) -					{ -						use_tri1a2 = FALSE; -					} -					else if (!tri_21b) -					{ -						use_tri1a2 = TRUE; -					} -					else -					{ -						LLVector3 d1 = p1 - pa; -						LLVector3 d2 = p2 - pb; - -						if (d1.magVecSquared() < d2.magVecSquared()) -						{ -							use_tri1a2 = TRUE; -						} -						else -						{ -							use_tri1a2 = FALSE; -						} -					} - -					if (use_tri1a2) -					{ -						index[count++] = pt1; -						index[count++] = pt2; -						index[count++] = pt1 + 1; -						pt1++; -					} -					else -					{ -						index[count++] = pt1; -						index[count++] = pt2; -						index[count++] = pt2 - 1; -						pt2--; -					} -				} -			} -		} -		else -		{ -			// Open solid - -			for (t = 0; t < size_t - 1; t++) -			{ -				// Outer face + 1 cut face -				for (s = 0; s < size_s - 1; s++) -				{ -					i  = s + t*size_s; - -					index[count++]  = i;				// x,y -					index[count++]  = i + 1;			// x+1,y -					index[count++]  = i + size_s;		// x,y+1 - -					index[count++]  = i + size_s;		// x,y+1 -					index[count++]  = i + 1;			// x+1,y -					index[count++]  = i + size_s + 1;	// x+1,y+1 -				} - -				// The other cut face -				index[count++] = (size_s - 1) + (t*size_s);		// x,y -				index[count++] = 0 + t*size_s;					// x+1,y -				index[count++] = (size_s - 1) + (t+1)*size_s;	// x,y+1 - -				index[count++] = (size_s - 1) + (t+1)*size_s;	// x,y+1 -				index[count++] = 0 + (t*size_s);				// x+1,y -				index[count++] = 0 + (t+1)*size_s;				// x+1,y+1 -			} - -			// Do the top and bottom caps, if necessary -			if (path_open) -			{ -				for (s = 0; s < size_s - 2; s++) -				{ -					index[count++] = s+1; -					index[count++] = s; -					index[count++] = size_s - 1; -				} - -				// We've got a top cap -				S32 offset = (size_t - 1)*size_s; -				for (s = 0; s < size_s - 2; s++) -				{ -					// Inverted ordering from bottom cap. -					index[count++] = offset + size_s - 1; -					index[count++] = offset + s; -					index[count++] = offset + s + 1; -				} -			} -		} -	} -	else if (hollow) -	{ -		// Closed hollow -		// Outer face -		 -		for (t = 0; t < size_t - 1; t++) -		{ -			for (s = 0; s < size_s_out - 1; s++) -			{ -				i  = s + t*size_s; - -				index[count++]  = i;				// x,y -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + size_s;		// x,y+1 - -				index[count++]  = i + size_s;		// x,y+1 -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + 1 + size_s;	// x+1,y+1 -			} -		} - -		// Inner face -		// Invert facing from outer face -		for (t = 0; t < size_t - 1; t++) -		{ -			for (s = size_s_out; s < size_s - 1; s++) -			{ -				i  = s + t*size_s; - -				index[count++]  = i;				// x,y -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + size_s;		// x,y+1 - -				index[count++]  = i + size_s;		// x,y+1 -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + 1 + size_s;	// x+1,y+1 -			} -		} - -		// Do the top and bottom caps, if necessary -		if (path_open) -		{ -			// Top cap -			S32 pt1 = 0; -			S32 pt2 = size_s-1; -			S32 i   = (size_t - 1)*size_s; - -			while (pt2 - pt1 > 1) -			{ -				// Use the profile points instead of the mesh, since you want -				// the un-transformed profile distances. -				LLVector3 p1 = getProfile().mProfile[pt1]; -				LLVector3 p2 = getProfile().mProfile[pt2]; -				LLVector3 pa = getProfile().mProfile[pt1+1]; -				LLVector3 pb = getProfile().mProfile[pt2-1]; - -				p1.mV[VZ] = 0.f; -				p2.mV[VZ] = 0.f; -				pa.mV[VZ] = 0.f; -				pb.mV[VZ] = 0.f; - -				// Use area of triangle to determine backfacing -				F32 area_1a2, area_1ba, area_21b, area_2ab; -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -				BOOL use_tri1a2 = TRUE; -				BOOL tri_1a2 = TRUE; -				BOOL tri_21b = TRUE; - -				if (area_1a2 < 0) -				{ -					tri_1a2 = FALSE; -				} -				if (area_2ab < 0) -				{ -					// Can't use, because it contains point b -					tri_1a2 = FALSE; -				} -				if (area_21b < 0) -				{ -					tri_21b = FALSE; -				} -				if (area_1ba < 0) -				{ -					// Can't use, because it contains point b -					tri_21b = FALSE; -				} - -				if (!tri_1a2) -				{ -					use_tri1a2 = FALSE; -				} -				else if (!tri_21b) -				{ -					use_tri1a2 = TRUE; -				} -				else -				{ -					LLVector3 d1 = p1 - pa; -					LLVector3 d2 = p2 - pb; - -					if (d1.magVecSquared() < d2.magVecSquared()) -					{ -						use_tri1a2 = TRUE; -					} -					else -					{ -						use_tri1a2 = FALSE; -					} -				} - -				if (use_tri1a2) -				{ -					index[count++] = pt1 + i; -					index[count++] = pt1 + 1 + i; -					index[count++] = pt2 + i; -					pt1++; -				} -				else -				{ -					index[count++] = pt1 + i; -					index[count++] = pt2 - 1 + i; -					index[count++] = pt2 + i; -					pt2--; -				} -			} - -			// Bottom cap -			pt1          = 0; -			pt2          = size_s-1; -			while (pt2 - pt1 > 1) -			{ -				// Use the profile points instead of the mesh, since you want -				// the un-transformed profile distances. -				LLVector3 p1 = getProfile().mProfile[pt1]; -				LLVector3 p2 = getProfile().mProfile[pt2]; -				LLVector3 pa = getProfile().mProfile[pt1+1]; -				LLVector3 pb = getProfile().mProfile[pt2-1]; - -				p1.mV[VZ] = 0.f; -				p2.mV[VZ] = 0.f; -				pa.mV[VZ] = 0.f; -				pb.mV[VZ] = 0.f; - -				// Use area of triangle to determine backfacing -				F32 area_1a2, area_1ba, area_21b, area_2ab; -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); - -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); - -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); - -				BOOL use_tri1a2 = TRUE; -				BOOL tri_1a2 = TRUE; -				BOOL tri_21b = TRUE; - -				if (area_1a2 < 0) -				{ -					tri_1a2 = FALSE; -				} -				if (area_2ab < 0) -				{ -					// Can't use, because it contains point b -					tri_1a2 = FALSE; -				} -				if (area_21b < 0) -				{ -					tri_21b = FALSE; -				} -				if (area_1ba < 0) -				{ -					// Can't use, because it contains point b -					tri_21b = FALSE; -				} - -				if (!tri_1a2) -				{ -					use_tri1a2 = FALSE; -				} -				else if (!tri_21b) -				{ -					use_tri1a2 = TRUE; -				} -				else -				{ -					LLVector3 d1 = p1 - pa; -					LLVector3 d2 = p2 - pb; - -					if (d1.magVecSquared() < d2.magVecSquared()) -					{ -						use_tri1a2 = TRUE; -					} -					else -					{ -						use_tri1a2 = FALSE; -					} -				} - -				if (use_tri1a2) -				{ -					index[count++] = pt1; -					index[count++] = pt2; -					index[count++] = pt1 + 1; -					pt1++; -				} -				else -				{ -					index[count++] = pt1; -					index[count++] = pt2; -					index[count++] = pt2 - 1; -					pt2--; -				} -			} -		}		 -	} -	else -	{ -		// Closed solid.  Easy case. -		for (t = 0; t < size_t - 1; t++) -		{ -			for (s = 0; s < size_s - 1; s++) -			{ -				// Should wrap properly, but for now... -				i  = s + t*size_s; - -				index[count++]  = i;				// x,y -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + size_s;		// x,y+1 - -				index[count++]  = i + size_s;		// x,y+1 -				index[count++]  = i + 1;			// x+1,y -				index[count++]  = i + size_s + 1;	// x+1,y+1 -			} -		} - -		// Do the top and bottom caps, if necessary -		if (path_open) -		{ -			// bottom cap -			for (s = 1; s < size_s - 2; s++) -			{ -				index[count++] = s+1; -				index[count++] = s; -				index[count++] = 0; -			} - -			// top cap -			S32 offset = (size_t - 1)*size_s; -			for (s = 1; s < size_s - 2; s++) -			{ -				// Inverted ordering from bottom cap. -				index[count++] = offset; -				index[count++] = offset + s; -				index[count++] = offset + s + 1; -			} -		} -	} - -#ifdef LL_DEBUG -	// assert that we computed the correct number of indices -	if (count != expected_num_triangle_indices ) -	{ -		llerrs << "bad index count prediciton:" -			<< "  expected=" << expected_num_triangle_indices  -			<< " actual=" << count << llendl; -	} -#endif - -#if 0 -	// verify that each index does not point beyond the size of the mesh -	S32 num_vertices = mMesh.size(); -	for (i = 0; i < count; i+=3) -	{ -		llinfos << index[i] << ":" << index[i+1] << ":" << index[i+2] << llendl; -		llassert(index[i] < num_vertices); -		llassert(index[i+1] < num_vertices); -		llassert(index[i+2] < num_vertices); -	} -#endif - -	num_indices = count; -	return index; -} -  void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts)  { //attempt to approximate the number of triangles that will result from generating a volume LoD set for the   	//supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost @@ -4198,63 +3523,6 @@ void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts)  	}  } -S32 LLVolume::getNumTriangleIndices() const -{ -	BOOL profile_open = getProfile().isOpen(); -	BOOL hollow = (mParams.getProfileParams().getHollow() > 0); -	BOOL path_open = getPath().isOpen(); - -	S32 size_s, size_s_out, size_t; -	size_s = getProfile().getTotal(); -	size_s_out = getProfile().getTotalOut(); -	size_t = getPath().mPath.size(); - -	S32 count = 0; -	if (profile_open)		/* Flawfinder: ignore */ -	{ -		if (hollow) -		{ -			// Open hollow -- much like the closed solid, except we  -			// we need to stitch up the gap between s=0 and s=size_s-1 -			count = (size_t - 1) * (((size_s -1) * 6) + 6); -		} -		else -		{ -			count = (size_t - 1) * (((size_s -1) * 6) + 6);  -		} -	} -	else if (hollow) -	{ -		// Closed hollow -		// Outer face -		count = (size_t - 1) * (size_s_out - 1) * 6; - -		// Inner face -		count += (size_t - 1) * ((size_s - 1) - size_s_out) * 6; -	} -	else -	{ -		// Closed solid.  Easy case. -		count = (size_t - 1) * (size_s - 1) * 6; -	} - -	if (path_open) -	{ -		S32 cap_triangle_count = size_s - 3; -		if ( profile_open -			|| hollow ) -		{ -			cap_triangle_count = size_s - 2; -		} -		if ( cap_triangle_count > 0 ) -		{ -			// top and bottom caps -			count += cap_triangle_count * 2 * 3; -		} -	} -	return count; -} -  S32 LLVolume::getNumTriangles(S32* vcount) const  { @@ -5180,6 +4448,7 @@ LLVolumeFace::LLVolumeFace() :  	mNumS(0),  	mNumT(0),  	mNumVertices(0), +	mNumAllocatedVertices(0),  	mNumIndices(0),  	mPositions(NULL),  	mNormals(NULL), @@ -5187,7 +4456,8 @@ LLVolumeFace::LLVolumeFace() :  	mTexCoords(NULL),  	mIndices(NULL),  	mWeights(NULL), -	mOctree(NULL) +	mOctree(NULL), +	mOptimized(FALSE)  {  	mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);  	mExtents[0].splat(-0.5f); @@ -5203,6 +4473,7 @@ LLVolumeFace::LLVolumeFace(const LLVolumeFace& src)  	mNumS(0),  	mNumT(0),  	mNumVertices(0), +	mNumAllocatedVertices(0),  	mNumIndices(0),  	mPositions(NULL),  	mNormals(NULL), @@ -5240,8 +4511,6 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  	freeData(); -	LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 3*sizeof(LLVector4a)); -  	resizeVertices(src.mNumVertices);  	resizeIndices(src.mNumIndices); @@ -5257,12 +4526,6 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  		{  			LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);  		} -		else -		{ -			ll_aligned_free_16(mTexCoords) ; -			mTexCoords = NULL ; -		} -  		if (src.mBinormals)  		{ @@ -5294,6 +4557,8 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)  		LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size);  	} +	mOptimized = src.mOptimized; +  	//delete   	return *this;  } @@ -5308,12 +4573,13 @@ LLVolumeFace::~LLVolumeFace()  void LLVolumeFace::freeData()  { -	ll_aligned_free_16(mPositions); +	ll_aligned_free(mPositions);  	mPositions = NULL; -	ll_aligned_free_16( mNormals); + +	//normals and texture coordinates are part of the same buffer as mPositions, do not free them separately  	mNormals = NULL; -	ll_aligned_free_16(mTexCoords);  	mTexCoords = NULL; +  	ll_aligned_free_16(mIndices);  	mIndices = NULL;  	ll_aligned_free_16(mBinormals); @@ -5331,52 +4597,23 @@ BOOL LLVolumeFace::create(LLVolume* volume, BOOL partial_build)  	delete mOctree;  	mOctree = NULL; +	LL_CHECK_MEMORY  	BOOL ret = FALSE ;  	if (mTypeMask & CAP_MASK)  	{  		ret = createCap(volume, partial_build); +		LL_CHECK_MEMORY  	}  	else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK))  	{  		ret = createSide(volume, partial_build); +		LL_CHECK_MEMORY  	}  	else  	{  		llerrs << "Unknown/uninitialized face type!" << llendl;  	} -	//update the range of the texture coordinates -	if(ret) -	{ -		mTexCoordExtents[0].setVec(1.f, 1.f) ; -		mTexCoordExtents[1].setVec(0.f, 0.f) ; - -		for(U32 i = 0 ; i < mNumVertices ; i++) -		{ -			if(mTexCoordExtents[0].mV[0] > mTexCoords[i].mV[0]) -			{ -				mTexCoordExtents[0].mV[0] = mTexCoords[i].mV[0] ; -			} -			if(mTexCoordExtents[1].mV[0] < mTexCoords[i].mV[0]) -			{ -				mTexCoordExtents[1].mV[0] = mTexCoords[i].mV[0] ; -			} - -			if(mTexCoordExtents[0].mV[1] > mTexCoords[i].mV[1]) -			{ -				mTexCoordExtents[0].mV[1] = mTexCoords[i].mV[1] ; -			} -			if(mTexCoordExtents[1].mV[1] < mTexCoords[i].mV[1]) -			{ -				mTexCoordExtents[1].mV[1] = mTexCoords[i].mV[1] ; -			}			 -		} -		mTexCoordExtents[0].mV[0] = llmax(0.f, mTexCoordExtents[0].mV[0]) ; -		mTexCoordExtents[0].mV[1] = llmax(0.f, mTexCoordExtents[0].mV[1]) ; -		mTexCoordExtents[1].mV[0] = llmin(1.f, mTexCoordExtents[1].mV[0]) ; -		mTexCoordExtents[1].mV[1] = llmin(1.f, mTexCoordExtents[1].mV[1]) ; -	} -  	return ret ;  } @@ -5492,22 +4729,13 @@ void LLVolumeFace::optimize(F32 angle_cutoff)  		}  	} -	llassert(new_face.mNumIndices == mNumIndices); -	llassert(new_face.mNumVertices <= mNumVertices); - -	if (angle_cutoff > 1.f && !mNormals) -	{ -		ll_aligned_free_16(new_face.mNormals); -		new_face.mNormals = NULL; -	} - -	if (!mTexCoords) +	// Only swap data if we've actually optimized the mesh +	// +	if (new_face.mNumVertices <= mNumVertices)  	{ -		ll_aligned_free_16(new_face.mTexCoords); -		new_face.mTexCoords = NULL; +		llassert(new_face.mNumIndices == mNumIndices); +		swapData(new_face);  	} - -	swapData(new_face);  }  class LLVCacheTriangleData; @@ -5517,14 +4745,14 @@ class LLVCacheVertexData  public:  	S32 mIdx;  	S32 mCacheTag; -	F32 mScore; +	F64 mScore;  	U32 mActiveTriangles;  	std::vector<LLVCacheTriangleData*> mTriangles;  	LLVCacheVertexData()  	{  		mCacheTag = -1; -		mScore = 0.f; +		mScore = 0.0;  		mActiveTriangles = 0;  		mIdx = -1;  	} @@ -5534,13 +4762,13 @@ class LLVCacheTriangleData  {  public:  	bool mActive; -	F32 mScore; +	F64 mScore;  	LLVCacheVertexData* mVertex[3];  	LLVCacheTriangleData()  	{  		mActive = true; -		mScore = 0.f; +		mScore = 0.0;  		mVertex[0] = mVertex[1] = mVertex[2] = NULL;  	} @@ -5551,7 +4779,7 @@ public:  		{  			if (mVertex[i])  			{ -				llassert_always(mVertex[i]->mActiveTriangles > 0); +				llassert(mVertex[i]->mActiveTriangles > 0);  				mVertex[i]->mActiveTriangles--;  			}  		} @@ -5563,44 +4791,44 @@ public:  	}  }; -const F32 FindVertexScore_CacheDecayPower = 1.5f; -const F32 FindVertexScore_LastTriScore = 0.75f; -const F32 FindVertexScore_ValenceBoostScale = 2.0f; -const F32 FindVertexScore_ValenceBoostPower = 0.5f; +const F64 FindVertexScore_CacheDecayPower = 1.5; +const F64 FindVertexScore_LastTriScore = 0.75; +const F64 FindVertexScore_ValenceBoostScale = 2.0; +const F64 FindVertexScore_ValenceBoostPower = 0.5;  const U32 MaxSizeVertexCache = 32; +const F64 FindVertexScore_Scaler = 1.0/(MaxSizeVertexCache-3); -F32 find_vertex_score(LLVCacheVertexData& data) +F64 find_vertex_score(LLVCacheVertexData& data)  { -	if (data.mActiveTriangles == 0) -	{ //no triangle references this vertex -		return -1.f; -	} - -	F32 score = 0.f; +	F64 score = -1.0; -	S32 cache_idx = data.mCacheTag; +	if (data.mActiveTriangles >= 0) +	{  +		score = 0.0; +		 +		S32 cache_idx = data.mCacheTag; -	if (cache_idx < 0) -	{ -		//not in cache -	} -	else -	{ -		if (cache_idx < 3) -		{ //vertex was in the last triangle -			score = FindVertexScore_LastTriScore; +		if (cache_idx < 0) +		{ +			//not in cache  		}  		else -		{ //more points for being higher in the cache -			F32 scaler = 1.f/(MaxSizeVertexCache-3); -			score = 1.f-((cache_idx-3)*scaler); -			score = powf(score, FindVertexScore_CacheDecayPower); +		{ +			if (cache_idx < 3) +			{ //vertex was in the last triangle +				score = FindVertexScore_LastTriScore; +			} +			else +			{ //more points for being higher in the cache +				score = 1.0-((cache_idx-3)*FindVertexScore_Scaler); +				score = pow(score, FindVertexScore_CacheDecayPower); +			}  		} -	} -	//bonus points for having low valence -	F32 valence_boost = powf((F32)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); -	score += FindVertexScore_ValenceBoostScale * valence_boost; +		//bonus points for having low valence +		F64 valence_boost = pow((F64)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower); +		score += FindVertexScore_ValenceBoostScale * valence_boost; +	}  	return score;  } @@ -5707,32 +4935,44 @@ public:  	void updateScores()  	{ -		for (U32 i = MaxSizeVertexCache; i < MaxSizeVertexCache+3; ++i) -		{ //trailing 3 vertices aren't actually in the cache for scoring purposes -			if (mCache[i]) +		LLVCacheVertexData** data_iter = mCache+MaxSizeVertexCache; +		LLVCacheVertexData** end_data = mCache+MaxSizeVertexCache+3; + +		while(data_iter != end_data) +		{ +			LLVCacheVertexData* data = *data_iter++; +			//trailing 3 vertices aren't actually in the cache for scoring purposes +			if (data)  			{ -				mCache[i]->mCacheTag = -1; +				data->mCacheTag = -1;  			}  		} -		for (U32 i = 0; i < MaxSizeVertexCache; ++i) +		data_iter = mCache; +		end_data = mCache+MaxSizeVertexCache; + +		while (data_iter != end_data)  		{ //update scores of vertices in cache -			if (mCache[i]) +			LLVCacheVertexData* data = *data_iter++; +			if (data)  			{ -				mCache[i]->mScore = find_vertex_score(*(mCache[i])); -				llassert_always(mCache[i]->mCacheTag == i); +				data->mScore = find_vertex_score(*data);  			}  		}  		mBestTriangle = NULL;  		//update triangle scores -		for (U32 i = 0; i < MaxSizeVertexCache+3; ++i) +		data_iter = mCache; +		end_data = mCache+MaxSizeVertexCache+3; + +		while (data_iter != end_data)  		{ -			if (mCache[i]) +			LLVCacheVertexData* data = *data_iter++; +			if (data)  			{ -				for (U32 j = 0; j < mCache[i]->mTriangles.size(); ++j) +				for (std::vector<LLVCacheTriangleData*>::iterator iter = data->mTriangles.begin(), end_iter = data->mTriangles.end(); iter != end_iter; ++iter)  				{ -					LLVCacheTriangleData* tri = mCache[i]->mTriangles[j]; +					LLVCacheTriangleData* tri = *iter;  					if (tri->mActive)  					{  						tri->mScore = tri->mVertex[0]->mScore; @@ -5749,13 +4989,17 @@ public:  		}  		//knock trailing 3 vertices off the cache -		for (U32 i = MaxSizeVertexCache; i < MaxSizeVertexCache+3; ++i) +		data_iter = mCache+MaxSizeVertexCache; +		end_data = mCache+MaxSizeVertexCache+3; +		while (data_iter != end_data)  		{ -			if (mCache[i]) +			LLVCacheVertexData* data = *data_iter; +			if (data)  			{ -				llassert_always(mCache[i]->mCacheTag == -1); -				mCache[i] = NULL; +				llassert(data->mCacheTag == -1); +				*data_iter = NULL;  			} +			++data_iter;  		}  	}  }; @@ -5765,6 +5009,9 @@ void LLVolumeFace::cacheOptimize()  { //optimize for vertex cache according to Forsyth method:     // http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html +	llassert(!mOptimized); +	mOptimized = TRUE; +  	LLVCacheLRU cache;  	if (mNumVertices < 3) @@ -5810,12 +5057,14 @@ void LLVolumeFace::cacheOptimize()  	for (U32 i = 0; i < mNumVertices; i++)  	{ //initialize score values (no cache -- might try a fifo cache here) -		vertex_data[i].mScore = find_vertex_score(vertex_data[i]); -		vertex_data[i].mActiveTriangles = vertex_data[i].mTriangles.size(); +		LLVCacheVertexData& data = vertex_data[i]; -		for (U32 j = 0; j < vertex_data[i].mTriangles.size(); ++j) +		data.mScore = find_vertex_score(data); +		data.mActiveTriangles = data.mTriangles.size(); + +		for (U32 j = 0; j < data.mActiveTriangles; ++j)  		{ -			vertex_data[i].mTriangles[j]->mScore += vertex_data[i].mScore; +			data.mTriangles[j]->mScore += data.mScore;  		}  	} @@ -5885,10 +5134,10 @@ void LLVolumeFace::cacheOptimize()  	//allocate space for new buffer  	S32 num_verts = mNumVertices; -	LLVector4a* pos = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); -	LLVector4a* norm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);  	S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; -	LLVector2* tc = (LLVector2*) ll_aligned_malloc_16(size); +	LLVector4a* pos = (LLVector4a*) ll_aligned_malloc(sizeof(LLVector4a)*2*num_verts+size, 64); +	LLVector4a* norm = pos + num_verts; +	LLVector2* tc = (LLVector2*) (norm + num_verts);  	LLVector4a* wght = NULL;  	if (mWeights) @@ -5936,9 +5185,8 @@ void LLVolumeFace::cacheOptimize()  		mIndices[i] = new_idx[mIndices[i]];  	} -	ll_aligned_free_16(mPositions); -	ll_aligned_free_16(mNormals); -	ll_aligned_free_16(mTexCoords); +	ll_aligned_free(mPositions); +	// DO NOT free mNormals and mTexCoords as they are part of mPositions buffer  	ll_aligned_free_16(mWeights);  	ll_aligned_free_16(mBinormals); @@ -6060,8 +5308,10 @@ void	LerpPlanarVertex(LLVolumeFace::VertexData& v0,  BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  { -	const std::vector<LLVolume::Point>& mesh = volume->getMesh(); -	const std::vector<LLVector3>& profile = volume->getProfile().mProfile; +	LL_CHECK_MEMORY		 + +	const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); +	const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile;  	S32 max_s = volume->getProfile().getTotal();  	S32 max_t = volume->getPath().mPath.size(); @@ -6086,9 +5336,9 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  		VertexData baseVert;  		for(S32 t = 0; t < 4; t++)  		{ -			corners[t].getPosition().load3( mesh[offset + (grid_size*t)].mPos.mV); -			corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f; -			corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1]; +			corners[t].getPosition().load4a(mesh[offset + (grid_size*t)].getF32ptr()); +			corners[t].mTexCoord.mV[0] = profile[grid_size*t][0]+0.5f; +			corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t][1];  		}  		{ @@ -6169,6 +5419,9 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  		mCenter->mul(0.5f);   	} +	llassert(less_than_max_mag(mExtents[0])); +	llassert(less_than_max_mag(mExtents[1])); +  	if (!partial_build)  	{  		resizeIndices(grid_size*grid_size*6); @@ -6199,6 +5452,7 @@ BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)  		}  	} +	LL_CHECK_MEMORY  	return TRUE;  } @@ -6217,8 +5471,8 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	S32 num_vertices = 0, num_indices = 0; -	const std::vector<LLVolume::Point>& mesh = volume->getMesh(); -	const std::vector<LLVector3>& profile = volume->getProfile().mProfile; +	const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); +	const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile;  	// All types of caps have the same number of vertices and indices  	num_vertices = profile.size(); @@ -6238,13 +5492,14 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	{  		resizeVertices(num_vertices);  		allocateBinormals(num_vertices); -  		if (!partial_build)  		{  			resizeIndices(num_indices);  		}  	} +	LL_CHECK_MEMORY; +  	S32 max_s = volume->getProfile().getTotal();  	S32 max_t = volume->getPath().mPath.size(); @@ -6275,35 +5530,68 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	LLVector4a* binorm = (LLVector4a*) mBinormals;  	// Copy the vertices into the array -	for (S32 i = 0; i < num_vertices; i++) + +	const LLVector4a* src = mesh.mArray+offset; +	const LLVector4a* end = src+num_vertices; +	 +	min = *src; +	max = min; +	 +	 +	const LLVector4a* p = profile.mArray; + +	if (mTypeMask & TOP_MASK)  	{ -		if (mTypeMask & TOP_MASK) -		{ -			tc[i].mV[0] = profile[i].mV[0]+0.5f; -			tc[i].mV[1] = profile[i].mV[1]+0.5f; -		} -		else +		min_uv.set((*p)[0]+0.5f, +					(*p)[1]+0.5f); + +		max_uv = min_uv; + +		while(src < end)  		{ -			// Mirror for underside. -			tc[i].mV[0] = profile[i].mV[0]+0.5f; -			tc[i].mV[1] = 0.5f - profile[i].mV[1]; -		} +			tc->mV[0] = (*p)[0]+0.5f; +			tc->mV[1] = (*p)[1]+0.5f; -		pos[i].load3(mesh[i + offset].mPos.mV); +			llassert(less_than_max_mag(*src)); +			update_min_max(min,max,*src); +			update_min_max(min_uv, max_uv, *tc); -		if (i == 0) -		{ -			max = pos[i]; -			min = max; -			min_uv = max_uv = tc[i]; +			*pos = *src; +		 +			++p; +			++tc; +			++src; +			++pos;  		} -		else +	} +	else +	{ + +		min_uv.set((*p)[0]+0.5f, +				   0.5f - (*p)[1]); +		max_uv = min_uv; + +		while(src < end)  		{ -			update_min_max(min,max,pos[i]); -			update_min_max(min_uv, max_uv, tc[i]); +			// Mirror for underside. +			tc->mV[0] = (*p)[0]+0.5f; +			tc->mV[1] = 0.5f - (*p)[1]; +		 +			llassert(less_than_max_mag(*src)); +			update_min_max(min,max,*src); +			update_min_max(min_uv, max_uv, *tc); +		 +			*pos = *src; +		 +			++p; +			++tc; +			++src; +			++pos;  		}  	} +	LL_CHECK_MEMORY +  	mCenter->setAdd(min, max);  	mCenter->mul(0.5f);  @@ -6340,15 +5628,25 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK))  	{ -		pos[num_vertices] = *mCenter; -		tc[num_vertices] = cuv; +		*pos++ = *mCenter; +		*tc++ = cuv;  		num_vertices++;  	} -		 -	for (S32 i = 0; i < num_vertices; i++) +	 +	LL_CHECK_MEMORY + +	F32* dst_binorm = (F32*) binorm; +	F32* end_binorm = (F32*) (binorm+num_vertices); + +	F32* dst_norm = (F32*) norm; +	 +	while (dst_binorm < end_binorm)  	{ -		binorm[i].load4a(binormal.getF32ptr()); -		norm[i].load4a(normal.getF32ptr()); +		binormal.store4a(dst_binorm); +		normal.store4a(dst_norm); + +		dst_binorm += 4; +		dst_norm += 4;  	}  	if (partial_build) @@ -6369,33 +5667,38 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  			{  				// Use the profile points instead of the mesh, since you want  				// the un-transformed profile distances. -				LLVector3 p1 = profile[pt1]; -				LLVector3 p2 = profile[pt2]; -				LLVector3 pa = profile[pt1+1]; -				LLVector3 pb = profile[pt2-1]; +				const LLVector4a& p1 = profile[pt1]; +				const LLVector4a& p2 = profile[pt2]; +				const LLVector4a& pa = profile[pt1+1]; +				const LLVector4a& pb = profile[pt2-1]; -				p1.mV[VZ] = 0.f; -				p2.mV[VZ] = 0.f; -				pa.mV[VZ] = 0.f; -				pb.mV[VZ] = 0.f; +				const F32* p1V = p1.getF32ptr(); +				const F32* p2V = p2.getF32ptr(); +				const F32* paV = pa.getF32ptr(); +				const F32* pbV = pb.getF32ptr(); + +				//p1.mV[VZ] = 0.f; +				//p2.mV[VZ] = 0.f; +				//pa.mV[VZ] = 0.f; +				//pb.mV[VZ] = 0.f;  				// Use area of triangle to determine backfacing  				F32 area_1a2, area_1ba, area_21b, area_2ab; -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); +				area_1a2 =  (p1V[0]*paV[1] - paV[0]*p1V[1]) + +							(paV[0]*p2V[1] - p2V[0]*paV[1]) + +							(p2V[0]*p1V[1] - p1V[0]*p2V[1]); -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); +				area_1ba =  (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + +							(pbV[0]*paV[1] - paV[0]*pbV[1]) + +							(paV[0]*p1V[1] - p1V[0]*paV[1]); -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); +				area_21b =  (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + +							(p1V[0]*pbV[1] - pbV[0]*p1V[1]) + +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]); -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); +				area_2ab =  (p2V[0]*paV[1] - paV[0]*p2V[1]) + +							(paV[0]*pbV[1] - pbV[0]*paV[1]) + +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]);  				BOOL use_tri1a2 = TRUE;  				BOOL tri_1a2 = TRUE; @@ -6430,10 +5733,13 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  				}  				else  				{ -					LLVector3 d1 = p1 - pa; -					LLVector3 d2 = p2 - pb; +					LLVector4a d1; +					d1.setSub(p1, pa); +					 +					LLVector4a d2;  +					d2.setSub(p2, pb); -					if (d1.magVecSquared() < d2.magVecSquared()) +					if (d1.dot3(d1) < d2.dot3(d2))  					{  						use_tri1a2 = TRUE;  					} @@ -6472,33 +5778,33 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  			{  				// Use the profile points instead of the mesh, since you want  				// the un-transformed profile distances. -				LLVector3 p1 = profile[pt1]; -				LLVector3 p2 = profile[pt2]; -				LLVector3 pa = profile[pt1+1]; -				LLVector3 pb = profile[pt2-1]; - -				p1.mV[VZ] = 0.f; -				p2.mV[VZ] = 0.f; -				pa.mV[VZ] = 0.f; -				pb.mV[VZ] = 0.f; - +				const LLVector4a& p1 = profile[pt1]; +				const LLVector4a& p2 = profile[pt2]; +				const LLVector4a& pa = profile[pt1+1]; +				const LLVector4a& pb = profile[pt2-1]; + +				const F32* p1V = p1.getF32ptr(); +				const F32* p2V = p2.getF32ptr(); +				const F32* paV = pa.getF32ptr(); +				const F32* pbV = pb.getF32ptr(); +				  				// Use area of triangle to determine backfacing  				F32 area_1a2, area_1ba, area_21b, area_2ab; -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) + -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) + -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]); +				area_1a2 =  (p1V[0]*paV[1] - paV[0]*p1V[1]) + +							(paV[0]*p2V[1] - p2V[0]*paV[1]) + +							(p2V[0]*p1V[1] - p1V[0]*p2V[1]); -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) + -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]); +				area_1ba =  (p1V[0]*pbV[1] - pbV[0]*p1V[1]) + +							(pbV[0]*paV[1] - paV[0]*pbV[1]) + +							(paV[0]*p1V[1] - p1V[0]*paV[1]); -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) + -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); +				area_21b =  (p2V[0]*p1V[1] - p1V[0]*p2V[1]) + +							(p1V[0]*pbV[1] - pbV[0]*p1V[1]) + +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]); -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) + -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) + -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]); +				area_2ab =  (p2V[0]*paV[1] - paV[0]*p2V[1]) + +							(paV[0]*pbV[1] - pbV[0]*paV[1]) + +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]);  				BOOL use_tri1a2 = TRUE;  				BOOL tri_1a2 = TRUE; @@ -6533,10 +5839,12 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  				}  				else  				{ -					LLVector3 d1 = p1 - pa; -					LLVector3 d2 = p2 - pb; +					LLVector4a d1; +					d1.setSub(p1,pa); +					LLVector4a d2; +					d2.setSub(p2,pb); -					if (d1.magVecSquared() < d2.magVecSquared()) +					if (d1.dot3(d1) < d2.dot3(d2))  					{  						use_tri1a2 = TRUE;  					} @@ -6585,6 +5893,8 @@ BOOL LLVolumeFace::createCap(LLVolume* volume, BOOL partial_build)  	} + +	LL_CHECK_MEMORY  	return TRUE;  } @@ -6650,24 +5960,22 @@ void LLVolumeFace::createBinormals()  void LLVolumeFace::resizeVertices(S32 num_verts)  { -	ll_aligned_free_16(mPositions); -	ll_aligned_free_16(mNormals); +	ll_aligned_free(mPositions); +	//DO NOT free mNormals and mTexCoords as they are part of mPositions buffer  	ll_aligned_free_16(mBinormals); -	ll_aligned_free_16(mTexCoords); - +	  	mBinormals = NULL;  	if (num_verts)  	{ -		mPositions = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); -		ll_assert_aligned(mPositions, 16); -		mNormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts); -		ll_assert_aligned(mNormals, 16); -  		//pad texture coordinate block end to allow for QWORD reads  		S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF; -		mTexCoords = (LLVector2*) ll_aligned_malloc_16(size); -		ll_assert_aligned(mTexCoords, 16); + +		mPositions = (LLVector4a*) ll_aligned_malloc(sizeof(LLVector4a)*2*num_verts+size, 64); +		mNormals = mPositions+num_verts; +		mTexCoords = (LLVector2*) (mNormals+num_verts); + +		ll_assert_aligned(mPositions, 64);  	}  	else  	{ @@ -6677,6 +5985,7 @@ void LLVolumeFace::resizeVertices(S32 num_verts)  	}  	mNumVertices = num_verts; +	mNumAllocatedVertices = num_verts;  }  void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv) @@ -6687,27 +5996,43 @@ void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv)  void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc)  {  	S32 new_verts = mNumVertices+1; -	S32 new_size = new_verts*16; -	S32 old_size = mNumVertices*16; -	//positions -	mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_size, old_size); -	ll_assert_aligned(mPositions,16); +	if (new_verts > mNumAllocatedVertices) +	{  +		//double buffer size on expansion +		new_verts *= 2; + +		S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF; +		S32 old_tc_size = ((mNumVertices*8)+0xF) & ~0xF; + +		S32 old_vsize = mNumVertices*16; +		 +		S32 new_size = new_verts*16*2+new_tc_size; + +		LLVector4a* old_buf = mPositions; + +		mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64); +		mNormals = mPositions+new_verts; +		mTexCoords = (LLVector2*) (mNormals+new_verts); + +		//positions +		LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize); +		 +		//normals +		LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize); -	//normals -	mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_size, old_size); -	ll_assert_aligned(mNormals,16); - -	//tex coords -	new_size = ((new_verts*8)+0xF) & ~0xF; -	old_size = ((mNumVertices*8)+0xF) & ~0xF; -	mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, new_size, old_size); -	ll_assert_aligned(mTexCoords,16); +		//tex coords +		LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tc_size); +		//just clear binormals +		ll_aligned_free_16(mBinormals); -	//just clear binormals -	ll_aligned_free_16(mBinormals); -	mBinormals = NULL; +		ll_aligned_free(old_buf); + +		mNumAllocatedVertices = new_verts; + +		mBinormals = NULL; +	}  	mPositions[mNumVertices] = pos;  	mNormals[mNumVertices] = norm; @@ -6796,13 +6121,23 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat  		llerrs << "Cannot append empty face." << llendl;  	} +	U32 old_vsize = mNumVertices*16; +	U32 new_vsize = new_count * 16; +	U32 old_tcsize = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF; +	U32 new_tcsize = (new_count*sizeof(LLVector2)+0xF) & ~0xF; +	U32 new_size = new_vsize * 2 + new_tcsize; +  	//allocate new buffer space -	mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_count*sizeof(LLVector4a), mNumVertices*sizeof(LLVector4a)); -	ll_assert_aligned(mPositions, 16); -	mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_count*sizeof(LLVector4a), mNumVertices*sizeof(LLVector4a)); -	ll_assert_aligned(mNormals, 16); -	mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF, (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF); -	ll_assert_aligned(mTexCoords, 16); +	LLVector4a* old_buf = mPositions; +	mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64); +	mNormals = mPositions + new_count; +	mTexCoords = (LLVector2*) (mNormals+new_count); + +	mNumAllocatedVertices = new_count; + +	LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize); +	LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize); +	LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tcsize);  	mNumVertices = new_count; @@ -6862,6 +6197,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat  BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  { +	LL_CHECK_MEMORY  	BOOL flat = mTypeMask & FLAT_MASK;  	U8 sculpt_type = volume->getParams().getSculptType(); @@ -6872,9 +6208,9 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  	S32 num_vertices, num_indices; -	const std::vector<LLVolume::Point>& mesh = volume->getMesh(); -	const std::vector<LLVector3>& profile = volume->getProfile().mProfile; -	const std::vector<LLPath::PathPt>& path_data = volume->getPath().mPath; +	const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh(); +	const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile; +	const LLAlignedArray<LLPath::PathPt,64>& path_data = volume->getPath().mPath;  	S32 max_s = volume->getProfile().getTotal(); @@ -6895,15 +6231,19 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  		}  	} +	LL_CHECK_MEMORY +  	LLVector4a* pos = (LLVector4a*) mPositions; -	LLVector4a* norm = (LLVector4a*) mNormals;  	LLVector2* tc = (LLVector2*) mTexCoords; -	S32 begin_stex = llfloor( profile[mBeginS].mV[2] ); +	F32 begin_stex = floorf(profile[mBeginS][2]);  	S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS;  	S32 cur_vertex = 0; +	S32 end_t = mBeginT+mNumT; +	bool test = (mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2; +  	// Copy the vertices into the array -	for (t = mBeginT; t < mBeginT + mNumT; t++) +	for (t = mBeginT; t < end_t; t++)  	{  		tt = path_data[t].mTexT;  		for (s = 0; s < num_s; s++) @@ -6924,11 +6264,11 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  				// Get s value for tex-coord.  				if (!flat)  				{ -					ss = profile[mBeginS + s].mV[2]; +					ss = profile[mBeginS + s][2];  				}  				else  				{ -					ss = profile[mBeginS + s].mV[2] - begin_stex; +					ss = profile[mBeginS + s][2] - begin_stex;  				}  			} @@ -6948,20 +6288,17 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  				i = mBeginS + s + max_s*t;  			} -			pos[cur_vertex].load3(mesh[i].mPos.mV); -			tc[cur_vertex] = LLVector2(ss,tt); +			llassert(less_than_max_mag(mesh[i])); +			mesh[i].store4a((F32*)(pos+cur_vertex)); +			tc[cur_vertex].set(ss,tt); -			norm[cur_vertex].clear();  			cur_vertex++; -			if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2 && s > 0) +			if (test && s > 0)  			{ - -				pos[cur_vertex].load3(mesh[i].mPos.mV); -				tc[cur_vertex] = LLVector2(ss,tt); -			 -				norm[cur_vertex].clear(); -				 +				llassert(less_than_max_mag(mesh[i])); +				mesh[i].store4a((F32*)(pos+cur_vertex)); +				tc[cur_vertex].set(ss,tt);  				cur_vertex++;  			}  		} @@ -6978,28 +6315,66 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  			}  			i = mBeginS + s + max_s*t; -			ss = profile[mBeginS + s].mV[2] - begin_stex; -			pos[cur_vertex].load3(mesh[i].mPos.mV); -			tc[cur_vertex] = LLVector2(ss,tt); -			norm[cur_vertex].clear();  -			 +			ss = profile[mBeginS + s][2] - begin_stex; + +			llassert(less_than_max_mag(mesh[i])); +			mesh[i].store4a((F32*)(pos+cur_vertex)); +			tc[cur_vertex].set(ss,tt); +						  			cur_vertex++;  		}  	} +	LL_CHECK_MEMORY -	//get bounding box for this side -	LLVector4a& face_min = mExtents[0]; -	LLVector4a& face_max = mExtents[1]; +	  	mCenter->clear(); -	face_min = face_max = pos[0]; +	LLVector4a* cur_pos = pos; +	LLVector4a* end_pos = pos + mNumVertices; -	for (U32 i = 1; i < mNumVertices; ++i) +	//get bounding box for this side +	LLVector4a face_min; +	LLVector4a face_max; +	 +	face_min = face_max = *cur_pos++; +		 +	while (cur_pos < end_pos)  	{ -		update_min_max(face_min, face_max, pos[i]); +		update_min_max(face_min, face_max, *cur_pos++);  	} +	mExtents[0] = face_min; +	mExtents[1] = face_max; + +	U32 tc_count = mNumVertices; +	if (tc_count%2 == 1) +	{ //odd number of texture coordinates, duplicate last entry to padded end of array +		tc_count++; +		mTexCoords[mNumVertices] = mTexCoords[mNumVertices-1]; +	} + +	LLVector4a* cur_tc = (LLVector4a*) mTexCoords; +	LLVector4a* end_tc = (LLVector4a*) (mTexCoords+tc_count); + +	LLVector4a tc_min;  +	LLVector4a tc_max;  + +	tc_min = tc_max = *cur_tc++; + +	while (cur_tc < end_tc) +	{ +		update_min_max(tc_min, tc_max, *cur_tc++); +	} + +	F32* minp = tc_min.getF32ptr(); +	F32* maxp = tc_max.getF32ptr(); + +	mTexCoordExtents[0].mV[0] = llmin(minp[0], minp[2]); +	mTexCoordExtents[0].mV[1] = llmin(minp[1], minp[3]); +	mTexCoordExtents[1].mV[0] = llmax(maxp[0], maxp[2]); +	mTexCoordExtents[1].mV[1] = llmax(maxp[1], maxp[3]); +  	mCenter->setAdd(face_min, face_max);  	mCenter->mul(0.5f); @@ -7064,39 +6439,114 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  		}  	} +	LL_CHECK_MEMORY +  	//clear normals -	for (U32 i = 0; i < mNumVertices; i++) +	F32* dst = (F32*) mNormals; +	F32* end = (F32*) (mNormals+mNumVertices); +	LLVector4a zero = LLVector4a::getZero(); + +	while (dst < end)  	{ -		mNormals[i].clear(); +		zero.store4a(dst); +		dst += 4;  	} +	LL_CHECK_MEMORY +  	//generate normals  -	for (U32 i = 0; i < mNumIndices/3; i++) //for each triangle -	{ -		const U16* idx = &(mIndices[i*3]); -		 +	U32 count = mNumIndices/3; -		LLVector4a* v[] =  -		{	pos+idx[0], pos+idx[1], pos+idx[2] }; -		 -		LLVector4a* n[] =  -		{	norm+idx[0], norm+idx[1], norm+idx[2] }; +	LLVector4a* norm = mNormals; + +	static LLAlignedArray<LLVector4a, 64> triangle_normals; +	triangle_normals.resize(count); +	LLVector4a* output = triangle_normals.mArray; +	LLVector4a* end_output = output+count; + +	U16* idx = mIndices; + +	while (output < end_output) +	{ +		LLVector4a b,v1,v2; +		b.load4a((F32*) (pos+idx[0])); +		v1.load4a((F32*) (pos+idx[1])); +		v2.load4a((F32*) (pos+idx[2]));  		//calculate triangle normal -		LLVector4a a, b, c; +		LLVector4a a; -		a.setSub(*v[0], *v[1]); -		b.setSub(*v[0], *v[2]); -		c.setCross3(a,b); +		a.setSub(b, v1); +		b.sub(v2); + + +		LLQuad& vector1 = *((LLQuad*) &v1); +		LLQuad& vector2 = *((LLQuad*) &v2); -		n[0]->add(c); -		n[1]->add(c); -		n[2]->add(c); +		LLQuad& amQ = *((LLQuad*) &a); +		LLQuad& bmQ = *((LLQuad*) &b); + +		//v1.setCross3(t,v0); +		//setCross3(const LLVector4a& a, const LLVector4a& b) +		// Vectors are stored in memory in w, z, y, x order from high to low +		// Set vector1 = { a[W], a[X], a[Z], a[Y] } +		vector1 = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 0, 2, 1 )); +		// Set vector2 = { b[W], b[Y], b[X], b[Z] } +		vector2 = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 1, 0, 2 )); +		// mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] } +		vector2 = _mm_mul_ps( vector1, vector2 ); +		// vector3 = { a[W], a[Y], a[X], a[Z] } +		amQ = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 1, 0, 2 )); +		// vector4 = { b[W], b[X], b[Z], b[Y] } +		bmQ = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 0, 2, 1 )); +		// mQ = { 0, a[X]*b[Y] - a[Y]*b[X], a[Z]*b[X] - a[X]*b[Z], a[Y]*b[Z] - a[Z]*b[Y] } +		vector1 = _mm_sub_ps( vector2, _mm_mul_ps( amQ, bmQ )); + +		v1.store4a((F32*) output); + +		output++; +		idx += 3; +	} + +	idx = mIndices; + +	LLVector4a* src = triangle_normals.mArray; +	 +	for (U32 i = 0; i < count; i++) //for each triangle +	{ +		LLVector4a c; +		c.load4a((F32*) (src++)); + +		LLVector4a* n0p = norm+idx[0]; +		LLVector4a* n1p = norm+idx[1]; +		LLVector4a* n2p = norm+idx[2]; + +		idx += 3; + +		LLVector4a n0,n1,n2; +		n0.load4a((F32*) n0p); +		n1.load4a((F32*) n1p); +		n2.load4a((F32*) n2p); + +		n0.add(c); +		n1.add(c); +		n2.add(c);  		//even out quad contributions -		n[i%2+1]->add(c); +		switch (i%2+1) +		{ +			case 0: n0.add(c); break; +			case 1: n1.add(c); break; +			case 2: n2.add(c); break; +		}; + +		n0.store4a((F32*) n0p); +		n1.store4a((F32*) n1p); +		n2.store4a((F32*) n2p);  	} +	LL_CHECK_MEMORY +  	// adjust normals based on wrapping and stitching  	LLVector4a top; @@ -7228,6 +6678,8 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)  	} +	LL_CHECK_MEMORY +  	return TRUE;  } @@ -7281,3 +6733,4 @@ void calc_binormal_from_triangle(LLVector4a& binormal,  		binormal.set( 0, 1 , 0 );  	}  } + diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index c845556557..6b599a4126 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -37,7 +37,6 @@ class LLPath;  template <class T> class LLOctreeNode; -class LLVector4a;  class LLVolumeFace;  class LLVolume;  class LLVolumeTriangle; @@ -50,12 +49,15 @@ class LLVolumeTriangle;  #include "v3math.h"  #include "v3dmath.h"  #include "v4math.h" +#include "llvector4a.h" +#include "llmatrix4a.h"  #include "llquaternion.h"  #include "llstrider.h"  #include "v4coloru.h"  #include "llrefcount.h"  #include "llpointer.h"  #include "llfile.h" +#include "llalignedarray.h"  //============================================================================ @@ -708,16 +710,16 @@ public:  		LLFaceID  mFaceID;  	}; -	std::vector<LLVector3> mProfile;	 -	std::vector<LLVector2> mNormals; +	LLAlignedArray<LLVector4a, 64> mProfile;	 +	//LLAlignedArray<LLVector4a, 64> mNormals;  	std::vector<Face>      mFaces; -	std::vector<LLVector3> mEdgeNormals; -	std::vector<LLVector3> mEdgeCenters; + +	//LLAlignedArray<LLVector4a, 64> mEdgeNormals; +	//LLAlignedArray<LLVector4a, 64> mEdgeCenters;  	friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile);  protected: -	void genNormals(const LLProfileParams& params);  	static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);  	void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0); @@ -741,13 +743,29 @@ protected:  class LLPath  {  public: -	struct PathPt +	class PathPt  	{ -		LLVector3	 mPos; -		LLVector2    mScale; -		LLQuaternion mRot; +	public: +		LLMatrix4a   mRot; +		LLVector4a	 mPos; +		 +		LLVector4a   mScale;  		F32			 mTexT; -		PathPt() { mPos.setVec(0,0,0); mTexT = 0; mScale.setVec(0,0); mRot.loadIdentity(); } +		F32 pad[3]; //for alignment +		PathPt()  +		{  +			mPos.clear();  +			mTexT = 0;  +			mScale.clear();  +			mRot.setRows(LLVector4a(1,0,0,0), +						LLVector4a(0,1,0,0), +						LLVector4a(0,0,1,0)); + +			//distinguished data in the pad for debugging +			pad[0] = 3.14159f; +			pad[1] = -3.14159f; +			pad[2] = 0.585f; +		}  	};  public: @@ -779,7 +797,7 @@ public:  	friend std::ostream& operator<<(std::ostream &s, const LLPath &path);  public: -	std::vector<PathPt> mPath; +	LLAlignedArray<PathPt, 64> mPath;  protected:  	BOOL		  mOpen; @@ -912,6 +930,7 @@ public:  	LLVector2   mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face.  	S32 mNumVertices; +	S32 mNumAllocatedVertices;  	S32 mNumIndices;  	LLVector4a* mPositions; @@ -933,6 +952,9 @@ public:  	LLOctreeNode<LLVolumeTriangle>* mOctree; +	//whether or not face has been cache optimized +	BOOL mOptimized; +  private:  	BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);  	BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE); @@ -947,11 +969,7 @@ protected:  	~LLVolume(); // use unref  public: -	struct Point -	{ -		LLVector3 mPos; -	}; - +		  	struct FaceParams  	{  		LLFaceID mFaceID; @@ -974,8 +992,8 @@ public:  	const LLProfile& getProfile() const						{ return *mProfilep; }  	LLPath& getPath() const									{ return *mPathp; }  	void resizePath(S32 length); -	const std::vector<Point>& getMesh() const				{ return mMesh; } -	const LLVector3& getMeshPt(const U32 i) const			{ return mMesh[i].mPos; } +	const LLAlignedArray<LLVector4a,64>&	getMesh() const				{ return mMesh; } +	const LLVector4a& getMeshPt(const U32 i) const			{ return mMesh[i]; }  	void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); } @@ -990,10 +1008,7 @@ public:  	S32 getSculptLevel() const                              { return mSculptLevel; }  	void setSculptLevel(S32 level)							{ mSculptLevel = level; } -	S32 *getTriangleIndices(U32 &num_indices) const; - -	// returns number of triangle indeces required for path/profile mesh -	S32 getNumTriangleIndices() const; +	  	static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);  	S32 getNumTriangles(S32* vcount = NULL) const; @@ -1066,7 +1081,8 @@ public:  	LLVolumeParams mParams;  	LLPath *mPathp;  	LLProfile *mProfilep; -	std::vector<Point> mMesh; +	LLAlignedArray<LLVector4a,64> mMesh; +	  	BOOL mGenerateSingleFace;  	typedef std::vector<LLVolumeFace> face_list_t; diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp index f2a3e059ef..c02483ccf5 100644 --- a/indra/llmessage/llcurl.cpp +++ b/indra/llmessage/llcurl.cpp @@ -1815,10 +1815,10 @@ CURL*  LLCurl::newEasyHandle()  	}  	sTotalHandles++; -	CURL* ret = curl_easy_init() ; +	CURL* ret = LLCurlHandleHandler::getInstance()->CreateCurlHandle();  	if(!ret)  	{ -		llwarns << "curl_easy_init failed." << llendl ; +		llwarns << "failed to create curl handle." << llendl ;  	}  	return ret ; @@ -1848,3 +1848,24 @@ void LLCurlFF::check_multi_code(CURLMcode code)  {  	check_curl_multi_code(code);  } + +CURL* LLCurlHandleHandler::the_one_true_curl_handle; + +LLCurlHandleHandler::LLCurlHandleHandler() +{ +	the_one_true_curl_handle = curl_easy_init(); +	curl_easy_setopt(the_one_true_curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); +	curl_easy_setopt(the_one_true_curl_handle, CURLOPT_NOSIGNAL, 1); +	curl_easy_setopt(the_one_true_curl_handle, CURLOPT_NOPROGRESS, 1); +	curl_easy_setopt(the_one_true_curl_handle, CURLOPT_ENCODING, "");	 +	curl_easy_setopt(the_one_true_curl_handle, CURLOPT_AUTOREFERER, 1); +	curl_easy_setopt(the_one_true_curl_handle, CURLOPT_FOLLOWLOCATION, 1);	 +	curl_easy_setopt(the_one_true_curl_handle, CURLOPT_SSL_VERIFYPEER, 1); +	curl_easy_setopt(the_one_true_curl_handle, CURLOPT_SSL_VERIFYHOST, 0); +	curl_easy_setopt(the_one_true_curl_handle, CURLOPT_DNS_CACHE_TIMEOUT, 0); +} + +CURL* LLCurlHandleHandler::CreateCurlHandle() +{ +	return curl_easy_duphandle(the_one_true_curl_handle); +} diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h index 7bcf61e233..a03333157c 100644 --- a/indra/llmessage/llcurl.h +++ b/indra/llmessage/llcurl.h @@ -45,7 +45,7 @@  #include "llqueuedthread.h"  #include "llframetimer.h"  #include "llpointer.h" - +#include "llsingleton.h"  class LLMutex;  class LLCurlThread; @@ -53,6 +53,14 @@ class LLCurlThread;  // For whatever reason, this is not typedef'd in curl.h  typedef size_t (*curl_header_callback)(void *ptr, size_t size, size_t nmemb, void *stream); +class LLCurlHandleHandler : public LLSingleton<LLCurlHandleHandler> +{ +public: +	static CURL* the_one_true_curl_handle; +	LLCurlHandleHandler(); +	static CURL* CreateCurlHandle(); +}; +  class LLCurl  {  	LOG_CLASS(LLCurl); diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp index 26cafa025f..41a0310ce0 100644 --- a/indra/llmessage/llpartdata.cpp +++ b/indra/llmessage/llpartdata.cpp @@ -37,53 +37,46 @@ -const S32 PS_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; // 18 -const S32 PS_DATA_BLOCK_SIZE = 68 + PS_PART_DATA_BLOCK_SIZE; // 68 + 18 = 86 +const S32 PS_PART_DATA_GLOW_SIZE = 2; +const S32 PS_PART_DATA_BLEND_SIZE = 2; +const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18 +const S32 PS_SYS_DATA_BLOCK_SIZE = 68; +const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+ +									PS_LEGACY_PART_DATA_BLOCK_SIZE + +									PS_PART_DATA_BLEND_SIZE + +									PS_PART_DATA_GLOW_SIZE+ +									8; //two S32 size fields + +const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE; + + +const U32 PART_DATA_MASK = LLPartData::LL_PART_DATA_GLOW | LLPartData::LL_PART_DATA_BLEND; +  const F32 MAX_PART_SCALE = 4.f; -BOOL LLPartData::pack(LLDataPacker &dp) +bool LLPartData::hasGlow() const  { -	LLColor4U coloru; -	dp.packU32(mFlags, "pdflags"); -	dp.packFixed(mMaxAge, "pdmaxage", FALSE, 8, 8); -	coloru.setVec(mStartColor); -	dp.packColor4U(coloru, "pdstartcolor"); -	coloru.setVec(mEndColor); -	dp.packColor4U(coloru, "pdendcolor"); -	dp.packFixed(mStartScale.mV[0], "pdstartscalex", FALSE, 3, 5); -	dp.packFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5); -	dp.packFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5); -	dp.packFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5); -	return TRUE; +	return mStartGlow > 0.f || mEndGlow > 0.f;  } -LLSD LLPartData::asLLSD() const +bool LLPartData::hasBlendFunc() const  { -	LLSD sd = LLSD(); -	sd["pdflags"] = ll_sd_from_U32(mFlags); -	sd["pdmaxage"] = mMaxAge; -	sd["pdstartcolor"] = ll_sd_from_color4(mStartColor); -	sd["pdendcolor"] = ll_sd_from_color4(mEndColor); -	sd["pdstartscale"] = ll_sd_from_vector2(mStartScale); -	sd["pdendscale"] = ll_sd_from_vector2(mEndScale); -	return sd; +	return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;  } -bool LLPartData::fromLLSD(LLSD& sd) +S32 LLPartData::getSize() const  { -	mFlags = ll_U32_from_sd(sd["pdflags"]); -	mMaxAge = (F32)sd["pdmaxage"].asReal(); -	mStartColor = ll_color4_from_sd(sd["pdstartcolor"]); -	mEndColor = ll_color4_from_sd(sd["pdendcolor"]); -	mStartScale = ll_vector2_from_sd(sd["pdstartscale"]); -	mEndScale = ll_vector2_from_sd(sd["pdendscale"]); -	return true; +	S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE; +	if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE; +	if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE; + +	return size;  } -BOOL LLPartData::unpack(LLDataPacker &dp) +BOOL LLPartData::unpackLegacy(LLDataPacker &dp)  {  	LLColor4U coloru; @@ -98,9 +91,70 @@ BOOL LLPartData::unpack(LLDataPacker &dp)  	dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5);  	dp.unpackFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5);  	dp.unpackFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5); + +	mStartGlow = 0.f; +	mEndGlow = 0.f; +	mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; +	mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; +  	return TRUE;  } +BOOL LLPartData::unpack(LLDataPacker &dp) +{ +	S32 size = 0; +	dp.unpackS32(size, "partsize"); + +	unpackLegacy(dp); +	size -= PS_LEGACY_PART_DATA_BLOCK_SIZE; + +	if (mFlags & LL_PART_DATA_GLOW) +	{ +		if (size < PS_PART_DATA_GLOW_SIZE) return FALSE; + +		U8 tmp_glow = 0; +		dp.unpackU8(tmp_glow,"pdstartglow"); +		mStartGlow = tmp_glow / 255.f; +		dp.unpackU8(tmp_glow,"pdendglow"); +		mEndGlow = tmp_glow / 255.f; + +		size -= PS_PART_DATA_GLOW_SIZE; +	} +	else +	{ +		mStartGlow = 0.f; +		mEndGlow = 0.f; +	} + +	if (mFlags & LL_PART_DATA_BLEND) +	{ +		if (size < PS_PART_DATA_BLEND_SIZE) return FALSE; +		dp.unpackU8(mBlendFuncSource,"pdblendsource"); +		dp.unpackU8(mBlendFuncDest,"pdblenddest"); +		size -= PS_PART_DATA_BLEND_SIZE; +	} +	else +	{ +		mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; +		mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; +	} + +	if (size > 0) +	{ //leftover bytes, unrecognized parameters +		U8 feh = 0; +		while (size > 0) +		{ //read remaining bytes in block +			dp.unpackU8(feh, "whippang"); +			size--; +		} + +		//this particle system won't display properly, better to not show anything +		return FALSE; +	} + + +	return TRUE; +}  void LLPartData::setFlags(const U32 flags)  { @@ -148,6 +202,18 @@ void LLPartData::setEndAlpha(const F32 alpha)  	mEndColor.mV[3] = alpha;  } +// static +bool LLPartData::validBlendFunc(S32 func) +{ +	if (func >= 0 +		&& func < LL_PART_BF_COUNT +		&& func != UNSUPPORTED_DEST_ALPHA +		&& func != UNSUPPORTED_ONE_MINUS_DEST_ALPHA) +	{ +		return true; +	} +	return false; +}  LLPartSysData::LLPartSysData()  { @@ -160,6 +226,10 @@ LLPartSysData::LLPartSysData()  	mPartData.mStartScale = LLVector2(1.f, 1.f);  	mPartData.mEndScale = LLVector2(1.f, 1.f);  	mPartData.mMaxAge = 10.0; +	mPartData.mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA; +	mPartData.mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; +	mPartData.mStartGlow = 0.f; +	mPartData.mEndGlow = 0.f;  	mMaxAge = 0.0;  	mStartAge = 0.0; @@ -175,38 +245,7 @@ LLPartSysData::LLPartSysData()  	mNumParticles = 0;  } - -BOOL LLPartSysData::pack(LLDataPacker &dp) -{ -	dp.packU32(mCRC, "pscrc"); -	dp.packU32(mFlags, "psflags"); -	dp.packU8(mPattern, "pspattern"); -	dp.packFixed(mMaxAge, "psmaxage", FALSE, 8, 8); -	dp.packFixed(mStartAge, "psstartage", FALSE, 8, 8); -	dp.packFixed(mInnerAngle, "psinnerangle", FALSE, 3, 5); -	dp.packFixed(mOuterAngle, "psouterangle", FALSE, 3, 5); -	dp.packFixed(mBurstRate, "psburstrate", FALSE, 8, 8); -	dp.packFixed(mBurstRadius, "psburstradius", FALSE, 8, 8); -	dp.packFixed(mBurstSpeedMin, "psburstspeedmin", FALSE, 8, 8); -	dp.packFixed(mBurstSpeedMax, "psburstspeedmax", FALSE, 8, 8); -	dp.packU8(mBurstPartCount, "psburstpartcount"); - -	dp.packFixed(mAngularVelocity.mV[0], "psangvelx", TRUE, 8, 7); -	dp.packFixed(mAngularVelocity.mV[1], "psangvely", TRUE, 8, 7); -	dp.packFixed(mAngularVelocity.mV[2], "psangvelz", TRUE, 8, 7); - -	dp.packFixed(mPartAccel.mV[0], "psaccelx", TRUE, 8, 7); -	dp.packFixed(mPartAccel.mV[1], "psaccely", TRUE, 8, 7); -	dp.packFixed(mPartAccel.mV[2], "psaccelz", TRUE, 8, 7); - -	dp.packUUID(mPartImageID, "psuuid"); -	dp.packUUID(mTargetUUID, "pstargetuuid"); -	mPartData.pack(dp); -	return TRUE; -} - - -BOOL LLPartSysData::unpack(LLDataPacker &dp) +BOOL LLPartSysData::unpackSystem(LLDataPacker &dp)  {  	dp.unpackU32(mCRC, "pscrc");  	dp.unpackU32(mFlags, "psflags"); @@ -232,10 +271,48 @@ BOOL LLPartSysData::unpack(LLDataPacker &dp)  	dp.unpackUUID(mPartImageID, "psuuid");  	dp.unpackUUID(mTargetUUID, "pstargetuuid"); -	mPartData.unpack(dp);  	return TRUE;  } +BOOL LLPartSysData::unpackLegacy(LLDataPacker &dp) +{ +	unpackSystem(dp); +	mPartData.unpackLegacy(dp); + +	return TRUE; +} + +BOOL LLPartSysData::unpack(LLDataPacker &dp) +{ +	// syssize is currently unused.  Adding now when modifying the 'version to make extensible in the future +	S32 size = 0; +	dp.unpackS32(size, "syssize"); +	 +	if (size != PS_SYS_DATA_BLOCK_SIZE) +	{ //unexpected size, this viewer doesn't know how to parse this particle system +		 +		//skip to LLPartData block +		U8 feh = 0; +		 +		for (U32 i = 0; i < size; ++i) +		{ +			dp.unpackU8(feh, "whippang"); +		} +				 +		dp.unpackS32(size, "partsize"); +		//skip LLPartData block +		for (U32 i = 0; i < size; ++i) +		{ +			dp.unpackU8(feh, "whippang"); +		} +		return FALSE; +	} + +	unpackSystem(dp); +	 +	return mPartData.unpack(dp); +} +  std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)  {  	s << "Flags: " << std::hex << data.mFlags; @@ -253,7 +330,7 @@ std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)  BOOL LLPartSysData::isNullPS(const S32 block_num)  { -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; +	U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];  	U32 crc;  	S32 size; @@ -264,14 +341,28 @@ BOOL LLPartSysData::isNullPS(const S32 block_num)  	{  		return TRUE;  	} -	else if (size != PS_DATA_BLOCK_SIZE) +	 +	if (size > PS_MAX_DATA_BLOCK_SIZE)  	{ -		llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl; +		//size is too big, newer particle version unsupported  		return TRUE;  	} -	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE); -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); +	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE); + +	LLDataPackerBinaryBuffer dp(ps_data_block, size); +	if (size > PS_LEGACY_DATA_BLOCK_SIZE) +	{ +		// non legacy systems pack a size before the CRC +		S32 tmp = 0; +		dp.unpackS32(tmp, "syssize"); + +		if (tmp > PS_SYS_DATA_BLOCK_SIZE) +		{ //unknown system data block size, don't know how to parse it, treat as NULL +			return TRUE; +		} +	} +  	dp.unpackU32(crc, "crc");  	if (crc == 0) @@ -281,50 +372,37 @@ BOOL LLPartSysData::isNullPS(const S32 block_num)  	return FALSE;  } - -//static -BOOL LLPartSysData::packNull() -{ -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; -	gMessageSystem->addBinaryData("PSBlock", ps_data_block, 0); -	return TRUE; -} - - -BOOL LLPartSysData::packBlock() -{ -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; - -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); -	pack(dp); - -	// Add to message -	gMessageSystem->addBinaryData("PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE); - -	return TRUE; -}                                          - -  BOOL LLPartSysData::unpackBlock(const S32 block_num)  { -	U8 ps_data_block[PS_DATA_BLOCK_SIZE]; +	U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];  	// Check size of block  	S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock"); -	if (size != PS_DATA_BLOCK_SIZE) +	if (size > PS_MAX_DATA_BLOCK_SIZE)  	{ -		llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl; +		// Larger packets are newer and unsupported  		return FALSE;  	}  	// Get from message -	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE); +	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE); -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE); -	unpack(dp); +	LLDataPackerBinaryBuffer dp(ps_data_block, size); -	return TRUE; +	if (size == PS_LEGACY_DATA_BLOCK_SIZE) +	{ +		return unpackLegacy(dp); +	} +	else +	{ +		return unpack(dp); +	} +} + +bool LLPartSysData::isLegacyCompatible() const +{ +	return !mPartData.hasGlow() && !mPartData.hasBlendFunc();  }  void LLPartSysData::clampSourceParticleRate() diff --git a/indra/llmessage/llpartdata.h b/indra/llmessage/llpartdata.h index a4ef058b30..ed5c1a6ac7 100644 --- a/indra/llmessage/llpartdata.h +++ b/indra/llmessage/llpartdata.h @@ -70,7 +70,12 @@ enum LLPSScriptFlags  	LLPS_SRC_TARGET_UUID,  	LLPS_SRC_OMEGA,  	LLPS_SRC_ANGLE_BEGIN, -	LLPS_SRC_ANGLE_END +	LLPS_SRC_ANGLE_END, + +	LLPS_PART_BLEND_FUNC_SOURCE, +	LLPS_PART_BLEND_FUNC_DEST, +	LLPS_PART_START_GLOW, +	LLPS_PART_END_GLOW  }; @@ -83,11 +88,13 @@ public:  		mParameter(0.f)  	{  	} +	BOOL unpackLegacy(LLDataPacker &dp);  	BOOL unpack(LLDataPacker &dp); +  	BOOL pack(LLDataPacker &dp); -	LLSD asLLSD() const; -	operator LLSD() const {return asLLSD(); } -	bool fromLLSD(LLSD& sd); +	 +	bool hasGlow() const; +	bool hasBlendFunc() const;  	// Masks for the different particle flags  	enum @@ -102,17 +109,39 @@ public:  		LL_PART_TARGET_LINEAR_MASK =	0x80,		// Particle uses a direct linear interpolation  		LL_PART_EMISSIVE_MASK =			0x100,		// Particle is "emissive", instead of being lit  		LL_PART_BEAM_MASK =				0x200,		// Particle is a "beam" connecting source and target +		LL_PART_RIBBON_MASK =			0x400,		// Particles are joined together into one continuous triangle strip  		// Not implemented yet!  		//LL_PART_RANDOM_ACCEL_MASK =		0x100,		// Particles have random acceleration  		//LL_PART_RANDOM_VEL_MASK =		0x200,		// Particles have random velocity shifts"  		//LL_PART_TRAIL_MASK =			0x400,		// Particles have historical "trails" +		//sYSTEM SET FLAGS +		LL_PART_DATA_GLOW =				0x10000, +		LL_PART_DATA_BLEND =			0x20000, +  		// Viewer side use only!  		LL_PART_HUD =					0x40000000,  		LL_PART_DEAD_MASK =				0x80000000,  	}; +	enum +	{ +		LL_PART_BF_ONE = 0, +		LL_PART_BF_ZERO = 1, +		LL_PART_BF_DEST_COLOR = 2, +		LL_PART_BF_SOURCE_COLOR = 3, +		LL_PART_BF_ONE_MINUS_DEST_COLOR = 4, +		LL_PART_BF_ONE_MINUS_SOURCE_COLOR = 5, +		UNSUPPORTED_DEST_ALPHA = 6, +		LL_PART_BF_SOURCE_ALPHA = 7, +		UNSUPPORTED_ONE_MINUS_DEST_ALPHA = 8, +		LL_PART_BF_ONE_MINUS_SOURCE_ALPHA = 9, +		LL_PART_BF_COUNT = 10 +	}; + +	static bool validBlendFunc(S32 func); +  	void setFlags(const U32 flags);  	void setMaxAge(const F32 max_age);  	void setStartScale(const F32 xs, F32 ys); @@ -126,6 +155,9 @@ public:  	friend class LLPartSysData;  	friend class LLViewerPartSourceScript; +private: +	S32 getSize() const; +  	// These are public because I'm really lazy...  public:  	U32					mFlags;						// Particle state/interpolators in effect @@ -137,6 +169,12 @@ public:  	LLVector3			mPosOffset;					// Offset from source if using FOLLOW_SOURCE  	F32					mParameter;					// A single floating point parameter + +	F32					mStartGlow; +	F32					mEndGlow; +	 +	U8					mBlendFuncSource; +	U8					mBlendFuncDest;  }; @@ -146,15 +184,13 @@ public:  	LLPartSysData();  	BOOL unpack(LLDataPacker &dp); -	BOOL pack(LLDataPacker &dp); - -	 +	BOOL unpackLegacy(LLDataPacker &dp);  	BOOL unpackBlock(const S32 block_num); -	BOOL packBlock(); - -	static BOOL packNull(); +		  	static BOOL isNullPS(const S32 block_num); // Returns FALSE if this is a "NULL" particle system (i.e. no system) +	bool isLegacyCompatible() const; +  	// Different masks for effects on the source  	enum  	{ @@ -187,7 +223,12 @@ public:  	void clampSourceParticleRate();  	friend std::ostream&	 operator<<(std::ostream& s, const LLPartSysData &data);		// Stream a + +	S32 getdataBlockSize() const; +private: +	BOOL unpackSystem(LLDataPacker &dp); +  public:  	// Public because I'm lazy.... diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp index 034680caf8..38b743fb75 100644 --- a/indra/llmessage/lltransfermanager.cpp +++ b/indra/llmessage/lltransfermanager.cpp @@ -606,16 +606,21 @@ void LLTransferManager::processTransferAbort(LLMessageSystem *msgp, void **)  void LLTransferManager::reliablePacketCallback(void **user_data, S32 result)  {  	LLUUID *transfer_idp = (LLUUID *)user_data; -	if (result) +	if (result && +		transfer_idp != NULL)  	{ -		llwarns << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << llendl;  		LLTransferSource *tsp = gTransferManager.findTransferSource(*transfer_idp);  		if (tsp)  		{ +			llwarns << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << llendl;  			LLTransferSourceChannel *tscp = tsp->mChannelp;  			tsp->abortTransfer();  			tscp->deleteTransfer(tsp);  		} +		else +		{ +			llwarns << "Aborting reliable transfer " << *transfer_idp << " but can't find the LLTransferSource object" << llendl; +		}  	}  	delete transfer_idp;  } @@ -892,22 +897,26 @@ LLTransferSource *LLTransferSourceChannel::findTransferSource(const LLUUID &tran  } -BOOL LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp) +void LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)  { - -	LLPriQueueMap<LLTransferSource *>::pqm_iter iter; -	for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++) +	if (tsp)  	{ -		if (iter->second == tsp) +		LLPriQueueMap<LLTransferSource *>::pqm_iter iter; +		for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)  		{ -			delete tsp; -			mTransferSources.mMap.erase(iter); -			return TRUE; +			if (iter->second == tsp) +			{ +				delete tsp; +				mTransferSources.mMap.erase(iter); +				return; +			}  		} -	} -	llerrs << "Unable to find transfer source to delete!" << llendl; -	return FALSE; +		llwarns << "Unable to find transfer source id "  +			<< tsp->getID() +			<< " to delete!"  +			<< llendl; +	}  } @@ -1008,21 +1017,26 @@ LLTransferTarget *LLTransferTargetChannel::findTransferTarget(const LLUUID &tran  } -BOOL LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp) +void LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)  { -	tt_iter iter; -	for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++) +	if (ttp)  	{ -		if (*iter == ttp) +		tt_iter iter; +		for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)  		{ -			delete ttp; -			mTransferTargets.erase(iter); -			return TRUE; +			if (*iter == ttp) +			{ +				delete ttp; +				mTransferTargets.erase(iter); +				return; +			}  		} -	} -	llerrs << "Unable to find transfer target to delete!" << llendl; -	return FALSE; +		llwarns << "Unable to find transfer target id "  +			<< ttp->getID() +			<< " to delete!"  +			<< llendl; +	}  } diff --git a/indra/llmessage/lltransfermanager.h b/indra/llmessage/lltransfermanager.h index 252e05d1d1..6aad153c24 100644 --- a/indra/llmessage/lltransfermanager.h +++ b/indra/llmessage/lltransfermanager.h @@ -199,7 +199,7 @@ public:  	void				addTransferSource(LLTransferSource *sourcep);  	LLTransferSource	*findTransferSource(const LLUUID &transfer_id); -	BOOL				deleteTransfer(LLTransferSource *tsp); +	void				deleteTransfer(LLTransferSource *tsp);  	void					setThrottleID(const S32 throttle_id)	{ mThrottleID = throttle_id; } @@ -232,7 +232,7 @@ public:  						 const F32 priority);  	LLTransferTarget		*findTransferTarget(const LLUUID &transfer_id); -	BOOL					deleteTransfer(LLTransferTarget *ttp); +	void					deleteTransfer(LLTransferTarget *ttp);  	LLTransferChannelType	getChannelType() const		{ return mChannelType; } diff --git a/indra/llmessage/tests/llpartdata_test.cpp b/indra/llmessage/tests/llpartdata_test.cpp index 9123bd06c7..de81e0bbb2 100644 --- a/indra/llmessage/tests/llpartdata_test.cpp +++ b/indra/llmessage/tests/llpartdata_test.cpp @@ -38,10 +38,34 @@  namespace tut  { + +	//bunch of sniffed data that *should* be a valid particle system +	static U8 msg[] = {  +		0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,  +		0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x80, 0x00, 0x80,  +		0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x5e, 0x12, 0x0b, 0xa1, 0x58, 0x05, 0xdc, 0x57, 0x66,  +		0xb7, 0xf5, 0xac, 0x4b, 0xd1, 0x8f, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x0a, 0xff,  +		0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,  +		0x00, 0x7e, 0xc6, 0x81, 0xdc, 0x7e, 0xc6, 0x81, 0xdc, 0x77, 0xcf, 0xef, 0xd4, 0xce, 0x64, 0x1a, 0x7e,  +		0x26, 0x87, 0x55, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0x77, 0xcf, 0x98, 0xa3, 0xab,  +		0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf2,  +		0xf1, 0x65, 0x32, 0x1b, 0xef, 0x18, 0x70, 0x66, 0xba, 0x30, 0xa0, 0x11, 0xaa, 0x2f, 0xb0, 0xab, 0xd0,  +		0x30, 0x7d, 0xbd, 0x01, 0x00, 0xf8, 0x0d, 0xb8, 0x30, 0x01, 0x00, 0x00, 0x00, 0xce, 0xc6, 0x81, 0xdc,  +		0xce, 0xc6, 0x81, 0xdc, 0xc7, 0xcf, 0xef, 0xd4, 0x75, 0x65, 0x1a, 0x7f, 0x62, 0x6f, 0x55, 0x7f, 0x6d,  +		0x65, 0x22, 0x7f, 0x6d, 0x65, 0x22, 0x7f, 0xc7, 0xcf, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,  +		0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xf2, 0xf1, 0x62, 0x12, 0x1b, 0xef,  +		0x18, 0x7e, 0xbd, 0x01, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  +		0x00, 0x00, 0x00, 0x00, 0x7c, 0xac, 0x28, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48,  +		0xe0, 0xb9, 0x30, 0x03, 0xe1, 0xb9, 0x30, 0xbb, 0x00, 0x00, 0x00, 0x48, 0xe0, 0xb9, 0x30, 0x36, 0xd9,  +		0x81, 0xdc, 0x36, 0xd9, 0x81, 0xdc, 0x3f, 0xd0, 0xef, 0xd4, 0xa5, 0x7a, 0x72, 0x7f, 0x26, 0x30, 0x55,  +		0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x3f, 0xd0, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab,  +		0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00 };  	struct partdata_test  	{  	}; +  	typedef test_group<partdata_test> partdata_test_t;  	typedef partdata_test_t::object partdata_test_object_t;  	tut::partdata_test_t tut_partdata_test("LLPartData"); @@ -49,168 +73,82 @@ namespace tut  	template<> template<>  	void partdata_test_object_t::test<1>()  	{ -		LLPartData llpdata,llpdata1; -		U8 pkbuf[128]; - -		llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | -		LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK | -		LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK | -		LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK); - -		llpdata.setMaxAge(29.3f); - -		LLVector3 llvec1(1.0f, .5f, .25f); -		llpdata.setStartColor(llvec1); -		llpdata.setStartAlpha(.7f); - -		LLVector3 llvec2(.2f, .3f, 1.0f); -		llpdata.setEndColor(llvec2); -		llpdata.setEndAlpha(1.0f); +		LLPartSysData llpsysdata; +		LLDataPackerBinaryBuffer dp1(msg, sizeof(msg)); -		llpdata.setStartScale(3.23f, 4.0f); -		llpdata.setEndScale(2.4678f, 1.0f); +		ensure("LLPartSysData::unpack failed.", llpsysdata.unpack(dp1)); -		LLDataPackerBinaryBuffer dp((U8*)pkbuf, 128); -		llpdata.pack(dp); -		S32 cur_size = dp.getCurrentSize(); -		 -		LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size); -		llpdata1.unpack(dp1); - -		ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags); -		ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8); - -		ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8); -		ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8); -		ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8); -		ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8); - -		ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8); -		ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8); -		ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8); -		ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8); - -		ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5); -		ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5); - -		ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5); -		ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5); -	} - - -	template<> template<> -	void partdata_test_object_t::test<2>() -	{ -		LLPartData llpdata,llpdata1; - -		llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | -		LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK | -		LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK | -		LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK); -		 -		llpdata.setMaxAge(29.3f); - -		LLVector3 llvec1(1.0f, .5f, .25f); -		llpdata.setStartColor(llvec1); -		llpdata.setStartAlpha(.7f); - -		LLVector3 llvec2(.2f, .3f, 1.0f); -		llpdata.setEndColor(llvec2); -		llpdata.setEndAlpha(1.0f); - -		llpdata.setStartScale(3.23f, 4.0f); -		llpdata.setEndScale(2.4678f, 1.0f); - -		LLSD llsd = llpdata.asLLSD(); - -		llpdata1.fromLLSD(llsd); - -		ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags); -		ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8); - -		ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8); -		ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8); -		ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8); -		ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8); - -		ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8); -		ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8); -		ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8); -		ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8); - -		ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5); -		ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5); - -		ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5); -		ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5); -	} - - -//*********llpartsysdata*********** - -	template<> template<> -	void partdata_test_object_t::test<3>() -	{ -		LLPartSysData llpsysdata, llpsysdata1; -		U8 pkbuf[256]; -		llpsysdata.setBurstSpeedMin(33.33f); -		ensure("1.mBurstSpeedMin coudnt be set", 33.33f == llpsysdata.mBurstSpeedMin); - -		llpsysdata.setBurstSpeedMax(44.44f);  -		ensure("2.mBurstSpeedMax coudnt be set", 44.44f == llpsysdata.mBurstSpeedMax); - -		llpsysdata.setBurstRadius(45.55f); -		ensure("3.mBurstRadius coudnt be set", 45.55f == llpsysdata.mBurstRadius); - -		LLVector3 llvec(44.44f, 111.11f, -40.4f); -		llpsysdata.setPartAccel(llvec); - -		llpsysdata.mCRC = 0xFFFFFFFF; -		llpsysdata.mFlags = 0x20; - -		llpsysdata.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY; - -		llpsysdata.mMaxAge = 99.99f; -		llpsysdata.mStartAge = 18.5f; -		llpsysdata.mInnerAngle = 4.234f; -		llpsysdata.mOuterAngle = 7.123f; -		llpsysdata.mBurstRate  = 245.53f; -		llpsysdata.mBurstPartCount = 0xFF; -		llpsysdata.mAngularVelocity = llvec; - -		llpsysdata.mPartImageID.generate(); -		llpsysdata.mTargetUUID.generate(); +		//mCRC	1	unsigned int +		ensure("mCRC different after unpacking", llpsysdata.mCRC == (U32) 1); +		//mFlags	0	unsigned int +		ensure ("mFlags different after unpacking", llpsysdata.mFlags == (U32) 0); +		//mPattern	1 ''	unsigned char +		ensure ("mPattern different after unpacking", llpsysdata.mPattern == (U8) 1); +		//mInnerAngle	0.00000000	float +		ensure_approximately_equals("mInnerAngle different after unpacking", llpsysdata.mInnerAngle, 0.f, 8); +		//mOuterAngle	0.00000000	float +		ensure_approximately_equals("mOuterAngle different after unpacking", llpsysdata.mOuterAngle, 0.f, 8); +		//mAngularVelocity	0,0,0 +		ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[0], 0.f, 8); +		ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[1], 0.f, 8); +		ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[2], 0.f, 8); +		//mBurstRate	0.097656250	float +		ensure_approximately_equals("mBurstRate different after unpacking", llpsysdata.mBurstRate, 0.097656250f, 8); +		//mBurstPartCount	1 ''	unsigned char +		ensure("mBurstPartCount different after unpacking", llpsysdata.mBurstPartCount == (U8) 1); +		//mBurstRadius	0.00000000	float +		ensure_approximately_equals("mBurstRadius different after unpacking", llpsysdata.mBurstRadius, 0.f, 8); +		//mBurstSpeedMin	1.0000000	float +		ensure_approximately_equals("mBurstSpeedMin different after unpacking", llpsysdata.mBurstSpeedMin, 1.f, 8); +		//mBurstSpeedMax	1.0000000	float +		ensure_approximately_equals("mBurstSpeedMax different after unpacking", llpsysdata.mBurstSpeedMax, 1.f, 8); +		//mMaxAge	0.00000000	float +		ensure_approximately_equals("mMaxAge different after unpacking", llpsysdata.mMaxAge, 0.f, 8); +		//mStartAge	0.00000000	float +		ensure_approximately_equals("mStartAge different after unpacking", llpsysdata.mStartAge, 0.f, 8); +		//mPartAccel	<0,0,0> +		ensure_approximately_equals("mPartAccel.mV[0] different after unpacking", llpsysdata.mPartAccel.mV[0], 0.f, 7); +		ensure_approximately_equals("mPartAccel.mV[1] different after unpacking", llpsysdata.mPartAccel.mV[1], 0.f, 7); +		ensure_approximately_equals("mPartAccel.mV[2] different after unpacking", llpsysdata.mPartAccel.mV[2], 0.f, 7); + +		//mPartData +		LLPartData& data = llpsysdata.mPartData; + +		//mFlags	132354	unsigned int +		ensure ("mPartData.mFlags different after unpacking", data.mFlags == (U32) 132354); +		//mMaxAge	10.000000	float +		ensure_approximately_equals("mPartData.mMaxAge different after unpacking", data.mMaxAge, 10.f, 8);  +		//mStartColor	<1,1,1,1> +		ensure_approximately_equals("mPartData.mStartColor.mV[0] different after unpacking", data.mStartColor.mV[0], 1.f, 8); +		ensure_approximately_equals("mPartData.mStartColor.mV[1] different after unpacking", data.mStartColor.mV[1], 1.f, 8); +		ensure_approximately_equals("mPartData.mStartColor.mV[2] different after unpacking", data.mStartColor.mV[2], 1.f, 8); +		ensure_approximately_equals("mPartData.mStartColor.mV[3] different after unpacking", data.mStartColor.mV[3], 1.f, 8); +		//mEndColor	<1,1,0,0> +		ensure_approximately_equals("mPartData.mEndColor.mV[0] different after unpacking", data.mEndColor.mV[0], 1.f, 8); +		ensure_approximately_equals("mPartData.mEndColor.mV[1] different after unpacking", data.mEndColor.mV[1], 1.f, 8); +		ensure_approximately_equals("mPartData.mEndColor.mV[2] different after unpacking", data.mEndColor.mV[2], 0.f, 8); +		ensure_approximately_equals("mPartData.mEndColor.mV[3] different after unpacking", data.mEndColor.mV[3], 0.f, 8); +		//mStartScale	<1,1> +		ensure_approximately_equals("mPartData.mStartScale.mV[0] different after unpacking", data.mStartScale.mV[0], 1.f, 8); +		ensure_approximately_equals("mPartData.mStartScale.mV[1] different after unpacking", data.mStartScale.mV[1], 1.f, 8); +		//mEndScale	<0,0> +		ensure_approximately_equals("mPartData.mEndScale.mV[0] different after unpacking", data.mEndScale.mV[0], 0.f, 8); +		ensure_approximately_equals("mPartData.mEndScale.mV[1] different after unpacking", data.mEndScale.mV[1], 0.f, 8); +		//mPosOffset	<0,0,0> +		ensure_approximately_equals("mPartData.mPosOffset.mV[0] different after unpacking", data.mPosOffset.mV[0], 0.f, 8); +		ensure_approximately_equals("mPartData.mPosOffset.mV[1] different after unpacking", data.mPosOffset.mV[1], 0.f, 8); +		ensure_approximately_equals("mPartData.mPosOffset.mV[2] different after unpacking", data.mPosOffset.mV[2], 0.f, 8); +		//mParameter	0.00000000	float +		ensure_approximately_equals("mPartData.mParameter different after unpacking", data.mParameter, 0.f, 8); -		LLDataPackerBinaryBuffer dp((U8*)pkbuf, 256); -		llpsysdata.pack(dp); -		S32 cur_size = dp.getCurrentSize(); -		LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size); -		llpsysdata1.unpack(dp1); - -		ensure("1.mCRC's not equal", llpsysdata.mCRC == llpsysdata1.mCRC); -		ensure("2.mFlags's not equal", llpsysdata.mFlags == llpsysdata1.mFlags); -		ensure("3.mPattern's not equal", llpsysdata.mPattern == llpsysdata1.mPattern); -		ensure_approximately_equals("4.mMaxAge's not equal", llpsysdata.mMaxAge , llpsysdata1.mMaxAge, 8); -		ensure_approximately_equals("5.mStartAge's not equal", llpsysdata.mStartAge, llpsysdata1.mStartAge, 8); -		ensure_approximately_equals("6.mOuterAngle's not equal", llpsysdata.mOuterAngle, llpsysdata1.mOuterAngle, 5); -		ensure_approximately_equals("7.mInnerAngles's not equal", llpsysdata.mInnerAngle, llpsysdata1.mInnerAngle, 5); -		ensure_approximately_equals("8.mBurstRate's not equal", llpsysdata.mBurstRate, llpsysdata1.mBurstRate, 8); -		ensure("9.mBurstPartCount's not equal", llpsysdata.mBurstPartCount == llpsysdata1.mBurstPartCount); - -		ensure_approximately_equals("10.mBurstSpeedMin's not equal", llpsysdata.mBurstSpeedMin, llpsysdata1.mBurstSpeedMin, 8); -		ensure_approximately_equals("11.mBurstSpeedMax's not equal", llpsysdata.mBurstSpeedMax, llpsysdata1.mBurstSpeedMax, 8); - -		ensure_approximately_equals("12.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[0], llpsysdata1.mAngularVelocity.mV[0], 7); -		ensure_approximately_equals("13.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[1], llpsysdata1.mAngularVelocity.mV[1], 7); -		ensure_approximately_equals("14.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[2], llpsysdata1.mAngularVelocity.mV[2], 7); -			 -		ensure_approximately_equals("15.mPartAccel's not equal", llpsysdata.mPartAccel.mV[0], llpsysdata1.mPartAccel.mV[0], 7); -		ensure_approximately_equals("16.mPartAccel's not equal", llpsysdata.mPartAccel.mV[1], llpsysdata1.mPartAccel.mV[1], 7); -		ensure_approximately_equals("17.mPartAccel's not equal", llpsysdata.mPartAccel.mV[2], llpsysdata1.mPartAccel.mV[2], 7); - -		ensure("18.mPartImageID's not equal", llpsysdata.mPartImageID == llpsysdata1.mPartImageID); -		ensure("19.mTargetUUID's not equal", llpsysdata.mTargetUUID == llpsysdata1.mTargetUUID); -		ensure_approximately_equals("20.mBurstRadius's not equal", llpsysdata.mBurstRadius, llpsysdata1.mBurstRadius, 8); +		//mStartGlow	0.00000000	float +		ensure_approximately_equals("mPartData.mStartGlow different after unpacking", data.mStartGlow, 0.f, 8); +		//mEndGlow	0.00000000	float +		ensure_approximately_equals("mPartData.mEndGlow different after unpacking", data.mEndGlow, 0.f, 8); +		//mBlendFuncSource	2 ''	unsigned char +		ensure("mPartData.mBlendFuncSource different after unpacking", data.mBlendFuncSource == (U8) 2); +		//mBlendFuncDest	1 ''	unsigned char  +		ensure("mPartData.mBlendFuncDest different after unpacking", data.mBlendFuncDest == (U8) 1);  	}  } diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index 5ed05e2201..ef6eb75a6b 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -186,27 +186,73 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa  	LLVolumeFace::VertexMapData::PointMap point_map; -	for (U32 i = 0; i < idx.getCount(); i += idx_stride) +	U32 index_count  = idx.getCount(); +	U32 vertex_count = pos_source  ? v.getCount()  : 0; +	U32 tc_count     = tc_source   ? tc.getCount() : 0; +	U32 norm_count   = norm_source ? n.getCount()  : 0; + +	for (U32 i = 0; i < index_count; i += idx_stride)  	{  		LLVolumeFace::VertexData cv;  		if (pos_source)  		{ +			// guard against model data specifiying out of range indices or verts +			// +			if (((i + pos_offset) > index_count) +			 || ((idx[i+pos_offset]*3+2) > vertex_count)) +			{ +				return LLModel::BAD_ELEMENT; +			} +  			cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0],  								v[idx[i+pos_offset]*3+1],  								v[idx[i+pos_offset]*3+2])); + +			if (!cv.getPosition().isFinite3()) +			{ +				return LLModel::BAD_ELEMENT; +			}  		}  		if (tc_source)  		{ +			// guard against model data specifiying out of range indices or tcs +			// +			if (((i + tc_offset) > index_count) +			 || ((idx[i+pos_offset]*2+1) > tc_count)) +			{ +				return LLModel::BAD_ELEMENT; +			} +  			cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],  								tc[idx[i+tc_offset]*2+1]); + +			if (!cv.mTexCoord.isFinite()) +			{ +				llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl; +				return LLModel::BAD_ELEMENT; +			}  		}  		if (norm_source)  		{ +			// guard against model data specifiying out of range indices or norms +			// +			if (((i + norm_offset) > index_count) +				|| ((idx[i+norm_offset]*3+2) > norm_count)) +			{ +				return LLModel::BAD_ELEMENT; +			} +  			cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],  								n[idx[i+norm_offset]*3+1],  								n[idx[i+norm_offset]*3+2])); + +			if (!cv.getNormal().isFinite3()) +			{ +				llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl; +				return LLModel::BAD_ELEMENT; +			}  		}  		BOOL found = FALSE; @@ -261,13 +307,13 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa  			LLVolumeFace& new_face = *face_list.rbegin();  			if (!norm_source)  			{ -				ll_aligned_free_16(new_face.mNormals); +				//ll_aligned_free_16(new_face.mNormals);  				new_face.mNormals = NULL;  			}  			if (!tc_source)  			{ -				ll_aligned_free_16(new_face.mTexCoords); +				//ll_aligned_free_16(new_face.mTexCoords);  				new_face.mTexCoords = NULL;  			} @@ -292,13 +338,13 @@ LLModel::EModelStatus load_face_from_dom_triangles(std::vector<LLVolumeFace>& fa  		LLVolumeFace& new_face = *face_list.rbegin();  		if (!norm_source)  		{ -			ll_aligned_free_16(new_face.mNormals); +			//ll_aligned_free_16(new_face.mNormals);  			new_face.mNormals = NULL;  		}  		if (!tc_source)  		{ -			ll_aligned_free_16(new_face.mTexCoords); +			//ll_aligned_free_16(new_face.mTexCoords);  			new_face.mTexCoords = NULL;  		}  	} @@ -364,6 +410,11 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac  	LLVolumeFace::VertexMapData::PointMap point_map; +	U32 index_count  = idx.getCount(); +	U32 vertex_count = pos_source  ? v.getCount()  : 0; +	U32 tc_count     = tc_source   ? tc.getCount() : 0; +	U32 norm_count   = norm_source ? n.getCount()  : 0; +  	U32 cur_idx = 0;  	for (U32 i = 0; i < vcount.getCount(); ++i)  	{ //for each polygon @@ -376,22 +427,65 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac  			if (pos_source)  			{ +				// guard against model data specifiying out of range indices or verts +				// +				if (((i + pos_offset) > index_count) +				 || ((idx[i+pos_offset]*3+2) > vertex_count)) +				{ +					return LLModel::BAD_ELEMENT; +				} +  				cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0],  									v[idx[cur_idx+pos_offset]*3+1],  									v[idx[cur_idx+pos_offset]*3+2]); + +				if (!cv.getPosition().isFinite3()) +				{ +					llwarns << "Found NaN while loading positions from DAE-Model, invalid model." << llendl; +					return LLModel::BAD_ELEMENT; +				} +  			}  			if (tc_source)  			{ +				// guard against model data specifiying out of range indices or tcs +				// +				if (((i + pos_offset) > index_count) +				 || ((idx[cur_idx+tc_offset]*2+1) > tc_count)) +				{ +					return LLModel::BAD_ELEMENT; +				} +  				cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],  									tc[idx[cur_idx+tc_offset]*2+1]); + +				if (!cv.mTexCoord.isFinite()) +				{ +					llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl; +					return LLModel::BAD_ELEMENT; +				}  			}  			if (norm_source)  			{ +				// guard against model data specifiying out of range indices or norms +				// +				if (((i + pos_offset) > index_count) +				 || ((idx[cur_idx+norm_offset]*3+2) > norm_count)) +				{ +					return LLModel::BAD_ELEMENT; +				} +  				cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],  									n[idx[cur_idx+norm_offset]*3+1],  									n[idx[cur_idx+norm_offset]*3+2]); + +				if (!cv.getNormal().isFinite3()) +				{ +					llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl; +					return LLModel::BAD_ELEMENT; +				}  			}  			cur_idx += idx_stride; @@ -480,13 +574,13 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac  				LLVolumeFace& new_face = *face_list.rbegin();  				if (!norm_source)  				{ -					ll_aligned_free_16(new_face.mNormals); +					//ll_aligned_free_16(new_face.mNormals);  					new_face.mNormals = NULL;  				}  				if (!tc_source)  				{ -					ll_aligned_free_16(new_face.mTexCoords); +					//ll_aligned_free_16(new_face.mTexCoords);  					new_face.mTexCoords = NULL;  				} @@ -514,13 +608,13 @@ LLModel::EModelStatus load_face_from_dom_polylist(std::vector<LLVolumeFace>& fac  		LLVolumeFace& new_face = *face_list.rbegin();  		if (!norm_source)  		{ -			ll_aligned_free_16(new_face.mNormals); +			//ll_aligned_free_16(new_face.mNormals);  			new_face.mNormals = NULL;  		}  		if (!tc_source)  		{ -			ll_aligned_free_16(new_face.mTexCoords); +			//ll_aligned_free_16(new_face.mTexCoords);  			new_face.mTexCoords = NULL;  		}  	} @@ -632,6 +726,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac  				vert.getPosition().set(v->get(v_idx),  								v->get(v_idx+1),  								v->get(v_idx+2)); + +				if (!vert.getPosition().isFinite3()) +				{ +					llwarns << "Found NaN while loading position data from DAE-Model, invalid model." << llendl; +					return LLModel::BAD_ELEMENT; +				}  			}  			//bounds check n and t lookups because some FBX to DAE converters @@ -644,6 +744,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac  				vert.getNormal().set(n->get(n_idx),  								n->get(n_idx+1),  								n->get(n_idx+2)); + +				if (!vert.getNormal().isFinite3()) +				{ +					llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl; +					return LLModel::BAD_ELEMENT; +				}  			}  			else  			{ @@ -657,6 +763,12 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac  				t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount());  				vert.mTexCoord.setVec(t->get(t_idx),  								t->get(t_idx+1));								 + +				if (!vert.mTexCoord.isFinite()) +				{ +					llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl; +					return LLModel::BAD_ELEMENT; +				}  			}  			else  			{ @@ -730,13 +842,13 @@ LLModel::EModelStatus load_face_from_dom_polygons(std::vector<LLVolumeFace>& fac  		LLVolumeFace& new_face = *face_list.rbegin();  		if (!n)  		{ -			ll_aligned_free_16(new_face.mNormals); +			//ll_aligned_free_16(new_face.mNormals);  			new_face.mNormals = NULL;  		}  		if (!t)  		{ -			ll_aligned_free_16(new_face.mTexCoords); +			//ll_aligned_free_16(new_face.mTexCoords);  			new_face.mTexCoords = NULL;  		}  	} @@ -1036,7 +1148,7 @@ void LLModel::setVolumeFaceData(  	}  	else  	{ -		ll_aligned_free_16(face.mNormals); +		//ll_aligned_free_16(face.mNormals);  		face.mNormals = NULL;  	} @@ -1047,7 +1159,7 @@ void LLModel::setVolumeFaceData(  	}  	else  	{ -		ll_aligned_free_16(face.mTexCoords); +		//ll_aligned_free_16(face.mTexCoords);  		face.mTexCoords = NULL;  	} @@ -1246,7 +1358,7 @@ void LLModel::generateNormals(F32 angle_cutoff)  		}  		else  		{ -			ll_aligned_free_16(new_face.mTexCoords); +			//ll_aligned_free_16(new_face.mTexCoords);  			new_face.mTexCoords = NULL;  		} diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index d521114c9e..d8ccbf7b24 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -59,6 +59,7 @@ BOOL gDebugGL = FALSE;  BOOL gClothRipple = FALSE;  BOOL gHeadlessClient = FALSE;  BOOL gGLActive = FALSE; +BOOL gGLDebugLoggingEnabled = TRUE;  static const std::string HEADLESS_VENDOR_STRING("Linden Lab");  static const std::string HEADLESS_RENDERER_STRING("Headless"); @@ -72,6 +73,7 @@ std::ofstream gFailLog;  #define APIENTRY  #endif +  void APIENTRY gl_debug_callback(GLenum source,                                  GLenum type,                                  GLuint id, @@ -80,22 +82,25 @@ void APIENTRY gl_debug_callback(GLenum source,                                  const GLchar* message,                                  GLvoid* userParam)  { -	if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) -	{ -		llwarns << "----- GL ERROR --------" << llendl; -	} -	else +	if (gGLDebugLoggingEnabled)  	{ -		llwarns << "----- GL WARNING -------" << llendl; -	} -	llwarns << "Type: " << std::hex << type << llendl; -	llwarns << "ID: " << std::hex << id << llendl; -	llwarns << "Severity: " << std::hex << severity << llendl; -	llwarns << "Message: " << message << llendl; -	llwarns << "-----------------------" << llendl; -	if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) -	{ -		llerrs << "Halting on GL Error" << llendl; +		if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) +		{ +			llwarns << "----- GL ERROR --------" << llendl; +		} +		else +		{ +			llwarns << "----- GL WARNING -------" << llendl; +		} +		llwarns << "Type: " << std::hex << type << llendl; +		llwarns << "ID: " << std::hex << id << llendl; +		llwarns << "Severity: " << std::hex << severity << llendl; +		llwarns << "Message: " << message << llendl; +		llwarns << "-----------------------" << llendl; +		if (severity == GL_DEBUG_SEVERITY_HIGH_ARB) +		{ +			llerrs << "Halting on GL Error" << llendl; +		}  	}  }  #endif @@ -253,6 +258,7 @@ PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback = NULL;  PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL;  PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL;  PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL; +PFNGLBINDBUFFERBASEPROC glBindBufferBase = NULL;  //GL_ARB_debug_output  PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL; @@ -730,7 +736,7 @@ bool LLGLManager::initGL()  #if LL_WINDOWS  	if (mHasDebugOutput && gDebugGL)  	{ //setup debug output callback -		//glDebugMessageControlARB(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE); +		glDebugMessageControlARB(GL_DONT_CARE, GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_ARB, GL_DEBUG_SEVERITY_LOW_ARB, 0, NULL, GL_TRUE);  		glDebugMessageCallbackARB((GLDEBUGPROCARB) gl_debug_callback, NULL);  		glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB);  	} @@ -1219,6 +1225,7 @@ void LLGLManager::initExtensions()  		glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");  		glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");  		glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange"); +		glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferBase");  	}  	if (mHasDebugOutput)  	{ @@ -1466,7 +1473,7 @@ void do_assert_glerror()  void assert_glerror()  { -	if (!gGLActive) +/*	if (!gGLActive)  	{  		//llwarns << "GL used while not active!" << llendl; @@ -1475,8 +1482,13 @@ void assert_glerror()  			//ll_fail("GL used while not active");  		}  	} +*/ -	if (gDebugGL)  +	if (!gDebugGL)  +	{ +		//funny looking if for branch prediction -- gDebugGL is almost always false and assert_glerror is called often +	} +	else  	{  		do_assert_glerror();  	} diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 823de9d361..133c2de1f5 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -350,10 +350,10 @@ public:  	Generic pooling scheme for things which use GL names (used for occlusion queries and vertex buffer objects).  	Prevents thrashing of GL name caches by avoiding calls to glGenFoo and glDeleteFoo.  */ -class LLGLNamePool : public LLInstanceTracker<LLGLNamePool> +class LLGLNamePool : public INSTANCE_TRACKER(LLGLNamePool)  {  public: -	typedef LLInstanceTracker<LLGLNamePool> tracker_t; +	typedef INSTANCE_TRACKER(LLGLNamePool) tracker_t;  	struct NameEntry  	{ diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 509de51f4d..a92ed428da 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -533,6 +533,7 @@ extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;  extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;  extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;  extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; +extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;  #elif LL_WINDOWS @@ -771,6 +772,7 @@ extern PFNGLBEGINTRANSFORMFEEDBACKPROC glBeginTransformFeedback;  extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;  extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;  extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; +extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;  //GL_ARB_debug_output  extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 7cbf39096e..298a03f32a 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -128,8 +128,8 @@ void LLGLSLShader::unload()  	stop_glerror();  } -BOOL LLGLSLShader::createShader(vector<string> * attributes, -								vector<string> * uniforms, +BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes, +								std::vector<LLStaticHashedString> * uniforms,  								U32 varying_count,  								const char** varyings)  { @@ -209,7 +209,8 @@ BOOL LLGLSLShader::createShader(vector<string> * attributes,  		for (S32 i = 0; i < channel_count; i++)  		{ -			uniform1i(llformat("tex%d", i), i); +			LLStaticHashedString uniName(llformat("tex%d", i)); +			uniform1i(uniName, i);  		}  		S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten @@ -266,7 +267,7 @@ void LLGLSLShader::attachObjects(GLhandleARB* objects, S32 count)  	}  } -BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes) +BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attributes)  {  	//before linking, make sure reserved attributes always have consistent locations  	for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++) @@ -300,7 +301,7 @@ BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)  		{  			for (U32 i = 0; i < numAttributes; i++)  			{ -				const char* name = (*attributes)[i].c_str(); +				const char* name = (*attributes)[i].String().c_str();  				S32 index = glGetAttribLocationARB(mProgramObject, name);  				if (index != -1)  				{ @@ -316,7 +317,7 @@ BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)  	return FALSE;  } -void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms) +void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> * uniforms)  {  	if (index == -1)  	{ @@ -341,7 +342,8 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)  			is_array[0] = 0;  		} -		mUniformMap[name] = location; +		LLStaticHashedString hashedName(name); +		mUniformMap[hashedName] = location;  		LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL;  		//find the index of this uniform @@ -362,7 +364,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)  			for (U32 i = 0; i < uniforms->size(); i++)  			{  				if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1) -					&& ((*uniforms)[i] == name)) +					&& ((*uniforms)[i].String() == name))  				{  					//found it  					mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location; @@ -386,7 +388,7 @@ GLint LLGLSLShader::mapUniformTextureChannel(GLint location, GLenum type)  	return -1;  } -BOOL LLGLSLShader::mapUniforms(const vector<string> * uniforms) +BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)  {  	BOOL res = TRUE; @@ -793,18 +795,18 @@ void LLGLSLShader::uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, c  	}  } -GLint LLGLSLShader::getUniformLocation(const string& uniform) +GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform)  {  	GLint ret = -1;  	if (mProgramObject > 0)  	{ -		std::map<string, GLint>::iterator iter = mUniformMap.find(uniform); +		LLStaticStringTable<GLint>::iterator iter = mUniformMap.find(uniform);  		if (iter != mUniformMap.end())  		{  			if (gDebugGL)  			{  				stop_glerror(); -				if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.c_str())) +				if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.String().c_str()))  				{  					llerrs << "Uniform does not match." << llendl;  				} @@ -841,10 +843,10 @@ GLint LLGLSLShader::getAttribLocation(U32 attrib)  	}  } -void LLGLSLShader::uniform1i(const string& uniform, GLint v) +void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v)  {  	GLint location = getUniformLocation(uniform); -				 +  	if (location >= 0)  	{  		std::map<GLint, LLVector4>::iterator iter = mValue.find(location); @@ -857,10 +859,10 @@ void LLGLSLShader::uniform1i(const string& uniform, GLint v)  	}  } -void LLGLSLShader::uniform1f(const string& uniform, GLfloat v) +void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v)  {  	GLint location = getUniformLocation(uniform); -				 +  	if (location >= 0)  	{  		std::map<GLint, LLVector4>::iterator iter = mValue.find(location); @@ -873,10 +875,10 @@ void LLGLSLShader::uniform1f(const string& uniform, GLfloat v)  	}  } -void LLGLSLShader::uniform2f(const string& uniform, GLfloat x, GLfloat y) +void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y)  {  	GLint location = getUniformLocation(uniform); -				 +  	if (location >= 0)  	{  		std::map<GLint, LLVector4>::iterator iter = mValue.find(location); @@ -890,10 +892,10 @@ void LLGLSLShader::uniform2f(const string& uniform, GLfloat x, GLfloat y)  } -void LLGLSLShader::uniform3f(const string& uniform, GLfloat x, GLfloat y, GLfloat z) +void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z)  {  	GLint location = getUniformLocation(uniform); -				 +  	if (location >= 0)  	{  		std::map<GLint, LLVector4>::iterator iter = mValue.find(location); @@ -906,23 +908,7 @@ void LLGLSLShader::uniform3f(const string& uniform, GLfloat x, GLfloat y, GLfloa  	}  } -void LLGLSLShader::uniform4f(const string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ -	GLint location = getUniformLocation(uniform); - -	if (location >= 0) -	{ -		std::map<GLint, LLVector4>::iterator iter = mValue.find(location); -		LLVector4 vec(x,y,z,w); -		if (iter == mValue.end() || shouldChange(iter->second,vec)) -		{ -			glUniform4fARB(location, x,y,z,w); -			mValue[location] = vec; -		} -	} -} - -void LLGLSLShader::uniform1fv(const string& uniform, U32 count, const GLfloat* v) +void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)  {  	GLint location = getUniformLocation(uniform); @@ -938,10 +924,10 @@ void LLGLSLShader::uniform1fv(const string& uniform, U32 count, const GLfloat* v  	}  } -void LLGLSLShader::uniform2fv(const string& uniform, U32 count, const GLfloat* v) +void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)  {  	GLint location = getUniformLocation(uniform); -				 +  	if (location >= 0)  	{  		std::map<GLint, LLVector4>::iterator iter = mValue.find(location); @@ -954,10 +940,10 @@ void LLGLSLShader::uniform2fv(const string& uniform, U32 count, const GLfloat* v  	}  } -void LLGLSLShader::uniform3fv(const string& uniform, U32 count, const GLfloat* v) +void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)  {  	GLint location = getUniformLocation(uniform); -				 +  	if (location >= 0)  	{  		std::map<GLint, LLVector4>::iterator iter = mValue.find(location); @@ -970,7 +956,7 @@ void LLGLSLShader::uniform3fv(const string& uniform, U32 count, const GLfloat* v  	}  } -void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v) +void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)  {  	GLint location = getUniformLocation(uniform); @@ -988,27 +974,7 @@ void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v  	}  } -void LLGLSLShader::uniformMatrix2fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v) -{ -	GLint location = getUniformLocation(uniform); -				 -	if (location >= 0) -	{ -		glUniformMatrix2fvARB(location, count, transpose, v); -	} -} - -void LLGLSLShader::uniformMatrix3fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v) -{ -	GLint location = getUniformLocation(uniform); -				 -	if (location >= 0) -	{ -		glUniformMatrix3fvARB(location, count, transpose, v); -	} -} - -void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v) +void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v)  {  	GLint location = getUniformLocation(uniform); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index cf21101e35..019d5a86d6 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -29,6 +29,7 @@  #include "llgl.h"  #include "llrender.h" +#include "llstaticstringtable.h"  class LLShaderFeatures  { @@ -75,16 +76,16 @@ public:  	static bool sNoFixedFunction;  	void unload(); -	BOOL createShader(std::vector<std::string> * attributes, -						std::vector<std::string> * uniforms, +	BOOL createShader(std::vector<LLStaticHashedString> * attributes, +						std::vector<LLStaticHashedString> * uniforms,  						U32 varying_count = 0,  						const char** varyings = NULL);  	BOOL attachObject(std::string object);  	void attachObject(GLhandleARB object);  	void attachObjects(GLhandleARB* objects = NULL, S32 count = 0); -	BOOL mapAttributes(const std::vector<std::string> * attributes); -	BOOL mapUniforms(const std::vector<std::string> * uniforms); -	void mapUniform(GLint index, const std::vector<std::string> * uniforms); +	BOOL mapAttributes(const std::vector<LLStaticHashedString> * attributes); +	BOOL mapUniforms(const std::vector<LLStaticHashedString> *); +	void mapUniform(GLint index, const std::vector<LLStaticHashedString> *);  	void uniform1i(U32 index, GLint i);  	void uniform1f(U32 index, GLfloat v);  	void uniform2f(U32 index, GLfloat x, GLfloat y); @@ -95,29 +96,26 @@ public:  	void uniform2fv(U32 index, U32 count, const GLfloat* v);  	void uniform3fv(U32 index, U32 count, const GLfloat* v);  	void uniform4fv(U32 index, U32 count, const GLfloat* v); -	void uniform1i(const std::string& uniform, GLint i); -	void uniform1f(const std::string& uniform, GLfloat v); -	void uniform2f(const std::string& uniform, GLfloat x, GLfloat y); -	void uniform3f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z); -	void uniform4f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -	void uniform1iv(const std::string& uniform, U32 count, const GLint* i); -	void uniform1fv(const std::string& uniform, U32 count, const GLfloat* v); -	void uniform2fv(const std::string& uniform, U32 count, const GLfloat* v); -	void uniform3fv(const std::string& uniform, U32 count, const GLfloat* v); -	void uniform4fv(const std::string& uniform, U32 count, const GLfloat* v);  	void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);  	void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);  	void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v); -	void uniformMatrix2fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); -	void uniformMatrix3fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); -	void uniformMatrix4fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v); +	void uniform1i(const LLStaticHashedString& uniform, GLint i); +	void uniform1f(const LLStaticHashedString& uniform, GLfloat v); +	void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y); +	void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z); +	void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); +	void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); +	void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); +	void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v); +	void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v);  	void setMinimumAlpha(F32 minimum);  	void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);  	void vertexAttrib4fv(U32 index, GLfloat* v); -	GLint getUniformLocation(const std::string& uniform); +	//GLint getUniformLocation(const std::string& uniform); +	GLint getUniformLocation(const LLStaticHashedString& uniform);	  	GLint getUniformLocation(U32 index);  	GLint getAttribLocation(U32 attrib); @@ -143,7 +141,7 @@ public:  	GLhandleARB mProgramObject;  	std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel  	std::vector<GLint> mUniform;   //lookup table of uniform enum to uniform location -	std::map<std::string, GLint> mUniformMap;  //lookup map of uniform name to uniform location +	LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location  	std::map<GLint, LLVector4> mValue; //lookup map of uniform location to last known value  	std::vector<GLint> mTexture;  	S32 mActiveTextureChannels; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 249b8da880..28b7830b0e 100755 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -715,9 +715,12 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  					mMipLevels = wpo2(llmax(w, h)); -					//use legacy mipmap generation mode -					glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE); -					 +					if (!gGLManager.mHasFramebufferObject) +					{ +						//use legacy mipmap generation mode +						glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE); +					} +										  					LLImageGL::setManualImage(mTarget, 0, mFormatInternal,  								 w, h,   								 mFormatPrimary, mFormatType, @@ -732,6 +735,11 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips)  						glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);  						stop_glerror();  					} + +					if (gGLManager.mHasFramebufferObject) +					{ +						glGenerateMipmap(mTarget); +					}  				}  			}  			else @@ -1071,6 +1079,16 @@ void LLImageGL::generateTextures(LLTexUnit::eTextureType type, U32 format, S32 n  	LLFastTimer t(FTM_GENERATE_TEXTURES);  	bool empty = true; +	if (LLRender::sGLCoreProfile) +	{ +		switch (format) +		{ +			case GL_LUMINANCE8: format = GL_RGB8; break; +			case GL_LUMINANCE8_ALPHA8: +			case GL_ALPHA8: format = GL_RGBA8; break; +		} +	} +  	dead_texturelist_t::iterator iter = sDeadTextureList[type].find(format);  	if (iter != sDeadTextureList[type].end()) @@ -1098,6 +1116,16 @@ void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip  {  	if (gGLManager.mInited)  	{ +		if (LLRender::sGLCoreProfile) +		{ +			switch (format) +			{ +				case GL_LUMINANCE8: format = GL_RGB8; break; +				case GL_LUMINANCE8_ALPHA8: +				case GL_ALPHA8: format = GL_RGBA8; break; +			} +		} +  		if (format == 0 ||  type == LLTexUnit::TT_CUBE_MAP || mip_levels == -1)  		{ //unknown internal format or unknown number of mip levels, not safe to reuse  			glDeleteTextures(numTextures, textures); diff --git a/indra/llrender/llpostprocess.cpp b/indra/llrender/llpostprocess.cpp index c0045c8044..4c36185b08 100644 --- a/indra/llrender/llpostprocess.cpp +++ b/indra/llrender/llpostprocess.cpp @@ -31,6 +31,21 @@  #include "llsdserialize.h"  #include "llrender.h" +static LLStaticHashedString sRenderTexture("RenderTexture"); +static LLStaticHashedString sBrightness("brightness"); +static LLStaticHashedString sContrast("contrast"); +static LLStaticHashedString sContrastBase("contrastBase"); +static LLStaticHashedString sSaturation("saturation"); +static LLStaticHashedString sLumWeights("lumWeights"); +static LLStaticHashedString sNoiseTexture("NoiseTexture"); +static LLStaticHashedString sBrightMult("brightMult"); +static LLStaticHashedString sNoiseStrength("noiseStrength"); +static LLStaticHashedString sExtractLow("extractLow"); +static LLStaticHashedString sExtractHigh("extractHigh"); +static LLStaticHashedString sBloomStrength("bloomStrength"); +static LLStaticHashedString sTexelSize("texelSize"); +static LLStaticHashedString sBlurDirection("blurDirection"); +static LLStaticHashedString sBlurWidth("blurWidth");  LLPostProcess * gPostProcess = NULL; @@ -258,12 +273,12 @@ void LLPostProcess::applyColorFilterShader(void)  void LLPostProcess::createColorFilterShader(void)  {  	/// Define uniform names -	colorFilterUniforms["RenderTexture"] = 0; -	colorFilterUniforms["brightness"] = 0; -	colorFilterUniforms["contrast"] = 0; -	colorFilterUniforms["contrastBase"] = 0; -	colorFilterUniforms["saturation"] = 0; -	colorFilterUniforms["lumWeights"] = 0; +	colorFilterUniforms[sRenderTexture] = 0; +	colorFilterUniforms[sBrightness] = 0; +	colorFilterUniforms[sContrast] = 0; +	colorFilterUniforms[sContrastBase] = 0; +	colorFilterUniforms[sSaturation] = 0; +	colorFilterUniforms[sLumWeights] = 0;  }  void LLPostProcess::applyNightVisionShader(void) @@ -307,11 +322,11 @@ void LLPostProcess::applyNightVisionShader(void)  void LLPostProcess::createNightVisionShader(void)  {  	/// Define uniform names -	nightVisionUniforms["RenderTexture"] = 0; -	nightVisionUniforms["NoiseTexture"] = 0; -	nightVisionUniforms["brightMult"] = 0;	 -	nightVisionUniforms["noiseStrength"] = 0; -	nightVisionUniforms["lumWeights"] = 0;	 +	nightVisionUniforms[sRenderTexture] = 0; +	nightVisionUniforms[sNoiseTexture] = 0; +	nightVisionUniforms[sBrightMult] = 0;	 +	nightVisionUniforms[sNoiseStrength] = 0; +	nightVisionUniforms[sLumWeights] = 0;	  	createNoiseTexture(mNoiseTexture);  } @@ -326,25 +341,25 @@ void LLPostProcess::createBloomShader(void)  	createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));  	/// Create Bloom Extract Shader -	bloomExtractUniforms["RenderTexture"] = 0; -	bloomExtractUniforms["extractLow"] = 0; -	bloomExtractUniforms["extractHigh"] = 0;	 -	bloomExtractUniforms["lumWeights"] = 0;	 +	bloomExtractUniforms[sRenderTexture] = 0; +	bloomExtractUniforms[sExtractLow] = 0; +	bloomExtractUniforms[sExtractHigh] = 0;	 +	bloomExtractUniforms[sLumWeights] = 0;	  	/// Create Bloom Blur Shader -	bloomBlurUniforms["RenderTexture"] = 0; -	bloomBlurUniforms["bloomStrength"] = 0;	 -	bloomBlurUniforms["texelSize"] = 0; -	bloomBlurUniforms["blurDirection"] = 0; -	bloomBlurUniforms["blurWidth"] = 0; +	bloomBlurUniforms[sRenderTexture] = 0; +	bloomBlurUniforms[sBloomStrength] = 0;	 +	bloomBlurUniforms[sTexelSize] = 0; +	bloomBlurUniforms[sBlurDirection] = 0; +	bloomBlurUniforms[sBlurWidth] = 0;  }  void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog)  {  	/// Find uniform locations and insert into map	 -	std::map<const char *, GLuint>::iterator i; +	glslUniforms::iterator i;  	for (i  = uniforms.begin(); i != uniforms.end(); ++i){ -		i->second = glGetUniformLocationARB(prog, i->first); +		i->second = glGetUniformLocationARB(prog, i->first.String().c_str());  	}  } diff --git a/indra/llrender/llpostprocess.h b/indra/llrender/llpostprocess.h index e19de44c60..6894505753 100644 --- a/indra/llrender/llpostprocess.h +++ b/indra/llrender/llpostprocess.h @@ -1,266 +1,267 @@ -/**  - * @file llpostprocess.h - * @brief LLPostProcess class definition - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - *  - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - *  - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - * Lesser General Public License for more details. - *  - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA - *  - * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA - * $/LicenseInfo$ - */ - -#ifndef LL_POSTPROCESS_H -#define LL_POSTPROCESS_H - -#include <map> -#include <fstream> -#include "llgl.h" -#include "llglheaders.h" - -class LLPostProcess  -{ -public: - -	typedef enum _QuadType { -		QUAD_NORMAL, -		QUAD_NOISE, -		QUAD_BLOOM_EXTRACT, -		QUAD_BLOOM_COMBINE -	} QuadType; - -	/// GLSL Shader Encapsulation Struct -	typedef std::map<const char *, GLuint> glslUniforms; - -	struct PostProcessTweaks : public LLSD { -		inline PostProcessTweaks() : LLSD(LLSD::emptyMap()) -		{ -		} - -		inline LLSD & brightMult() { -			return (*this)["brightness_multiplier"]; -		} - -		inline LLSD & noiseStrength() { -			return (*this)["noise_strength"]; -		} - -		inline LLSD & noiseSize() { -			return (*this)["noise_size"]; -		} - -		inline LLSD & extractLow() { -			return (*this)["extract_low"]; -		} - -		inline LLSD & extractHigh() { -			return (*this)["extract_high"]; -		} - -		inline LLSD & bloomWidth() { -			return (*this)["bloom_width"]; -		} - -		inline LLSD & bloomStrength() { -			return (*this)["bloom_strength"]; -		} - -		inline LLSD & brightness() { -			return (*this)["brightness"]; -		} - -		inline LLSD & contrast() { -			return (*this)["contrast"]; -		} - -		inline LLSD & contrastBaseR() { -			return (*this)["contrast_base"][0]; -		} - -		inline LLSD & contrastBaseG() { -			return (*this)["contrast_base"][1]; -		} - -		inline LLSD & contrastBaseB() { -			return (*this)["contrast_base"][2]; -		} - -		inline LLSD & contrastBaseIntensity() { -			return (*this)["contrast_base"][3]; -		} - -		inline LLSD & saturation() { -			return (*this)["saturation"]; -		} - -		inline LLSD & useNightVisionShader() { -			return (*this)["enable_night_vision"]; -		} - -		inline LLSD & useBloomShader() { -			return (*this)["enable_bloom"]; -		} - -		inline LLSD & useColorFilter() { -			return (*this)["enable_color_filter"]; -		} - - -		inline F32 getBrightMult() const { -			return F32((*this)["brightness_multiplier"].asReal()); -		} - -		inline F32 getNoiseStrength() const { -			return F32((*this)["noise_strength"].asReal()); -		} - -		inline F32 getNoiseSize() const { -			return F32((*this)["noise_size"].asReal()); -		} - -		inline F32 getExtractLow() const { -			return F32((*this)["extract_low"].asReal()); -		} - -		inline F32 getExtractHigh() const { -			return F32((*this)["extract_high"].asReal()); -		} - -		inline F32 getBloomWidth() const { -			return F32((*this)["bloom_width"].asReal()); -		} - -		inline F32 getBloomStrength() const { -			return F32((*this)["bloom_strength"].asReal()); -		} - -		inline F32 getBrightness() const { -			return F32((*this)["brightness"].asReal()); -		} - -		inline F32 getContrast() const { -			return F32((*this)["contrast"].asReal()); -		} - -		inline F32 getContrastBaseR() const { -			return F32((*this)["contrast_base"][0].asReal()); -		} - -		inline F32 getContrastBaseG() const { -			return F32((*this)["contrast_base"][1].asReal()); -		} - -		inline F32 getContrastBaseB() const { -			return F32((*this)["contrast_base"][2].asReal()); -		} - -		inline F32 getContrastBaseIntensity() const { -			return F32((*this)["contrast_base"][3].asReal()); -		} - -		inline F32 getSaturation() const { -			return F32((*this)["saturation"].asReal()); -		} - -	}; -	 -	bool initialized; -	PostProcessTweaks tweaks; - -	// the map of all availible effects -	LLSD mAllEffects; - -private: -	LLPointer<LLImageGL> mSceneRenderTexture ; -	LLPointer<LLImageGL> mNoiseTexture ; -	LLPointer<LLImageGL> mTempBloomTexture ; - -public: -	LLPostProcess(void); - -	~LLPostProcess(void); - -	void apply(unsigned int width, unsigned int height); -	void invalidate() ; - -	/// Perform global initialization for this class. -	static void initClass(void); - -	// Cleanup of global data that's only inited once per class. -	static void cleanupClass(); - -	void setSelectedEffect(std::string const & effectName); - -	inline std::string const & getSelectedEffect(void) const { -		return mSelectedEffectName; -	} - -	void saveEffect(std::string const & effectName); - -private: -		/// read in from file -	std::string mShaderErrorString; -	unsigned int screenW; -	unsigned int screenH; - -	float noiseTextureScale; -	 -	/// Shader Uniforms -	glslUniforms nightVisionUniforms; -	glslUniforms bloomExtractUniforms; -	glslUniforms bloomBlurUniforms; -	glslUniforms colorFilterUniforms; - -	// the name of currently selected effect in mAllEffects -	// invariant: tweaks == mAllEffects[mSelectedEffectName] -	std::string mSelectedEffectName; - -	/// General functions -	void initialize(unsigned int width, unsigned int height); -	void doEffects(void); -	void applyShaders(void); -	bool shadersEnabled(void); - -	/// Night Vision Functions -	void createNightVisionShader(void); -	void applyNightVisionShader(void); - -	/// Bloom Functions -	void createBloomShader(void); -	void applyBloomShader(void); - -	/// Color Filter Functions -	void createColorFilterShader(void); -	void applyColorFilterShader(void); - -	/// OpenGL Helper Functions -	void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog); -	void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height); -	void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height); -	void createNoiseTexture(LLPointer<LLImageGL>& texture); -	bool checkError(void); -	void checkShaderError(GLhandleARB shader); -	void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type); -	void viewOrthogonal(unsigned int width, unsigned int height); -	void changeOrthogonal(unsigned int width, unsigned int height); -	void viewPerspective(void); -}; - -extern LLPostProcess * gPostProcess; - - -#endif // LL_POSTPROCESS_H +/** 
 + * @file llpostprocess.h
 + * @brief LLPostProcess class definition
 + *
 + * $LicenseInfo:firstyear=2007&license=viewerlgpl$
 + * Second Life Viewer Source Code
 + * Copyright (C) 2010, Linden Research, Inc.
 + * 
 + * This library is free software; you can redistribute it and/or
 + * modify it under the terms of the GNU Lesser General Public
 + * License as published by the Free Software Foundation;
 + * version 2.1 of the License only.
 + * 
 + * This library is distributed in the hope that it will be useful,
 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 + * Lesser General Public License for more details.
 + * 
 + * You should have received a copy of the GNU Lesser General Public
 + * License along with this library; if not, write to the Free Software
 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 + * 
 + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 + * $/LicenseInfo$
 + */
 +
 +#ifndef LL_POSTPROCESS_H
 +#define LL_POSTPROCESS_H
 +
 +#include <map>
 +#include <fstream>
 +#include "llgl.h"
 +#include "llglheaders.h"
 +#include "llstaticstringtable.h"
 +
 +class LLPostProcess 
 +{
 +public:
 +
 +	typedef enum _QuadType {
 +		QUAD_NORMAL,
 +		QUAD_NOISE,
 +		QUAD_BLOOM_EXTRACT,
 +		QUAD_BLOOM_COMBINE
 +	} QuadType;
 +
 +	/// GLSL Shader Encapsulation Struct
 +	typedef LLStaticStringTable<GLuint> glslUniforms;
 +
 +	struct PostProcessTweaks : public LLSD {
 +		inline PostProcessTweaks() : LLSD(LLSD::emptyMap())
 +		{
 +		}
 +
 +		inline LLSD & brightMult() {
 +			return (*this)["brightness_multiplier"];
 +		}
 +
 +		inline LLSD & noiseStrength() {
 +			return (*this)["noise_strength"];
 +		}
 +
 +		inline LLSD & noiseSize() {
 +			return (*this)["noise_size"];
 +		}
 +
 +		inline LLSD & extractLow() {
 +			return (*this)["extract_low"];
 +		}
 +
 +		inline LLSD & extractHigh() {
 +			return (*this)["extract_high"];
 +		}
 +
 +		inline LLSD & bloomWidth() {
 +			return (*this)["bloom_width"];
 +		}
 +
 +		inline LLSD & bloomStrength() {
 +			return (*this)["bloom_strength"];
 +		}
 +
 +		inline LLSD & brightness() {
 +			return (*this)["brightness"];
 +		}
 +
 +		inline LLSD & contrast() {
 +			return (*this)["contrast"];
 +		}
 +
 +		inline LLSD & contrastBaseR() {
 +			return (*this)["contrast_base"][0];
 +		}
 +
 +		inline LLSD & contrastBaseG() {
 +			return (*this)["contrast_base"][1];
 +		}
 +
 +		inline LLSD & contrastBaseB() {
 +			return (*this)["contrast_base"][2];
 +		}
 +
 +		inline LLSD & contrastBaseIntensity() {
 +			return (*this)["contrast_base"][3];
 +		}
 +
 +		inline LLSD & saturation() {
 +			return (*this)["saturation"];
 +		}
 +
 +		inline LLSD & useNightVisionShader() {
 +			return (*this)["enable_night_vision"];
 +		}
 +
 +		inline LLSD & useBloomShader() {
 +			return (*this)["enable_bloom"];
 +		}
 +
 +		inline LLSD & useColorFilter() {
 +			return (*this)["enable_color_filter"];
 +		}
 +
 +
 +		inline F32 getBrightMult() const {
 +			return F32((*this)["brightness_multiplier"].asReal());
 +		}
 +
 +		inline F32 getNoiseStrength() const {
 +			return F32((*this)["noise_strength"].asReal());
 +		}
 +
 +		inline F32 getNoiseSize() const {
 +			return F32((*this)["noise_size"].asReal());
 +		}
 +
 +		inline F32 getExtractLow() const {
 +			return F32((*this)["extract_low"].asReal());
 +		}
 +
 +		inline F32 getExtractHigh() const {
 +			return F32((*this)["extract_high"].asReal());
 +		}
 +
 +		inline F32 getBloomWidth() const {
 +			return F32((*this)["bloom_width"].asReal());
 +		}
 +
 +		inline F32 getBloomStrength() const {
 +			return F32((*this)["bloom_strength"].asReal());
 +		}
 +
 +		inline F32 getBrightness() const {
 +			return F32((*this)["brightness"].asReal());
 +		}
 +
 +		inline F32 getContrast() const {
 +			return F32((*this)["contrast"].asReal());
 +		}
 +
 +		inline F32 getContrastBaseR() const {
 +			return F32((*this)["contrast_base"][0].asReal());
 +		}
 +
 +		inline F32 getContrastBaseG() const {
 +			return F32((*this)["contrast_base"][1].asReal());
 +		}
 +
 +		inline F32 getContrastBaseB() const {
 +			return F32((*this)["contrast_base"][2].asReal());
 +		}
 +
 +		inline F32 getContrastBaseIntensity() const {
 +			return F32((*this)["contrast_base"][3].asReal());
 +		}
 +
 +		inline F32 getSaturation() const {
 +			return F32((*this)["saturation"].asReal());
 +		}
 +
 +	};
 +	
 +	bool initialized;
 +	PostProcessTweaks tweaks;
 +
 +	// the map of all availible effects
 +	LLSD mAllEffects;
 +
 +private:
 +	LLPointer<LLImageGL> mSceneRenderTexture ;
 +	LLPointer<LLImageGL> mNoiseTexture ;
 +	LLPointer<LLImageGL> mTempBloomTexture ;
 +
 +public:
 +	LLPostProcess(void);
 +
 +	~LLPostProcess(void);
 +
 +	void apply(unsigned int width, unsigned int height);
 +	void invalidate() ;
 +
 +	/// Perform global initialization for this class.
 +	static void initClass(void);
 +
 +	// Cleanup of global data that's only inited once per class.
 +	static void cleanupClass();
 +
 +	void setSelectedEffect(std::string const & effectName);
 +
 +	inline std::string const & getSelectedEffect(void) const {
 +		return mSelectedEffectName;
 +	}
 +
 +	void saveEffect(std::string const & effectName);
 +
 +private:
 +		/// read in from file
 +	std::string mShaderErrorString;
 +	unsigned int screenW;
 +	unsigned int screenH;
 +
 +	float noiseTextureScale;
 +	
 +	/// Shader Uniforms
 +	glslUniforms nightVisionUniforms;
 +	glslUniforms bloomExtractUniforms;
 +	glslUniforms bloomBlurUniforms;
 +	glslUniforms colorFilterUniforms;
 +
 +	// the name of currently selected effect in mAllEffects
 +	// invariant: tweaks == mAllEffects[mSelectedEffectName]
 +	std::string mSelectedEffectName;
 +
 +	/// General functions
 +	void initialize(unsigned int width, unsigned int height);
 +	void doEffects(void);
 +	void applyShaders(void);
 +	bool shadersEnabled(void);
 +
 +	/// Night Vision Functions
 +	void createNightVisionShader(void);
 +	void applyNightVisionShader(void);
 +
 +	/// Bloom Functions
 +	void createBloomShader(void);
 +	void applyBloomShader(void);
 +
 +	/// Color Filter Functions
 +	void createColorFilterShader(void);
 +	void applyColorFilterShader(void);
 +
 +	/// OpenGL Helper Functions
 +	void getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog);
 +	void createTexture(LLPointer<LLImageGL>& texture, unsigned int width, unsigned int height);
 +	void copyFrameBuffer(U32 & texture, unsigned int width, unsigned int height);
 +	void createNoiseTexture(LLPointer<LLImageGL>& texture);
 +	bool checkError(void);
 +	void checkShaderError(GLhandleARB shader);
 +	void drawOrthoQuad(unsigned int width, unsigned int height, QuadType type);
 +	void viewOrthogonal(unsigned int width, unsigned int height);
 +	void changeOrthogonal(unsigned int width, unsigned int height);
 +	void viewPerspective(void);
 +};
 +
 +extern LLPostProcess * gPostProcess;
 +
 +
 +#endif // LL_POSTPROCESS_H
 diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index c60eb8d9d9..18ca5b35f0 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -225,26 +225,15 @@ void LLTexUnit::disable(void)  bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)  {  	stop_glerror(); -	if (mIndex < 0) return false; - +	if (mIndex >= 0) +	{  	gGL.flush();  	LLImageGL* gl_tex = NULL ; -	if (texture == NULL || !(gl_tex = texture->getGLTexture())) +		if (texture != NULL && (gl_tex = texture->getGLTexture()))  	{ -		llwarns << "NULL LLTexUnit::bind texture" << llendl; -		return false; -	} - -	if (!gl_tex->getTexName()) //if texture does not exist +			if (gl_tex->getTexName()) //if texture exists  	{ -		//if deleted, will re-generate it immediately -		texture->forceImmediateUpdate() ; - -		gl_tex->forceUpdateBindStats() ; -		return texture->bindDefaultImage(mIndex); -	} -  	//in audit, replace the selected texture by the default one.  	if ((mCurrTexture != gl_tex->getTexName()) || forceBind)  	{ @@ -265,6 +254,27 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)  			setTextureFilteringOption(gl_tex->mFilterOption);  		}  	} +			} +			else +			{ +				//if deleted, will re-generate it immediately +				texture->forceImmediateUpdate() ; + +				gl_tex->forceUpdateBindStats() ; +				return texture->bindDefaultImage(mIndex); +			} +		} +		else +		{ +			llwarns << "NULL LLTexUnit::bind texture" << llendl; +			return false; +		} +	} +	else +	{ // mIndex < 0 +		return false; +	} +  	return true;  } @@ -1058,6 +1068,16 @@ LLRender::~LLRender()  void LLRender::init()  { +	if (sGLCoreProfile && !LLVertexBuffer::sUseVAO) +	{ //bind a dummy vertex array object so we're core profile compliant +#ifdef GL_ARB_vertex_array_object +		U32 ret; +		glGenVertexArrays(1, &ret); +		glBindVertexArray(ret); +#endif +	} + +  	llassert_always(mBuffer.isNull()) ;  	stop_glerror();  	mBuffer = new LLVertexBuffer(immediate_mask, 0); @@ -2280,6 +2300,22 @@ void LLRender::diffuseColor4ubv(const U8* c)  	}  } +void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a) +{ +	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; +	llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL); + +	if (shader) +	{ +		shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f); +	} +	else +	{ +		glColor4ub(r,g,b,a); +	} +} + +  void LLRender::debugTexUnits(void)  {  	LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 78a310e525..90b1ec2f57 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -388,6 +388,7 @@ public:  	void diffuseColor4f(F32 r, F32 g, F32 b, F32 a);  	void diffuseColor4fv(const F32* c);  	void diffuseColor4ubv(const U8* c); +	void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a);  	void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count);  	void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count); diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index 25109268e8..4a4f6a7a2f 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -458,6 +458,12 @@ U32 LLRenderTarget::getTexture(U32 attachment) const  	return mTex[attachment];  } +U32 LLRenderTarget::getNumTextures() const +{ +	return mTex.size(); +} + +  void LLRenderTarget::bindTexture(U32 index, S32 channel)  {  	gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index)); diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index 765a727b5b..a7bc4e1385 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -112,6 +112,7 @@ public:  	LLTexUnit::eTextureType getUsage(void) const { return mUsage; }  	U32 getTexture(U32 attachment = 0) const; +	U32 getNumTextures() const;  	U32 getDepth(void) const { return mDepth; }  	bool hasStencil() const { return mStencil; } diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index b6a9a6b653..825f80a6dc 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -974,7 +974,9 @@ void LLShaderMgr::initAttribsAndUniforms()  	mReservedUniforms.push_back("texture_matrix1");  	mReservedUniforms.push_back("texture_matrix2");  	mReservedUniforms.push_back("texture_matrix3"); -	llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_MATRIX3+1); +	mReservedUniforms.push_back("object_plane_s"); +	mReservedUniforms.push_back("object_plane_t"); +	llassert(mReservedUniforms.size() == LLShaderMgr::OBJECT_PLANE_T+1);  	mReservedUniforms.push_back("viewport"); @@ -1116,6 +1118,48 @@ void LLShaderMgr::initAttribsAndUniforms()  	mReservedUniforms.push_back("bloomMap");  	mReservedUniforms.push_back("projectionMap"); +	mReservedUniforms.push_back("matrixPalette"); +	 +	 +	mReservedUniforms.reserve(12); +	mReservedUniforms.push_back("screenTex"); +	mReservedUniforms.push_back("screenDepth"); +	mReservedUniforms.push_back("refTex"); +	mReservedUniforms.push_back("eyeVec"); +	mReservedUniforms.push_back("time"); +	mReservedUniforms.push_back("d1"); +	mReservedUniforms.push_back("d2"); +	mReservedUniforms.push_back("lightDir"); +	mReservedUniforms.push_back("specular"); +	mReservedUniforms.push_back("lightExp"); +	mReservedUniforms.push_back("waterFogColor"); +	mReservedUniforms.push_back("waterFogDensity"); +	mReservedUniforms.push_back("waterFogKS"); +	mReservedUniforms.push_back("refScale"); +	mReservedUniforms.push_back("waterHeight"); +	mReservedUniforms.push_back("waterPlane"); +	mReservedUniforms.push_back("normScale"); +	mReservedUniforms.push_back("fresnelScale"); +	mReservedUniforms.push_back("fresnelOffset"); +	mReservedUniforms.push_back("blurMultiplier"); +	mReservedUniforms.push_back("sunAngle"); +	mReservedUniforms.push_back("scaledAngle"); +	mReservedUniforms.push_back("sunAngle2"); +	 +	mReservedUniforms.push_back("camPosLocal"); + +	mReservedUniforms.push_back("gWindDir"); +	mReservedUniforms.push_back("gSinWaveParams"); +	mReservedUniforms.push_back("gGravity"); + +	mReservedUniforms.push_back("detail_0"); +	mReservedUniforms.push_back("detail_1"); +	mReservedUniforms.push_back("detail_2"); +	mReservedUniforms.push_back("detail_3"); +	mReservedUniforms.push_back("alpha_ramp"); + +	mReservedUniforms.push_back("origin"); +  	llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);  	std::set<std::string> dupe_check; diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index 7a16b7c20f..77e90372e0 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -47,6 +47,8 @@ public:  		TEXTURE_MATRIX1,  		TEXTURE_MATRIX2,  		TEXTURE_MATRIX3, +		OBJECT_PLANE_S, +		OBJECT_PLANE_T,  		VIEWPORT,  		LIGHT_POSITION,  		LIGHT_DIRECTION, @@ -164,7 +166,49 @@ public:  		DEFERRED_LIGHT,  		DEFERRED_BLOOM,  		DEFERRED_PROJECTION, +		 +		AVATAR_MATRIX, + +		WATER_SCREENTEX, +		WATER_SCREENDEPTH, +		WATER_REFTEX, +		WATER_EYEVEC, +		WATER_TIME, +		WATER_WAVE_DIR1, +		WATER_WAVE_DIR2, +		WATER_LIGHT_DIR, +		WATER_SPECULAR, +		WATER_SPECULAR_EXP, +		WATER_FOGCOLOR, +		WATER_FOGDENSITY, +		WATER_FOGKS, +		WATER_REFSCALE, +		WATER_WATERHEIGHT, +		WATER_WATERPLANE, +		WATER_NORM_SCALE, +		WATER_FRESNEL_SCALE, +		WATER_FRESNEL_OFFSET, +		WATER_BLUR_MULTIPLIER, +		WATER_SUN_ANGLE, +		WATER_SCALED_ANGLE, +		WATER_SUN_ANGLE2, +		 +		WL_CAMPOSLOCAL, + +		AVATAR_WIND, +		AVATAR_SINWAVE, +		AVATAR_GRAVITY, + +		TERRAIN_DETAIL0, +		TERRAIN_DETAIL1, +		TERRAIN_DETAIL2, +		TERRAIN_DETAIL3, +		TERRAIN_ALPHARAMP, +		 +		SHINY_ORIGIN, +  		END_RESERVED_UNIFORMS +  	} eGLSLReservedUniforms;  	// singleton pattern implementation diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 4909b43e8a..87fb76e46e 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -85,6 +85,7 @@ const U32 LL_VBO_POOL_SEED_COUNT = vbo_block_index(LL_VBO_POOL_MAX_SEED_SIZE);  //static  LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB);  LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB); +LLVBOPool LLVertexBuffer::sDynamicCopyVBOPool(GL_DYNAMIC_COPY_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); @@ -199,7 +200,10 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)  		if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)  		{  			glBufferDataARB(mType, size, 0, mUsage); -			ret = (U8*) ll_aligned_malloc_16(size); +			if (mUsage != GL_DYNAMIC_COPY_ARB) +			{ //data will be provided by application +				ret = (U8*) ll_aligned_malloc(size, 64); +			}  		}  		else  		{ //always use a true hint of static draw when allocating non-client-backed buffers @@ -252,7 +256,7 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)  	llassert(vbo_block_size(size) == size);  	deleteBuffer(name); -	ll_aligned_free_16((U8*) buffer); +	ll_aligned_free((U8*) buffer);  	if (mType == GL_ARRAY_BUFFER_ARB)  	{ @@ -306,7 +310,7 @@ void LLVBOPool::cleanup()  			if (r.mClientData)  			{ -				ll_aligned_free_16((void*) r.mClientData); +				ll_aligned_free((void*) r.mClientData);  			}  			l.pop_front(); @@ -393,6 +397,7 @@ void LLVertexBuffer::seedPools()  {  	sStreamVBOPool.seedPool();  	sDynamicVBOPool.seedPool(); +	sDynamicCopyVBOPool.seedPool();  	sStreamIBOPool.seedPool();  	sDynamicIBOPool.seedPool();  } @@ -878,6 +883,7 @@ void LLVertexBuffer::cleanupClass()  	sDynamicIBOPool.cleanup();  	sStreamVBOPool.cleanup();  	sDynamicVBOPool.cleanup(); +	sDynamicCopyVBOPool.cleanup();  	if(sPrivatePoolp)  	{ @@ -914,13 +920,16 @@ S32 LLVertexBuffer::determineUsage(S32 usage)  	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 -			ret_usage = GL_STREAM_DRAW_ARB; -		} -		else +		if (ret_usage != GL_DYNAMIC_COPY_ARB)  		{ -			ret_usage = GL_DYNAMIC_DRAW_ARB; +			if (sDisableVBOMapping) +			{ //always use stream draw if VBO mapping is disabled +				ret_usage = GL_STREAM_DRAW_ARB; +			} +			else +			{ +				ret_usage = GL_DYNAMIC_DRAW_ARB; +			}  		}  	} @@ -1070,10 +1079,15 @@ void LLVertexBuffer::genBuffer(U32 size)  	{  		mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);  	} -	else +	else if (mUsage == GL_DYNAMIC_DRAW_ARB)  	{  		mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);  	} +	else +	{ +		mMappedData = sDynamicCopyVBOPool.allocate(mGLBuffer, mSize); +	} +  	sGLCount++;  } @@ -1287,7 +1301,7 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create)  		//actually allocate space for the vertex buffer if using VBO mapping  		flush(); -		if (gGLManager.mHasVertexArrayObject && useVBOs() && (LLRender::sGLCoreProfile || sUseVAO)) +		if (gGLManager.mHasVertexArrayObject && useVBOs() && (sUseVAO))  		{  #if GL_ARB_vertex_array_object  			mGLArray = getVAOName(); @@ -1443,21 +1457,18 @@ bool LLVertexBuffer::useVBOs() const  //---------------------------------------------------------------------------- -bool expand_region(LLVertexBuffer::MappedRegion& region, S32 index, S32 count) +bool expand_region(LLVertexBuffer::MappedRegion& region, S32 start, S32 end)  { -	S32 end = index+count; -	S32 region_end = region.mIndex+region.mCount; -	  	if (end < region.mIndex || -		index > region_end) +		start > region.mEnd)  	{ //gap exists, do not merge  		return false;  	} -	S32 new_end = llmax(end, region_end); -	S32 new_index = llmin(index, region.mIndex); -	region.mIndex = new_index; -	region.mCount = new_end-new_index; +	region.mEnd = llmax(end, region.mEnd); +	region.mIndex = llmin(start, region.mIndex); +	region.mCount = region.mEnd-region.mIndex; +  	return true;  } @@ -1467,7 +1478,6 @@ static LLFastTimer::DeclareTimer FTM_VBO_MAP_BUFFER("VBO Map");  // Map for data access  volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, bool map_range)  { -	bindGLBuffer(true);  	if (mFinal)  	{  		llerrs << "LLVertexBuffer::mapVeretxBuffer() called on a finalized buffer." << llendl; @@ -1488,23 +1498,23 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo  			bool mapped = false;  			//see if range is already mapped -			for (U32 i = 0; i < mMappedVertexRegions.size(); ++i) +			S32 start_index = mOffsets[type]+index*sTypeSize[type]; +			S32 end_index = start_index+count*sTypeSize[type]; + +			for (std::vector<MappedRegion>::iterator iter = mMappedVertexRegions.begin(), end = mMappedVertexRegions.end(); iter != end; ++iter)  			{ -				MappedRegion& region = mMappedVertexRegions[i]; -				if (region.mType == type) +				MappedRegion& region = *iter; +				if (expand_region(region, index, end_index))  				{ -					if (expand_region(region, index, count)) -					{ -						mapped = true; -						break; -					} +					mapped = true; +					break;  				}  			}  			if (!mapped)  			{  				//not already mapped, map new region -				MappedRegion region(type, mMappable && map_range ? -1 : index, count); +				MappedRegion region(mMappable && map_range ? -1 : start_index, end_index-start_index);  				mMappedVertexRegions.push_back(region);  			}  		} @@ -1528,6 +1538,7 @@ volatile U8* LLVertexBuffer::mapVertexBuffer(S32 type, S32 index, S32 count, boo  			{  				volatile U8* src = NULL;  				waitFence(); +				bindGLBuffer();  				if (gGLManager.mHasMapBufferRange)  				{  					if (map_range) @@ -1648,7 +1659,6 @@ static LLFastTimer::DeclareTimer FTM_VBO_MAP_INDEX("IBO Map");  volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range)  { -	bindGLIndices(true);  	if (mFinal)  	{  		llerrs << "LLVertexBuffer::mapIndexBuffer() called on a finalized buffer." << llendl; @@ -1667,12 +1677,14 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range  				count = mNumIndices-index;  			} +			S32 end = index+count; +  			bool mapped = false;  			//see if range is already mapped  			for (U32 i = 0; i < mMappedIndexRegions.size(); ++i)  			{  				MappedRegion& region = mMappedIndexRegions[i]; -				if (expand_region(region, index, count)) +				if (expand_region(region, index, end))  				{  					mapped = true;  					break; @@ -1682,7 +1694,7 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range  			if (!mapped)  			{  				//not already mapped, map new region -				MappedRegion region(TYPE_INDEX, mMappable && map_range ? -1 : index, count); +				MappedRegion region(mMappable && map_range ? -1 : index, count);  				mMappedIndexRegions.push_back(region);  			}  		} @@ -1698,23 +1710,23 @@ volatile U8* LLVertexBuffer::mapIndexBuffer(S32 index, S32 count, bool map_range  			sMappedCount++;  			stop_glerror();	 -			if (gDebugGL && useVBOs()) -			{ -				GLint elem = 0; -				glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem); - -				if (elem != mGLIndices) -				{ -					llerrs << "Wrong index buffer bound!" << llendl; -				} -			} -  			if(!mMappable)  			{  				map_range = false;  			}  			else  			{ +				bindGLIndices(); +				if (gDebugGL && useVBOs()) +				{ +					GLint elem = 0; +					glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &elem); + +					if (elem != mGLIndices) +					{ +						llerrs << "Wrong index buffer bound!" << llendl; +					} +				}  				volatile U8* src = NULL;  				waitFence();  				if (gGLManager.mHasMapBufferRange) @@ -1827,8 +1839,10 @@ void LLVertexBuffer::unmapBuffer()  	if (mMappedData && mVertexLocked)  	{ +		llassert(mUsage != GL_DYNAMIC_COPY_ARB); +		  		LLFastTimer t(FTM_VBO_UNMAP); -		bindGLBuffer(true); +		bindGLBuffer();  		updated_all = mIndexLocked; //both vertex and index buffers done updating  		if(!mMappable) @@ -1839,8 +1853,8 @@ void LLVertexBuffer::unmapBuffer()  				for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)  				{  					const MappedRegion& region = mMappedVertexRegions[i]; -					S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; -					S32 length = sTypeSize[region.mType]*region.mCount; +					S32 offset = region.mIndex; +					S32 length = region.mCount;  					glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, offset, length, (U8*) mMappedData+offset);  					stop_glerror();  				} @@ -1864,8 +1878,8 @@ void LLVertexBuffer::unmapBuffer()  					for (U32 i = 0; i < mMappedVertexRegions.size(); ++i)  					{  						const MappedRegion& region = mMappedVertexRegions[i]; -						S32 offset = region.mIndex >= 0 ? mOffsets[region.mType]+sTypeSize[region.mType]*region.mIndex : 0; -						S32 length = sTypeSize[region.mType]*region.mCount; +						S32 offset = region.mIndex; +						S32 length = region.mCount;  						if (gGLManager.mHasMapBufferRange)  						{  							LLFastTimer t(FTM_VBO_FLUSH_RANGE); @@ -2078,7 +2092,6 @@ bool LLVertexBuffer::bindGLArray()  	if (mGLArray && sGLRenderArray != mGLArray)  	{  		{ -			LLFastTimer t(FTM_BIND_GL_ARRAY);  #if GL_ARB_vertex_array_object  			glBindVertexArray(mGLArray);  #endif @@ -2105,22 +2118,15 @@ bool LLVertexBuffer::bindGLBuffer(bool force_bind)  	if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))  	{ -		LLFastTimer t(FTM_BIND_GL_BUFFER); -		/*if (sMapped) -		{ -			llerrs << "VBO bound while another VBO mapped!" << llendl; -		}*/ +		//LLFastTimer t(FTM_BIND_GL_BUFFER); <-- this timer is showing up as a hotspot (irony) +		  		glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);  		sGLRenderBuffer = mGLBuffer;  		sBindCount++;  		sVBOActive = true; -		if (mGLArray) -		{ -			llassert(sGLRenderArray == mGLArray); -			//mCachedRenderBuffer = mGLBuffer; -		} - +		llassert(!mGLArray || sGLRenderArray == mGLArray); +		  		ret = true;  	} @@ -2362,7 +2368,8 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)  		if (data_mask & MAP_COLOR)  		{  			S32 loc = TYPE_COLOR; -			void* ptr = (void*)(base + mOffsets[TYPE_COLOR]); +			//bind emissive instead of color pointer if emissive is present +			void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]);  			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);  		}  		if (data_mask & MAP_EMISSIVE) @@ -2370,6 +2377,12 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)  			S32 loc = TYPE_EMISSIVE;  			void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);  			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); + +			if (!(data_mask & MAP_COLOR)) +			{ //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps +				loc = TYPE_COLOR; +				glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr); +			}  		}  		if (data_mask & MAP_WEIGHT)  		{ @@ -2452,11 +2465,10 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask)  	llglassertok();  } -LLVertexBuffer::MappedRegion::MappedRegion(S32 type, S32 index, S32 count) -: mType(type), mIndex(index), mCount(count) +LLVertexBuffer::MappedRegion::MappedRegion(S32 index, S32 count) +: mIndex(index), mCount(count)  {  -	llassert(mType == LLVertexBuffer::TYPE_INDEX ||  -			mType < LLVertexBuffer::TYPE_TEXTURE_INDEX); +	mEnd = mIndex+mCount;	  }	 diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index 11fa4ab6a0..52559d3505 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -104,11 +104,11 @@ public:  	class MappedRegion  	{  	public: -		S32 mType;  		S32 mIndex;  		S32 mCount; +		S32 mEnd; -		MappedRegion(S32 type, S32 index, S32 count); +		MappedRegion(S32 index, S32 count);  	};  	LLVertexBuffer(const LLVertexBuffer& rhs) @@ -125,9 +125,10 @@ public:  	static LLVBOPool sStreamVBOPool;  	static LLVBOPool sDynamicVBOPool; +	static LLVBOPool sDynamicCopyVBOPool;  	static LLVBOPool sStreamIBOPool;  	static LLVBOPool sDynamicIBOPool; - +	  	static std::list<U32> sAvailableVAOName;  	static U32 sCurVAOName; diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp index c216d593a2..fdfaf284de 100644 --- a/indra/llui/llconsole.cpp +++ b/indra/llui/llconsole.cpp @@ -243,7 +243,6 @@ void LLConsole::draw()  void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color)   {  	LLSD paragraph_color_segments; -	  	paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText);  	LLSD color_sd = color.getValue();  	paragraph_color_segments[0]["color"]=color_sd; diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h index f32f1dd74c..b264aeb7eb 100644 --- a/indra/llui/llconsole.h +++ b/indra/llui/llconsole.h @@ -34,9 +34,10 @@  class LLSD; -class LLConsole : public LLFixedBuffer, public LLUICtrl, public LLInstanceTracker<LLConsole> +class LLConsole : public LLFixedBuffer, public LLUICtrl, public INSTANCE_TRACKER(LLConsole)  {  public: +  	typedef enum e_font_size  	{  		MONOSPACE = -1, diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 4dba1e645f..f28ceb0ce4 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -112,15 +112,18 @@ struct LLCoordFloater : LLCoord<LL_COORD_FLOATER>  	bool operator!=(const LLCoordFloater& other) const { return !(*this == other); }  	void setFloater(LLFloater& floater); + +	  }; -class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater> +class LLFloater : public LLPanel, public INSTANCE_TRACKER(LLFloater)  {  	friend class LLFloaterView;  	friend class LLFloaterReg;  	friend class LLMultiFloater;  public: +  	struct KeyCompare  	{  //		static bool compare(const LLSD& a, const LLSD& b); diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index fdb4108afb..fdb4108afb 100755..100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp diff --git a/indra/llui/llfolderviewitem.h b/indra/llui/llfolderviewitem.h index ca31931e19..ca31931e19 100755..100644 --- a/indra/llui/llfolderviewitem.h +++ b/indra/llui/llfolderviewitem.h diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 795dacdbb0..5f9dbb33ad 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -367,7 +367,7 @@ void LLKeywords::findSegments(std::vector<LLTextSegmentPtr>* seg_list, const LLW  	const llwchar* base = wtext.c_str();  	const llwchar* cur = base; - +        (void)line;  	while( *cur )  	{  		if( *cur == '\n' || cur == base ) diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index e33ac1d5c2..7115ad496a 100644 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -476,7 +476,7 @@ void LLLayoutStack::createResizeBar(LLLayoutPanel* panelp)  		if (lp->mResizeBar == NULL)  		{  			LLResizeBar::Side side = (mOrientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; - +			(void)resize_bar_rect;  			LLResizeBar::Params resize_params;  			resize_params.name("resize");  			resize_params.resizing_view(lp); @@ -864,3 +864,4 @@ void LLLayoutStack::updateResizeBarLimits()  		previous_visible_panelp = visible_panelp;  	}  } + diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 02c664f1a0..a8b5466242 100644 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -35,9 +35,10 @@  class LLLayoutPanel; -class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack> +class LLLayoutStack : public LLView, public INSTANCE_TRACKER(LLLayoutStack)  {  public: +  	typedef enum e_layout_orientation  	{  		HORIZONTAL, diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 1789f003b9..8bafbd53d8 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -1121,7 +1121,7 @@ bool LLNotificationChannelBase::updateItem(const LLSD& payload, LLNotificationPt  LLNotificationChannel::LLNotificationChannel(const Params& p)  :	LLNotificationChannelBase(p.filter()), -	LLInstanceTracker<LLNotificationChannel, std::string>(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()), +	LLInstanceTracker<LLNotificationChannel, InstanceTrackType_LLNotificationContext, std::string>(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString()),  	mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString())  {  	BOOST_FOREACH(const std::string& source, p.sources) @@ -1135,7 +1135,7 @@ LLNotificationChannel::LLNotificationChannel(const std::string& name,  											 const std::string& parent,  											 LLNotificationFilter filter)   :	LLNotificationChannelBase(filter), -	LLInstanceTracker<LLNotificationChannel, std::string>(name), +	LLInstanceTracker<LLNotificationChannel, InstanceTrackType_LLNotificationContext, std::string>(name),  	mName(name)  {  	// bind to notification broadcast diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 87573c2a56..2561125aa5 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -135,10 +135,11 @@ typedef LLFunctorRegistration<LLNotificationResponder> LLNotificationFunctorRegi  // context data that can be looked up via a notification's payload by the display logic  // derive from this class to implement specific contexts -class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID> +class LLNotificationContext : public INSTANCE_TRACKER_KEYED(LLNotificationContext, LLUUID)  {  public: -	LLNotificationContext() : LLInstanceTracker<LLNotificationContext, LLUUID>(LLUUID::generateNewID()) + +	LLNotificationContext() : INSTANCE_TRACKER_KEYED(LLNotificationContext, LLUUID)(LLUUID::generateNewID())  	{  	} @@ -814,7 +815,7 @@ typedef boost::intrusive_ptr<LLNotificationChannel> LLNotificationChannelPtr;  class LLNotificationChannel :   	boost::noncopyable,   	public LLNotificationChannelBase, -	public LLInstanceTracker<LLNotificationChannel, std::string> +	public LLInstanceTracker<LLNotificationChannel, InstanceTrackType_LLNotificationContext, std::string>  {  	LOG_CLASS(LLNotificationChannel); diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index e70992129a..b25f9b913c 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -2338,7 +2338,6 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round,  {  	// Figure out which line we're nearest to.  	LLRect doc_rect = mDocumentView->getRect(); -  	S32 doc_y = local_y - doc_rect.mBottom;  	// binary search for line that starts before local_y diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 3d9f5cbbc2..5d0ac9eeb4 100644 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -838,6 +838,7 @@ void LLToolBar::draw()  	if (mDragAndDropTarget && !mButtonCommands.empty())  	{  		LLRect caret_rect = caret->getRect(); +		(void)toolbar_rect;  		if (getOrientation(mSideType) == LLLayoutStack::HORIZONTAL)  		{  			caret->setRect(LLRect(mDragx-caret_rect.getWidth()/2+1, diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index e9147d552e..06d7e4907a 100644 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -39,9 +39,10 @@ class LLWindowCallbacks;  // Refer to llwindow_test in test/common/llwindow for usage example -class LLWindow : public LLInstanceTracker<LLWindow> +class LLWindow : public INSTANCE_TRACKER(LLWindow)  {  public: +  	struct LLWindowResolution  	{  		S32 mWidth; diff --git a/indra/llxml/llcontrol.cpp b/indra/llxml/llcontrol.cpp index 666c03e9ff..f82750af47 100644 --- a/indra/llxml/llcontrol.cpp +++ b/indra/llxml/llcontrol.cpp @@ -316,7 +316,7 @@ LLPointer<LLControlVariable> LLControlGroup::getControl(const std::string& name)  ////////////////////////////////////////////////////////////////////////////  LLControlGroup::LLControlGroup(const std::string& name) -:	LLInstanceTracker<LLControlGroup, std::string>(name) +:	INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name)  {  	mTypeString[TYPE_U32] = "U32";  	mTypeString[TYPE_S32] = "S32"; diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index ee7d1d50b7..6ea010f4f9 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -180,7 +180,7 @@ 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> +class LLControlGroup : public INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)  {  	LOG_CLASS(LLControlGroup); @@ -197,7 +197,7 @@ public:  	~LLControlGroup();  	void cleanup(); -	typedef LLInstanceTracker<LLControlGroup, std::string>::instance_iter instance_iter; +	typedef INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)::instance_iter instance_iter;  	LLControlVariablePtr getControl(const std::string& name); @@ -306,7 +306,7 @@ public:  //! without have to manually create and bind a listener to a local  //! object.  template <class T> -class LLControlCache : public LLRefCount, public LLInstanceTracker<LLControlCache<T>, std::string> +class LLControlCache : public LLRefCount, public LLInstanceTracker<LLControlCache<T>, InstanceTrackType_LLControlCache, std::string>  {  public:  	// This constructor will declare a control if it doesn't exist in the contol group @@ -314,7 +314,7 @@ public:  					const std::string& name,   					const T& default_value,   					const std::string& comment) -	:	LLInstanceTracker<LLControlCache<T>, std::string >(name) +	:	LLInstanceTracker<LLControlCache<T>, InstanceTrackType_LLControlCache, std::string >(name)  	{  		if(!group.controlExists(name))  		{ @@ -329,7 +329,7 @@ public:  	LLControlCache(LLControlGroup& group,  					const std::string& name) -	:	LLInstanceTracker<LLControlCache<T>, std::string >(name) +	:	LLInstanceTracker<LLControlCache<T>, InstanceTrackType_LLControlCache, std::string >(name)  	{  		if(!group.controlExists(name))  		{ diff --git a/indra/lscript/lscript_byteformat.h b/indra/lscript/lscript_byteformat.h index a294def734..9650574622 100644 --- a/indra/lscript/lscript_byteformat.h +++ b/indra/lscript/lscript_byteformat.h @@ -530,6 +530,9 @@ typedef enum e_lscript_runtime_permissions  	SCRIPT_PERMISSION_TRACK_CAMERA,  	SCRIPT_PERMISSION_CONTROL_CAMERA,  	SCRIPT_PERMISSION_TELEPORT, +	SCRIPT_PERMISSION_EXPERIENCE,  +	SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT, +	SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS,  	SCRIPT_PERMISSION_EOF  } LSCRIPTRunTimePermissions; @@ -547,6 +550,9 @@ const U32 LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_EOF] =  	(0x1 << 10),//	SCRIPT_PERMISSION_TRACK_CAMERA  	(0x1 << 11),//	SCRIPT_PERMISSION_CONTROL_CAMERA  	(0x1 << 12),//	SCRIPT_PERMISSION_TELEPORT +	(0x1 << 13),//  SCRIPT_PERMISSION_EXPERIENCE +	(0x1 << 14),//  SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT +	(0x1 << 15),//  SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS  };  // http_request string constants diff --git a/indra/lscript/lscript_compile/indra.l b/indra/lscript/lscript_compile/indra.l index 71da95b8f5..0d93f5cba2 100644 --- a/indra/lscript/lscript_compile/indra.l +++ b/indra/lscript/lscript_compile/indra.l @@ -237,6 +237,8 @@ extern "C" { int yyerror(const char *fmt, ...); }  "PERMISSION_TRACK_CAMERA"		{ count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TRACK_CAMERA]; return(INTEGER_CONSTANT); }  "PERMISSION_CONTROL_CAMERA"		{ count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CONTROL_CAMERA]; return(INTEGER_CONSTANT); }  "PERMISSION_TELEPORT"			{ count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TELEPORT]; return(INTEGER_CONSTANT); } +"PERMISSION_SILENT_ESTATE_MANAGEMENT"   { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT]; return(INTEGER_CONSTANT); } +"PERMISSION_OVERRIDE_ANIMATIONS"    { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS]; return(INTEGER_CONSTANT); }  "INVENTORY_TEXTURE"					{ count(); yylval.ival = LLAssetType::AT_TEXTURE; return(INTEGER_CONSTANT); }  "INVENTORY_SOUND"					{ count(); yylval.ival = LLAssetType::AT_SOUND; return(INTEGER_CONSTANT); } @@ -378,6 +380,10 @@ extern "C" { int yyerror(const char *fmt, ...); }  "PSYS_PART_END_SCALE"	{ count(); yylval.ival = LLPS_PART_END_SCALE; return (INTEGER_CONSTANT); }  "PSYS_PART_MAX_AGE"		{ count(); yylval.ival = LLPS_PART_MAX_AGE; return (INTEGER_CONSTANT); } +"PSYS_PART_BLEND_FUNC_SOURCE"	{ count(); yylval.ival = LLPS_PART_BLEND_FUNC_SOURCE; return (INTEGER_CONSTANT); } +"PSYS_PART_BLEND_FUNC_DEST"		{ count(); yylval.ival = LLPS_PART_BLEND_FUNC_DEST; return (INTEGER_CONSTANT); } +"PSYS_PART_START_GLOW"	{ count(); yylval.ival = LLPS_PART_START_GLOW; return (INTEGER_CONSTANT); } +"PSYS_PART_END_GLOW"	{ count(); yylval.ival = LLPS_PART_END_GLOW; return (INTEGER_CONSTANT); }  "PSYS_PART_WIND_MASK"				{ count(); yylval.ival = LLPartData::LL_PART_WIND_MASK; return(INTEGER_CONSTANT); }  "PSYS_PART_INTERP_COLOR_MASK"		{ count(); yylval.ival = LLPartData::LL_PART_INTERP_COLOR_MASK; return(INTEGER_CONSTANT); } @@ -388,6 +394,16 @@ extern "C" { int yyerror(const char *fmt, ...); }  "PSYS_PART_TARGET_POS_MASK"			{ count(); yylval.ival = LLPartData::LL_PART_TARGET_POS_MASK; return(INTEGER_CONSTANT); }  "PSYS_PART_EMISSIVE_MASK"			{ count(); yylval.ival = LLPartData::LL_PART_EMISSIVE_MASK; return(INTEGER_CONSTANT); }  "PSYS_PART_TARGET_LINEAR_MASK"		{ count(); yylval.ival = LLPartData::LL_PART_TARGET_LINEAR_MASK; return(INTEGER_CONSTANT); } +"PSYS_PART_RIBBON_MASK"				{ count(); yylval.ival = LLPartData::LL_PART_RIBBON_MASK; return(INTEGER_CONSTANT); } + +"PSYS_PART_BF_ONE"						{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ZERO"						{ count(); yylval.ival = LLPartData::LL_PART_BF_ZERO; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_DEST_COLOR"				{ count(); yylval.ival = LLPartData::LL_PART_BF_DEST_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_SOURCE_COLOR"				{ count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ONE_MINUS_DEST_COLOR"		{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_DEST_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR"	{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_COLOR; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_SOURCE_ALPHA"				{ count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_ALPHA; return(INTEGER_CONSTANT); } +"PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA"	{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; return(INTEGER_CONSTANT); }  "PSYS_SRC_MAX_AGE"					{ count(); yylval.ival = LLPS_SRC_MAX_AGE; return(INTEGER_CONSTANT); } diff --git a/indra/lscript/lscript_execute/lscript_readlso.cpp b/indra/lscript/lscript_execute/lscript_readlso.cpp index 8b41cb5a72..c88b43ed83 100644 --- a/indra/lscript/lscript_execute/lscript_readlso.cpp +++ b/indra/lscript/lscript_execute/lscript_readlso.cpp @@ -145,7 +145,7 @@ void LLScriptLSOParse::printGlobals(LLFILE *fp)  		// get offset to skip past name  		varoffset = global_v_offset;  		bytestream2integer(mRawData, global_v_offset); -		 +		(void)offset; //hush little compiler  		// get typeexport  		type = *(mRawData + global_v_offset++); @@ -347,6 +347,7 @@ void LLScriptLSOParse::printStates(LLFILE *fp)  				S32 temp_end;  				opcode_end = worst_case_opcode_end; +				(void)opcode_end;  				for (k = LSTT_STATE_BEGIN; k < LSTT_STATE_END; k++)  				{ @@ -354,6 +355,7 @@ void LLScriptLSOParse::printStates(LLFILE *fp)  					{  						temp_end = bytestream2integer(mRawData, read_ahead);  						bytestream2integer(mRawData, read_ahead); +						(void)dummy;  						if (  (temp_end < opcode_end)  							&&(temp_end > event_offset))  						{ diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 4f7ce88165..b4039db5dd 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -120,6 +120,7 @@ set(viewer_SOURCE_FILES      llavatariconctrl.cpp      llavatarlist.cpp      llavatarlistitem.cpp +    llavatarrenderinfoaccountant.cpp      llavatarpropertiesprocessor.cpp      llblockedlistitem.cpp      llblocklist.cpp @@ -701,6 +702,7 @@ set(viewer_HEADER_FILES      llavatarlist.h      llavatarlistitem.h      llavatarpropertiesprocessor.h +    llavatarrenderinfoaccountant.h      llblockedlistitem.h      llblocklist.h      llbox.h diff --git a/indra/newview/app_settings/keywords.ini b/indra/newview/app_settings/keywords.ini index 0b346286c8..ef0f78d4d4 100644 --- a/indra/newview/app_settings/keywords.ini +++ b/indra/newview/app_settings/keywords.ini @@ -92,6 +92,8 @@ PERMISSION_CHANGE_LINKS			Passed to llRequestPermissions library function to req  PERMISSION_TRACK_CAMERA			Passed to llRequestPermissions library function to request permission to track agent's camera  PERMISSION_CONTROL_CAMERA		Passed to llRequestPermissions library function to request permission to change agent's camera  PERMISSION_TELEPORT				Passed to llRequestPermissions library function to request permission to teleport agent +PERMISSION_SILENT_ESTATE_MANAGEMENT	Passed to llRequestPermissions library function to request permission to modify estate settings without notifying the owner +PERMISSION_OVERRIDE_ANIMATIONS	Passed to llRequestPermissions library function to request permission to change agent's default animations  DEBUG_CHANNEL		Chat channel reserved for debug and error messages from scripts  PUBLIC_CHANNEL		Chat channel that broadcasts to all nearby users @@ -129,6 +131,7 @@ PSYS_PART_FOLLOW_VELOCITY_MASK  PSYS_PART_TARGET_POS_MASK  PSYS_PART_EMISSIVE_MASK  PSYS_PART_TARGET_LINEAR_MASK +PSYS_PART_RIBBON_MASK  PSYS_SRC_PATTERN  PSYS_SRC_INNERANGLE	Deprecated -- Use PSYS_SRC_ANGLE_BEGIN @@ -145,12 +148,24 @@ PSYS_SRC_ACCEL  PSYS_SRC_TEXTURE  PSYS_SRC_TARGET_KEY  PSYS_SRC_OMEGA +PSYS_PART_BLEND_FUNC_SOURCE +PSYS_PART_BLEND_FUNC_DEST +PSYS_PART_START_GLOW +PSYS_PART_END_GLOW  PSYS_SRC_PATTERN_DROP  PSYS_SRC_PATTERN_EXPLODE  PSYS_SRC_PATTERN_ANGLE  PSYS_SRC_PATTERN_ANGLE_CONE  PSYS_SRC_PATTERN_ANGLE_CONE_EMPTY +PSYS_PART_BF_ONE +PSYS_PART_BF_ZERO +PSYS_PART_BF_DEST_COLOR +PSYS_PART_BF_SOURCE_COLOR +PSYS_PART_BF_ONE_MINUS_DEST_COLOR +PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR +PSYS_PART_BF_SOURCE_ALPHA +PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA  OBJECT_UNKNOWN_DETAIL	Returned by llGetObjectDetails when passed an invalid object parameter type  OBJECT_NAME				Used with llGetObjectDetails to get an object's name diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b291de0dbd..c7895fbd99 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -9466,10 +9466,21 @@      <key>Value</key>      <integer>0</integer>    </map> +  <key>RenderAutoMuteRenderCostLimit</key> +  <map> +    <key>Comment</key> +    <string>Maximum render weight before an avatar is automatically visually muted (0 to not use this limit).</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <integer>0</integer> +  </map>    <key>RenderAutoMuteSurfaceAreaLimit</key>    <map>      <key>Comment</key> -    <string>Maximum surface area of attachments before an avatar is automatically visually muted (0 for no limit).</string> +    <string>Maximum surface area of attachments before an avatar is automatically visually muted (0 to not use this limit).</string>      <key>Persist</key>      <integer>1</integer>      <key>Type</key> @@ -9477,6 +9488,39 @@      <key>Value</key>      <integer>0</integer>    </map> +  <key>RenderAutoMuteEnabled</key> +  <map> +    <key>Comment</key> +    <string>Apply visual muting to high cost, non-friends, not in IM, or somewhat distant avatars</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>0</integer> +  </map> +  <key>RenderAutoMuteLogging</key> +  <map> +    <key>Comment</key> +    <string>Show extra information in viewer logs about avatar rendering costs</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>Boolean</string> +    <key>Value</key> +    <integer>0</integer> +  </map> +  <key>RenderAutoMuteVisibilityRank</key> +  <map> +    <key>Comment</key> +    <string>Number of avatars to show normally for visual muting mode.</string> +    <key>Persist</key> +    <integer>1</integer> +    <key>Type</key> +    <string>U32</string> +    <key>Value</key> +    <integer>0</integer> +  </map>    <key>RenderAutoHideSurfaceAreaLimit</key>    <map> diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl index bfd9b9b3eb..29a6d842d2 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/avatarF.glsl @@ -31,6 +31,8 @@ out vec4 frag_data[3];  uniform sampler2D diffuseMap; +uniform float minimum_alpha; +  VARYING vec3 vary_normal;  VARYING vec2 vary_texcoord0; @@ -38,7 +40,7 @@ void main()  {  	vec4 diff = texture2D(diffuseMap, vary_texcoord0.xy); -	if (diff.a < 0.2) +	if (diff.a < minimum_alpha)  	{  		discard;  	} diff --git a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl b/indra/newview/app_settings/shaders/class1/deferred/giF.glsl deleted file mode 100644 index da1b234240..0000000000 --- a/indra/newview/app_settings/shaders/class1/deferred/giF.glsl +++ /dev/null @@ -1,190 +0,0 @@ -/**  - * @file giF.glsl - * - * $LicenseInfo:firstyear=2007&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2007, 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$ - */ -  -#extension GL_ARB_texture_rectangle : enable - -#ifdef DEFINE_GL_FRAGCOLOR -out vec4 frag_color; -#else -#define frag_color gl_FragColor -#endif - -uniform sampler2DRect depthMap; -uniform sampler2DRect normalMap; -uniform sampler2D noiseMap; - -uniform sampler2D		diffuseGIMap; -uniform sampler2D		normalGIMap; -uniform sampler2D		depthGIMap; - -uniform sampler2D		lightFunc; - -// Inputs -VARYING vec2 vary_fragcoord; - -uniform vec2 screen_res; - -uniform mat4 inv_proj; -uniform mat4 gi_mat;  //gPipeline.mGIMatrix - eye space to sun space -uniform mat4 gi_mat_proj; //gPipeline.mGIMatrixProj - eye space to projected sun space -uniform mat4 gi_norm_mat; //gPipeline.mGINormalMatrix - eye space normal to sun space normal matrix -uniform mat4 gi_inv_proj; //gPipeline.mGIInvProj - projected sun space to sun space -uniform float gi_radius; -uniform float gi_intensity; -uniform int gi_samples; -uniform vec2 gi_kern[25]; -uniform vec2 gi_scale; -uniform vec3 gi_quad; -uniform vec3 gi_spec; -uniform float gi_direction_weight; -uniform float gi_light_offset; - -vec4 getPosition(vec2 pos_screen) -{ -	float depth = texture2DRect(depthMap, pos_screen.xy).a; -	vec2 sc = pos_screen.xy*2.0; -	sc /= screen_res; -	sc -= vec2(1.0,1.0); -	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); -	vec4 pos = inv_proj * ndc; -	pos /= pos.w; -	pos.w = 1.0; -	return pos; -} - -vec4 getGIPosition(vec2 gi_tc) -{ -	float depth = texture2D(depthGIMap, gi_tc).a; -	vec2 sc = gi_tc*2.0; -	sc -= vec2(1.0, 1.0); -	vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0); -	vec4 pos = gi_inv_proj*ndc; -	pos.xyz /= pos.w; -	pos.w = 1.0; -	return pos; -} - -vec3 giAmbient(vec3 pos, vec3 norm) -{ -	vec4 gi_c = gi_mat_proj * vec4(pos, 1.0); -	gi_c.xyz /= gi_c.w; - -	vec4 gi_pos = gi_mat*vec4(pos,1.0); -	vec3 gi_norm = (gi_norm_mat*vec4(norm,1.0)).xyz; -	gi_norm = normalize(gi_norm); -	 -	vec2 tcx = gi_norm.xy; -	vec2 tcy = gi_norm.yx; -	 -	vec4 eye_pos = gi_mat*vec4(0,0,0,1.0); -	 -	vec3 eye_dir = normalize(gi_pos.xyz-eye_pos.xyz/eye_pos.w); -	 -	//vec3 eye_dir = vec3(0,0,-1); -	//eye_dir = (gi_norm_mat*vec4(eye_dir, 1.0)).xyz; -	//eye_dir = normalize(eye_dir); -	 -	//float round_x = gi_scale.x; -	//float round_y = gi_scale.y; -	 -	vec3 debug = texture2D(normalGIMap, gi_c.xy).rgb*0.5+0.5; -	debug.xz = vec2(0.0,0.0); -	//debug = fract(debug); -	 -	float round_x = 1.0/64.0; -	float round_y = 1.0/64.0; -	 -	//gi_c.x = floor(gi_c.x/round_x+0.5)*round_x; -	//gi_c.y = floor(gi_c.y/round_y+0.5)*round_y; -	 -	float fda = 0.0; -	vec3 fdiff = vec3(0,0,0); -	 -	vec3 rcol = vec3(0,0,0); -	 -	float fsa = 0.0; -	 -	for (int i = -1; i < 2; i+=2 ) -	{ -		for (int j = -1; j < 2; j+=2) -		{ -			vec2 tc = vec2(i, j)*0.75; -			vec3 nz = texture2D(noiseMap, vary_fragcoord.xy/128.0+tc*0.5).xyz; -			//tc += gi_norm.xy*nz.z; -			tc += nz.xy*2.0; -			tc /= gi_samples; -			tc += gi_c.xy; -			 -			vec3 lnorm = -normalize(texture2D(normalGIMap, tc.xy).xyz*2.0-1.0); -			vec3 lpos = getGIPosition(tc.xy).xyz; -							 -			vec3 at = lpos-gi_pos.xyz; -			float dist = dot(at,at); -			float da = clamp(1.0/(gi_spec.x*dist), 0.0, 1.0); -			 -			if (da > 0.0) -			{ -				//add angular attenuation -				vec3 ldir = at; -				float ang_atten = clamp(dot(ldir, gi_norm), 0.0, 1.0); -			 -				float ld = -dot(ldir, lnorm); -				 -				if (ang_atten > 0.0 && ld < 0.0) -				{ -					vec3 diff = texture2D(diffuseGIMap, tc.xy).xyz; -					da = da*ang_atten; -					fda += da; -					fdiff += diff*da; -				} -			} -		} -	} - -	fdiff /= max(gi_spec.y*fda, gi_quad.z); -	fdiff = clamp(fdiff, vec3(0), vec3(1)); -	 -	vec3 ret = fda*fdiff; -	//ret = ret*ret*gi_quad.x+ret*gi_quad.y+gi_quad.z;			 - -	//fda *= nz.z; -	 -	//rcol.rgb *= gi_intensity; -	//return rcol.rgb+vary_AmblitColor.rgb*0.25; -	//return vec4(debug, 0.0); -	//return vec4(fda*fdiff, 0.0); -	return clamp(ret,vec3(0.0), vec3(1.0)); -	//return debug.xyz; -} - -void main()  -{ -	vec2 pos_screen = vary_fragcoord.xy; -	vec4 pos = getPosition(pos_screen); -	vec3 norm = texture2DRect(normalMap, pos_screen).xyz; -	norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm -	 -	frag_color.xyz = giAmbient(pos, norm); -} diff --git a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl index 3427d6db57..1149aec30b 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/waterF.glsl @@ -53,13 +53,11 @@ uniform vec3 specular;  uniform float lightExp;  uniform float refScale;  uniform float kd; -uniform vec2 screenRes;  uniform vec3 normScale;  uniform float fresnelScale;  uniform float fresnelOffset;  uniform float blurMultiplier; -uniform vec2 screen_res; -uniform mat4 norm_mat; //region space to screen space +uniform mat3 normal_matrix;  //bigWave is (refCoord.w, view.w);  VARYING vec4 refCoord; @@ -157,7 +155,7 @@ void main()  	//wavef.z *= 0.1f;  	//wavef = normalize(wavef); -	vec3 screenspacewavef = (norm_mat*vec4(wavef, 1.0)).xyz; +	vec3 screenspacewavef = normal_matrix*wavef;  	frag_data[0] = vec4(color.rgb, 0.5); // diffuse  	frag_data[1] = vec4(0.5,0.5,0.5, 0.95); // speccolor*spec, spec diff --git a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl index 0d8dab0a41..485e48537c 100644 --- a/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/underWaterF.glsl @@ -43,13 +43,11 @@ uniform vec2 fbScale;  uniform float refScale;  uniform float znear;  uniform float zfar; -uniform float kd;  uniform vec4 waterPlane;  uniform vec3 eyeVec;  uniform vec4 waterFogColor;  uniform float waterFogDensity;  uniform float waterFogKS; -uniform vec2 screenRes;  //bigWave is (refCoord.w, view.w);  VARYING vec4 refCoord; diff --git a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl index 79bffab745..1fd7bdaa5c 100644 --- a/indra/newview/app_settings/shaders/class1/environment/waterF.glsl +++ b/indra/newview/app_settings/shaders/class1/environment/waterF.glsl @@ -42,8 +42,6 @@ uniform vec3 lightDir;  uniform vec3 specular;  uniform float lightExp;  uniform float refScale; -uniform float kd; -uniform vec2 screenRes;  uniform vec3 normScale;  uniform float fresnelScale;  uniform float fresnelOffset; diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 8c42defa73..bd1929b0c0 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -3048,6 +3048,30 @@ void LLAgent::sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request)  	sendReliableMessage();  } +// Send a message to the region to stop the NULL animation state +// This will reset animation state overrides for the agent. +void LLAgent::sendAnimationStateReset() +{ +	if (gAgentID.isNull() || !mRegionp) +	{ +		return; +	} + +	LLMessageSystem* msg = gMessageSystem; +	msg->newMessageFast(_PREHASH_AgentAnimation); +	msg->nextBlockFast(_PREHASH_AgentData); +	msg->addUUIDFast(_PREHASH_AgentID, getID()); +	msg->addUUIDFast(_PREHASH_SessionID, getSessionID()); + +	msg->nextBlockFast(_PREHASH_AnimationList); +	msg->addUUIDFast(_PREHASH_AnimID, LLUUID::null ); +	msg->addBOOLFast(_PREHASH_StartAnim, FALSE); + +	msg->nextBlockFast(_PREHASH_PhysicalAvatarEventList); +	msg->addBinaryDataFast(_PREHASH_TypeData, NULL, 0); +	sendReliableMessage(); +} +  void LLAgent::sendWalkRun(bool running)  {  	LLMessageSystem* msgsys = gMessageSystem; @@ -4126,6 +4150,8 @@ void LLAgent::stopCurrentAnimations()  	// avatar, propagating this change back to the server.  	if (isAgentAvatarValid())  	{ +		LLDynamicArray<LLUUID> anim_ids; +  		for ( LLVOAvatar::AnimIterator anim_it =  			      gAgentAvatarp->mPlayingAnimations.begin();  		      anim_it != gAgentAvatarp->mPlayingAnimations.end(); @@ -4143,10 +4169,15 @@ void LLAgent::stopCurrentAnimations()  				// stop this animation locally  				gAgentAvatarp->stopMotion(anim_it->first, TRUE);  				// ...and tell the server to tell everyone. -				sendAnimationRequest(anim_it->first, ANIM_REQUEST_STOP); +				anim_ids.push_back(anim_it->first);  			}  		} +		sendAnimationRequests(anim_ids, ANIM_REQUEST_STOP); + +		// Tell the region to clear any animation state overrides. +		sendAnimationStateReset(); +  		// re-assert at least the default standing animation, because  		// viewers get confused by avs with no associated anims.  		sendAnimationRequest(ANIM_AGENT_STAND, diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index f5f26f69d8..c5b4476318 100644 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -431,6 +431,8 @@ public:  	void			onAnimStop(const LLUUID& id);  	void			sendAnimationRequests(LLDynamicArray<LLUUID> &anim_ids, EAnimRequest request);  	void			sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request); +	void			sendAnimationStateReset(); +  	void			endAnimationUpdateUI();  	void			unpauseAnimation() { mPauseRequest = NULL; }  	BOOL			getCustomAnim() const { return mCustomAnim; } diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index f0481db89b..4f92f67ca0 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -97,6 +97,7 @@  #include "llupdaterservice.h"  #include "llfloatertexturefetchdebugger.h"  #include "llspellcheck.h" +#include "llavatarrenderinfoaccountant.h"  // Linden library includes  #include "llavatarnamecache.h" @@ -553,7 +554,7 @@ static void settings_to_globals()  	LLSurface::setTextureSize(gSavedSettings.getU32("RegionTextureSize"));  	LLRender::sGLCoreProfile = gSavedSettings.getBOOL("RenderGLCoreProfile"); - +	LLVertexBuffer::sUseVAO = gSavedSettings.getBOOL("RenderUseVAO");  	LLImageGL::sGlobalUseAnisotropic	= gSavedSettings.getBOOL("RenderAnisotropic");  	LLImageGL::sCompressTextures		= gSavedSettings.getBOOL("RenderCompressTextures");  	LLVOVolume::sLODFactor				= gSavedSettings.getF32("RenderVolumeLODFactor"); @@ -4613,6 +4614,9 @@ void LLAppViewer::idle()  		gObjectList.updateApparentAngles(gAgent);  	} +	// Update AV render info +	LLAvatarRenderInfoAccountant::idle(); +  	{  		LLFastTimer t(FTM_AUDIO_UPDATE); diff --git a/indra/newview/llavatarrenderinfoaccountant.cpp b/indra/newview/llavatarrenderinfoaccountant.cpp new file mode 100644 index 0000000000..54144677f4 --- /dev/null +++ b/indra/newview/llavatarrenderinfoaccountant.cpp @@ -0,0 +1,371 @@ +/** + * @file   llavatarrenderinfoaccountant.cpp + * @author Dave Simmons + * @date   2013-02-28 + * @brief   + *  + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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$ + */ + +// Precompiled header +#include "llviewerprecompiledheaders.h" +// associated header +#include "llavatarrenderinfoaccountant.h" +// STL headers +// std headers +// external library headers +// other Linden headers +#include "llcharacter.h" +#include "llhttpclient.h" +#include "lltimer.h" +#include "llviewercontrol.h" +#include "llviewerobjectlist.h" +#include "llviewerregion.h" +#include "llvoavatar.h" +#include "llworld.h" + + +static	const std::string KEY_AGENTS = "agents";			// map +static 	const std::string KEY_WEIGHT = "weight";			// integer +static	const std::string KEY_GEOMETRY = "geometry";		// integer +static	const std::string KEY_SURFACE =	"surface";			// float + +static	const std::string KEY_IDENTIFIER = "identifier"; +static	const std::string KEY_MESSAGE = "message"; +static	const std::string KEY_ERROR = "error"; + + +// Send data updates about once per minute, only need per-frame resolution +LLFrameTimer LLAvatarRenderInfoAccountant::sRenderInfoReportTimer; + + +// HTTP responder class for GET request for avatar render weight information +class LLAvatarRenderInfoGetResponder : public LLHTTPClient::Responder +{ +public: +	LLAvatarRenderInfoGetResponder(U64 region_handle) : mRegionHandle(region_handle) +	{ +	} + +	virtual void error(U32 statusNum, const std::string& reason) +	{ +		LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); +		if (regionp) +		{ +			llwarns << "HTTP error result for avatar weight GET: " << statusNum  +				<< ", " << reason +				<< " returned by region " << regionp->getName() +				<< llendl; +		} +		else +		{ +			llwarns << "Avatar render weight GET error recieved but region not found for "  +				<< mRegionHandle  +				<< ", error " << statusNum  +				<< ", " << reason +				<< llendl; +		} + +	} + +	virtual void result(const LLSD& content) +	{ +		LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); +		if (regionp) +		{ +			if (LLAvatarRenderInfoAccountant::logRenderInfo()) +			{ +				llinfos << "Result for avatar weights request for region " << regionp->getName() << ":" << llendl; +			} + +			if (content.isMap()) +			{ +				if (content.has(KEY_AGENTS)) +				{ +					const LLSD & agents = content[KEY_AGENTS]; +					if (agents.isMap()) +					{ +						LLSD::map_const_iterator	report_iter = agents.beginMap(); +						while (report_iter != agents.endMap()) +						{ +							LLUUID target_agent_id = LLUUID(report_iter->first); +							const LLSD & agent_info_map = report_iter->second; +							LLViewerObject* avatarp = gObjectList.findObject(target_agent_id); +							if (avatarp &&  +								avatarp->isAvatar() && +								agent_info_map.isMap()) +							{	// Extract the data for this avatar + +								if (LLAvatarRenderInfoAccountant::logRenderInfo()) +								{ +									llinfos << " Agent " << target_agent_id  +										<< ": " << agent_info_map << llendl; +								} + +								if (agent_info_map.has(KEY_WEIGHT)) +								{ +									((LLVOAvatar *) avatarp)->setReportedVisualComplexity(agent_info_map[KEY_WEIGHT].asInteger()); +								} +								if (agent_info_map.has(KEY_GEOMETRY)) +								{ +									((LLVOAvatar *) avatarp)->setReportedAttachmentGeometryBytes(agent_info_map[KEY_GEOMETRY].asInteger()); +								} +								if (agent_info_map.has(KEY_SURFACE)) +								{ +									((LLVOAvatar *) avatarp)->setReportedAttachmentSurfaceArea((F32) agent_info_map[KEY_SURFACE].asReal()); +								} +							} +							report_iter++; +						} +					} +				}	// has "agents" +				else if (content.has(KEY_ERROR)) +				{ +					const LLSD & error = content[KEY_ERROR]; +					llwarns << "Avatar render info GET error: " +						<< error[KEY_IDENTIFIER] +						<< ": " << error[KEY_MESSAGE]  +						<< " from region " << regionp->getName() +						<< llendl; +				} +			} +		} +		else +		{ +			llinfos << "Avatar render weight info recieved but region not found for "  +				<< mRegionHandle << llendl; +		} +	} + +private: +	U64		mRegionHandle; +}; + + +// HTTP responder class for POST request for avatar render weight information +class LLAvatarRenderInfoPostResponder : public LLHTTPClient::Responder +{ +public: +	LLAvatarRenderInfoPostResponder(U64 region_handle) : mRegionHandle(region_handle) +	{ +	} + +	virtual void error(U32 statusNum, const std::string& reason) +	{ +		LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); +		if (regionp) +		{ +			llwarns << "HTTP error result for avatar weight POST: " << statusNum  +				<< ", " << reason +				<< " returned by region " << regionp->getName() +				<< llendl; +		} +		else +		{ +			llwarns << "Avatar render weight POST error recieved but region not found for "  +				<< mRegionHandle  +				<< ", error " << statusNum  +				<< ", " << reason +				<< llendl; +		} +	} + +	virtual void result(const LLSD& content) +	{ +		LLViewerRegion * regionp = LLWorld::getInstance()->getRegionFromHandle(mRegionHandle); +		if (regionp) +		{ +			if (LLAvatarRenderInfoAccountant::logRenderInfo()) +			{ +				llinfos << "Result for avatar weights POST for region " << regionp->getName() +					<< ": " << content << llendl; +			} + +			if (content.isMap()) +			{ +				if (content.has(KEY_ERROR)) +				{ +					const LLSD & error = content[KEY_ERROR]; +					llwarns << "Avatar render info POST error: " +						<< error[KEY_IDENTIFIER] +						<< ": " << error[KEY_MESSAGE]  +						<< " from region " << regionp->getName() +						<< llendl; +				} +			} +		} +		else +		{ +			llinfos << "Avatar render weight POST result recieved but region not found for "  +				<< mRegionHandle << llendl; +		} +	} + +private: +	U64		mRegionHandle; +}; + + +// static  +// Send request for one region, no timer checks +void LLAvatarRenderInfoAccountant::sendRenderInfoToRegion(LLViewerRegion * regionp) +{ +	std::string url = regionp->getCapability("AvatarRenderInfo"); +	if (!url.empty()) +	{ +		if (logRenderInfo()) +		{ +			llinfos << "Sending avatar render info to region " +				<< regionp->getName()  +				<< " from " << url +				<< llendl; +		} + +		// Build the render info to POST to the region +		LLSD report = LLSD::emptyMap(); +		LLSD agents = LLSD::emptyMap(); +				 +		std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); +		while( iter != LLCharacter::sInstances.end() ) +		{ +			LLVOAvatar* avatar = dynamic_cast<LLVOAvatar*>(*iter); +			if (avatar && +				avatar->getRezzedStatus() == 2 &&					// Fully rezzed +				!avatar->isDead() &&								// Not dead yet +				avatar->getObjectHost() == regionp->getHost())		// Ensure it's on the same region +			{ +				avatar->calculateUpdateRenderCost();			// Make sure the numbers are up-to-date + +				LLSD info = LLSD::emptyMap(); +				if (avatar->getVisualComplexity() > 0) +				{ +					info[KEY_WEIGHT] = avatar->getVisualComplexity(); +				} +				if (avatar->getAttachmentGeometryBytes() > 0) +				{ +					info[KEY_GEOMETRY] = (S32) avatar->getAttachmentGeometryBytes(); +				} +				if (avatar->getAttachmentSurfaceArea() > 0.f) +				{ +					info[KEY_SURFACE] = avatar->getAttachmentSurfaceArea(); +				} +				if (info.size() > 0) +				{ +					agents[avatar->getID().asString()] = info; +				} + +				if (logRenderInfo()) +				{ +					llinfos << "Sending avatar render info for " << avatar->getID() +						<< ": " << info << llendl; +				} +			} +			iter++; +		} + +		report[KEY_AGENTS] = agents; +		if (agents.size() > 0) +		{ +			LLHTTPClient::post(url, report, new LLAvatarRenderInfoPostResponder(regionp->getHandle())); +		} +	} +} + + + + +// static  +// Send request for one region, no timer checks +void LLAvatarRenderInfoAccountant::getRenderInfoFromRegion(LLViewerRegion * regionp) +{ +	std::string url = regionp->getCapability("AvatarRenderInfo"); +	if (!url.empty()) +	{ +		if (logRenderInfo()) +		{ +			llinfos << "Requesting avatar render info for region " +				<< regionp->getName()  +				<< " from " << url +				<< llendl; +		} + +		// First send a request to get the latest data +		LLHTTPClient::get(url, new LLAvatarRenderInfoGetResponder(regionp->getHandle())); +	} +} + + +// static +// Called every frame - send render weight requests to every region +void LLAvatarRenderInfoAccountant::idle() +{ +	if (sRenderInfoReportTimer.hasExpired()) +	{ +		const F32 SECS_BETWEEN_REGION_SCANS   =  5.f;		// Scan the region list every 5 seconds +		const F32 SECS_BETWEEN_REGION_REQUEST = 60.0;		// Update each region every 60 seconds +	 +		S32 num_avs = LLCharacter::sInstances.size(); + +		// Check all regions and see if it's time to fetch/send data +		for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); +				iter != LLWorld::getInstance()->getRegionList().end(); ++iter) +		{ +			LLViewerRegion* regionp = *iter; +			if (regionp && +				regionp->isAlive() && +				regionp->capabilitiesReceived() &&						// Region has capability URLs available +				regionp->getRenderInfoRequestTimer().hasExpired())		// Time to make request +			{ +				sendRenderInfoToRegion(regionp); +				getRenderInfoFromRegion(regionp); + +				// Reset this regions timer, moving to longer intervals if there are lots of avatars around +				regionp->getRenderInfoRequestTimer().resetWithExpiry(SECS_BETWEEN_REGION_REQUEST + (2.f * num_avs)); +			} +		} + +		// We scanned all the regions, reset the request timer. +		sRenderInfoReportTimer.resetWithExpiry(SECS_BETWEEN_REGION_SCANS); +	} +} + + +// static +// Make sRenderInfoReportTimer expire so the next call to idle() will scan and query a new region +// called via LLViewerRegion::setCapabilitiesReceived() boost signals when the capabilities +// are returned for a new LLViewerRegion, and is the earliest time to get render info +void LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer() +{ +	if (logRenderInfo()) +	{ +		llinfos << "Viewer has new region capabilities" << llendl; +	} + +	sRenderInfoReportTimer.resetWithExpiry(0.f); +} + +// static  +bool LLAvatarRenderInfoAccountant::logRenderInfo() +{ +	static LLCachedControl<bool> render_mute_logging_enabled(gSavedSettings, "RenderAutoMuteLogging"); +	return render_mute_logging_enabled; +} diff --git a/indra/newview/llavatarrenderinfoaccountant.h b/indra/newview/llavatarrenderinfoaccountant.h new file mode 100644 index 0000000000..97dd9f0ad3 --- /dev/null +++ b/indra/newview/llavatarrenderinfoaccountant.h @@ -0,0 +1,56 @@ +/** + * @file   llavatarrenderinfoaccountant.h + * @author Dave Simmons + * @date   2013-02-28 + * @brief   + *  + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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$ + */ + +#if ! defined(LL_llavatarrenderinfoaccountant_H) +#define LL_llavatarrenderinfoaccountant_H + +class LLViewerRegion; + +// Class to gather avatar rendering information  +// that is sent to or fetched from regions. +class LLAvatarRenderInfoAccountant +{ +public: +	LLAvatarRenderInfoAccountant()	{}; +	~LLAvatarRenderInfoAccountant()	{}; + +	static void sendRenderInfoToRegion(LLViewerRegion * regionp); +	static void getRenderInfoFromRegion(LLViewerRegion * regionp); + +	static void expireRenderInfoReportTimer(); + +    static void idle(); + +	static bool logRenderInfo(); + +private: +	// Send data updates about once per minute, only need per-frame resolution +	static LLFrameTimer sRenderInfoReportTimer; +}; + +#endif /* ! defined(LL_llavatarrenderinfoaccountant_H) */ diff --git a/indra/newview/llconversationmodel.h b/indra/newview/llconversationmodel.h index 8766585049..8766585049 100755..100644 --- a/indra/newview/llconversationmodel.h +++ b/indra/newview/llconversationmodel.h diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp index b6c53e5e30..b6c53e5e30 100755..100644 --- a/indra/newview/llconversationview.cpp +++ b/indra/newview/llconversationview.cpp diff --git a/indra/newview/llconversationview.h b/indra/newview/llconversationview.h index 3eb2e63792..3eb2e63792 100755..100644 --- a/indra/newview/llconversationview.h +++ b/indra/newview/llconversationview.h diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index bb1d263670..2e3a9119b8 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -254,7 +254,7 @@ S32 LLDrawable::findReferences(LLDrawable *drawablep)  	return count;  } -static LLFastTimer::DeclareTimer FTM_ALLOCATE_FACE("Allocate Face", true); +static LLFastTimer::DeclareTimer FTM_ALLOCATE_FACE("Allocate Face");  LLFace*	LLDrawable::addFace(LLFacePool *poolp, LLViewerTexture *texturep)  { diff --git a/indra/newview/lldrawpool.cpp b/indra/newview/lldrawpool.cpp index 94dd927d26..d8f293cc62 100644 --- a/indra/newview/lldrawpool.cpp +++ b/indra/newview/lldrawpool.cpp @@ -472,6 +472,7 @@ void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture, BOOL ba  		{  			params.mGroup->rebuildMesh();  		} +		  		params.mVertexBuffer->setBuffer(mask);  		params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);  		gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 313b310e1e..6fa16825df 100644 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -394,10 +394,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  		if (group->mSpatialPartition->mRenderByGroup &&  		    !group->isDead())  		{ -			bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow. -				// All particle systems seem to come off the wire with texture entries which claim that they glow.  This is probably a bug in the data.  Suppress. -				group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE && -				group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE; +			static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GROUP_LOOP("Alpha Group"); +			LLFastTimer t(FTM_RENDER_ALPHA_GROUP_LOOP); + +			bool draw_glow_for_this_partition = mVertexShaderLevel > 0; // no shaders = no glow. + +			bool disable_cull = group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_PARTICLE || +				group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD_PARTICLE; + +			LLGLDisable cull(disable_cull ? GL_CULL_FACE : 0);  			LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; @@ -498,32 +503,31 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  					}  				} -				params.mVertexBuffer->setBuffer(mask); -				params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); -				gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); +				static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_PUSH("Alpha Push Verts"); +				{ +					LLFastTimer t(FTM_RENDER_ALPHA_PUSH); +					gGL.blendFunc((LLRender::eBlendFactor) params.mBlendFuncSrc, (LLRender::eBlendFactor) params.mBlendFuncDst, mAlphaSFactor, mAlphaDFactor); +					params.mVertexBuffer->setBuffer(mask); +					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset); +					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); +				}  				// If this alpha mesh has glow, then draw it a second time to add the destination-alpha (=glow).  Interleaving these state-changing calls could be expensive, but glow must be drawn Z-sorted with alpha.  				if (current_shader &&   					draw_glow_for_this_partition &&  					params.mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_EMISSIVE))  				{ +					static LLFastTimer::DeclareTimer FTM_RENDER_ALPHA_GLOW("Alpha Glow"); +					LLFastTimer t(FTM_RENDER_ALPHA_GLOW);  					// install glow-accumulating blend mode  					gGL.blendFunc(LLRender::BF_ZERO, LLRender::BF_ONE, // don't touch color  						      LLRender::BF_ONE, LLRender::BF_ONE); // add to alpha (glow) -					emissive_shader->bind(); -					 -					// glow doesn't use vertex colors from the mesh data -					params.mVertexBuffer->setBuffer((mask & ~LLVertexBuffer::MAP_COLOR) | LLVertexBuffer::MAP_EMISSIVE); +					params.mVertexBuffer->setBuffer(mask | LLVertexBuffer::MAP_EMISSIVE);  					// do the actual drawing, again  					params.mVertexBuffer->drawRange(params.mDrawMode, params.mStart, params.mEnd, params.mCount, params.mOffset);  					gPipeline.addTrianglesDrawn(params.mCount, params.mDrawMode); - -					// restore our alpha blend mode -					gGL.blendFunc(mColorSFactor, mColorDFactor, mAlphaSFactor, mAlphaDFactor); - -					current_shader->bind();  				}  				if (tex_setup) @@ -536,6 +540,8 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask)  		}  	} +	gGL.setSceneBlendType(LLRender::BT_ALPHA); +  	LLVertexBuffer::unbind();	  	if (!light_enabled) diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 38268b102b..91394f0767 100644 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -59,6 +59,7 @@ LLGLSLShader* LLDrawPoolAvatar::sVertexProgram = NULL;  BOOL	LLDrawPoolAvatar::sSkipOpaque = FALSE;  BOOL	LLDrawPoolAvatar::sSkipTransparent = FALSE;  S32 LLDrawPoolAvatar::sDiffuseChannel = 0; +F32 LLDrawPoolAvatar::sMinimumAlpha = 0.2f;  static bool is_deferred_render = false; @@ -272,7 +273,7 @@ void LLDrawPoolAvatar::beginPostDeferredAlpha()  	gPipeline.bindDeferredShader(*sVertexProgram); -	sVertexProgram->setMinimumAlpha(0.2f); +	sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);  	sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);  } @@ -620,7 +621,7 @@ void LLDrawPoolAvatar::beginRigid()  		if (sVertexProgram != NULL)  		{	//eyeballs render with the specular shader  			sVertexProgram->bind(); -			sVertexProgram->setMinimumAlpha(0.2f); +			sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);  		}  	}  	else @@ -671,7 +672,7 @@ void LLDrawPoolAvatar::beginDeferredRigid()  	sVertexProgram = &gDeferredNonIndexedDiffuseAlphaMaskNoColorProgram;  	sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);  	sVertexProgram->bind(); -	sVertexProgram->setMinimumAlpha(0.2f); +	sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);  }  void LLDrawPoolAvatar::endDeferredRigid() @@ -729,7 +730,7 @@ void LLDrawPoolAvatar::beginSkinned()  	if (LLGLSLShader::sNoFixedFunction)  	{ -		sVertexProgram->setMinimumAlpha(0.2f); +		sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);  	}  } @@ -1027,7 +1028,7 @@ void LLDrawPoolAvatar::beginDeferredSkinned()  	sRenderingSkinned = TRUE;  	sVertexProgram->bind(); -	sVertexProgram->setMinimumAlpha(0.2f); +	sVertexProgram->setMinimumAlpha(LLDrawPoolAvatar::sMinimumAlpha);  	sDiffuseChannel = sVertexProgram->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP);  	gGL.getTexUnit(0)->activate(); @@ -1138,7 +1139,10 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)  		if (impostor)  		{ -			if (LLPipeline::sRenderDeferred && !LLPipeline::sReflectionRender && avatarp->mImpostor.isComplete())  +			if (LLPipeline::sRenderDeferred && //rendering a deferred impostor +				!LLPipeline::sReflectionRender &&  +				avatarp->mImpostor.isComplete() && //impostor has required data channels +				avatarp->mImpostor.getNumTextures() >= 3)   			{  				if (normal_channel > -1)  				{ @@ -1151,115 +1155,93 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass)  			}  			avatarp->renderImpostor(LLColor4U(255,255,255,255), sDiffuseChannel);  		} -		return;  	} - -	llassert(LLPipeline::sImpostorRender || !avatarp->isVisuallyMuted()); - -	/*if (single_avatar && avatarp->mSpecialRenderMode >= 1) // 1=anim preview, 2=image preview,  3=morph view -	{ -		gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f)); -	}*/ -	 -	if (pass == 1) +	else if (pass == 1)  	{  		// render rigid meshes (eyeballs) first  		avatarp->renderRigid(); -		return;  	} - -	if (pass == 3) -	{ -		if (is_deferred_render) -		{ -			renderDeferredRiggedSimple(avatarp); -		} -		else -		{ -			renderRiggedSimple(avatarp); -		} -		return; -	} - -	if (pass == 4) -	{ -		if (is_deferred_render) -		{ -			renderDeferredRiggedBump(avatarp); -		} -		else +	else if (pass >= 3 && pass <= 9) +	{ //render rigged attachments +		if (!avatarp->isVisuallyMuted())		// These details are skipped for visually muted (plain imposter) avatars  		{ -			renderRiggedFullbright(avatarp); +			if (pass == 3)				// To do - use switch statement +			{ +				if (is_deferred_render) +				{ +					renderDeferredRiggedSimple(avatarp); +				} +				else +				{ +					renderRiggedSimple(avatarp); +				} +			} +			else if (pass == 4) +			{ +				if (is_deferred_render) +				{ +					renderDeferredRiggedBump(avatarp); +				} +				else +				{ +					renderRiggedFullbright(avatarp); +				} +			} +			else if (pass == 5) +			{ +				renderRiggedShinySimple(avatarp); +			} +			else if (pass == 6) +			{ +				renderRiggedFullbrightShiny(avatarp); +			} +			else if (pass == 7) +			{ +				renderRiggedAlpha(avatarp); +			} +			else if (pass == 8) +			{ +				renderRiggedFullbrightAlpha(avatarp); +			} +			else if (pass == 9) +			{ +				renderRiggedGlow(avatarp); +			}  		} - -		return; -	} - -	if (pass == 5) -	{ -		renderRiggedShinySimple(avatarp); -		return;  	} - -	if (pass == 6) -	{ -		renderRiggedFullbrightShiny(avatarp); -		return; -	} - -	if (pass >= 7 && pass < 9) +	else  	{ -		if (pass == 7) +		if ((sShaderLevel >= SHADER_LEVEL_CLOTH))  		{ -			renderRiggedAlpha(avatarp); -			return; +			LLMatrix4 rot_mat; +			LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat); +			LLMatrix4 cfr(OGL_TO_CFR_ROTATION); +			rot_mat *= cfr; +		 +			LLVector4 wind; +			wind.setVec(avatarp->mWindVec); +			wind.mV[VW] = 0; +			wind = wind * rot_mat; +			wind.mV[VW] = avatarp->mWindVec.mV[VW]; + +			sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV); +			F32 phase = -1.f * (avatarp->mRipplePhase); + +			F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f); +			LLVector4 sin_params(freq, freq, freq, phase); +			sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV); + +			LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f); +			gravity = gravity * rot_mat; +			sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV);  		} -		if (pass == 8) +		if( !single_avatar || (avatarp == single_avatar) )  		{ -			renderRiggedFullbrightAlpha(avatarp); -			return; +			avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE);  		}  	} - -	if (pass == 9) -	{ -		renderRiggedGlow(avatarp); -		 -		return; -	} -	 -	if ((sShaderLevel >= SHADER_LEVEL_CLOTH)) -	{ -		LLMatrix4 rot_mat; -		LLViewerCamera::getInstance()->getMatrixToLocal(rot_mat); -		LLMatrix4 cfr(OGL_TO_CFR_ROTATION); -		rot_mat *= cfr; -		 -		LLVector4 wind; -		wind.setVec(avatarp->mWindVec); -		wind.mV[VW] = 0; -		wind = wind * rot_mat; -		wind.mV[VW] = avatarp->mWindVec.mV[VW]; - -		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_WIND, 1, wind.mV); -		F32 phase = -1.f * (avatarp->mRipplePhase); - -		F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f); -		LLVector4 sin_params(freq, freq, freq, phase); -		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_SINWAVE, 1, sin_params.mV); - -		LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f); -		gravity = gravity * rot_mat; -		sVertexProgram->uniform4fv(LLViewerShaderMgr::AVATAR_GRAVITY, 1, gravity.mV); -	} - -	if( !single_avatar || (avatarp == single_avatar) ) -	{ -		avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); -	}  } -  void LLDrawPoolAvatar::getRiggedGeometry(LLFace* face, LLPointer<LLVertexBuffer>& buffer, U32 data_mask, const LLMeshSkinInfo* skin, LLVolume* volume, const LLVolumeFace& vol_face)  {  	face->setGeomIndex(0); @@ -1519,7 +1501,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)  				stop_glerror(); -				LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv("matrixPalette",  +				LLDrawPoolAvatar::sVertexProgram->uniformMatrix4fv(LLViewerShaderMgr::AVATAR_MATRIX,   					skin->mJointNames.size(),  					FALSE,  					(GLfloat*) mat[0].mMatrix); @@ -1547,7 +1529,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)  				LLDrawPoolBump::bindBumpMap(face, normal_channel);  			} -			if (face->mTextureMatrix) +			if (face->mTextureMatrix && vobj->mTexAnimMode)  			{  				gGL.matrixMode(LLRender::MM_TEXTURE);  				gGL.loadMatrix((F32*) face->mTextureMatrix->mMatrix); @@ -1561,6 +1543,8 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)  				buff->setBuffer(data_mask);  				buff->drawRange(LLRender::TRIANGLES, start, end, count, offset);		  			} + +			gPipeline.addTrianglesDrawn(count, LLRender::TRIANGLES);  		}  	}  } diff --git a/indra/newview/lldrawpoolavatar.h b/indra/newview/lldrawpoolavatar.h index 5551d8f6d8..544969001d 100644 --- a/indra/newview/lldrawpoolavatar.h +++ b/indra/newview/lldrawpoolavatar.h @@ -209,6 +209,7 @@ public:  	static BOOL sSkipOpaque;  	static BOOL sSkipTransparent;  	static S32 sDiffuseChannel; +	static F32 sMinimumAlpha;  	static LLGLSLShader* sVertexProgram;  }; diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp index e8d43c8631..49051e74a9 100644 --- a/indra/newview/lldrawpoolbump.cpp +++ b/indra/newview/lldrawpoolbump.cpp @@ -449,9 +449,6 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32&  	LLCubeMap* cube_map = gSky.mVOSkyp ? gSky.mVOSkyp->getCubeMap() : NULL;  	if( cube_map )  	{ -		cube_map->disable(); -		cube_map->restoreMatrix(); -  		if (!invisible && shader_level > 1)  		{  			shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); @@ -464,6 +461,10 @@ void LLDrawPoolBump::unbindCubeMap(LLGLSLShader* shader, S32 shader_level, S32&  				}  			}  		} +        // Moved below shader->disableTexture call to avoid false alarms from auto-re-enable of textures on stage 0 +        // MAINT-755 +		cube_map->disable(); +		cube_map->restoreMatrix();  	}  	if (!LLGLSLShader::sNoFixedFunction) @@ -1369,9 +1370,14 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerTexture *src_vi, LLI  					LLGLDisable blend(GL_BLEND);  					gGL.setColorMask(TRUE, TRUE);  					gNormalMapGenProgram.bind(); -					gNormalMapGenProgram.uniform1f("norm_scale", gSavedSettings.getF32("RenderNormalMapScale")); -					gNormalMapGenProgram.uniform1f("stepX", 1.f/bump->getWidth()); -					gNormalMapGenProgram.uniform1f("stepY", 1.f/bump->getHeight()); + +					static LLStaticHashedString sNormScale("norm_scale"); +					static LLStaticHashedString sStepX("stepX"); +					static LLStaticHashedString sStepY("stepY"); + +					gNormalMapGenProgram.uniform1f(sNormScale, gSavedSettings.getF32("RenderNormalMapScale")); +					gNormalMapGenProgram.uniform1f(sStepX, 1.f/bump->getWidth()); +					gNormalMapGenProgram.uniform1f(sStepY, 1.f/bump->getHeight());  					LLVector2 v((F32) bump->getWidth()/gPipeline.mScreen.getWidth(),  								(F32) bump->getHeight()/gPipeline.mScreen.getHeight()); diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index 0adb42428d..c3ec234223 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -354,8 +354,8 @@ void LLDrawPoolTerrain::renderFullShader()  	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;  	llassert(shader); -	shader->uniform4fv("object_plane_s", 1, tp0.mV); -	shader->uniform4fv("object_plane_t", 1, tp1.mV); +	shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV); +	shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV);  	gGL.matrixMode(LLRender::MM_TEXTURE);  	gGL.loadIdentity(); @@ -864,8 +864,8 @@ void LLDrawPoolTerrain::renderSimple()  	if (LLGLSLShader::sNoFixedFunction)  	{ -		sShader->uniform4fv("object_plane_s", 1, tp0.mV); -		sShader->uniform4fv("object_plane_t", 1, tp1.mV); +		sShader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0.mV); +		sShader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1.mV);  	}  	else  	{ diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 5ddc15df42..0d79631182 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -407,8 +407,8 @@ void LLDrawPoolWater::renderOpaqueLegacyWater()  	}  	else  	{ -		shader->uniform4fv("object_plane_s", 1, tp0); -		shader->uniform4fv("object_plane_t", 1, tp1); +		shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_S, 1, tp0); +		shader->uniform4fv(LLShaderMgr::OBJECT_PLANE_T, 1, tp1);  	}  	gGL.diffuseColor3f(1.f, 1.f, 1.f); @@ -546,7 +546,7 @@ void LLDrawPoolWater::shade()  	sTime = (F32)LLFrameTimer::getElapsedSeconds()*0.5f; -	S32 reftex = shader->enableTexture(LLViewerShaderMgr::WATER_REFTEX); +	S32 reftex = shader->enableTexture(LLShaderMgr::WATER_REFTEX);  	if (reftex > -1)  	{ @@ -577,12 +577,12 @@ void LLDrawPoolWater::shade()  		mWaterNormp->setFilteringOption(LLTexUnit::TFO_POINT);  	} -	S32 screentex = shader->enableTexture(LLViewerShaderMgr::WATER_SCREENTEX);	 +	S32 screentex = shader->enableTexture(LLShaderMgr::WATER_SCREENTEX);	  	if (screentex > -1)  	{ -		shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); -		shader->uniform1f(LLViewerShaderMgr::WATER_FOGDENSITY,  +		shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); +		shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY,   			param_mgr->getFogDensity());  		gPipeline.mWaterDis.bindTexture(0, screentex);  	} @@ -594,15 +594,9 @@ void LLDrawPoolWater::shade()  	if (mVertexShaderLevel == 1)  	{  		sWaterFogColor.mV[3] = param_mgr->mDensitySliderValue; -		shader->uniform4fv(LLViewerShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV); +		shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, sWaterFogColor.mV);  	} -	F32 screenRes[] =  -	{ -		1.f/gGLViewport[2], -		1.f/gGLViewport[3] -	}; -	shader->uniform2fv("screenRes", 1, screenRes);  	stop_glerror();  	S32 diffTex = shader->enableTexture(LLViewerShaderMgr::DIFFUSE_MAP); @@ -614,26 +608,26 @@ void LLDrawPoolWater::shade()  	light_diffuse *= 6.f;  	//shader->uniformMatrix4fv("inverse_ref", 1, GL_FALSE, (GLfloat*) gGLObliqueProjectionInverse.mMatrix); -	shader->uniform1f(LLViewerShaderMgr::WATER_WATERHEIGHT, eyedepth); -	shader->uniform1f(LLViewerShaderMgr::WATER_TIME, sTime); -	shader->uniform3fv(LLViewerShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV); -	shader->uniform3fv(LLViewerShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); -	shader->uniform1f(LLViewerShaderMgr::WATER_SPECULAR_EXP, light_exp); -	shader->uniform2fv(LLViewerShaderMgr::WATER_WAVE_DIR1, 1, param_mgr->getWave1Dir().mV); -	shader->uniform2fv(LLViewerShaderMgr::WATER_WAVE_DIR2, 1, param_mgr->getWave2Dir().mV); -	shader->uniform3fv(LLViewerShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); - -	shader->uniform3fv("normScale", 1, param_mgr->getNormalScale().mV); -	shader->uniform1f("fresnelScale", param_mgr->getFresnelScale()); -	shader->uniform1f("fresnelOffset", param_mgr->getFresnelOffset()); -	shader->uniform1f("blurMultiplier", param_mgr->getBlurMultiplier()); +	shader->uniform1f(LLShaderMgr::WATER_WATERHEIGHT, eyedepth); +	shader->uniform1f(LLShaderMgr::WATER_TIME, sTime); +	shader->uniform3fv(LLShaderMgr::WATER_EYEVEC, 1, LLViewerCamera::getInstance()->getOrigin().mV); +	shader->uniform3fv(LLShaderMgr::WATER_SPECULAR, 1, light_diffuse.mV); +	shader->uniform1f(LLShaderMgr::WATER_SPECULAR_EXP, light_exp); +	shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR1, 1, param_mgr->getWave1Dir().mV); +	shader->uniform2fv(LLShaderMgr::WATER_WAVE_DIR2, 1, param_mgr->getWave2Dir().mV); +	shader->uniform3fv(LLShaderMgr::WATER_LIGHT_DIR, 1, light_dir.mV); + +	shader->uniform3fv(LLShaderMgr::WATER_NORM_SCALE, 1, param_mgr->getNormalScale().mV); +	shader->uniform1f(LLShaderMgr::WATER_FRESNEL_SCALE, param_mgr->getFresnelScale()); +	shader->uniform1f(LLShaderMgr::WATER_FRESNEL_OFFSET, param_mgr->getFresnelOffset()); +	shader->uniform1f(LLShaderMgr::WATER_BLUR_MULTIPLIER, param_mgr->getBlurMultiplier());  	F32 sunAngle = llmax(0.f, light_dir.mV[2]);  	F32 scaledAngle = 1.f - sunAngle; -	shader->uniform1f("sunAngle", sunAngle); -	shader->uniform1f("scaledAngle", scaledAngle); -	shader->uniform1f("sunAngle2", 0.1f + 0.2f*sunAngle); +	shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE, sunAngle); +	shader->uniform1f(LLShaderMgr::WATER_SCALED_ANGLE, scaledAngle); +	shader->uniform1f(LLShaderMgr::WATER_SUN_ANGLE2, 0.1f + 0.2f*sunAngle);  	LLColor4 water_color;  	LLVector3 camera_up = LLViewerCamera::getInstance()->getUpAxis(); @@ -641,12 +635,12 @@ void LLDrawPoolWater::shade()  	if (LLViewerCamera::getInstance()->cameraUnderWater())  	{  		water_color.setVec(1.f, 1.f, 1.f, 0.4f); -		shader->uniform1f(LLViewerShaderMgr::WATER_REFSCALE, param_mgr->getScaleBelow()); +		shader->uniform1f(LLShaderMgr::WATER_REFSCALE, param_mgr->getScaleBelow());  	}  	else  	{  		water_color.setVec(1.f, 1.f, 1.f, 0.5f*(1.f + up_dot)); -		shader->uniform1f(LLViewerShaderMgr::WATER_REFSCALE, param_mgr->getScaleAbove()); +		shader->uniform1f(LLShaderMgr::WATER_REFSCALE, param_mgr->getScaleAbove());  	}  	if (water_color.mV[3] > 0.9f) @@ -690,11 +684,11 @@ void LLDrawPoolWater::shade()  	}  	shader->disableTexture(LLViewerShaderMgr::ENVIRONMENT_MAP, LLTexUnit::TT_CUBE_MAP); -	shader->disableTexture(LLViewerShaderMgr::WATER_SCREENTEX);	 +	shader->disableTexture(LLShaderMgr::WATER_SCREENTEX);	  	shader->disableTexture(LLViewerShaderMgr::BUMP_MAP);  	shader->disableTexture(LLViewerShaderMgr::DIFFUSE_MAP); -	shader->disableTexture(LLViewerShaderMgr::WATER_REFTEX); -	shader->disableTexture(LLViewerShaderMgr::WATER_SCREENDEPTH); +	shader->disableTexture(LLShaderMgr::WATER_REFTEX); +	shader->disableTexture(LLShaderMgr::WATER_SCREENDEPTH);  	if (deferred_render)  	{ diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp index b5faff7968..b0e69aa9b5 100644 --- a/indra/newview/lldrawpoolwlsky.cpp +++ b/indra/newview/lldrawpoolwlsky.cpp @@ -152,7 +152,8 @@ void LLDrawPoolWLSky::renderDome(F32 camHeightLocal, LLGLSLShader * shader) cons  	gGL.translatef(0.f,-camHeightLocal, 0.f);  	// Draw WL Sky	 -	shader->uniform3f("camPosLocal", 0.f, camHeightLocal, 0.f); +	static LLStaticHashedString sCamPosLocal("camPosLocal"); +	shader->uniform3f(sCamPosLocal, 0.f, camHeightLocal, 0.f);  	gSky.mVOWLSkyp->drawDome(); @@ -207,7 +208,8 @@ void LLDrawPoolWLSky::renderStars(void) const  	if (LLGLSLShader::sNoFixedFunction)  	{  		gCustomAlphaProgram.bind(); -		gCustomAlphaProgram.uniform1f("custom_alpha", star_alpha.mV[3]); +		static LLStaticHashedString sCustomAlpha("custom_alpha"); +		gCustomAlphaProgram.uniform1f(sCustomAlpha, star_alpha.mV[3]);  	}  	else  	{ diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 281f852b0a..e4c5590c5c 100755 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -51,10 +51,21 @@  #include "llviewerregion.h"  #include "llviewerwindow.h"  #include "llviewershadermgr.h" +#include "llvoavatar.h" +#if LL_LINUX +// Work-around spurious used before init warning on Vector4a +// +#pragma GCC diagnostic ignored "-Wuninitialized" +#endif + +extern BOOL gGLDebugLoggingEnabled;  #define LL_MAX_INDICES_COUNT 1000000 +static LLStaticHashedString sTextureIndexIn("texture_index_in"); +static LLStaticHashedString sColorIn("color_in"); +  BOOL LLFace::sSafeRenderSelect = TRUE; // FALSE  #define DOTVEC(a,b) (a.mV[0]*b.mV[0] + a.mV[1]*b.mV[1] + a.mV[2]*b.mV[2]) @@ -325,6 +336,12 @@ void LLFace::dirtyTexture()  		if (vobj)  		{  			vobj->mLODChanged = TRUE; + +			LLVOAvatar* avatar = vobj->getAvatar(); +			if (avatar) +			{ //avatar render cost may have changed +				avatar->updateVisualComplexity(); +			}  		}  		gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME, FALSE);  	}		 @@ -1159,6 +1176,15 @@ static LLFastTimer::DeclareTimer FTM_FACE_GEOM_COLOR("Color");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_EMISSIVE("Emissive");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_WEIGHTS("Weights");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_BINORMAL("Binormal"); + +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK("Face Feedback"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_POSITION("Feedback Position"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_NORMAL("Feedback  Normal"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_TEXTURE("Feedback  Texture"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_COLOR("Feedback  Color"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_EMISSIVE("Feedback  Emissive"); +static LLFastTimer::DeclareTimer FTM_FACE_GEOM_FEEDBACK_BINORMAL("Feedback Binormal"); +  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX("Index");  static LLFastTimer::DeclareTimer FTM_FACE_GEOM_INDEX_TAIL("Tail");  static LLFastTimer::DeclareTimer FTM_FACE_POSITION_STORE("Pos"); @@ -1382,12 +1408,15 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  #ifdef GL_TRANSFORM_FEEDBACK_BUFFER  	if (use_transform_feedback && +		mVertexBuffer->getUsage() == GL_DYNAMIC_COPY_ARB &&  		gTransformPositionProgram.mProgramObject && //transform shaders are loaded  		mVertexBuffer->useVBOs() && //target buffer is in VRAM  		!rebuild_weights && //TODO: add support for weights  		!volume.isUnique()) //source volume is NOT flexi  	{ //use transform feedback to pack vertex buffer - +		//gGLDebugLoggingEnabled = TRUE; +		LLFastTimer t(FTM_FACE_GEOM_FEEDBACK); +		LLGLEnable discard(GL_RASTERIZER_DISCARD);  		LLVertexBuffer* buff = (LLVertexBuffer*) vf.mVertexBuffer.get();  		if (vf.mVertexBuffer.isNull() || buff->getNumVerts() != vf.mNumVertices) @@ -1404,7 +1433,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_pos)  		{ -			LLFastTimer t(FTM_FACE_GEOM_POSITION); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_POSITION);  			gTransformPositionProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_VERTEX, mGeomIndex, mGeomCount); @@ -1418,7 +1447,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  			vp[2] = 0;  			vp[3] = 0; -			gTransformPositionProgram.uniform1i("texture_index_in", val); +			gTransformPositionProgram.uniform1i(sTextureIndexIn, val);  			glBeginTransformFeedback(GL_POINTS);  			buff->setBuffer(LLVertexBuffer::MAP_VERTEX); @@ -1429,14 +1458,14 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_color)  		{ -			LLFastTimer t(FTM_FACE_GEOM_COLOR); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_COLOR);  			gTransformColorProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_COLOR, mGeomIndex, mGeomCount);  			S32 val = *((S32*) color.mV); -			gTransformColorProgram.uniform1i("color_in", val); +			gTransformColorProgram.uniform1i(sColorIn, val);  			glBeginTransformFeedback(GL_POINTS);  			buff->setBuffer(LLVertexBuffer::MAP_VERTEX);  			push_for_transform(buff, vf.mNumVertices, mGeomCount); @@ -1445,7 +1474,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_emissive)  		{ -			LLFastTimer t(FTM_FACE_GEOM_EMISSIVE); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_EMISSIVE);  			gTransformColorProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_EMISSIVE, mGeomIndex, mGeomCount); @@ -1457,7 +1486,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  						 (glow << 16) |  						 (glow << 24); -			gTransformColorProgram.uniform1i("color_in", glow32); +			gTransformColorProgram.uniform1i(sColorIn, glow32);  			glBeginTransformFeedback(GL_POINTS);  			buff->setBuffer(LLVertexBuffer::MAP_VERTEX);  			push_for_transform(buff, vf.mNumVertices, mGeomCount); @@ -1466,7 +1495,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_normal)  		{ -			LLFastTimer t(FTM_FACE_GEOM_NORMAL); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_NORMAL);  			gTransformNormalProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_NORMAL, mGeomIndex, mGeomCount); @@ -1479,7 +1508,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_binormal)  		{ -			LLFastTimer t(FTM_FACE_GEOM_BINORMAL); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_BINORMAL);  			gTransformBinormalProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_BINORMAL, mGeomIndex, mGeomCount); @@ -1492,7 +1521,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_tcoord)  		{ -			LLFastTimer t(FTM_FACE_GEOM_TEXTURE); +			LLFastTimer t(FTM_FACE_GEOM_FEEDBACK_TEXTURE);  			gTransformTexCoordProgram.bind();  			mVertexBuffer->bindForFeedback(0, LLVertexBuffer::TYPE_TEXCOORD0, mGeomIndex, mGeomCount); @@ -1515,13 +1544,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		}  		glBindBufferARB(GL_TRANSFORM_FEEDBACK_BUFFER, 0); -  		gGL.popMatrix();  		if (cur_shader)  		{  			cur_shader->bind();  		} +		//gGLDebugLoggingEnabled = FALSE;  	}  	else  #endif @@ -1936,21 +1965,32 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_pos)  		{ -			LLFastTimer t(FTM_FACE_GEOM_POSITION); +			LLVector4a* src = vf.mPositions; +			 +			//_mm_prefetch((char*)src, _MM_HINT_T0); + +			LLVector4a* end = src+num_vertices; +			//LLVector4a* end_64 = end-4; + +			//LLFastTimer t(FTM_FACE_GEOM_POSITION);  			llassert(num_vertices > 0);  			mVertexBuffer->getVertexStrider(vert, mGeomIndex, mGeomCount, map_range); -  			LLMatrix4a mat_vert;  			mat_vert.loadu(mat_vert_in); +								 +			F32* dst = (F32*) vert.get(); +			F32* end_f32 = dst+mGeomCount*4; -			LLVector4a* src = vf.mPositions; -			volatile F32* dst = (volatile F32*) vert.get(); +			//_mm_prefetch((char*)dst, _MM_HINT_NTA); +			//_mm_prefetch((char*)src, _MM_HINT_NTA); +				 +			//_mm_prefetch((char*)dst, _MM_HINT_NTA); -			volatile F32* end = dst+num_vertices*4; -			LLVector4a res; +			LLVector4a res0; //,res1,res2,res3; +			  			LLVector4a texIdx;  			S32 index = mTextureIndex < 255 ? mTextureIndex : 0; @@ -1967,29 +2007,53 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  			texIdx.set(0,0,0,val); +			LLVector4a tmp; +  			{ -				LLFastTimer t(FTM_FACE_POSITION_STORE); -				LLVector4a tmp; +				//LLFastTimer t2(FTM_FACE_POSITION_STORE); -				do -				{	 -					mat_vert.affineTransform(*src++, res); -					tmp.setSelectWithMask(mask, texIdx, res); +				/*if (num_vertices > 4) +				{ //more than 64 bytes +					while (src < end_64) +					{	 +						_mm_prefetch((char*)src + 64, _MM_HINT_T0); +						_mm_prefetch((char*)dst + 64, _MM_HINT_T0); + +						mat_vert.affineTransform(*src, res0); +						tmp.setSelectWithMask(mask, texIdx, res0); +						tmp.store4a((F32*) dst); + +						mat_vert.affineTransform(*(src+1), res1); +						tmp.setSelectWithMask(mask, texIdx, res1); +						tmp.store4a((F32*) dst+4); + +						mat_vert.affineTransform(*(src+2), res2); +						tmp.setSelectWithMask(mask, texIdx, res2); +						tmp.store4a((F32*) dst+8); + +						mat_vert.affineTransform(*(src+3), res3); +						tmp.setSelectWithMask(mask, texIdx, res3); +						tmp.store4a((F32*) dst+12); + +						dst += 16; +						src += 4; +					} +				}*/ + +				while (src < end) +				{ +					mat_vert.affineTransform(*src++, res0); +					tmp.setSelectWithMask(mask, texIdx, res0);  					tmp.store4a((F32*) dst);  					dst += 4;  				} -				while(dst < end);  			} - +			  			{ -				LLFastTimer t(FTM_FACE_POSITION_PAD); -				S32 aligned_pad_vertices = mGeomCount - num_vertices; -				res.set(res[0], res[1], res[2], 0.f); - -				while (aligned_pad_vertices > 0) +				//LLFastTimer t(FTM_FACE_POSITION_PAD); +				while (dst < end_f32)  				{ -					--aligned_pad_vertices; -					res.store4a((F32*) dst); +					res0.store4a((F32*) dst);  					dst += 4;  				}  			} @@ -2003,15 +2067,17 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  		if (rebuild_normal)  		{ -			LLFastTimer t(FTM_FACE_GEOM_NORMAL); +			//LLFastTimer t(FTM_FACE_GEOM_NORMAL);  			mVertexBuffer->getNormalStrider(norm, mGeomIndex, mGeomCount, map_range);  			F32* normals = (F32*) norm.get(); -			for (S32 i = 0; i < num_vertices; i++) -			{	 +			LLVector4a* src = vf.mNormals; +			LLVector4a* end = src+num_vertices; +			 +			while (src < end) +			{  				LLVector4a normal; -				mat_normal.rotate(vf.mNormals[i], normal); -				normal.normalize3fast(); +				mat_normal.rotate(*src++, normal);  				normal.store4a(normals);  				normals += 4;  			} @@ -2028,11 +2094,13 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,  			mVertexBuffer->getBinormalStrider(binorm, mGeomIndex, mGeomCount, map_range);  			F32* binormals = (F32*) binorm.get(); -			for (S32 i = 0; i < num_vertices; i++) +			LLVector4a* src = vf.mBinormals; +			LLVector4a* end = vf.mBinormals+num_vertices; + +			while (src < end)  			{	  				LLVector4a binormal; -				mat_normal.rotate(vf.mBinormals[i], binormal); -				binormal.normalize3fast(); +				mat_normal.rotate(*src++, binormal);  				binormal.store4a(binormals);  				binormals += 4;  			} diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index fbf72b1a85..8e1a1df211 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -345,7 +345,7 @@ BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)  	return TRUE;  } -static LLFastTimer::DeclareTimer FTM_RENDER_TIMER("Timers", true); +static LLFastTimer::DeclareTimer FTM_RENDER_TIMER("Timers");  static std::map<LLFastTimer::NamedTimer*, LLColor4> sTimerColors; diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index caad0afec0..bf479dc92e 100644 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -689,30 +689,36 @@ void LLVolumeImplFlexible::doFlexibleUpdate()  								LLVector4(z_axis, 0.f),  								LLVector4(delta_pos, 1.f)); +	LL_CHECK_MEMORY  	for (i=0; i<=num_render_sections; ++i)  	{  		new_point = &path->mPath[i];  		LLVector3 pos = newSection[i].mPosition * rel_xform;  		LLQuaternion rot = mSection[i].mAxisRotation * newSection[i].mRotation * delta_rot; -		 -		if (!mUpdated || (new_point->mPos-pos).magVec()/mVO->mDrawable->mDistanceWRTCamera > 0.001f) +	 +		LLVector3 np(new_point->mPos.getF32ptr()); + +		if (!mUpdated || (np-pos).magVec()/mVO->mDrawable->mDistanceWRTCamera > 0.001f)  		{ -			new_point->mPos = newSection[i].mPosition * rel_xform; +			new_point->mPos.load3((newSection[i].mPosition * rel_xform).mV);  			mUpdated = FALSE;  		} -		new_point->mRot = rot; -		new_point->mScale = newSection[i].mScale; +		new_point->mRot.loadu(LLMatrix3(rot)); +		new_point->mScale.set(newSection[i].mScale.mV[0], newSection[i].mScale.mV[1], 0,1);  		new_point->mTexT = ((F32)i)/(num_render_sections);  	} - +	LL_CHECK_MEMORY  	mLastSegmentRotation = parentSegmentRotation;  } +static LLFastTimer::DeclareTimer FTM_FLEXI_PREBUILD("Flexi Prebuild"); +  void LLVolumeImplFlexible::preRebuild()  {  	if (!mUpdated)  	{ +		LLFastTimer t(FTM_FLEXI_PREBUILD);  		doFlexibleRebuild();  	}  } diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp index 116bd241c4..664f7d4fd6 100644 --- a/indra/newview/llfloaterhardwaresettings.cpp +++ b/indra/newview/llfloaterhardwaresettings.cpp @@ -89,8 +89,10 @@ void LLFloaterHardwareSettings::refresh()  void LLFloaterHardwareSettings::refreshEnabledState()  { +    F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); +      	S32 min_tex_mem = LLViewerTextureList::getMinVideoRamSetting(); -	S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(); +	S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier);  	getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem);  	getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem); diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index d4355007c1..6ef4d8717d 100644 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -2027,6 +2027,10 @@ void LLPanelLandOptions::refresh()  		mSnapshotCtrl->setImageAssetID(parcel->getSnapshotID());  		mSnapshotCtrl->setEnabled( can_change_identity ); +		// find out where we're looking and convert that to an angle in degrees on a regular compass (not the internal representation) +		LLVector3 user_look_at = parcel->getUserLookAt(); +		U32 user_look_at_angle = ( (U32)( ( atan2(user_look_at[1], -user_look_at[0]) + F_PI * 2 ) * RAD_TO_DEG + 0.5) - 90) % 360; +  		LLVector3 pos = parcel->getUserLocation();  		if (pos.isExactlyZero())  		{ @@ -2034,10 +2038,11 @@ void LLPanelLandOptions::refresh()  		}  		else  		{ -			mLocationText->setTextArg("[LANDING]",llformat("%d, %d, %d", +			mLocationText->setTextArg("[LANDING]",llformat("%d, %d, %d (%d\xC2\xB0)",  														   llround(pos.mV[VX]),  														   llround(pos.mV[VY]), -														   llround(pos.mV[VZ]))); +		   												   llround(pos.mV[VZ]), +														   user_look_at_angle));  		}  		mSetBtn->setEnabled( can_change_landing_point ); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 100f1d580b..19cec55837 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -290,6 +290,22 @@ bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a  bool validate_face(const LLVolumeFace& face)  { + +	for (U32 v = 0; v < face.mNumVertices; v++) +	{ +		if(face.mPositions && !face.mPositions[v].isFinite3()) +		{ +			llwarns << "NaN position data in face found!" << llendl; +			return false; +		} + +		if(face.mNormals && !face.mNormals[v].isFinite3()) +		{ +			llwarns << "NaN normal data in face found!" << llendl; +			return false; +		} +	} +  	for (U32 i = 0; i < face.mNumIndices; ++i)  	{  		if (face.mIndices[i] >= face.mNumVertices) @@ -305,8 +321,10 @@ bool validate_face(const LLVolumeFace& face)  		return false;  	} +  	/*const LLVector4a scale(0.5f); +  	for (U32 i = 0; i < face.mNumIndices; i+=3)  	{  		U16 idx1 = face.mIndices[i]; @@ -323,7 +341,6 @@ bool validate_face(const LLVolumeFace& face)  			return false;  		}  	}*/ -  	return true;  } @@ -5921,3 +5938,5 @@ void LLFloaterModelPreview::setPermissonsErrorStatus(U32 status, const std::stri  	LLNotificationsUtil::add("MeshUploadPermError");  } + + diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp index bbf88060c1..515d96e0e7 100755 --- a/indra/newview/llfloaterpreference.cpp +++ b/indra/newview/llfloaterpreference.cpp @@ -337,7 +337,7 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)  	mCommitCallbackRegistrar.add("Pref.HardwareDefaults",		boost::bind(&LLFloaterPreference::setHardwareDefaults, this));  	mCommitCallbackRegistrar.add("Pref.VertexShaderEnable",		boost::bind(&LLFloaterPreference::onVertexShaderEnable, this));  	mCommitCallbackRegistrar.add("Pref.WindowedMod",			boost::bind(&LLFloaterPreference::onCommitWindowedMode, this)); -	mCommitCallbackRegistrar.add("Pref.UpdateSliderText",		boost::bind(&LLFloaterPreference::onUpdateSliderText,this, _1,_2)); +	mCommitCallbackRegistrar.add("Pref.UpdateSliderText",		boost::bind(&LLFloaterPreference::refreshUI,this));  	mCommitCallbackRegistrar.add("Pref.QualityPerformance",		boost::bind(&LLFloaterPreference::onChangeQuality, this, _2));  	mCommitCallbackRegistrar.add("Pref.applyUIColor",			boost::bind(&LLFloaterPreference::applyUIColor, this ,_1, _2));  	mCommitCallbackRegistrar.add("Pref.getUIColor",				boost::bind(&LLFloaterPreference::getUIColor, this ,_1, _2)); @@ -1147,6 +1147,8 @@ void LLFloaterPreference::refreshEnabledState()  	//Deferred/SSAO/Shadows  	LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders"); +	LLCheckBoxCtrl* ctrl_deferred2 = getChild<LLCheckBoxCtrl>("UseLightShaders2"); +  	BOOL enabled = LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&   						shaders &&  @@ -1155,11 +1157,13 @@ void LLFloaterPreference::refreshEnabledState()  						(ctrl_wind_light->get()) ? TRUE : FALSE;  	ctrl_deferred->setEnabled(enabled); -	 +	ctrl_deferred2->setEnabled(enabled); +  	LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");  	LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF");  	LLComboBox* ctrl_shadow = getChild<LLComboBox>("ShadowDetail"); +	// note, okay here to get from ctrl_deferred as it's twin, ctrl_deferred2 will alway match it  	enabled = enabled && LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferredSSAO") && (ctrl_deferred->get() ? TRUE : FALSE);  	ctrl_ssao->setEnabled(enabled); @@ -1185,6 +1189,7 @@ void LLFloaterPreference::disableUnavailableSettings()  	LLCheckBoxCtrl* ctrl_wind_light    = getChild<LLCheckBoxCtrl>("WindLightUseAtmosShaders");  	LLCheckBoxCtrl* ctrl_avatar_impostors = getChild<LLCheckBoxCtrl>("AvatarImpostors");  	LLCheckBoxCtrl* ctrl_deferred = getChild<LLCheckBoxCtrl>("UseLightShaders"); +	LLCheckBoxCtrl* ctrl_deferred2 = getChild<LLCheckBoxCtrl>("UseLightShaders2");  	LLComboBox* ctrl_shadows = getChild<LLComboBox>("ShadowDetail");  	LLCheckBoxCtrl* ctrl_ssao = getChild<LLCheckBoxCtrl>("UseSSAO");  	LLCheckBoxCtrl* ctrl_dof = getChild<LLCheckBoxCtrl>("UseDoF"); @@ -1218,6 +1223,8 @@ void LLFloaterPreference::disableUnavailableSettings()  		ctrl_deferred->setEnabled(FALSE);  		ctrl_deferred->setValue(FALSE); +		ctrl_deferred2->setEnabled(FALSE); +		ctrl_deferred2->setValue(FALSE);  	}  	// disabled windlight @@ -1238,6 +1245,8 @@ void LLFloaterPreference::disableUnavailableSettings()  		ctrl_deferred->setEnabled(FALSE);  		ctrl_deferred->setValue(FALSE); +		ctrl_deferred2->setEnabled(FALSE); +		ctrl_deferred2->setValue(FALSE);  	}  	// disabled deferred @@ -1255,6 +1264,8 @@ void LLFloaterPreference::disableUnavailableSettings()  		ctrl_deferred->setEnabled(FALSE);  		ctrl_deferred->setValue(FALSE); +		ctrl_deferred2->setEnabled(FALSE); +		ctrl_deferred2->setValue(FALSE);  	}  	// disabled deferred SSAO @@ -1299,6 +1310,8 @@ void LLFloaterPreference::disableUnavailableSettings()  		ctrl_deferred->setEnabled(FALSE);  		ctrl_deferred->setValue(FALSE); +		ctrl_deferred2->setEnabled(FALSE); +		ctrl_deferred2->setValue(FALSE);  	}  	// disabled cloth @@ -1327,6 +1340,7 @@ void LLFloaterPreference::refresh()  	updateSliderText(getChild<LLSliderCtrl>("FlexibleMeshDetail",	true), getChild<LLTextBox>("FlexibleMeshDetailText",	true));  	updateSliderText(getChild<LLSliderCtrl>("TreeMeshDetail",		true), getChild<LLTextBox>("TreeMeshDetailText",		true));  	updateSliderText(getChild<LLSliderCtrl>("AvatarMeshDetail",		true), getChild<LLTextBox>("AvatarMeshDetailText",		true)); +	updateSliderText(getChild<LLSliderCtrl>("AvatarMeshDetail2",		true), getChild<LLTextBox>("AvatarMeshDetailText2",		true));  	updateSliderText(getChild<LLSliderCtrl>("AvatarPhysicsDetail",	true), getChild<LLTextBox>("AvatarPhysicsDetailText",		true));  	updateSliderText(getChild<LLSliderCtrl>("TerrainMeshDetail",	true), getChild<LLTextBox>("TerrainMeshDetailText",		true));  	updateSliderText(getChild<LLSliderCtrl>("RenderPostProcess",	true), getChild<LLTextBox>("PostProcessText",			true)); @@ -1578,16 +1592,9 @@ void LLFloaterPreference::setPersonalInfo(const std::string& visibility, bool im  	getChildView("chat_font_size")->setEnabled(TRUE);  } -void LLFloaterPreference::onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name) +void LLFloaterPreference::refreshUI()  { -	std::string ctrl_name = name.asString(); -	 -	if ((ctrl_name =="" )|| !hasChild(ctrl_name, TRUE)) -		return; -	 -	LLTextBox* text_box = getChild<LLTextBox>(name.asString()); -	LLSliderCtrl* slider = dynamic_cast<LLSliderCtrl*>(ctrl); -	updateSliderText(slider, text_box); +	refresh();  }  void LLFloaterPreference::updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box) diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h index 22e80a21cb..cb180f6f1e 100644 --- a/indra/newview/llfloaterpreference.h +++ b/indra/newview/llfloaterpreference.h @@ -154,8 +154,7 @@ public:  	void onChangeQuality(const LLSD& data);  	void updateSliderText(LLSliderCtrl* ctrl, LLTextBox* text_box); -	void onUpdateSliderText(LLUICtrl* ctrl, const LLSD& name); -//	void fractionFromDecimal(F32 decimal_val, S32& numerator, S32& denominator); +	void refreshUI();  	void onCommitParcelMediaAutoPlayEnable();  	void onCommitMediaEnabled(); diff --git a/indra/newview/llfloaterwebcontent.cpp b/indra/newview/llfloaterwebcontent.cpp index 3fe2518de6..94c3f4149c 100644 --- a/indra/newview/llfloaterwebcontent.cpp +++ b/indra/newview/llfloaterwebcontent.cpp @@ -54,7 +54,7 @@ LLFloaterWebContent::_Params::_Params()  LLFloaterWebContent::LLFloaterWebContent( const Params& params )  :	LLFloater( params ), -	LLInstanceTracker<LLFloaterWebContent, std::string>(params.id()), +	INSTANCE_TRACKER_KEYED(LLFloaterWebContent, std::string)(params.id()),  	mWebBrowser(NULL),  	mAddressCombo(NULL),  	mSecureLockIcon(NULL), diff --git a/indra/newview/llfloaterwebcontent.h b/indra/newview/llfloaterwebcontent.h index cfc87e9015..409c15fb0b 100644 --- a/indra/newview/llfloaterwebcontent.h +++ b/indra/newview/llfloaterwebcontent.h @@ -40,10 +40,11 @@ class LLIconCtrl;  class LLFloaterWebContent :  	public LLFloater,  	public LLViewerMediaObserver, -	public LLInstanceTracker<LLFloaterWebContent, std::string> +	public INSTANCE_TRACKER_KEYED(LLFloaterWebContent, std::string)  {  public: -	typedef LLInstanceTracker<LLFloaterWebContent, std::string> instance_tracker_t; + +	typedef INSTANCE_TRACKER_KEYED(LLFloaterWebContent, std::string) instance_tracker_t;      LOG_CLASS(LLFloaterWebContent);  	struct _Params : public LLInitParam::Block<_Params> diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index b62db70ec8..06bf294417 100644 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1681,7 +1681,8 @@ void LLManipTranslate::highlightIntersection(LLVector3 normal,  		gGL.getModelviewMatrix().inverse().mult_vec_matrix(plane); -		gClipProgram.uniform4fv("clip_plane", 1, plane.v); +		static LLStaticHashedString sClipPlane("clip_plane"); +		gClipProgram.uniform4fv(sClipPlane, 1, plane.v);  		BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES);  		BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 2075aeed63..6362165c77 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -81,7 +81,7 @@ LLMediaCtrl::Params::Params()  LLMediaCtrl::LLMediaCtrl( const Params& p) :  	LLPanel( p ), -	LLInstanceTracker<LLMediaCtrl, LLUUID>(LLUUID::generateNewID()), +	INSTANCE_TRACKER_KEYED(LLMediaCtrl, LLUUID)(LLUUID::generateNewID()),  	mTextureDepthBytes( 4 ),  	mBorder(NULL),  	mFrequentUpdates( true ), diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 7f2a5e1642..4fed21bf22 100644 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -42,10 +42,11 @@ class LLMediaCtrl :  	public LLPanel,  	public LLViewerMediaObserver,  	public LLViewerMediaEventEmitter, -	public LLInstanceTracker<LLMediaCtrl, LLUUID> +	public INSTANCE_TRACKER_KEYED(LLMediaCtrl, LLUUID)  {  	LOG_CLASS(LLMediaCtrl);  public: +  	struct Params : public LLInitParam::Block<Params, LLPanel::Params>   	{  		Optional<std::string>	start_url; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 17311dd75e..b1b31240e9 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -288,7 +288,14 @@ public:  	~LLMeshSkinInfoResponder()  	{ -		llassert(mProcessed); +		if (!LLApp::isQuitting() && +			!mProcessed && +			mMeshID.notNull()) +		{	// Something went wrong, retry +			llwarns << "Timeout or service unavailable, retrying loadMeshSkinInfo() for " << mMeshID << llendl; +			LLMeshRepository::sHTTPRetryCount++; +			gMeshRepo.mThread->loadMeshSkinInfo(mMeshID); +		}  	}  	virtual void completedRaw(U32 status, const std::string& reason, @@ -313,7 +320,14 @@ public:  	~LLMeshDecompositionResponder()  	{ -		llassert(mProcessed); +		if (!LLApp::isQuitting() && +			!mProcessed && +			mMeshID.notNull()) +		{	// Something went wrong, retry +			llwarns << "Timeout or service unavailable, retrying loadMeshDecomposition() for " << mMeshID << llendl; +			LLMeshRepository::sHTTPRetryCount++; +			gMeshRepo.mThread->loadMeshDecomposition(mMeshID); +		}  	}  	virtual void completedRaw(U32 status, const std::string& reason, @@ -338,7 +352,14 @@ public:  	~LLMeshPhysicsShapeResponder()  	{ -		llassert(mProcessed); +		if (!LLApp::isQuitting() && +			!mProcessed && +			mMeshID.notNull()) +		{	// Something went wrong, retry +			llwarns << "Timeout or service unavailable, retrying loadMeshPhysicsShape() for " << mMeshID << llendl; +			LLMeshRepository::sHTTPRetryCount++; +			gMeshRepo.mThread->loadMeshPhysicsShape(mMeshID); +		}  	}  	virtual void completedRaw(U32 status, const std::string& reason, @@ -588,7 +609,7 @@ void LLMeshRepoThread::run()  					if (!fetchMeshLOD(req.mMeshParams, req.mLOD, count))//failed, resubmit  					{  						mMutex->lock(); -						mLODReqQ.push(req) ;  +						mLODReqQ.push(req);   						mMutex->unlock();  					}  				} @@ -1200,8 +1221,7 @@ bool LLMeshRepoThread::headerReceived(const LLVolumeParams& mesh_params, U8* dat  			LLMutexLock lock(mHeaderMutex);  			mMeshHeaderSize[mesh_id] = header_size;  			mMeshHeader[mesh_id] = header; -			} - +		}  		LLMutexLock lock(mMutex); // make sure only one thread access mPendingLOD at the same time. @@ -1919,7 +1939,7 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,  	if (data_size < mRequestedBytes)  	{ -		if (status == 499 || status == 503) +		if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE)  		{ //timeout or service unavailable, try again  			llwarns << "Timeout or service unavailable, retrying." << llendl;  			LLMeshRepository::sHTTPRetryCount++; @@ -1927,7 +1947,7 @@ void LLMeshLODResponder::completedRaw(U32 status, const std::string& reason,  		}  		else  		{ -			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint +			llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint  			llwarns << "Unhandled status " << status << llendl;  		}  		return; @@ -1983,15 +2003,15 @@ void LLMeshSkinInfoResponder::completedRaw(U32 status, const std::string& reason  	if (data_size < mRequestedBytes)  	{ -		if (status == 499 || status == 503) +		if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE)  		{ //timeout or service unavailable, try again -			llwarns << "Timeout or service unavailable, retrying." << llendl; +			llwarns << "Timeout or service unavailable, retrying loadMeshSkinInfo() for " << mMeshID << llendl;  			LLMeshRepository::sHTTPRetryCount++;  			gMeshRepo.mThread->loadMeshSkinInfo(mMeshID);  		}  		else  		{ -			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint +			llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint  			llwarns << "Unhandled status " << status << llendl;  		}  		return; @@ -2046,15 +2066,15 @@ void LLMeshDecompositionResponder::completedRaw(U32 status, const std::string& r  	if (data_size < mRequestedBytes)  	{ -		if (status == 499 || status == 503) +		if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE)  		{ //timeout or service unavailable, try again -			llwarns << "Timeout or service unavailable, retrying." << llendl; +			llwarns << "Timeout or service unavailable, retrying loadMeshDecomposition() for " << mMeshID << llendl;  			LLMeshRepository::sHTTPRetryCount++;  			gMeshRepo.mThread->loadMeshDecomposition(mMeshID);  		}  		else  		{ -			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint +			llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint  			llwarns << "Unhandled status " << status << llendl;  		}  		return; @@ -2110,15 +2130,15 @@ void LLMeshPhysicsShapeResponder::completedRaw(U32 status, const std::string& re  	if (data_size < mRequestedBytes)  	{ -		if (status == 499 || status == 503) +		if (status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE)  		{ //timeout or service unavailable, try again -			llwarns << "Timeout or service unavailable, retrying." << llendl; +			llwarns << "Timeout or service unavailable, retrying loadMeshPhysicsShape() for " << mMeshID << llendl;  			LLMeshRepository::sHTTPRetryCount++;  			gMeshRepo.mThread->loadMeshPhysicsShape(mMeshID);  		}  		else  		{ -			llassert(status == 499 || status == 503); //intentionally trigger a breakpoint +			llassert(status == HTTP_INTERNAL_ERROR || status == HTTP_SERVICE_UNAVAILABLE); //intentionally trigger a breakpoint  			llwarns << "Unhandled status " << status << llendl;  		}  		return; @@ -2171,16 +2191,16 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,  		//	<< "Header responder failed with status: "  		//	<< status << ": " << reason << llendl; -		// 503 (service unavailable) or 499 (timeout) +		// 503 (service unavailable) or 499 (internal Linden-generated error)  		// can be due to server load and can be retried  		// TODO*: Add maximum retry logic, exponential backoff  		// and (somewhat more optional than the others) retries  		// again after some set period of time -		llassert(status == 503 || status == 499); +		llassert(status == HTTP_NOT_FOUND || status == HTTP_SERVICE_UNAVAILABLE || status == HTTP_REQUEST_TIME_OUT || status == HTTP_INTERNAL_ERROR); -		if (status == 503 || status == 499) +		if (status == HTTP_SERVICE_UNAVAILABLE || status == HTTP_REQUEST_TIME_OUT || status == HTTP_INTERNAL_ERROR)  		{ //retry  			llwarns << "Timeout or service unavailable, retrying." << llendl;  			LLMeshRepository::sHTTPRetryCount++; @@ -2192,7 +2212,7 @@ void LLMeshHeaderResponder::completedRaw(U32 status, const std::string& reason,  		}  		else  		{ -			llwarns << "Unhandled status." << llendl; +			llwarns << "Unhandled status: " << status << llendl;  		}  	} diff --git a/indra/newview/llnamelistctrl.h b/indra/newview/llnamelistctrl.h index 5aa1e1c458..d82727f018 100644 --- a/indra/newview/llnamelistctrl.h +++ b/indra/newview/llnamelistctrl.h @@ -64,9 +64,10 @@ private:  class LLNameListCtrl -:	public LLScrollListCtrl, public LLInstanceTracker<LLNameListCtrl> +:	public LLScrollListCtrl, public INSTANCE_TRACKER(LLNameListCtrl)  {  public: +  	typedef enum e_name_type  	{  		INDIVIDUAL, diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index e4c2e94230..9e07cedf18 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -1404,7 +1404,9 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node)  		if (bridge->mAvatar.notNull())  		{  			bridge->mAvatar->mAttachmentGeometryBytes -= mGeometryBytes; +			bridge->mAvatar->mAttachmentGeometryBytes = llmax(bridge->mAvatar->mAttachmentGeometryBytes, 0);  			bridge->mAvatar->mAttachmentSurfaceArea -= mSurfaceArea; +			bridge->mAvatar->mAttachmentSurfaceArea = llmax(bridge->mAvatar->mAttachmentSurfaceArea, 0.f);  		}  	} @@ -4648,7 +4650,9 @@ LLDrawInfo::LLDrawInfo(U16 start, U16 end, U32 count, U32 offset,  	mGroup(NULL),  	mFace(NULL),  	mDistance(0.f), -	mDrawMode(LLRender::TRIANGLES) +	mDrawMode(LLRender::TRIANGLES), +	mBlendFuncSrc(LLRender::BF_SOURCE_ALPHA), +	mBlendFuncDst(LLRender::BF_ONE_MINUS_SOURCE_ALPHA)  {  	mVertexBuffer->validateRange(mStart, mEnd, mCount, mOffset); diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index b1706d9d35..08e77855c4 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -119,6 +119,8 @@ public:  	LL_ALIGN_16(LLFace* mFace); //associated face  	F32 mDistance;  	U32 mDrawMode; +	U32 mBlendFuncSrc; +	U32 mBlendFuncDst;  	struct CompareTexture  	{ @@ -739,7 +741,7 @@ class LLVolumeGeometryManager: public LLGeometryManager  	virtual void rebuildGeom(LLSpatialGroup* group);  	virtual void rebuildMesh(LLSpatialGroup* group);  	virtual void getGeometry(LLSpatialGroup* group); -	void genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE); +	void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE);  	void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);  }; diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp index 9dfb29b905..49debe67f6 100644 --- a/indra/newview/lltoast.cpp +++ b/indra/newview/lltoast.cpp @@ -572,7 +572,7 @@ S32	LLToast::notifyParent(const LLSD& info)  //static  void LLToast::updateClass()  { -	for (LLInstanceTracker<LLToast>::instance_iter iter = LLInstanceTracker<LLToast>::beginInstances(); iter != LLInstanceTracker<LLToast>::endInstances(); )  +	for (INSTANCE_TRACKER(LLToast)::instance_iter iter = INSTANCE_TRACKER(LLToast)::beginInstances(); iter != INSTANCE_TRACKER(LLToast)::endInstances(); )   	{  		LLToast& toast = *iter++; diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h index ea62f758f8..718b464977 100644 --- a/indra/newview/lltoast.h +++ b/indra/newview/lltoast.h @@ -69,10 +69,11 @@ private :   * Represents toast pop-up.   * This is a parent view for all toast panels.   */ -class LLToast : public LLModalDialog, public LLInstanceTracker<LLToast> +class LLToast : public LLModalDialog, public INSTANCE_TRACKER(LLToast)  {  	friend class LLToastLifeTimer;  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; diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp index 8bfde2bcf1..9b5ccc0150 100644 --- a/indra/newview/lltoastnotifypanel.cpp +++ b/indra/newview/lltoastnotifypanel.cpp @@ -57,10 +57,10 @@ LLToastNotifyPanel::button_click_signal_t LLToastNotifyPanel::sButtonClickSignal  LLToastNotifyPanel::LLToastNotifyPanel(const LLNotificationPtr& notification, const LLRect& rect, bool show_images)   :	LLToastPanel(notification), -	LLInstanceTracker<LLToastNotifyPanel, LLUUID>(notification->getID()) +	LLInstanceTracker<LLToastNotifyPanel, InstanceTrackType_LLToast, LLUUID>(notification->getID())  {  	init(rect, show_images); -	} +}  void LLToastNotifyPanel::addDefaultButton()  {  	LLSD form_element; diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h index d02171b512..5de75a7a9f 100644 --- a/indra/newview/lltoastnotifypanel.h +++ b/indra/newview/lltoastnotifypanel.h @@ -47,7 +47,7 @@ class LLNotificationForm;   * @deprecated this class will be removed after all toast panel types are   *  implemented in separate classes.   */ -class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, LLUUID> +class LLToastNotifyPanel: public LLToastPanel, public LLInstanceTracker<LLToastNotifyPanel, InstanceTrackType_LLToast, LLUUID>  {  public:  	/** diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index cf59e67955..0f273a8241 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -212,13 +212,13 @@ void display_stats()  }  static LLFastTimer::DeclareTimer FTM_PICK("Picking"); -static LLFastTimer::DeclareTimer FTM_RENDER("Render", true); +static LLFastTimer::DeclareTimer FTM_RENDER("Render");  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("Image Update Bump"); -static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_LIST("List"); +static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_LIST("List", true);  static LLFastTimer::DeclareTimer FTM_IMAGE_UPDATE_DELETE("Delete");  static LLFastTimer::DeclareTimer FTM_RESIZE_WINDOW("Resize Window");  static LLFastTimer::DeclareTimer FTM_HUD_UPDATE("HUD Update"); diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp index a179b61cff..a179b61cff 100755..100644 --- a/indra/newview/llviewerfoldertype.cpp +++ b/indra/newview/llviewerfoldertype.cpp diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index c96764e892..ae38dc2fe9 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -2949,6 +2949,63 @@ bool enable_object_unmute()  	}  } + +// 0 = normal, 1 = always, 2 = never +class LLAvatarCheckImposterMode : public view_listener_t +{	 +	bool handleEvent(const LLSD& userdata) +	{ +		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); +		if (!object) return false; + +		LLVOAvatar* avatar = find_avatar_from_object(object);  +		if (!avatar) return false; +		 +		U32 mode = userdata.asInteger(); +		switch (mode)  +		{ +			case 0: +				return (avatar->getVisualMuteSettings() == LLVOAvatar::VISUAL_MUTE_NOT_SET); +			case 1: +				return (avatar->getVisualMuteSettings() == LLVOAvatar::ALWAYS_VISUAL_MUTE); +			case 2: +				return (avatar->getVisualMuteSettings() == LLVOAvatar::NEVER_VISUAL_MUTE); +			default: +				return false; +		} +	}	// handleEvent() +}; + +// 0 = normal, 1 = always, 2 = never +class LLAvatarSetImposterMode : public view_listener_t +{ +	bool handleEvent(const LLSD& userdata) +	{ +		LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject(); +		if (!object) return false; + +		LLVOAvatar* avatar = find_avatar_from_object(object);  +		if (!avatar) return false; +		 +		U32 mode = userdata.asInteger(); +		switch (mode)  +		{ +			case 0: +				avatar->setVisualMuteSettings(LLVOAvatar::VISUAL_MUTE_NOT_SET); +				return true; +			case 1: +				avatar->setVisualMuteSettings(LLVOAvatar::ALWAYS_VISUAL_MUTE); +				return true; +			case 2: +				avatar->setVisualMuteSettings(LLVOAvatar::NEVER_VISUAL_MUTE); +				return true; +			default: +				return false; +		} +	}	// handleEvent() +}; + +  class LLObjectMute : public view_listener_t  {  	bool handleEvent(const LLSD& userdata) @@ -8651,6 +8708,8 @@ void initialize_menus()  	view_listener_t::addMenu( new LLCheckPanelPeopleTab(), "SideTray.CheckPanelPeopleTab");  	 // Avatar pie menu +	view_listener_t::addMenu(new LLAvatarCheckImposterMode(), "Avatar.CheckImposterMode"); +	view_listener_t::addMenu(new LLAvatarSetImposterMode(), "Avatar.SetImposterMode");  	view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute");  	view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");  	view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact"); diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index fbdb991484..edca793b66 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -163,7 +163,10 @@ const std::string SCRIPT_QUESTIONS[SCRIPT_PERMISSION_EOF] =  		"ChangePermissions",  		"TrackYourCamera",  		"ControlYourCamera", -		"TeleportYourAgent" +		"TeleportYourAgent", +		"ExperiencePlaceholder", +		"ManageEstateSilently", +		"ChangeYourDefaultAnimations"  	};  const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] =  @@ -179,7 +182,10 @@ const BOOL SCRIPT_QUESTION_IS_CAUTION[SCRIPT_PERMISSION_EOF] =  	FALSE,	// ChangePermissions  	FALSE,	// TrackYourCamera,  	FALSE,	// ControlYourCamera -	FALSE	// TeleportYourAgent +	FALSE,	// TeleportYourAgent +	FALSE,  // ExperiencePlaceholder +	FALSE,	// ManageEstateSilently +	FALSE	// ChangeYourDefaultAnimations  };  bool friendship_offer_callback(const LLSD& notification, const LLSD& response) @@ -4121,7 +4127,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)  		{  			LLTracker::stopTracking(NULL);  		} -		else if ( is_teleport && !gAgent.getTeleportKeepsLookAt() ) +		else if ( is_teleport && !gAgent.getTeleportKeepsLookAt() && look_at.isExactlyZero())  		{  			//look at the beacon  			LLVector3 global_agent_pos = agent_pos; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index fcf5af76ff..ac517f1fb7 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1553,6 +1553,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				dp->setPassFlags(value);  				dp->unpackUUID(owner_id, "Owner"); +				mOwnerID = owner_id; +  				if (value & 0x80)  				{  					dp->unpackVector3(new_angv, "Omega"); @@ -1626,13 +1628,13 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,                  retval |= checkMediaURL(media_url);  				// -				// Unpack particle system data +				// Unpack particle system data (legacy)  				//  				if (value & 0x8)  				{ -					unpackParticleSource(*dp, owner_id); +					unpackParticleSource(*dp, owner_id, true);  				} -				else +				else if (!(value & 0x400))  				{  					deleteParticleSource();  				} @@ -1697,7 +1699,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,  				// keep local flags and overwrite remote-controlled flags  				mFlags = (mFlags & FLAGS_LOCAL) | flags; -					// ...new objects that should come in selected need to be added to the selected list +				// ...new objects that should come in selected need to be added to the selected list  				mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);  			}  			break; @@ -4606,7 +4608,7 @@ void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& own  	}  } -void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id) +void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy)  {  	if (!mPartSourcep.isNull() && mPartSourcep->isDead())  	{ @@ -4615,7 +4617,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_  	if (mPartSourcep)  	{  		// If we've got one already, just update the existing source (or remove it) -		if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp)) +		if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp, legacy))  		{  			mPartSourcep->setDead();  			mPartSourcep = NULL; @@ -4623,7 +4625,7 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_  	}  	else  	{ -		LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp); +		LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp, legacy);  		//If the owner is muted, don't create the system  		if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return;  		// We need to be able to deal with a particle source that hasn't changed, but still got an update! @@ -5469,6 +5471,11 @@ F32 LLAlphaObject::getPartSize(S32 idx)  	return 0.f;  } +void LLAlphaObject::getBlendFunc(S32 face, U32& src, U32& dst) +{ + +} +  // virtual  void LLStaticViewerObject::updateDrawable(BOOL force_damped)  { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 728d279c39..1b4291a1d1 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -584,6 +584,7 @@ public:  	} EPhysicsShapeType;  	LLUUID			mID; +	LLUUID			mOwnerID; //null if unknown  	// unique within region, not unique across regions  	// Local ID = 0 is not used @@ -662,7 +663,7 @@ protected:  	BOOL isOnMap();  	void unpackParticleSource(const S32 block_num, const LLUUID& owner_id); -	void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id); +	void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy);  	void deleteParticleSource();  	void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id); @@ -826,9 +827,12 @@ public:  								LLStrider<LLVector4a>& verticesp,  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp, -								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& colorsp, +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp) = 0; +	virtual void getBlendFunc(S32 face, U32& src, U32& dst); +  	F32 mDepth;  }; diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 61cdfd7818..21f1d2619c 100644 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -80,12 +80,31 @@ LLViewerPart::LLViewerPart() :  	mImagep(NULL)  {  	mPartSourcep = NULL; - +	mParent = NULL; +	mChild = NULL;  	++LLViewerPartSim::sParticleCount2 ;  }  LLViewerPart::~LLViewerPart()  { +	if (mPartSourcep.notNull() && mPartSourcep->mLastPart == this) +	{ +		mPartSourcep->mLastPart = NULL; +	} + +	//patch up holes in the ribbon +	if (mParent) +	{ +		llassert(mParent->mChild == this); +		mParent->mChild = mChild; +	} + +	if (mChild) +	{ +		llassert (mChild->mParent == this); +		mChild->mParent = mParent; +	} +  	mPartSourcep = NULL;  	--LLViewerPartSim::sParticleCount2 ; @@ -367,6 +386,9 @@ void LLViewerPartGroup::updateParticles(const F32 lastdt)  			part->mScale += frac*part->mEndScale;  		} +		// Do glow interpolation +		part->mGlow.mV[3] = (U8) (lerp(part->mStartGlow, part->mEndGlow, frac)*255.f); +  		// Set the last update time to now.  		part->mLastUpdateTime = cur_time; @@ -623,6 +645,9 @@ void LLViewerPartSim::updateSimulation()  {  	static LLFrameTimer update_timer; +	//reset VBO cursor +	LLVOPartGroup::sVBSlotCursor = 0; +  	const F32 dt = llmin(update_timer.getElapsedTimeAndResetF32(), 0.1f);   	if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES))) diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index c91fcf0691..095de2060c 100644 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -65,15 +65,22 @@ public:  	LLVPCallback		mVPCallback;				// Callback function for more complicated behaviors  	LLPointer<LLViewerPartSource> mPartSourcep;		// Particle source used for this object -	 + +	LLViewerPart*		mParent;					// particle to connect to if this is part of a particle ribbon +	LLViewerPart*		mChild;						// child particle for clean reference destruction  	// Current particle state (possibly used for rendering)  	LLPointer<LLViewerTexture>	mImagep;  	LLVector3		mPosAgent;  	LLVector3		mVelocity;  	LLVector3		mAccel; +	LLVector3		mAxis;  	LLColor4		mColor;  	LLVector2		mScale; +	F32				mStartGlow; +	F32				mEndGlow; +	LLColor4U		mGlow; +  	static U32		sNextPartID;  }; diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index b311f659fb..8c49ce646d 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -52,6 +52,8 @@ LLViewerPartSource::LLViewerPartSource(const U32 type) :  	static U32 id_seed = 0;  	mID = ++id_seed; +	mLastPart = NULL; +  	mDelay = 0 ;  } @@ -279,6 +281,22 @@ void LLViewerPartSourceScript::update(const F32 dt)  			{  				part->mFlags |= LLPartData::LL_PART_HUD;  			} + +			if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart) +			{ //set previous particle's parent to this particle to chain ribbon together +				mLastPart->mParent = part; +				part->mChild = mLastPart; +				part->mAxis = LLVector3(0,0,1); + +				if (mSourceObjectp.notNull()) +				{ +					LLQuaternion rot = mSourceObjectp->getRenderRotation(); +					part->mAxis *= rot; +				} +			} + +			mLastPart = part; +  			part->mMaxAge = mPartSysData.mPartData.mMaxAge;  			part->mStartColor = mPartSysData.mPartData.mStartColor;  			part->mEndColor = mPartSysData.mPartData.mEndColor; @@ -290,6 +308,13 @@ void LLViewerPartSourceScript::update(const F32 dt)  			part->mAccel = mPartSysData.mPartAccel; +			part->mBlendFuncDest = mPartSysData.mPartData.mBlendFuncDest; +			part->mBlendFuncSource = mPartSysData.mPartData.mBlendFuncSource; + +			part->mStartGlow = mPartSysData.mPartData.mStartGlow; +			part->mEndGlow = mPartSysData.mPartData.mEndGlow; +			part->mGlow = LLColor4U(0, 0, 0, (U8) (part->mStartGlow*255.f)); +			  			if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)  			{  				part->mPosAgent = mPosAgent; @@ -430,28 +455,51 @@ LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewer  } -LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp) +LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp, bool legacy)  {  	if (!pssp)  	{  		LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp); -		if (!new_pssp->mPartSysData.unpack(dp)) +		if (legacy)  		{ -			return NULL; +			if (!new_pssp->mPartSysData.unpackLegacy(dp)) +			{ +				return NULL; +			} +		} +		else +		{ +			if (!new_pssp->mPartSysData.unpack(dp)) +			{ +				return NULL; +			}  		} +		  		if (new_pssp->mPartSysData.mTargetUUID.notNull())  		{  			LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);  			new_pssp->setTargetObject(target_objp);  		} +		  		return new_pssp;  	}  	else  	{ -		if (!pssp->mPartSysData.unpack(dp)) +		if (legacy)  		{ -			return NULL; +			if (!pssp->mPartSysData.unpackLegacy(dp)) +			{ +				return NULL; +			}  		} +		else +		{ +			if (!pssp->mPartSysData.unpack(dp)) +			{ +				return NULL; +			} +		} +  		if (pssp->mPartSysData.mTargetUUID.notNull())  		{  			LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID); @@ -569,6 +617,11 @@ void LLViewerPartSourceSpiral::update(const F32 dt)  		part->mScale.mV[0] = 0.25f;  		part->mScale.mV[1] = 0.25f;  		part->mParameter = ll_frand(F_TWO_PI); +		part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; +		part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; +		part->mStartGlow = 0.f; +		part->mEndGlow = 0.f; +		part->mGlow = LLColor4U(0, 0, 0, 0);  		LLViewerPartSim::getInstance()->addPart(part);  	} @@ -721,6 +774,12 @@ void LLViewerPartSourceBeam::update(const F32 dt)  		part->mPosAgent = mPosAgent;  		part->mVelocity = mTargetPosAgent - mPosAgent; +		part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; +		part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; +		part->mStartGlow = 0.f; +		part->mEndGlow = 0.f; +		part->mGlow = LLColor4U(0, 0, 0, 0); +  		LLViewerPartSim::getInstance()->addPart(part);  	}  } @@ -825,6 +884,12 @@ void LLViewerPartSourceChat::update(const F32 dt)  		part->mScale.mV[0] = 0.25f;  		part->mScale.mV[1] = 0.25f;  		part->mParameter = ll_frand(F_TWO_PI); +		part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; +		part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; +		part->mStartGlow = 0.f; +		part->mEndGlow = 0.f; +		part->mGlow = LLColor4U(0, 0, 0, 0); +  		LLViewerPartSim::getInstance()->addPart(part);  	} diff --git a/indra/newview/llviewerpartsource.h b/indra/newview/llviewerpartsource.h index 28702d36a2..12e926173b 100644 --- a/indra/newview/llviewerpartsource.h +++ b/indra/newview/llviewerpartsource.h @@ -76,6 +76,7 @@ public:  	LLVector3	mLastUpdatePosAgent;  	LLPointer<LLViewerObject>	mSourceObjectp;  	U32 mID; +	LLViewerPart* mLastPart; //last particle emitted (for making particle ribbons)  protected:  	U32			mType; @@ -85,7 +86,6 @@ protected:  	F32			mLastPartTime;  	LLUUID		mOwnerUUID;  	LLPointer<LLViewerTexture>	mImagep; -  	// Particle information  	U32			mPartFlags; // Flags for the particle  	U32         mDelay ; //delay to start particles @@ -114,7 +114,7 @@ public:  	// Returns a new particle source to attach to an object...  	static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, const S32 block_num); -	static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp); +	static LLPointer<LLViewerPartSourceScript> unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp, bool legacy);  	static LLPointer<LLViewerPartSourceScript> createPSS(LLViewerObject *source_objp, const LLPartSysData& particle_parameters);  	LLViewerTexture *getImage() const				{ return mImagep; } diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index b8b53aa6e4..808bc9f3f7 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -44,6 +44,7 @@  #include "llagent.h"  #include "llagentcamera.h" +#include "llavatarrenderinfoaccountant.h"  #include "llcallingcard.h"  #include "llcaphttpsender.h"  #include "llcapabilitylistener.h" @@ -393,6 +394,9 @@ LLViewerRegion::LLViewerRegion(const U64 &handle,  	mImpl->mObjectPartition.push_back(new LLBridgePartition());	//PARTITION_BRIDGE  	mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE  	mImpl->mObjectPartition.push_back(NULL);						//PARTITION_NONE + +	mRenderInfoRequestTimer.resetWithExpiry(0.f);		// Set timer to be expired +	setCapabilitiesReceivedCallback(boost::bind(&LLAvatarRenderInfoAccountant::expireRenderInfoReportTimer));  } @@ -1577,6 +1581,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames)  	capabilityNames.append("AgentState");  	capabilityNames.append("AttachmentResources");  	capabilityNames.append("AvatarPickerSearch"); +	capabilityNames.append("AvatarRenderInfo");  	capabilityNames.append("CharacterProperties");  	capabilityNames.append("ChatSessionRequest");  	capabilityNames.append("CopyInventoryFromNotecard"); diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index b5fe4677b7..c442b47f6e 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -376,6 +376,8 @@ public:  	LLDynamicArray<U32> mMapAvatars;  	LLDynamicArray<LLUUID> mMapAvatarIDs; +	LLFrameTimer &	getRenderInfoRequestTimer()			{ return mRenderInfoRequestTimer;		}; +  private:  	LLViewerRegionImpl * mImpl; @@ -434,6 +436,8 @@ private:  	BOOL mReleaseNotesRequested;  	LLSD mSimulatorFeatures; + +	LLFrameTimer	mRenderInfoRequestTimer;  };  inline BOOL LLViewerRegion::getRegionProtocol(U64 protocol) const diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index ba9818946c..7d7889845d 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -52,6 +52,13 @@  #define UNIFORM_ERRS LL_ERRS("Shader")  #endif +static LLStaticHashedString sTexture0("texture0"); +static LLStaticHashedString sTexture1("texture1"); +static LLStaticHashedString sTex0("tex0"); +static LLStaticHashedString sTex1("tex1"); +static LLStaticHashedString sGlowMap("glowMap"); +static LLStaticHashedString sScreenMap("screenMap"); +  // Lots of STL stuff in here, using namespace std to keep things more readable  using std::vector;  using std::pair; @@ -304,47 +311,6 @@ void LLViewerShaderMgr::initAttribsAndUniforms(void)  	if (mReservedAttribs.empty())  	{  		LLShaderMgr::initAttribsAndUniforms(); - -		mAvatarUniforms.push_back("matrixPalette"); -		mAvatarUniforms.push_back("gWindDir"); -		mAvatarUniforms.push_back("gSinWaveParams"); -		mAvatarUniforms.push_back("gGravity"); - -		mWLUniforms.push_back("camPosLocal"); - -		mTerrainUniforms.reserve(5); -		mTerrainUniforms.push_back("detail_0"); -		mTerrainUniforms.push_back("detail_1"); -		mTerrainUniforms.push_back("detail_2"); -		mTerrainUniforms.push_back("detail_3"); -		mTerrainUniforms.push_back("alpha_ramp"); - -		mGlowUniforms.push_back("glowDelta"); -		mGlowUniforms.push_back("glowStrength"); - -		mGlowExtractUniforms.push_back("minLuminance"); -		mGlowExtractUniforms.push_back("maxExtractAlpha"); -		mGlowExtractUniforms.push_back("lumWeights"); -		mGlowExtractUniforms.push_back("warmthWeights"); -		mGlowExtractUniforms.push_back("warmthAmount"); - -		mShinyUniforms.push_back("origin"); - -		mWaterUniforms.reserve(12); -		mWaterUniforms.push_back("screenTex"); -		mWaterUniforms.push_back("screenDepth"); -		mWaterUniforms.push_back("refTex"); -		mWaterUniforms.push_back("eyeVec"); -		mWaterUniforms.push_back("time"); -		mWaterUniforms.push_back("d1"); -		mWaterUniforms.push_back("d2"); -		mWaterUniforms.push_back("lightDir"); -		mWaterUniforms.push_back("specular"); -		mWaterUniforms.push_back("lightExp"); -		mWaterUniforms.push_back("fogCol"); -		mWaterUniforms.push_back("kd"); -		mWaterUniforms.push_back("refScale"); -		mWaterUniforms.push_back("waterHeight");  	}	  } @@ -915,7 +881,7 @@ BOOL LLViewerShaderMgr::loadShadersEnvironment()  		gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainV.glsl", GL_VERTEX_SHADER_ARB));  		gTerrainProgram.mShaderFiles.push_back(make_pair("environment/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));  		gTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_ENVIRONMENT]; -		success = gTerrainProgram.createShader(NULL, &mTerrainUniforms); +		success = gTerrainProgram.createShader(NULL, NULL);  	}  	if (!success) @@ -953,7 +919,7 @@ BOOL LLViewerShaderMgr::loadShadersWater()  		gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterV.glsl", GL_VERTEX_SHADER_ARB));  		gWaterProgram.mShaderFiles.push_back(make_pair("environment/waterF.glsl", GL_FRAGMENT_SHADER_ARB));  		gWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_WATER]; -		success = gWaterProgram.createShader(NULL, &mWaterUniforms); +		success = gWaterProgram.createShader(NULL, NULL);  	}  	if (success) @@ -967,7 +933,7 @@ BOOL LLViewerShaderMgr::loadShadersWater()  		gUnderWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_WATER];  		gUnderWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; -		success = gUnderWaterProgram.createShader(NULL, &mWaterUniforms); +		success = gUnderWaterProgram.createShader(NULL, NULL);  	}  	if (success) @@ -985,7 +951,7 @@ BOOL LLViewerShaderMgr::loadShadersWater()  		gTerrainWaterProgram.mShaderFiles.push_back(make_pair("environment/terrainWaterF.glsl", GL_FRAGMENT_SHADER_ARB));  		gTerrainWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_ENVIRONMENT];  		gTerrainWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; -		terrainWaterSuccess = gTerrainWaterProgram.createShader(NULL, &mTerrainUniforms); +		terrainWaterSuccess = gTerrainWaterProgram.createShader(NULL, NULL);  	}	  	/// Keep track of water shader levels @@ -1034,7 +1000,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects()  		gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowV.glsl", GL_VERTEX_SHADER_ARB));  		gGlowProgram.mShaderFiles.push_back(make_pair("effects/glowF.glsl", GL_FRAGMENT_SHADER_ARB));  		gGlowProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT]; -		success = gGlowProgram.createShader(NULL, &mGlowUniforms); +		success = gGlowProgram.createShader(NULL, NULL);  		if (!success)  		{  			LLPipeline::sRenderGlow = FALSE; @@ -1048,7 +1014,7 @@ BOOL LLViewerShaderMgr::loadShadersEffects()  		gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractV.glsl", GL_VERTEX_SHADER_ARB));  		gGlowExtractProgram.mShaderFiles.push_back(make_pair("effects/glowExtractF.glsl", GL_FRAGMENT_SHADER_ARB));  		gGlowExtractProgram.mShaderLevel = mVertexShaderLevel[SHADER_EFFECT]; -		success = gGlowExtractProgram.createShader(NULL, &mGlowExtractUniforms); +		success = gGlowExtractProgram.createShader(NULL, NULL);  		if (!success)  		{  			LLPipeline::sRenderGlow = FALSE; @@ -1408,7 +1374,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterV.glsl", GL_VERTEX_SHADER_ARB));  		gDeferredWaterProgram.mShaderFiles.push_back(make_pair("deferred/waterF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; -		success = gDeferredWaterProgram.createShader(NULL, &mWaterUniforms); +		success = gDeferredWaterProgram.createShader(NULL, NULL);  	}  	if (success) @@ -1467,7 +1433,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowV.glsl", GL_VERTEX_SHADER_ARB));  		gDeferredAvatarShadowProgram.mShaderFiles.push_back(make_pair("deferred/avatarShadowF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredAvatarShadowProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; -		success = gDeferredAvatarShadowProgram.createShader(NULL, &mAvatarUniforms); +		success = gDeferredAvatarShadowProgram.createShader(NULL, NULL);  	}  	if (success) @@ -1488,7 +1454,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainV.glsl", GL_VERTEX_SHADER_ARB));  		gDeferredTerrainProgram.mShaderFiles.push_back(make_pair("deferred/terrainF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredTerrainProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; -		success = gDeferredTerrainProgram.createShader(NULL, &mTerrainUniforms); +		success = gDeferredTerrainProgram.createShader(NULL, NULL);  	}  	if (success) @@ -1499,7 +1465,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarV.glsl", GL_VERTEX_SHADER_ARB));  		gDeferredAvatarProgram.mShaderFiles.push_back(make_pair("deferred/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; -		success = gDeferredAvatarProgram.createShader(NULL, &mAvatarUniforms); +		success = gDeferredAvatarProgram.createShader(NULL, NULL);  	}  	if (success) @@ -1519,7 +1485,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaNonIndexedNoColorF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED]; -		success = gDeferredAvatarAlphaProgram.createShader(NULL, &mAvatarUniforms); +		success = gDeferredAvatarAlphaProgram.createShader(NULL, NULL);  		gDeferredAvatarAlphaProgram.mFeatures.calculatesLighting = true;  		gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true; @@ -1584,7 +1550,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredWLSkyProgram.mShaderFiles.push_back(make_pair("deferred/skyF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];  		gDeferredWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY; -		success = gDeferredWLSkyProgram.createShader(NULL, &mWLUniforms); +		success = gDeferredWLSkyProgram.createShader(NULL, NULL);  	}  	if (success) @@ -1595,7 +1561,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredWLCloudProgram.mShaderFiles.push_back(make_pair("deferred/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];  		gDeferredWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY; -		success = gDeferredWLCloudProgram.createShader(NULL, &mWLUniforms); +		success = gDeferredWLCloudProgram.createShader(NULL, NULL);  	}  	if (success) @@ -1606,7 +1572,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()  		gDeferredStarProgram.mShaderFiles.push_back(make_pair("deferred/starsF.glsl", GL_FRAGMENT_SHADER_ARB));  		gDeferredStarProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];  		gDeferredStarProgram.mShaderGroup = LLGLSLShader::SG_SKY; -		success = gDeferredStarProgram.createShader(NULL, &mWLUniforms); +		success = gDeferredStarProgram.createShader(NULL, NULL);  	}  	if (success) @@ -1957,7 +1923,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));  		gObjectShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));		  		gObjectShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; -		success = gObjectShinyNonIndexedProgram.createShader(NULL, &mShinyUniforms); +		success = gObjectShinyNonIndexedProgram.createShader(NULL, NULL);  	}  	if (success) @@ -1974,7 +1940,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		gObjectShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));  		gObjectShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];  		gObjectShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; -		success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, &mShinyUniforms); +		success = gObjectShinyNonIndexedWaterProgram.createShader(NULL, NULL);  	}  	if (success) @@ -1990,7 +1956,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));  		gObjectFullbrightShinyNonIndexedProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));  		gObjectFullbrightShinyNonIndexedProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; -		success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, &mShinyUniforms); +		success = gObjectFullbrightShinyNonIndexedProgram.createShader(NULL, NULL);  	}  	if (success) @@ -2008,7 +1974,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));  		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];  		gObjectFullbrightShinyNonIndexedWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; -		success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, &mShinyUniforms); +		success = gObjectFullbrightShinyNonIndexedWaterProgram.createShader(NULL, NULL);  	}  	if (success) @@ -2087,12 +2053,11 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		gObjectBumpProgram.mShaderFiles.push_back(make_pair("objects/bumpF.glsl", GL_FRAGMENT_SHADER_ARB));  		gObjectBumpProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];  		success = gObjectBumpProgram.createShader(NULL, NULL); -  		if (success)  		{ //lldrawpoolbump assumes "texture0" has channel 0 and "texture1" has channel 1  			gObjectBumpProgram.bind(); -			gObjectBumpProgram.uniform1i("texture0", 0); -			gObjectBumpProgram.uniform1i("texture1", 1); +			gObjectBumpProgram.uniform1i(sTexture0, 0); +			gObjectBumpProgram.uniform1i(sTexture1, 1);  			gObjectBumpProgram.unbind();  		}  	} @@ -2241,7 +2206,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));  		gObjectShinyProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));		  		gObjectShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; -		success = gObjectShinyProgram.createShader(NULL, &mShinyUniforms); +		success = gObjectShinyProgram.createShader(NULL, NULL);  	}  	if (success) @@ -2258,7 +2223,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		gObjectShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyV.glsl", GL_VERTEX_SHADER_ARB));  		gObjectShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];  		gObjectShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; -		success = gObjectShinyWaterProgram.createShader(NULL, &mShinyUniforms); +		success = gObjectShinyWaterProgram.createShader(NULL, NULL);  	}  	if (success) @@ -2274,7 +2239,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyV.glsl", GL_VERTEX_SHADER_ARB));  		gObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));  		gObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; -		success = gObjectFullbrightShinyProgram.createShader(NULL, &mShinyUniforms); +		success = gObjectFullbrightShinyProgram.createShader(NULL, NULL);  	}  	if (success) @@ -2292,7 +2257,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  		gObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));  		gObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];  		gObjectFullbrightShinyWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER; -		success = gObjectFullbrightShinyWaterProgram.createShader(NULL, &mShinyUniforms); +		success = gObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);  	}  	if (mVertexShaderLevel[SHADER_AVATAR] > 0) @@ -2377,7 +2342,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));  			gSkinnedObjectFullbrightShinyProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyF.glsl", GL_FRAGMENT_SHADER_ARB));  			gSkinnedObjectFullbrightShinyProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; -			success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, &mShinyUniforms); +			success = gSkinnedObjectFullbrightShinyProgram.createShader(NULL, NULL);  		}  		if (success) @@ -2394,7 +2359,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  			gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));  			gSkinnedObjectShinySimpleProgram.mShaderFiles.push_back(make_pair("objects/shinyF.glsl", GL_FRAGMENT_SHADER_ARB));  			gSkinnedObjectShinySimpleProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; -			success = gSkinnedObjectShinySimpleProgram.createShader(NULL, &mShinyUniforms); +			success = gSkinnedObjectShinySimpleProgram.createShader(NULL, NULL);  		}  		if (success) @@ -2451,7 +2416,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  			gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinySkinnedV.glsl", GL_VERTEX_SHADER_ARB));  			gSkinnedObjectFullbrightShinyWaterProgram.mShaderFiles.push_back(make_pair("objects/fullbrightShinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));  			gSkinnedObjectFullbrightShinyWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; -			success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, &mShinyUniforms); +			success = gSkinnedObjectFullbrightShinyWaterProgram.createShader(NULL, NULL);  		}  		if (success) @@ -2470,7 +2435,7 @@ BOOL LLViewerShaderMgr::loadShadersObject()  			gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinySimpleSkinnedV.glsl", GL_VERTEX_SHADER_ARB));  			gSkinnedObjectShinySimpleWaterProgram.mShaderFiles.push_back(make_pair("objects/shinyWaterF.glsl", GL_FRAGMENT_SHADER_ARB));  			gSkinnedObjectShinySimpleWaterProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; -			success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, &mShinyUniforms); +			success = gSkinnedObjectShinySimpleWaterProgram.createShader(NULL, NULL);  		}  	} @@ -2511,7 +2476,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()  		gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarV.glsl", GL_VERTEX_SHADER_ARB));  		gAvatarProgram.mShaderFiles.push_back(make_pair("avatar/avatarF.glsl", GL_FRAGMENT_SHADER_ARB));  		gAvatarProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR]; -		success = gAvatarProgram.createShader(NULL, &mAvatarUniforms); +		success = gAvatarProgram.createShader(NULL, NULL);  		if (success)  		{ @@ -2530,7 +2495,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()  			// Note: no cloth under water:  			gAvatarWaterProgram.mShaderLevel = llmin(mVertexShaderLevel[SHADER_AVATAR], 1);	  			gAvatarWaterProgram.mShaderGroup = LLGLSLShader::SG_WATER;				 -			success = gAvatarWaterProgram.createShader(NULL, &mAvatarUniforms); +			success = gAvatarWaterProgram.createShader(NULL, NULL);  		}  		/// Keep track of avatar levels @@ -2549,7 +2514,7 @@ BOOL LLViewerShaderMgr::loadShadersAvatar()  		gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarV.glsl", GL_VERTEX_SHADER_ARB));  		gAvatarPickProgram.mShaderFiles.push_back(make_pair("avatar/pickAvatarF.glsl", GL_FRAGMENT_SHADER_ARB));  		gAvatarPickProgram.mShaderLevel = mVertexShaderLevel[SHADER_AVATAR]; -		success = gAvatarPickProgram.createShader(NULL, &mAvatarUniforms); +		success = gAvatarPickProgram.createShader(NULL, NULL);  	}  	if (success) @@ -2651,7 +2616,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()  		if (success)  		{  			gSplatTextureRectProgram.bind(); -			gSplatTextureRectProgram.uniform1i("screenMap", 0); +			gSplatTextureRectProgram.uniform1i(sScreenMap, 0);  			gSplatTextureRectProgram.unbind();  		}  	} @@ -2667,8 +2632,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()  		if (success)  		{  			gGlowCombineProgram.bind(); -			gGlowCombineProgram.uniform1i("glowMap", 0); -			gGlowCombineProgram.uniform1i("screenMap", 1); +			gGlowCombineProgram.uniform1i(sGlowMap, 0); +			gGlowCombineProgram.uniform1i(sScreenMap, 1);  			gGlowCombineProgram.unbind();  		}  	} @@ -2684,8 +2649,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()  		if (success)  		{  			gGlowCombineFXAAProgram.bind(); -			gGlowCombineFXAAProgram.uniform1i("glowMap", 0); -			gGlowCombineFXAAProgram.uniform1i("screenMap", 1); +			gGlowCombineFXAAProgram.uniform1i(sGlowMap, 0); +			gGlowCombineFXAAProgram.uniform1i(sScreenMap, 1);  			gGlowCombineFXAAProgram.unbind();  		}  	} @@ -2702,8 +2667,8 @@ BOOL LLViewerShaderMgr::loadShadersInterface()  		if (success)  		{  			gTwoTextureAddProgram.bind(); -			gTwoTextureAddProgram.uniform1i("tex0", 0); -			gTwoTextureAddProgram.uniform1i("tex1", 1); +			gTwoTextureAddProgram.uniform1i(sTex0, 0); +			gTwoTextureAddProgram.uniform1i(sTex1, 1);  		}  	} @@ -2718,7 +2683,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()  		if (success)  		{  			gOneTextureNoColorProgram.bind(); -			gOneTextureNoColorProgram.uniform1i("tex0", 0); +			gOneTextureNoColorProgram.uniform1i(sTex0, 0);  		}  	} @@ -2733,7 +2698,7 @@ BOOL LLViewerShaderMgr::loadShadersInterface()  		if (success)  		{  			gSolidColorProgram.bind(); -			gSolidColorProgram.uniform1i("tex0", 0); +			gSolidColorProgram.uniform1i(sTex0, 0);  			gSolidColorProgram.unbind();  		}  	} @@ -2817,7 +2782,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()  		gWLSkyProgram.mShaderFiles.push_back(make_pair("windlight/skyF.glsl", GL_FRAGMENT_SHADER_ARB));  		gWLSkyProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];  		gWLSkyProgram.mShaderGroup = LLGLSLShader::SG_SKY; -		success = gWLSkyProgram.createShader(NULL, &mWLUniforms); +		success = gWLSkyProgram.createShader(NULL, NULL);  	}  	if (success) @@ -2829,7 +2794,7 @@ BOOL LLViewerShaderMgr::loadShadersWindLight()  		gWLCloudProgram.mShaderFiles.push_back(make_pair("windlight/cloudsF.glsl", GL_FRAGMENT_SHADER_ARB));  		gWLCloudProgram.mShaderLevel = mVertexShaderLevel[SHADER_WINDLIGHT];  		gWLCloudProgram.mShaderGroup = LLGLSLShader::SG_SKY; -		success = gWLCloudProgram.createShader(NULL, &mWLUniforms); +		success = gWLCloudProgram.createShader(NULL, NULL);  	}  	return success; diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index e3d28f2f5c..75173653e6 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -74,56 +74,7 @@ public:  		SHADER_COUNT  	}; -	typedef enum -	{ -		SHINY_ORIGIN = END_RESERVED_UNIFORMS -	} eShinyUniforms; - -	typedef enum -	{ -		WATER_SCREENTEX = END_RESERVED_UNIFORMS, -		WATER_SCREENDEPTH, -		WATER_REFTEX, -		WATER_EYEVEC, -		WATER_TIME, -		WATER_WAVE_DIR1, -		WATER_WAVE_DIR2, -		WATER_LIGHT_DIR, -		WATER_SPECULAR, -		WATER_SPECULAR_EXP, -		WATER_FOGCOLOR, -		WATER_FOGDENSITY, -		WATER_REFSCALE, -		WATER_WATERHEIGHT, -	} eWaterUniforms; - -	typedef enum -	{ -		WL_CAMPOSLOCAL = END_RESERVED_UNIFORMS, -		WL_WATERHEIGHT -	} eWLUniforms; - -	typedef enum -	{ -		TERRAIN_DETAIL0 = END_RESERVED_UNIFORMS, -		TERRAIN_DETAIL1, -		TERRAIN_DETAIL2, -		TERRAIN_DETAIL3, -		TERRAIN_ALPHARAMP -	} eTerrainUniforms; - -	typedef enum -	{ -		GLOW_DELTA = END_RESERVED_UNIFORMS -	} eGlowUniforms; - -	typedef enum -	{ -		AVATAR_MATRIX = END_RESERVED_UNIFORMS, -		AVATAR_WIND, -		AVATAR_SINWAVE, -		AVATAR_GRAVITY, -	} eAvatarUniforms; +	  	// simple model of forward iterator  	// http://www.sgi.com/tech/stl/ForwardIterator.html @@ -176,23 +127,6 @@ public:  	/* virtual */ void updateShaderUniforms(LLGLSLShader * shader);  private: -	 -	std::vector<std::string> mShinyUniforms; - -	//water parameters -	std::vector<std::string> mWaterUniforms; - -	std::vector<std::string> mWLUniforms; - -	//terrain parameters -	std::vector<std::string> mTerrainUniforms; - -	//glow parameters -	std::vector<std::string> mGlowUniforms; - -	std::vector<std::string> mGlowExtractUniforms; - -	std::vector<std::string> mAvatarUniforms;  	// the list of shaders we need to propagate parameters to.  	std::vector<LLGLSLShader *> mShaderList; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index d2af48f528..b70eae791c 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -558,15 +558,17 @@ void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image)  	llassert_always(mInitialized) ;  	llassert(image);  	if (image->isInImageList()) -	{ -		llerrs << "LLViewerTextureList::addImageToList - Image already in list" << llendl; +	{	// Flag is already set? +		llwarns << "LLViewerTextureList::addImageToList - image " << image->getID()  << " already in list" << llendl;  	} -	if((mImageList.insert(image)).second != true)  +	else  	{ -		llerrs << "Error happens when insert image to mImageList!" << llendl ; +		if((mImageList.insert(image)).second != true)  +		{ +			llwarns << "Error happens when insert image " << image->getID()  << " into mImageList!" << llendl ; +		} +		image->setInImageList(TRUE) ;  	} -	 -	image->setInImageList(TRUE) ;  }  void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image) @@ -574,24 +576,46 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)  	assert_main_thread();  	llassert_always(mInitialized) ;  	llassert(image); -	if (!image->isInImageList()) + +	S32 count = 0; +	if (image->isInImageList())  	{ -		llinfos << "RefCount: " << image->getNumRefs() << llendl ; +		count = mImageList.erase(image) ; +		if(count != 1)  +		{ +			llwarns << "Image  " << image->getID()  +				<< " had mInImageList set but mImageList.erase() returned " << count +				<< llendl; +		} +	} +	else +	{	// Something is wrong, image is expected in list or callers should check first +		llwarns << "Calling removeImageFromList() for " << image->getID()  +			<< " but doesn't have mInImageList set" +			<< " ref count is " << image->getNumRefs() +			<< llendl;  		uuid_map_t::iterator iter = mUUIDMap.find(image->getID()); -		if(iter == mUUIDMap.end() || iter->second != image) +		if(iter == mUUIDMap.end())  		{ -			llinfos << "Image is not in mUUIDMap!" << llendl ; +			llwarns << "Image  " << image->getID() << " is also not in mUUIDMap!" << llendl ; +		} +		else if (iter->second != image) +		{ +			llwarns << "Image  " << image->getID() << " was in mUUIDMap but with different pointer" << llendl ; +		} +		else +		{ +			llwarns << "Image  " << image->getID() << " was in mUUIDMap with same pointer" << llendl ; +		} +		count = mImageList.erase(image) ; +		if(count != 0)  +		{	// it was in the list already? +			llwarns << "Image  " << image->getID()  +				<< " had mInImageList false but mImageList.erase() returned " << count +				<< llendl;  		} -		llerrs << "LLViewerTextureList::removeImageFromList - Image not in list" << llendl;  	} -	S32 count = mImageList.erase(image) ; -	if(count != 1)  -	{ -		llinfos << image->getID() << llendl ; -		llerrs << "Error happens when remove image from mImageList: " << count << llendl ; -	} -        	image->setInImageList(FALSE) ;  } @@ -1234,7 +1258,7 @@ S32 LLViewerTextureList::getMinVideoRamSetting()  //static  // Returns max setting for TextureMemory (in MB) -S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended) +S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier)  {  	S32 max_texmem;  	if (gGLManager.mVRAM != 0) @@ -1278,7 +1302,10 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)  		max_texmem = llmin(max_texmem, (S32)(system_ram/2));  	else  		max_texmem = llmin(max_texmem, (S32)(system_ram)); -		 +     +    // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise +	max_texmem = llmin(max_texmem, (S32) (mem_multiplier * (F32) max_texmem)); +  	max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES);   	return max_texmem; @@ -1291,7 +1318,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)  	// Initialize the image pipeline VRAM settings  	S32 cur_mem = gSavedSettings.getS32("TextureMemory");  	F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); -	S32 default_mem = getMaxVideoRamSetting(true); // recommended default +	S32 default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default  	if (mem == 0)  	{  		mem = cur_mem > 0 ? cur_mem : default_mem; @@ -1301,10 +1328,7 @@ void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)  		mem = default_mem;  	} -	// limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise -	mem = llmin(mem, (S32) (mem_multiplier * (F32) default_mem)); - -	mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting()); +	mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier));  	if (mem != cur_mem)  	{  		gSavedSettings.setS32("TextureMemory", mem); diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 136042620d..26dc6dcbe2 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -114,7 +114,7 @@ public:  	void setDebugFetching(LLViewerFetchedTexture* tex, S32 debug_level);  	static S32 getMinVideoRamSetting(); -	static S32 getMaxVideoRamSetting(bool get_recommended = false); +	static S32 getMaxVideoRamSetting(bool get_recommended, float mem_multiplier);  private:  	void updateImagesDecodePriorities(); diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 0475e9fc89..a57679b71e 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -58,6 +58,7 @@  #include "llhudmanager.h"  #include "llhudnametag.h"  #include "llhudtext.h"				// for mText/mDebugText +#include "llimview.h"  #include "llinitparam.h"  #include "llkeyframefallmotion.h"  #include "llkeyframestandmotion.h" @@ -668,6 +669,9 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mSpecialRenderMode(0),  	mAttachmentGeometryBytes(0),  	mAttachmentSurfaceArea(0.f), +	mReportedVisualComplexity(-1), +	mReportedAttachmentGeometryBytes(-1), +	mReportedAttachmentSurfaceArea(-1.f),  	mTurning(FALSE),  	mLastSkeletonSerialNum( 0 ),  	mIsSitting(FALSE), @@ -701,6 +705,8 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mFullyLoaded(FALSE),  	mPreviousFullyLoaded(FALSE),  	mFullyLoadedInitialized(FALSE), +	mVisualComplexity(0), +	mVisualComplexityStale(TRUE),  	mLoadedCallbacksPaused(FALSE),  	mHasPelvisOffset( FALSE ),  	mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar")), @@ -769,6 +775,13 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,  	mLastPelvisToFoot = 0.0f;  	mPelvisFixup = 0.0f;  	mLastPelvisFixup = 0.0f; + +	mCachedVisualMute = !isSelf(); +	mCachedVisualMuteUpdateTime = LLFrameTimer::getTotalSeconds() + 5.0; +	mVisuallyMuteSetting = VISUAL_MUTE_NOT_SET; + +	F32 color_value = (F32) (getID().mData[0]); +	mMutedAVColor = calcMutedAVColor(color_value, 0, 256);  }  std::string LLVOAvatar::avString() const @@ -2971,14 +2984,82 @@ void LLVOAvatar::slamPosition()  	mRoot->updateWorldMatrixChildren();  } -bool LLVOAvatar::isVisuallyMuted() const +bool LLVOAvatar::isVisuallyMuted()  { -	static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); -	static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); -	 -	return LLMuteList::getInstance()->isMuted(getID())  -			|| (mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0)  -			|| (mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f); +	bool muted = false; + +	// Priority order (highest priority first) +	// * own avatar is never visually muted +	// * if on the "always draw normally" list, draw them normally +	// * if on the "always visually mute" list, mute them +	// * draw them normally if they meet the following criteria: +	//       - within the closest N avatars OR on friends list OR in an IM chat +	//       - AND aren't over the thresholds +	// * otherwise visually mute all other avatars + +	if (!isSelf()) +	{ +		static LLCachedControl<bool> render_mute_enabled(gSavedSettings, "RenderAutoMuteEnabled"); +		static LLCachedControl<U32> max_attachment_bytes(gSavedSettings, "RenderAutoMuteByteLimit"); +		static LLCachedControl<F32> max_attachment_area(gSavedSettings, "RenderAutoMuteSurfaceAreaLimit"); +		static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit"); +		static LLCachedControl<U32> visibility_rank(gSavedSettings, "RenderAutoMuteVisibilityRank"); + +		if (mVisuallyMuteSetting == ALWAYS_VISUAL_MUTE) +		{	// Always want to see this AV as an imposter +			muted = true; +		} +		else if (mVisuallyMuteSetting == NEVER_VISUAL_MUTE) +		{	// Never show as imposter +			muted = false; +		} +		else if (render_mute_enabled) +		{ +			F64 now = LLFrameTimer::getTotalSeconds(); + +			if (now < mCachedVisualMuteUpdateTime) +			{	// Use cached mute value +				muted = mCachedVisualMute; +			} +			else +			{	// Determine if visually muted or not + +				U32 max_cost = (U32) (max_render_cost*(LLVOAvatar::sLODFactor+0.5)); + +				muted = LLMuteList::getInstance()->isMuted(getID()) || +					(mAttachmentGeometryBytes > max_attachment_bytes && max_attachment_bytes > 0) || +					(mAttachmentSurfaceArea > max_attachment_area && max_attachment_area > 0.f) || +					(mVisualComplexity > max_cost && max_render_cost > 0); + +				// Could be part of the grand || collection above, but yanked out to make the logic visible +				if (!muted) +				{ +					if (visibility_rank > 0) +					{	// They are above the visibilty rank - mute them +						muted = (mVisibilityRank > visibility_rank); +					} +			 +					if (muted ||					// Don't mute friends or IMs +						visibility_rank == 0) +					{ +						muted = !(LLAvatarTracker::instance().isBuddy(getID())); +						if (muted) +						{	// Not a friend, so they are muted ... are they in an IM? +							LLUUID session_id = gIMMgr->computeSessionID(IM_NOTHING_SPECIAL,getID()); +							muted = !gIMMgr->hasSession(session_id); +						} +					} +				} + +				// Save visual mute state and set interval for updating +				const F64 SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES = 1.5; +				mCachedVisualMuteUpdateTime = now + SECONDS_BETWEEN_RENDER_AUTO_MUTE_UPDATES;		 +				mCachedVisualMute = muted; +			}  +		} +	} + +	return muted;  }  //------------------------------------------------------------------------ @@ -3076,7 +3157,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  	// the rest should only be done occasionally for far away avatars  	//-------------------------------------------------------------------- -	if (visible && (!isSelf() || isVisuallyMuted()) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter) +	bool visually_muted = isVisuallyMuted(); +	if (visible && (!isSelf() || visually_muted) && !mIsDummy && sUseImpostors && !mNeedsAnimUpdate && !sFreezeCounter)  	{  		const LLVector4a* ext = mDrawable->getSpatialExtents();  		LLVector4a size; @@ -3085,8 +3167,8 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent)  		F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f); -		if (isVisuallyMuted()) -		{ // muted avatars update at 16 hz +		if (visually_muted) +		{ // visually muted avatars update at 16 hz  			mUpdatePeriod = 16;  		}  		else if (mVisibilityRank <= LLVOAvatar::sMaxVisible || @@ -3886,9 +3968,11 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  		BOOL first_pass = TRUE;  		if (!LLDrawPoolAvatar::sSkipOpaque)  		{ +			bool visually_muted = isVisuallyMuted(); +  			if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender)  			{ -				if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy) +				if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy || visually_muted)  				{  					LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD);  					if (head_mesh) @@ -3898,7 +3982,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  					first_pass = FALSE;  				}  			} -			if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy) +			if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy || visually_muted)  			{  				LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY);  				if (upper_mesh) @@ -3908,7 +3992,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass)  				first_pass = FALSE;  			} -			if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy) +			if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy || visually_muted)  			{  				LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY);  				if (lower_mesh) @@ -5480,6 +5564,8 @@ const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_o  		return 0;  	} +	mVisualComplexityStale = TRUE; +  	if (viewer_object->isSelected())  	{  		LLSelectMgr::getInstance()->updateSelectionCenter(); @@ -5627,6 +5713,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object)  		if (attachment->isObjectAttached(viewer_object))  		{ +			mVisualComplexityStale = TRUE;  			cleanupAttachedMesh( viewer_object );  			attachment->removeObject(viewer_object);  			lldebugs << "Detaching object " << viewer_object->mID << " from " << attachment->getName() << llendl; @@ -7725,9 +7812,9 @@ void LLVOAvatar::updateImpostors()  	LLCharacter::sAllowInstancesChange = TRUE ;  } -BOOL LLVOAvatar::isImpostor() const +BOOL LLVOAvatar::isImpostor()  { -	return (isVisuallyMuted() || (sUseImpostors && mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE; +	return sUseImpostors && (isVisuallyMuted() || (mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE;  } @@ -7770,135 +7857,224 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d  	angle.mV[2] = da;  } +  void LLVOAvatar::idleUpdateRenderCost()  { -	static const U32 ARC_BODY_PART_COST = 200; -	static const U32 ARC_LIMIT = 20000; +	static LLCachedControl<U32> max_render_cost(gSavedSettings, "RenderAutoMuteRenderCostLimit"); -	static std::set<LLUUID> all_textures; +	static const U32 ARC_LIMIT = 20000;  	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_ATTACHMENT_BYTES))  	{ //set debug text to attachment geometry bytes here so render cost will override  		setDebugText(llformat("%.1f KB, %.2f m^2", mAttachmentGeometryBytes/1024.f, mAttachmentSurfaceArea));  	} -	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) +	if (!gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME) && max_render_cost == 0)  	{  		return;  	} -	U32 cost = 0; -	LLVOVolume::texture_cost_t textures; +	calculateUpdateRenderCost();				// Update mVisualComplexity if needed +	 +	doRenderCostNagging(max_render_cost);		// Remind the user their AV is too complex -	for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) +	if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHAME)) +	{ +		std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); +		setDebugText(llformat("%s %d", viz_string.c_str(), mVisualComplexity)); +		F32 green = 1.f-llclamp(((F32) mVisualComplexity-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); +		F32 red = llmin((F32) mVisualComplexity/(F32)ARC_LIMIT, 1.f); +		mText->setColor(LLColor4(red,green,0,1)); +	} +} + + +// Remind the user about their expensive avatar +void LLVOAvatar::doRenderCostNagging(U32 max_render_cost) +{ +	if (isSelf())  	{ -		const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); -		ETextureIndex tex_index = baked_dict->mTextureIndex; -		if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT))) +		static S32 sOldComplexity = 0; +		static F64 sLastRenderCostNagTime = 0.0; + +		const F64 RENDER_NAG_INTERVAL = 60.0; + +		F64 now = LLFrameTimer::getTotalSeconds(); +		if (sLastRenderCostNagTime > 0.0 && +			(now - sLastRenderCostNagTime) > RENDER_NAG_INTERVAL && +			sOldComplexity != mVisualComplexity)  		{ -			if (isTextureVisible(tex_index)) -			{ -				cost +=ARC_BODY_PART_COST; +			sOldComplexity = mVisualComplexity; + +			if (max_render_cost > 0) +			{ //pop up notification that you have exceeded a render cost limit +				if (mVisualComplexity > max_render_cost+max_render_cost/2) +				{ +					LLNotificationsUtil::add("ExceededHighDetailRenderCost"); +					sLastRenderCostNagTime = now; +				} +				else if (mVisualComplexity > max_render_cost) +				{ +					LLNotificationsUtil::add("ExceededMidDetailRenderCost"); +					sLastRenderCostNagTime = now; +				} +				else if (mVisualComplexity > max_render_cost/2) +				{ +					LLNotificationsUtil::add("ExceededLowDetailRenderCost"); +					sLastRenderCostNagTime = now; +				}  			}  		}  	} +} -	for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();  -		 iter != mAttachmentPoints.end(); -		 ++iter) +// Calculations for mVisualComplexity value +void LLVOAvatar::calculateUpdateRenderCost() +{ +	static const U32 ARC_BODY_PART_COST = 200; + +	// Diagnostic list of all textures on our avatar +	static std::set<LLUUID> all_textures; + +	if (mVisualComplexityStale)  	{ -		LLViewerJointAttachment* attachment = iter->second; -		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); -			 attachment_iter != attachment->mAttachedObjects.end(); -			 ++attachment_iter) +		mVisualComplexityStale = FALSE; +		U32 cost = 0; +		LLVOVolume::texture_cost_t textures; + +		for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++)  		{ -			const LLViewerObject* attached_object = (*attachment_iter); -			if (attached_object && !attached_object->isHUDAttachment()) +		    const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); +			ETextureIndex tex_index = baked_dict->mTextureIndex; +			if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT)))  			{ -				textures.clear(); -				const LLDrawable* drawable = attached_object->mDrawable; -				if (drawable) +				if (isTextureVisible(tex_index))  				{ -					const LLVOVolume* volume = drawable->getVOVolume(); -					if (volume) -					{ -						cost += volume->getRenderCost(textures); +					cost +=ARC_BODY_PART_COST; +				} +			} +		} + -						const_child_list_t children = volume->getChildren(); -						for (const_child_list_t::const_iterator child_iter = children.begin(); -							  child_iter != children.end(); -							  ++child_iter) +		for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();  +			 iter != 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) +			{ +				const LLViewerObject* attached_object = (*attachment_iter); +				if (attached_object && !attached_object->isHUDAttachment()) +				{ +					textures.clear(); +					const LLDrawable* drawable = attached_object->mDrawable; +					if (drawable) +					{ +						const LLVOVolume* volume = drawable->getVOVolume(); +						if (volume)  						{ -							LLViewerObject* child_obj = *child_iter; -							LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj ); -							if (child) +							cost += volume->getRenderCost(textures); + +							const_child_list_t children = volume->getChildren(); +							for (const_child_list_t::const_iterator child_iter = children.begin(); +								  child_iter != children.end(); +								  ++child_iter)  							{ -								cost += child->getRenderCost(textures); +								LLViewerObject* child_obj = *child_iter; +								LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj ); +								if (child) +								{ +									cost += child->getRenderCost(textures); +								}  							} -						} -						for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) -						{ -							// add the cost of each individual texture in the linkset -							cost += iter->second; +							for (LLVOVolume::texture_cost_t::iterator iter = textures.begin(); iter != textures.end(); ++iter) +							{ +								// add the cost of each individual texture in the linkset +								cost += iter->second; +							}  						}  					}  				}  			} -		} - -	} - +		} -	// Diagnostic output to identify all avatar-related textures. -	// Does not affect rendering cost calculation. -	// Could be wrapped in a debug option if output becomes problematic. -	if (isSelf()) -	{ -		// print any attachment textures we didn't already know about. -		for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it) +		// Diagnostic output to identify all avatar-related textures. +		// Does not affect rendering cost calculation. +		// Could be wrapped in a debug option if output becomes problematic. +		if (isSelf())  		{ -			LLUUID image_id = it->first; -			if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) -				continue; -			if (all_textures.find(image_id) == all_textures.end()) +			// print any attachment textures we didn't already know about. +			for (LLVOVolume::texture_cost_t::iterator it = textures.begin(); it != textures.end(); ++it)  			{ -				// attachment texture not previously seen. -				llinfos << "attachment_texture: " << image_id.asString() << llendl; -				all_textures.insert(image_id); +				LLUUID image_id = it->first; +				if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) +					continue; +				if (all_textures.find(image_id) == all_textures.end()) +				{ +					// attachment texture not previously seen. +					llinfos << "attachment_texture: " << image_id.asString() << llendl; +					all_textures.insert(image_id); +				}  			} -		} -		// print any avatar textures we didn't already know about -		for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); +			// print any avatar textures we didn't already know about +		    for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin();  			 iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); -			 ++iter) -		{ -			const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; -			// TODO: MULTI-WEARABLE: handle multiple textures for self -			const LLViewerTexture* te_image = getImage(iter->first,0); -			if (!te_image) -				continue; -			LLUUID image_id = te_image->getID(); -			if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) -				continue; -			if (all_textures.find(image_id) == all_textures.end()) +				 ++iter)  			{ -				llinfos << "local_texture: " << texture_dict->mName << ": " << image_id << llendl; -				all_textures.insert(image_id); +			    const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; +				// TODO: MULTI-WEARABLE: handle multiple textures for self +				const LLViewerTexture* te_image = getImage(iter->first,0); +				if (!te_image) +					continue; +				LLUUID image_id = te_image->getID(); +				if( image_id.isNull() || image_id == IMG_DEFAULT || image_id == IMG_DEFAULT_AVATAR) +					continue; +				if (all_textures.find(image_id) == all_textures.end()) +				{ +					llinfos << "local_texture: " << texture_dict->mName << ": " << image_id << llendl; +					all_textures.insert(image_id); +				}  			}  		} + +		mVisualComplexity = cost;  	} +} -	 -	std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); -	setDebugText(llformat("%s %d", viz_string.c_str(), cost)); -	mVisualComplexity = cost; -	F32 green = 1.f-llclamp(((F32) cost-(F32)ARC_LIMIT)/(F32)ARC_LIMIT, 0.f, 1.f); -	F32 red = llmin((F32) cost/(F32)ARC_LIMIT, 1.f); -	mText->setColor(LLColor4(red,green,0,1)); + +// static +LLColor4 LLVOAvatar::calcMutedAVColor(F32 value, S32 range_low, S32 range_high) +{ +	F32 clamped_value = llmin(value, (F32) range_high); +	clamped_value = llmax(value, (F32) range_low); +	F32 spectrum = (clamped_value / range_high);		// spectrum is between 0 and 1.f + +	// Array of colors.  These are arranged so only one RGB color changes between each step,  +	// and it loops back to red so there is an even distribution.  It is not a heat map +	const S32 NUM_SPECTRUM_COLORS = 7;               +	static LLColor4 * spectrum_color[NUM_SPECTRUM_COLORS] = { &LLColor4::red, &LLColor4::magenta, &LLColor4::blue, &LLColor4::cyan, &LLColor4::green, &LLColor4::yellow, &LLColor4::red }; +  +	spectrum = spectrum * (NUM_SPECTRUM_COLORS - 1);		// Scale to range of number of colors +	S32 spectrum_index_1  = floor(spectrum);				// Desired color will be after this index +	S32 spectrum_index_2  = spectrum_index_1 + 1;			//    and before this index (inclusive) +	F32 fractBetween = spectrum - (F32)(spectrum_index_1);  // distance between the two indexes (0-1) +  +	LLColor4 new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween); +	new_color.normalize(); +	new_color *= 0.9f; + +	//llinfos << "From value " << std::setprecision(3) << value << " returning color " << new_color  +	//	<< " using indexes " << spectrum_index_1 << ", " << spectrum_index_2 +	//	<< " and fractBetween " << fractBetween +	//	<< llendl; + +	return new_color;  }  // static diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 85f6f25009..8862056066 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -250,6 +250,25 @@ public:  	static void		invalidateNameTags();  	void			addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font);  	void 			idleUpdateRenderCost(); +	void			doRenderCostNagging(U32 max_render_cost); +	void			calculateUpdateRenderCost(); +	void			updateVisualComplexity() { mVisualComplexityStale = TRUE; } +	 +	S32				getVisualComplexity()			{ return mVisualComplexity;				};		// Numbers calculated here by rendering AV +	S32				getAttachmentGeometryBytes()	{ return mAttachmentGeometryBytes;		};		// number of bytes in attached geometry +	F32				getAttachmentSurfaceArea()		{ return mAttachmentSurfaceArea;		};		// estimated surface area of attachments + +	S32				getReportedVisualComplexity()					{ return mReportedVisualComplexity;				};	// Numbers as reported by the SL server +	void			setReportedVisualComplexity(S32 value)			{ mReportedVisualComplexity = value;			}; +	S32				getReportedAttachmentGeometryBytes()			{ return mReportedAttachmentGeometryBytes;		};	//number of bytes in attached geometry +	void			setReportedAttachmentGeometryBytes(S32 value)	{ mReportedAttachmentGeometryBytes = value;		}; +	F32				getReportedAttachmentSurfaceArea()		{ return mReportedAttachmentSurfaceArea;				};		//estimated surface area of attachments +	void			setReportedAttachmentSurfaceArea(F32 value)		{ mReportedAttachmentSurfaceArea = value;		}; +	 +	S32				getUpdatePeriod()				{ return mUpdatePeriod;			}; +	const LLColor4 &  getMutedAVColor()				{ return mMutedAVColor;			}; + +  	void 			idleUpdateBelowWater();  	//-------------------------------------------------------------------- @@ -303,12 +322,15 @@ public:  	static void 	logPendingPhasesAllAvatars();  	void 			logMetricsTimerRecord(const std::string& phase_name, F32 elapsed, bool completed); +	static LLColor4 calcMutedAVColor(F32 value, S32 range_low, S32 range_high); +  protected:  	LLViewerStats::PhaseMap& getPhases() { return mPhases; }  	BOOL			updateIsFullyLoaded();  	BOOL			processFullyLoadedChange(bool loading);  	void			updateRuthTimer(bool loading);  	F32 			calcMorphAmount(); +  private:  	BOOL			mFirstFullyVisible;  	BOOL			mFullyLoaded; @@ -316,6 +338,8 @@ private:  	BOOL			mFullyLoadedInitialized;  	S32				mFullyLoadedFrameCounter;  	S32				mVisualComplexity; +	BOOL			mVisualComplexityStale; +	LLColor4		mMutedAVColor;  	LLFrameTimer	mFullyLoadedTimer;  	LLFrameTimer	mRuthTimer; @@ -369,7 +393,16 @@ public:  public:  	U32 		renderImpostor(LLColor4U color = LLColor4U(255,255,255,255), S32 diffuse_channel = 0); -	bool		isVisuallyMuted() const; +	bool		isVisuallyMuted(); + +	enum VisualMuteSettings +	{ +		VISUAL_MUTE_NOT_SET = 0, +		ALWAYS_VISUAL_MUTE  = 1, +		NEVER_VISUAL_MUTE   = 2 +	}; +	void		setVisualMuteSettings(VisualMuteSettings set)		{ mVisuallyMuteSetting = set;	}; +	VisualMuteSettings  getVisualMuteSettings()						{ return mVisuallyMuteSetting;	};  	U32 		renderRigid();  	U32 		renderSkinned(EAvatarRenderPass pass); @@ -380,9 +413,13 @@ public:  	static void	destroyGL();  	static void	restoreGL();  	S32			mSpecialRenderMode; // special lighting -	U32			mAttachmentGeometryBytes; //number of bytes in attached geometry +	S32			mAttachmentGeometryBytes; //number of bytes in attached geometry  	F32			mAttachmentSurfaceArea; //estimated surface area of attachments +	S32			mReportedVisualComplexity;			// Numbers as reported by the SL server +	S32			mReportedAttachmentGeometryBytes;	//number of bytes in attached geometry +	F32			mReportedAttachmentSurfaceArea;		//estimated surface area of attachments +  private:  	bool		shouldAlphaMask(); @@ -392,6 +429,11 @@ private:  	S32	 		mUpdatePeriod;  	S32  		mNumInitFaces; //number of faces generated when creating the avatar drawable, does not inculde splitted faces due to long vertex buffer. +	bool		mCachedVisualMute;				// cached return value for isVisuallyMuted() +	F64			mCachedVisualMuteUpdateTime;	// Time to update mCachedVisualMute + +	VisualMuteSettings		mVisuallyMuteSetting;			// Always or never visually mute this AV +  	//--------------------------------------------------------------------  	// Morph masks  	//-------------------------------------------------------------------- @@ -430,7 +472,7 @@ private:  	// Impostors  	//--------------------------------------------------------------------  public: -	BOOL 		isImpostor() const; +	BOOL 		isImpostor();  	BOOL 	    needsImpostorUpdate() const;  	const LLVector3& getImpostorOffset() const;  	const LLVector2& getImpostorDim() const; diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 6a25b765cf..f40d55161f 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -476,6 +476,7 @@ void LLVOGrass::getGeometry(S32 idx,  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp)  {  	if(!mNumBlades)//stop rendering grass @@ -708,7 +709,11 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group)  		facep->setIndicesIndex(index_count);  		facep->setVertexBuffer(buffer);  		facep->setPoolType(LLDrawPool::POOL_ALPHA); -		object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + +		//dummy parameter (unused by this implementation) +		LLStrider<LLColor4U> emissivep; + +		object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, emissivep, indicesp);  		vertex_count += facep->getGeomCount();  		index_count += facep->getIndicesCount(); diff --git a/indra/newview/llvograss.h b/indra/newview/llvograss.h index b9835b8802..1fe9990cea 100644 --- a/indra/newview/llvograss.h +++ b/indra/newview/llvograss.h @@ -63,6 +63,7 @@ public:  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp);  	void updateFaceSize(S32 idx) { } diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index e67e2ab7f4..99b3accda8 100644 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -49,17 +49,11 @@ const F32 MAX_PART_LIFETIME = 120.f;  extern U64 gFrameTime;  LLPointer<LLVertexBuffer> LLVOPartGroup::sVB = NULL; -S32 LLVOPartGroup::sVBSlotFree[]; -S32* LLVOPartGroup::sVBSlotCursor = NULL; +S32 LLVOPartGroup::sVBSlotCursor = 0;  void LLVOPartGroup::initClass()  { -	for (S32 i = 0; i < LL_MAX_PARTICLE_COUNT; ++i) -	{ -		sVBSlotFree[i] = i; -	} - -	sVBSlotCursor = sVBSlotFree; +	  }  //static @@ -122,36 +116,33 @@ void LLVOPartGroup::destroyGL()  //static  S32 LLVOPartGroup::findAvailableVBSlot()  { -	if (sVBSlotCursor >= sVBSlotFree+LL_MAX_PARTICLE_COUNT) +	if (sVBSlotCursor >= LL_MAX_PARTICLE_COUNT)  	{ //no more available slots  		return -1;  	} -	S32 ret = *sVBSlotCursor; -	sVBSlotCursor++; - -	return ret; +	return sVBSlotCursor++;  }  bool ll_is_part_idx_allocated(S32 idx, S32* start, S32* end)  { -	while (start < end) +	/*while (start < end)  	{  		if (*start == idx)  		{ //not allocated (in free list)  			return false;  		}  		++start; -	} +	}*/  	//allocated (not in free list) -	return true; +	return false;  }  //static  void LLVOPartGroup::freeVBSlot(S32 idx)  { -	llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0); +	/*llassert(idx < LL_MAX_PARTICLE_COUNT && idx >= 0);  	//llassert(sVBSlotCursor > sVBSlotFree);  	//llassert(ll_is_part_idx_allocated(idx, sVBSlotCursor, sVBSlotFree+LL_MAX_PARTICLE_COUNT)); @@ -159,7 +150,7 @@ void LLVOPartGroup::freeVBSlot(S32 idx)  	{  		sVBSlotCursor--;  		*sVBSlotCursor = idx; -	} +	}*/  }  LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) @@ -189,6 +180,7 @@ F32 LLVOPartGroup::getBinRadius()  void LLVOPartGroup::updateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)  {		  	const LLVector3& pos_agent = getPositionAgent(); +  	newMin.load3( (pos_agent - mScale).mV);  	newMax.load3( (pos_agent + mScale).mV);  	LLVector4a pos; @@ -273,6 +265,16 @@ F32 LLVOPartGroup::getPartSize(S32 idx)  	return 0.f;  } +void LLVOPartGroup::getBlendFunc(S32 idx, U32& src, U32& dst) +{ +	if (idx < (S32) mViewerPartGroupp->mParticles.size()) +	{ +		LLViewerPart* part = mViewerPartGroupp->mParticles[idx]; +		src = part->mBlendFuncSource; +		dst = part->mBlendFuncDest; +	} +} +  LLVector3 LLVOPartGroup::getCameraPosition() const  {  	return gAgentCamera.getCameraPositionAgent(); @@ -332,13 +334,42 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)  	mDepth = 0.f;  	S32 i = 0 ;  	LLVector3 camera_agent = getCameraPosition(); +	 +	F32 max_scale = 0.f; + +  	for (i = 0 ; i < (S32)mViewerPartGroupp->mParticles.size(); i++)  	{  		const LLViewerPart *part = mViewerPartGroupp->mParticles[i]; + +		//remember the largest particle +		max_scale = llmax(max_scale, part->mScale.mV[0], part->mScale.mV[1]); + +		if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK) +		{ //include ribbon segment length in scale +			const LLVector3* pos_agent = NULL; +			if (part->mParent) +			{ +				pos_agent = &(part->mParent->mPosAgent); +			} +			else if (part->mPartSourcep.notNull()) +			{ +				pos_agent = &(part->mPartSourcep->mPosAgent); +			} + +			if (pos_agent) +			{ +				F32 dist = (*pos_agent-part->mPosAgent).length(); + +				max_scale = llmax(max_scale, dist); +			} +		} +  		LLVector3 part_pos_agent(part->mPosAgent);  		LLVector3 at(part_pos_agent - camera_agent); +		  		F32 camera_dist_squared = at.lengthSquared();  		F32 inv_camera_dist_squared;  		if (camera_dist_squared > 1.f) @@ -411,6 +442,9 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable)  		facep->setSize(0, 0);  	} +	//record max scale (used to stretch bounding box for visibility culling) +	mScale.set(max_scale, max_scale, max_scale); +  	mDrawable->movePartition();  	LLPipeline::sCompiles++;  	return TRUE; @@ -478,74 +512,129 @@ BOOL LLVOPartGroup::lineSegmentIntersect(const LLVector3& start, const LLVector3  void LLVOPartGroup::getGeometry(const LLViewerPart& part,  								LLStrider<LLVector4a>& verticesp)  { -	LLVector4a part_pos_agent; -	part_pos_agent.load3(part.mPosAgent.mV); -	LLVector4a camera_agent; -	camera_agent.load3(getCameraPosition().mV);  -	LLVector4a at; -	at.setSub(part_pos_agent, camera_agent); -	LLVector4a up(0, 0, 1); -	LLVector4a right; - -	right.setCross3(at, up); -	right.normalize3fast(); -	up.setCross3(right, at); -	up.normalize3fast(); - -	if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK) +	if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK)  	{ -		LLVector4a normvel; -		normvel.load3(part.mVelocity.mV); -		normvel.normalize3fast(); -		LLVector2 up_fracs; -		up_fracs.mV[0] = normvel.dot3(right).getF32(); -		up_fracs.mV[1] = normvel.dot3(up).getF32(); -		up_fracs.normalize(); -		LLVector4a new_up; -		LLVector4a new_right; - -		//new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up; -		LLVector4a t = right; -		t.mul(up_fracs.mV[0]); -		new_up = up; -		new_up.mul(up_fracs.mV[1]); -		new_up.add(t); - -		//new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up; -		t = right; -		t.mul(up_fracs.mV[1]); -		new_right = up; -		new_right.mul(up_fracs.mV[0]); -		t.sub(new_right); - -		up = new_up; -		right = t; -		up.normalize3fast(); -		right.normalize3fast(); +		LLVector4a axis, pos, paxis, ppos; +		F32 scale, pscale; + +		pos.load3(part.mPosAgent.mV); +		axis.load3(part.mAxis.mV); +		scale = part.mScale.mV[0]; +		 +		if (part.mParent) +		{ +			ppos.load3(part.mParent->mPosAgent.mV); +			paxis.load3(part.mParent->mAxis.mV); +			pscale = part.mParent->mScale.mV[0]; +		} +		else +		{ //use source object as position +			 +			if (part.mPartSourcep->mSourceObjectp.notNull()) +			{ +				LLVector3 v = LLVector3(0,0,1); +				v *= part.mPartSourcep->mSourceObjectp->getRenderRotation(); +				paxis.load3(v.mV); +				ppos.load3(part.mPartSourcep->mPosAgent.mV); +				pscale = part.mStartScale.mV[0]; +			} +			else +			{ //no source object, no parent, nothing to draw +				ppos = pos; +				pscale = scale; +				paxis = axis; +			} +		} + +		LLVector4a p0, p1, p2, p3; + +		scale *= 0.5f; +		pscale *= 0.5f; + +		axis.mul(scale); +		paxis.mul(pscale); + +		p0.setAdd(pos, axis); +		p1.setSub(pos,axis); +		p2.setAdd(ppos, paxis); +		p3.setSub(ppos, paxis); + +		(*verticesp++) = p2; +		(*verticesp++) = p3; +		(*verticesp++) = p0; +		(*verticesp++) = p1;  	} +	else +	{ +		LLVector4a part_pos_agent; +		part_pos_agent.load3(part.mPosAgent.mV); +		LLVector4a camera_agent; +		camera_agent.load3(getCameraPosition().mV);  +		LLVector4a at; +		at.setSub(part_pos_agent, camera_agent); +		LLVector4a up(0, 0, 1); +		LLVector4a right; + +		right.setCross3(at, up); +		right.normalize3fast(); +		up.setCross3(right, at); +		up.normalize3fast(); -	right.mul(0.5f*part.mScale.mV[0]); -	up.mul(0.5f*part.mScale.mV[1]); +		if (part.mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK) +		{ +			LLVector4a normvel; +			normvel.load3(part.mVelocity.mV); +			normvel.normalize3fast(); +			LLVector2 up_fracs; +			up_fracs.mV[0] = normvel.dot3(right).getF32(); +			up_fracs.mV[1] = normvel.dot3(up).getF32(); +			up_fracs.normalize(); +			LLVector4a new_up; +			LLVector4a new_right; + +			//new_up = up_fracs.mV[0] * right + up_fracs.mV[1]*up; +			LLVector4a t = right; +			t.mul(up_fracs.mV[0]); +			new_up = up; +			new_up.mul(up_fracs.mV[1]); +			new_up.add(t); + +			//new_right = up_fracs.mV[1] * right - up_fracs.mV[0]*up; +			t = right; +			t.mul(up_fracs.mV[1]); +			new_right = up; +			new_right.mul(up_fracs.mV[0]); +			t.sub(new_right); + +			up = new_up; +			right = t; +			up.normalize3fast(); +			right.normalize3fast(); +		} +		right.mul(0.5f*part.mScale.mV[0]); +		up.mul(0.5f*part.mScale.mV[1]); -	//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) -	// this works because there is actually a 4th float stored after the vertex position which is used as a texture index -	// also, somebody please VECTORIZE THIS -	LLVector4a ppapu; -	LLVector4a ppamu; +		//HACK -- the verticesp->mV[3] = 0.f here are to set the texture index to 0 (particles don't use texture batching, maybe they should) +		// this works because there is actually a 4th float stored after the vertex position which is used as a texture index +		// also, somebody please VECTORIZE THIS -	ppapu.setAdd(part_pos_agent, up); -	ppamu.setSub(part_pos_agent, up); +		LLVector4a ppapu; +		LLVector4a ppamu; -	verticesp->setSub(ppapu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; -	verticesp->setSub(ppamu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; -	verticesp->setAdd(ppapu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; -	verticesp->setAdd(ppamu, right); -	(*verticesp++).getF32ptr()[3] = 0.f; +		ppapu.setAdd(part_pos_agent, up); +		ppamu.setSub(part_pos_agent, up); + +		verticesp->setSub(ppapu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +		verticesp->setSub(ppamu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +		verticesp->setAdd(ppapu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +		verticesp->setAdd(ppamu, right); +		(*verticesp++).getF32ptr()[3] = 0.f; +	}  } @@ -555,6 +644,7 @@ void LLVOPartGroup::getGeometry(S32 idx,  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp)  {  	if (idx >= (S32) mViewerPartGroupp->mParticles.size()) @@ -566,10 +656,40 @@ void LLVOPartGroup::getGeometry(S32 idx,  	getGeometry(part, verticesp); -	*colorsp++ = part.mColor; -	*colorsp++ = part.mColor; -	*colorsp++ = part.mColor; -	*colorsp++ = part.mColor; +	LLColor4U pcolor; +	LLColor4U color = part.mColor; + +	LLColor4U pglow; + +	if (part.mFlags & LLPartData::LL_PART_RIBBON_MASK) +	{ //make sure color blends properly +		if (part.mParent) +		{ +			pglow = part.mParent->mGlow; +			pcolor = part.mParent->mColor; +		} +		else  +		{ +			pglow = LLColor4U(0, 0, 0, (U8) (255.f*part.mStartGlow)); +			pcolor = part.mStartColor; +		} +	} +	else +	{ +		pglow = part.mGlow; +		pcolor = color; +	} + +	*colorsp++ = pcolor; +	*colorsp++ = pcolor; +	*colorsp++ = color; +	*colorsp++ = color; + +	*emissivep++ = pglow; +	*emissivep++ = pglow; +	*emissivep++ = part.mGlow; +	*emissivep++ = part.mGlow; +  	if (!(part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK))  	{ //not fullbright, needs normal @@ -712,10 +832,13 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  	LLStrider<LLVector3> normalsp;  	LLStrider<LLVector2> texcoordsp;  	LLStrider<LLColor4U> colorsp; +	LLStrider<LLColor4U> emissivep;  	buffer->getVertexStrider(verticesp);  	buffer->getNormalStrider(normalsp);  	buffer->getColorStrider(colorsp); +	buffer->getEmissiveStrider(emissivep); +  	LLSpatialGroup::drawmap_elem_t& draw_vec = group->mDrawMap[mRenderPass];	 @@ -724,7 +847,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		LLFace* facep = *i;  		LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); -		if (!facep->isState(LLFace::PARTICLE)) +		//if (!facep->isState(LLFace::PARTICLE))  		{ //set the indices of this face  			S32 idx = LLVOPartGroup::findAvailableVBSlot();  			if (idx >= 0) @@ -733,7 +856,7 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  				facep->setIndicesIndex(idx*6);  				facep->setVertexBuffer(LLVOPartGroup::sVB);  				facep->setPoolType(LLDrawPool::POOL_ALPHA); -				facep->setState(LLFace::PARTICLE); +				//facep->setState(LLFace::PARTICLE);  			}  			else  			{ @@ -748,8 +871,9 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		LLStrider<LLVector3> cur_norm = normalsp + geom_idx;  		LLStrider<LLVector2> cur_tc = texcoordsp + geom_idx;  		LLStrider<LLColor4U> cur_col = colorsp + geom_idx; +		LLStrider<LLColor4U> cur_glow = emissivep + geom_idx; -		object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_idx); +		object->getGeometry(facep->getTEOffset(), cur_vert, cur_norm, cur_tc, cur_col, cur_glow, cur_idx);  		llassert(facep->getGeomCount() == 4);  		llassert(facep->getIndicesCount() == 6); @@ -765,9 +889,16 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  		bool batched = false; +		U32 bf_src = LLRender::BF_SOURCE_ALPHA; +		U32 bf_dst = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; + +		object->getBlendFunc(facep->getTEOffset(), bf_src, bf_dst); +  		if (idx >= 0 &&  			draw_vec[idx]->mTexture == facep->getTexture() && -			draw_vec[idx]->mFullbright == fullbright) +			draw_vec[idx]->mFullbright == fullbright && +			draw_vec[idx]->mBlendFuncDst == bf_dst && +			draw_vec[idx]->mBlendFuncSrc == bf_src)  		{  			if (draw_vec[idx]->mEnd == facep->getGeomIndex()-1)  			{ @@ -799,6 +930,8 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group)  			info->mExtents[0] = group->mObjectExtents[0];  			info->mExtents[1] = group->mObjectExtents[1];  			info->mVSize = vsize; +			info->mBlendFuncDst = bf_dst; +			info->mBlendFuncSrc = bf_src;  			draw_vec.push_back(info);  			//for alpha sorting  			facep->setDrawInfo(info); diff --git a/indra/newview/llvopartgroup.h b/indra/newview/llvopartgroup.h index ce05a0282e..3c2e0344a2 100644 --- a/indra/newview/llvopartgroup.h +++ b/indra/newview/llvopartgroup.h @@ -42,8 +42,7 @@ public:  	//vertex buffer for holding all particles  	static LLPointer<LLVertexBuffer> sVB; -	static S32 sVBSlotFree[LL_MAX_PARTICLE_COUNT]; -	static S32* sVBSlotCursor; +	static S32 sVBSlotCursor;  	static void initClass();  	static void restoreGL(); @@ -57,6 +56,7 @@ public:  							LLVertexBuffer::MAP_NORMAL |  							LLVertexBuffer::MAP_TEXCOORD0 |  							LLVertexBuffer::MAP_COLOR | +							LLVertexBuffer::MAP_EMISSIVE |  							LLVertexBuffer::MAP_TEXTURE_INDEX  	}; @@ -91,10 +91,12 @@ public:  								LLStrider<LLVector3>& normalsp,   								LLStrider<LLVector2>& texcoordsp,  								LLStrider<LLColor4U>& colorsp,  +								LLStrider<LLColor4U>& emissivep,  								LLStrider<U16>& indicesp);  	void updateFaceSize(S32 idx) { }  	F32 getPartSize(S32 idx); +	void getBlendFunc(S32 idx, U32& src, U32& dst);  	LLUUID getPartOwner(S32 idx);  	LLUUID getPartSource(S32 idx); diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index cac6d4939b..00a109546e 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -99,6 +99,8 @@ static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles");  static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");  static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures"); +extern BOOL gGLDebugLoggingEnabled; +  // Implementation class of LLMediaDataClientObject.  See llmediadataclient.h  class LLMediaDataClientObjectImpl : public LLMediaDataClientObject  { @@ -382,7 +384,6 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  	}  	else  	{ -		// CORY TO DO: Figure out how to get the value here  		if (update_type != OUT_TERSE_IMPROVED)  		{  			LLVolumeParams volume_params; @@ -451,6 +452,11 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,  				mFaceMappingChanged = TRUE;  				mTexAnimMode = 0;  			} + +			if (value & 0x400) +			{ //particle system (new) +				unpackParticleSource(*dp, mOwnerID, false); +			}  		}  		else  		{ @@ -1049,8 +1055,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  				}  			}  		} - - +		  		static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback");  		bool cache_in_vram = use_transform_feedback && gTransformPositionProgram.mProgramObject && @@ -1067,7 +1072,9 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo  					break;  				}  				volume->genBinormals(i); +				//gGLDebugLoggingEnabled = TRUE;  				LLFace::cacheFaceInVRAM(face); +				//gGLDebugLoggingEnabled = FALSE;  			}  		} @@ -1116,6 +1123,12 @@ void LLVOVolume::notifyMeshLoaded()  {   	mSculptChanged = TRUE;  	gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); + +	LLVOAvatar* avatar = getAvatar(); +	if (avatar) +	{ +		avatar->updateVisualComplexity(); +	}  }  // sculpt replaces generate() for sculpted surfaces @@ -1144,28 +1157,38 @@ void LLVOVolume::sculpt()  		S32 current_discard = getVolume()->getSculptLevel() ;  		if(current_discard < -2)  		{ -			static S32 low_sculpty_discard_warning_count = 100; -			if (++low_sculpty_discard_warning_count >= 100) -			{	// Log first time, then every 100 afterwards otherwise this can flood the logs +			static S32 low_sculpty_discard_warning_count = 1; +			S32 exponent = llmax(1, llfloor( log10((F64) low_sculpty_discard_warning_count) )); +			S32 interval = pow(10.0, exponent); +			if ( low_sculpty_discard_warning_count < 10 || +				(low_sculpty_discard_warning_count % interval) == 0) +			{	// Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs  				llwarns << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID()   					<< " at " << current_discard  -					<< " is less than -2." << llendl; -				low_sculpty_discard_warning_count = 0; +					<< " is less than -2."  +					<< " Hit this " << low_sculpty_discard_warning_count << " times" +					<< llendl;  			} +			low_sculpty_discard_warning_count++;  			// corrupted volume... don't update the sculpty  			return;  		}  		else if (current_discard > MAX_DISCARD_LEVEL)  		{ -			static S32 high_sculpty_discard_warning_count = 100; -			if (++high_sculpty_discard_warning_count >= 100) -			{	// Log first time, then every 100 afterwards otherwise this can flood the logs +			static S32 high_sculpty_discard_warning_count = 1; +			S32 exponent = llmax(1, llfloor( log10((F64) high_sculpty_discard_warning_count) )); +			S32 interval = pow(10.0, exponent); +			if ( high_sculpty_discard_warning_count < 10 || +				(high_sculpty_discard_warning_count % interval) == 0) +			{	// Log first 10 time, then decreasing intervals afterwards otherwise this can flood the logs  				llwarns << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID()   					<< " at " << current_discard  -					<< " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl; -				high_sculpty_discard_warning_count = 0; +					<< " is more than than allowed max of " << MAX_DISCARD_LEVEL +					<< ".  Hit this " << high_sculpty_discard_warning_count << " times" +					<< llendl;  			} +			high_sculpty_discard_warning_count++;  			// corrupted volume... don't update the sculpty			  			return; @@ -1258,7 +1281,7 @@ BOOL LLVOVolume::calcLOD()  	else  	{  		distance = mDrawable->mDistanceWRTCamera; -		radius = getVolume()->mLODScaleBias.scaledVec(getScale()).length(); +		radius = getVolume() ? getVolume()->mLODScaleBias.scaledVec(getScale()).length() : getScale().length();  	}  	//hold onto unmodified distance for debugging @@ -1288,7 +1311,7 @@ BOOL LLVOVolume::calcLOD()  	{  		//setDebugText(llformat("%.2f:%.2f, %d", debug_distance, radius, cur_detail)); -		setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex())); +		//setDebugText(llformat("%d", mDrawable->getFace(0)->getTextureIndex()));  	}  	if (cur_detail != mLOD) @@ -2980,7 +3003,7 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p  		//transform view vector into volume space  		view_vector -= getRenderPosition(); -		mDrawable->mDistanceWRTCamera = view_vector.length(); +		//mDrawable->mDistanceWRTCamera = view_vector.length();  		LLQuaternion worldRot = getRenderRotation();  		view_vector = view_vector * ~worldRot;  		if (!isVolumeGlobal()) @@ -3836,10 +3859,13 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  	}  	//build matrix palette -	LLMatrix4a mp[64]; +	static const size_t kMaxJoints = 64; + +	LLMatrix4a mp[kMaxJoints];  	LLMatrix4* mat = (LLMatrix4*) mp; -	for (U32 j = 0; j < skin->mJointNames.size(); ++j) +	U32 maxJoints = llmin(skin->mJointNames.size(), kMaxJoints); +	for (U32 j = 0; j < maxJoints; ++j)  	{  		LLJoint* joint = avatar->getJoint(skin->mJointNames[j]);  		if (joint) @@ -3894,8 +3920,10 @@ void LLRiggedVolume::update(const LLMeshSkinInfo* skin, LLVOAvatar* avatar, cons  						F32 w = wght[k];  						LLMatrix4a src; -						src.setMul(mp[idx[k]], w); - +						// Insure ref'd bone is in our clamped array of mats +						llassert(idx[k] < kMaxJoints); +						// clamp k to kMaxJoints to avoid reading garbage off stack in release +						src.setMul(mp[idx[(k < kMaxJoints) ? k : 0]], w);  						final_mat.add(src);  					} @@ -4214,7 +4242,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	if (pAvatarVO)  	{  		pAvatarVO->mAttachmentGeometryBytes -= group->mGeometryBytes; +		pAvatarVO->mAttachmentGeometryBytes = llmax(pAvatarVO->mAttachmentGeometryBytes, 0);  		pAvatarVO->mAttachmentSurfaceArea -= group->mSurfaceArea; +		pAvatarVO->mAttachmentSurfaceArea = llmax(pAvatarVO->mAttachmentSurfaceArea, 0.f);  	}  	group->mGeometryBytes = 0; @@ -4227,11 +4257,20 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	mFaceList.clear(); -	std::vector<LLFace*> fullbright_faces; -	std::vector<LLFace*> bump_faces; -	std::vector<LLFace*> simple_faces; +	const U32 MAX_FACE_COUNT = 4096; +	 +	static LLFace** fullbright_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); +	static LLFace** bump_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); +	static LLFace** simple_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); +	static LLFace** alpha_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); +	 +	U32 fullbright_count = 0; +	U32 bump_count = 0; +	U32 simple_count = 0; +	U32 alpha_count = 0; -	std::vector<LLFace*> alpha_faces; + +	  	U32 useage = group->mSpatialPartition->mBufferUsage;  	U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); @@ -4242,6 +4281,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	bool emissive = false; +	 +  	{  		LLFastTimer t(FTM_REBUILD_VOLUME_FACE_LIST); @@ -4543,7 +4584,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  					{  						if (facep->canRenderAsMask())  						{ //can be treated as alpha mask -							simple_faces.push_back(facep); +							if (simple_count < MAX_FACE_COUNT) +							{ +								simple_faces[simple_count++] = facep; +							}  						}  						else  						{ @@ -4551,7 +4595,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  							{ //only treat as alpha in the pipeline if < 100% transparent  								drawablep->setState(LLDrawable::HAS_ALPHA);  							} -							alpha_faces.push_back(facep); +							if (alpha_count < MAX_FACE_COUNT) +							{ +								alpha_faces[alpha_count++] = facep; +							}  						}  					}  					else @@ -4566,33 +4613,51 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  						{  							if (te->getBumpmap())  							{ //needs normal + binormal -								bump_faces.push_back(facep); +								if (bump_count < MAX_FACE_COUNT) +								{ +									bump_faces[bump_count++] = facep; +								}  							}  							else if (te->getShiny() || !te->getFullbright())  							{ //needs normal -								simple_faces.push_back(facep); +								if (simple_count < MAX_FACE_COUNT) +								{ +									simple_faces[simple_count++] = facep; +								}  							}  							else   							{ //doesn't need normal  								facep->setState(LLFace::FULLBRIGHT); -								fullbright_faces.push_back(facep); +								if (fullbright_count < MAX_FACE_COUNT) +								{ +									fullbright_faces[fullbright_count++] = facep; +								}  							}  						}  						else  						{  							if (te->getBumpmap() && LLPipeline::sRenderBump)  							{ //needs normal + binormal -								bump_faces.push_back(facep); +								if (bump_count < MAX_FACE_COUNT) +								{ +									bump_faces[bump_count++] = facep; +								}  							}  							else if ((te->getShiny() && LLPipeline::sRenderBump) ||  								!(te->getFullbright() || bake_sunlight))  							{ //needs normal -								simple_faces.push_back(facep); +								if (simple_count < MAX_FACE_COUNT) +								{ +									simple_faces[simple_count++] = facep; +								}  							}  							else   							{ //doesn't need normal  								facep->setState(LLFace::FULLBRIGHT); -								fullbright_faces.push_back(facep); +								if (fullbright_count < MAX_FACE_COUNT) +								{ +									fullbright_faces[fullbright_count++] = facep; +								}  							}  						}  					} @@ -4642,17 +4707,17 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	if (batch_textures)  	{  		bump_mask |= LLVertexBuffer::MAP_BINORMAL; -		genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, FALSE, TRUE); -		genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, FALSE, TRUE); -		genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, FALSE, TRUE); -		genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, TRUE, TRUE); +		genDrawInfo(group, simple_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, simple_faces, simple_count, FALSE, TRUE); +		genDrawInfo(group, fullbright_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, fullbright_faces, fullbright_count, FALSE, TRUE); +		genDrawInfo(group, bump_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, bump_faces, bump_count, FALSE, FALSE); +		genDrawInfo(group, alpha_mask | LLVertexBuffer::MAP_TEXTURE_INDEX, alpha_faces, alpha_count, TRUE, TRUE);  	}  	else  	{ -		genDrawInfo(group, simple_mask, simple_faces); -		genDrawInfo(group, fullbright_mask, fullbright_faces); -		genDrawInfo(group, bump_mask, bump_faces, FALSE, TRUE); -		genDrawInfo(group, alpha_mask, alpha_faces, TRUE); +		genDrawInfo(group, simple_mask, simple_faces, simple_count); +		genDrawInfo(group, fullbright_mask, fullbright_faces, fullbright_count); +		genDrawInfo(group, bump_mask, bump_faces, bump_count,  FALSE, FALSE); +		genDrawInfo(group, alpha_mask, alpha_faces, alpha_count, TRUE);  	} @@ -4684,6 +4749,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)  	}  } +static LLFastTimer::DeclareTimer FTM_REBUILD_MESH_FLUSH("Flush Mesh");  void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  { @@ -4693,11 +4759,14 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  		LLFastTimer ftm(FTM_REBUILD_VOLUME_VB);  		LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers -		S32 num_mapped_veretx_buffer = LLVertexBuffer::sMappedCount ; -  		group->mBuilt = 1.f; -		std::set<LLVertexBuffer*> mapped_buffers; +		S32 num_mapped_vertex_buffer = LLVertexBuffer::sMappedCount ; + +		const U32 MAX_BUFFER_COUNT = 4096; +		LLVertexBuffer* locked_buffer[MAX_BUFFER_COUNT]; + +		U32 buffer_count = 0;  		for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter)  		{ @@ -4707,7 +4776,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  			{  				LLVOVolume* vobj = drawablep->getVOVolume();  				vobj->preRebuild(); - +				  				if (drawablep->isState(LLDrawable::ANIMATED_CHILD))  				{  					vobj->updateRelativeXform(true); @@ -4732,9 +4801,9 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  							} -							if (buff->isLocked()) +							if (buff->isLocked() && buffer_count < MAX_BUFFER_COUNT)  							{ -								mapped_buffers.insert(buff); +								locked_buffer[buffer_count++] = buff;  							}  						}  					} @@ -4750,21 +4819,24 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)  			}  		} -		for (std::set<LLVertexBuffer*>::iterator iter = mapped_buffers.begin(); iter != mapped_buffers.end(); ++iter) -		{ -			(*iter)->flush(); -		} - -		// don't forget alpha -		if(group != NULL &&  -		   !group->mVertexBuffer.isNull() &&  -		   group->mVertexBuffer->isLocked())  		{ -			group->mVertexBuffer->flush(); +			LLFastTimer t(FTM_REBUILD_MESH_FLUSH); +			for (LLVertexBuffer** iter = locked_buffer, ** end_iter = locked_buffer+buffer_count; iter != end_iter; ++iter) +			{ +				(*iter)->flush(); +			} +		 +			// don't forget alpha +			if(group != NULL &&  +			   !group->mVertexBuffer.isNull() &&  +			   group->mVertexBuffer->isLocked()) +			{ +				group->mVertexBuffer->flush(); +			}  		}  		//if not all buffers are unmapped -		if(num_mapped_veretx_buffer != LLVertexBuffer::sMappedCount)  +		if(num_mapped_vertex_buffer != LLVertexBuffer::sMappedCount)   		{  			llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ;   			for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) @@ -4824,12 +4896,22 @@ static LLFastTimer::DeclareTimer FTM_GEN_DRAW_INFO_RESIZE_VB("Resize VB"); -void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::vector<LLFace*>& faces, BOOL distance_sort, BOOL batch_textures) +void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort, BOOL batch_textures)  {  	LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO);  	U32 buffer_usage = group->mBufferUsage; +	static LLCachedControl<bool> use_transform_feedback(gSavedSettings, "RenderUseTransformFeedback"); + +	if (use_transform_feedback && +		gTransformPositionProgram.mProgramObject && //transform shaders are loaded +		buffer_usage == GL_DYNAMIC_DRAW_ARB && //target buffer is in VRAM +		!(mask & LLVertexBuffer::MAP_WEIGHT4)) //TODO: add support for weights +	{ +		buffer_usage = GL_DYNAMIC_COPY_ARB; +	} +  #if LL_DARWIN  	// HACK from Leslie:  	// Disable VBO usage for alpha on Mac OS X because it kills the framerate @@ -4850,17 +4932,18 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  		if (!distance_sort)  		{  			//sort faces by things that break batches -			std::sort(faces.begin(), faces.end(), CompareBatchBreakerModified()); +			std::sort(faces, faces+face_count, CompareBatchBreakerModified());  		}  		else  		{  			//sort faces by distance -			std::sort(faces.begin(), faces.end(), LLFace::CompareDistanceGreater()); +			std::sort(faces, faces+face_count, LLFace::CompareDistanceGreater());  		}  	}  	bool hud_group = group->isHUDGroup() ; -	std::vector<LLFace*>::iterator face_iter = faces.begin(); +	LLFace** face_iter = faces; +	LLFace** end_faces = faces+face_count;  	LLSpatialGroup::buffer_map_t buffer_map; @@ -4889,7 +4972,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  	//NEVER use more than 16 texture index channels (workaround for prevalent driver bug)  	texture_index_channels = llmin(texture_index_channels, 16); -	while (face_iter != faces.end()) +	bool flexi = false; + +	while (face_iter != end_faces)  	{  		//pull off next face  		LLFace* facep = *face_iter; @@ -4915,11 +5000,16 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  		U32 index_count = facep->getIndicesCount();  		U32 geom_count = facep->getGeomCount(); +		flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); +  		//sum up vertices needed for this render batch -		std::vector<LLFace*>::iterator i = face_iter; +		LLFace** i = face_iter;  		++i; -		std::vector<LLViewerTexture*> texture_list; +		const U32 MAX_TEXTURE_COUNT = 32; +		LLViewerTexture* texture_list[MAX_TEXTURE_COUNT]; +		 +		U32 texture_count = 0;  		{  			LLFastTimer t(FTM_GEN_DRAW_INFO_FACE_SIZE); @@ -4927,12 +5017,15 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  			{  				U8 cur_tex = 0;  				facep->setTextureIndex(cur_tex); -				texture_list.push_back(tex); - +				if (texture_count < MAX_TEXTURE_COUNT) +				{ +					texture_list[texture_count++] = tex; +				} +				  				if (can_batch_texture(facep))  				{ //populate texture_list with any textures that can be batched  				  //move i to the next unbatchable face -					while (i != faces.end()) +					while (i != end_faces)  					{  						facep = *i; @@ -4947,7 +5040,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  							if (distance_sort)  							{ //textures might be out of order, see if texture exists in current batch  								bool found = false; -								for (U32 tex_idx = 0; tex_idx < texture_list.size(); ++tex_idx) +								for (U32 tex_idx = 0; tex_idx < texture_count; ++tex_idx)  								{  									if (facep->getTexture() == texture_list[tex_idx])  									{ @@ -4959,7 +5052,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  								if (!found)  								{ -									cur_tex = texture_list.size(); +									cur_tex = texture_count;  								}  							}  							else @@ -4974,7 +5067,10 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  							tex = facep->getTexture(); -							texture_list.push_back(tex); +							if (texture_count < MAX_TEXTURE_COUNT) +							{ +								texture_list[texture_count++] = tex; +							}  						}  						if (geom_count + facep->getGeomCount() > max_vertices) @@ -4983,6 +5079,9 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  						}  						++i; + +						flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); +  						index_count += facep->getIndicesCount();  						geom_count += facep->getGeomCount(); @@ -4994,7 +5093,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  			}  			else  			{ -				while (i != faces.end() &&  +				while (i != end_faces &&   					(LLPipeline::sTextureBindTest || (distance_sort || (*i)->getTexture() == tex)))  				{  					facep = *i; @@ -5012,8 +5111,16 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::  					++i;  					index_count += facep->getIndicesCount();  					geom_count += facep->getGeomCount(); + +					flexi = flexi || facep->getViewerObject()->getVolume()->isUnique(); +				}  				}  			} + + +		if (flexi && buffer_usage && buffer_usage != GL_STREAM_DRAW_ARB) +		{ +			buffer_usage = GL_STREAM_DRAW_ARB;  		}  		//create vertex buffer diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp index 4f52ff9778..548890b5b5 100644 --- a/indra/newview/llwaterparammanager.cpp +++ b/indra/newview/llwaterparammanager.cpp @@ -188,13 +188,11 @@ void LLWaterParamManager::updateShaderUniforms(LLGLSLShader * shader)  	if (shader->mShaderGroup == LLGLSLShader::SG_WATER)  	{  		shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, LLWLParamManager::getInstance()->getRotatedLightDir().mV); -		shader->uniform3fv("camPosLocal", 1, LLViewerCamera::getInstance()->getOrigin().mV); -		shader->uniform4fv("waterFogColor", 1, LLDrawPoolWater::sWaterFogColor.mV); -		shader->uniform1f("waterFogEnd", LLDrawPoolWater::sWaterFogEnd); -		shader->uniform4fv("waterPlane", 1, mWaterPlane.mV); -		shader->uniform1f("waterFogDensity", getFogDensity()); -		shader->uniform1f("waterFogKS", mWaterFogKS); -		shader->uniform1f("distance_multiplier", 0); +		shader->uniform4fv(LLShaderMgr::WATER_FOGCOLOR, 1, LLDrawPoolWater::sWaterFogColor.mV); +		shader->uniform4fv(LLShaderMgr::WATER_WATERPLANE, 1, mWaterPlane.mV); +		shader->uniform1f(LLShaderMgr::WATER_FOGDENSITY, getFogDensity()); +		shader->uniform1f(LLShaderMgr::WATER_FOGKS, mWaterFogKS); +		shader->uniform1f(LLViewerShaderMgr::DISTANCE_MULTIPLIER, 0);  	}  } diff --git a/indra/newview/llwaterparamset.h b/indra/newview/llwaterparamset.h index b28585af59..368cb0ccba 100644 --- a/indra/newview/llwaterparamset.h +++ b/indra/newview/llwaterparamset.h @@ -33,6 +33,7 @@  #include "v4math.h"  #include "v4color.h"  #include "llviewershadermgr.h" +#include "llstringtable.h"  class LLWaterParamSet; @@ -47,6 +48,9 @@ public:  private:  	LLSD mParamValues; +	std::vector<LLStaticHashedString> mParamHashedNames; + +	void updateHashedNames();  public: @@ -140,6 +144,17 @@ inline void LLWaterParamSet::setAll(const LLSD& val)  			mParamValues[mIt->first] = mIt->second;  		}  	} +	updateHashedNames(); +} + +inline void LLWaterParamSet::updateHashedNames() +{ +	mParamHashedNames.clear(); +	// Iterate through values +	for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter) +	{ +		mParamHashedNames.push_back(LLStaticHashedString(iter->first)); +	}  }  inline const LLSD& LLWaterParamSet::getAll() diff --git a/indra/newview/llwlanimator.h b/indra/newview/llwlanimator.h index 5223b45343..810f4cf7e5 100644 --- a/indra/newview/llwlanimator.h +++ b/indra/newview/llwlanimator.h @@ -137,3 +137,4 @@ private:  };  #endif // LL_WL_ANIMATOR_H + diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp index 6077208799..04d41a2512 100644 --- a/indra/newview/llwlparammanager.cpp +++ b/indra/newview/llwlparammanager.cpp @@ -352,7 +352,7 @@ void LLWLParamManager::updateShaderUniforms(LLGLSLShader * shader)  	if (shader->mShaderGroup == LLGLSLShader::SG_DEFAULT)  	{  		shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, mRotatedLightDir.mV); -		shader->uniform3fv("camPosLocal", 1, LLViewerCamera::getInstance()->getOrigin().mV); +		shader->uniform3fv(LLShaderMgr::WL_CAMPOSLOCAL, 1, LLViewerCamera::getInstance()->getOrigin().mV);  	}   	else if (shader->mShaderGroup == LLGLSLShader::SG_SKY) @@ -360,7 +360,7 @@ void LLWLParamManager::updateShaderUniforms(LLGLSLShader * shader)  		shader->uniform4fv(LLViewerShaderMgr::LIGHTNORM, 1, mClampedLightDir.mV);  	} -	shader->uniform1f("scene_light_strength", mSceneLightStrength); +	shader->uniform1f(LLShaderMgr::SCENE_LIGHT_STRENGTH, mSceneLightStrength);  } diff --git a/indra/newview/llwlparammanager.h b/indra/newview/llwlparammanager.h index 72422500fc..e13aed98ed 100644 --- a/indra/newview/llwlparammanager.h +++ b/indra/newview/llwlparammanager.h @@ -412,3 +412,4 @@ inline LLVector4 LLWLParamManager::getRotatedLightDir(void) const  }  #endif + diff --git a/indra/newview/llwlparamset.cpp b/indra/newview/llwlparamset.cpp index b04d30db55..b307f19e8a 100644 --- a/indra/newview/llwlparamset.cpp +++ b/indra/newview/llwlparamset.cpp @@ -38,6 +38,22 @@  #include <sstream> +static LLStaticHashedString sStarBrightness("star_brightness"); +static LLStaticHashedString sPresetNum("preset_num"); +static LLStaticHashedString sSunAngle("sun_angle"); +static LLStaticHashedString sEastAngle("east_angle"); +static LLStaticHashedString sEnableCloudScroll("enable_cloud_scroll"); +static LLStaticHashedString sCloudScrollRate("cloud_scroll_rate"); +static LLStaticHashedString sLightNorm("lightnorm"); +static LLStaticHashedString sCloudDensity("cloud_pos_density1"); +static LLStaticHashedString sCloudScale("cloud_scale"); +static LLStaticHashedString sCloudShadow("cloud_shadow"); +static LLStaticHashedString sDensityMultiplier("density_multiplier"); +static LLStaticHashedString sDistanceMultiplier("distance_multiplier"); +static LLStaticHashedString sHazeDensity("haze_density"); +static LLStaticHashedString sHazeHorizon("haze_horizon"); +static LLStaticHashedString sMaxY("max_y"); +  LLWLParamSet::LLWLParamSet(void) :  	mName("Unnamed Preset"),  	mCloudScrollXOffset(0.f), mCloudScrollYOffset(0.f)	 @@ -48,21 +64,24 @@ static LLFastTimer::DeclareTimer FTM_WL_PARAM_UPDATE("WL Param Update");  void LLWLParamSet::update(LLGLSLShader * shader) const   {	  	LLFastTimer t(FTM_WL_PARAM_UPDATE); - -	for(LLSD::map_const_iterator i = mParamValues.beginMap(); -		i != mParamValues.endMap(); -		++i) +	LLSD::map_const_iterator i = mParamValues.beginMap(); +	std::vector<LLStaticHashedString>::const_iterator n = mParamHashedNames.begin(); +	for(;(i != mParamValues.endMap()) && (n != mParamHashedNames.end());++i, n++)  	{ -		const std::string& param = i->first; +		const LLStaticHashedString& param = *n; -		if (param == "star_brightness" || param == "preset_num" || param == "sun_angle" || -			param == "east_angle" || param == "enable_cloud_scroll" || -			param == "cloud_scroll_rate" || param == "lightnorm" )  +		// check that our pre-hashed names are still tracking the mParamValues map correctly +		// +		llassert(param.String() == i->first); + +		if (param == sStarBrightness || param == sPresetNum || param == sSunAngle || +			param == sEastAngle || param == sEnableCloudScroll || +			param == sCloudScrollRate || param == sLightNorm )   		{  			continue;  		} -		if (param == "cloud_pos_density1") +		if (param == sCloudDensity)  		{  			LLVector4 val;  			val.mV[0] = F32(i->second[0].asReal()) + mCloudScrollXOffset; @@ -74,10 +93,10 @@ void LLWLParamSet::update(LLGLSLShader * shader) const  			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" ) +		else if (param == sCloudScale || param == sCloudShadow || +				 param == sDensityMultiplier || param == sDistanceMultiplier || +				 param == sHazeDensity || param == sHazeHorizon || +				 param == sMaxY )  		{  			F32 val = (F32) i->second[0].asReal(); @@ -378,3 +397,14 @@ void LLWLParamSet::updateCloudScrolling(void)  		mCloudScrollYOffset += F32(delta_t * (getCloudScrollY() - 10.f) / 100.f);  	}  } + +void LLWLParamSet::updateHashedNames() +{ +	mParamHashedNames.clear(); +	// Iterate through values +	for(LLSD::map_iterator iter = mParamValues.beginMap(); iter != mParamValues.endMap(); ++iter) +	{ +		mParamHashedNames.push_back(LLStaticHashedString(iter->first)); +	} +} + diff --git a/indra/newview/llwlparamset.h b/indra/newview/llwlparamset.h index b087119dd5..6e5f1d3a4b 100644 --- a/indra/newview/llwlparamset.h +++ b/indra/newview/llwlparamset.h @@ -29,9 +29,11 @@  #include <string>  #include <map> +#include <vector>  #include "v4math.h"  #include "v4color.h" +#include "llstaticstringtable.h"  class LLWLParamSet;  class LLGLSLShader; @@ -47,9 +49,12 @@ public:  private:  	LLSD mParamValues; -	 +	std::vector<LLStaticHashedString> mParamHashedNames; +  	float mCloudScrollXOffset, mCloudScrollYOffset; +	void updateHashedNames(); +  public:  	LLWLParamSet(); @@ -177,6 +182,8 @@ inline void LLWLParamSet::setAll(const LLSD& val)  	if(val.isMap()) {  		mParamValues = val;  	} + +	updateHashedNames();  }  inline const LLSD& LLWLParamSet::getAll() @@ -236,3 +243,4 @@ inline F32 LLWLParamSet::getCloudScrollY() {  #endif // LL_WLPARAM_SET_H + diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 1940cf541e..ae334d4bd2 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -1792,3 +1792,5 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask )  	}  	return FALSE;  } + + diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 340291159c..442c3ef124 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -254,6 +254,17 @@ LLFastTimer::DeclareTimer FTM_RENDER_DEFERRED("Deferred Shading");  static LLFastTimer::DeclareTimer FTM_STATESORT_DRAWABLE("Sort Drawables");  static LLFastTimer::DeclareTimer FTM_STATESORT_POSTSORT("Post Sort"); +static LLStaticHashedString sTint("tint"); +static LLStaticHashedString sAmbiance("ambiance"); +static LLStaticHashedString sAlphaScale("alpha_scale"); +static LLStaticHashedString sNormMat("norm_mat"); +static LLStaticHashedString sOffset("offset"); +static LLStaticHashedString sScreenRes("screenRes"); +static LLStaticHashedString sDelta("delta"); +static LLStaticHashedString sDistFactor("dist_factor"); +static LLStaticHashedString sKern("kern"); +static LLStaticHashedString sKernScale("kern_scale"); +  //----------------------------------------  std::string gPoolNames[] =   { @@ -2864,7 +2875,7 @@ void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera)  					llassert(vobj); // trying to catch a bad assumption  					if (vobj) // this test may not be needed, see above  					{ -						const LLVOAvatar* av = vobj->asAvatar(); +						LLVOAvatar* av = vobj->asAvatar();  						if (av && av->isImpostor())  						{  							return; @@ -4634,9 +4645,9 @@ void LLPipeline::renderDebug()  					if (LLGLSLShader::sNoFixedFunction)  					{					  						gPathfindingProgram.bind();			 -						gPathfindingProgram.uniform1f("tint", 1.f); -						gPathfindingProgram.uniform1f("ambiance", 1.f); -						gPathfindingProgram.uniform1f("alpha_scale", 1.f); +						gPathfindingProgram.uniform1f(sTint, 1.f); +						gPathfindingProgram.uniform1f(sAmbiance, 1.f); +						gPathfindingProgram.uniform1f(sAlphaScale, 1.f);  					}  					//Requried character physics capsule render parameters @@ -4653,7 +4664,7 @@ void LLPipeline::renderDebug()  							llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot );				  							gGL.setColorMask(true, false);  							LLGLEnable blend(GL_BLEND); -							gPathfindingProgram.uniform1f("alpha_scale", 0.90f); +							gPathfindingProgram.uniform1f(sAlphaScale, 0.90f);  							llPathingLibInstance->renderSimpleShapeCapsuleID( gGL, id, pos, rot );  							gPathfindingProgram.bind();  						} @@ -4680,9 +4691,9 @@ void LLPipeline::renderDebug()  					{					  						gPathfindingProgram.bind(); -						gPathfindingProgram.uniform1f("tint", 1.f); -						gPathfindingProgram.uniform1f("ambiance", ambiance); -						gPathfindingProgram.uniform1f("alpha_scale", 1.f); +						gPathfindingProgram.uniform1f(sTint, 1.f); +						gPathfindingProgram.uniform1f(sAmbiance, ambiance); +						gPathfindingProgram.uniform1f(sAlphaScale, 1.f);  					}  					if ( !pathfindingConsole->isRenderWorld() ) @@ -4706,7 +4717,7 @@ void LLPipeline::renderDebug()  						if ( pathfindingConsole->isRenderWorld() )  						{					  							LLGLEnable blend(GL_BLEND); -							gPathfindingProgram.uniform1f("alpha_scale", 0.66f); +							gPathfindingProgram.uniform1f(sAlphaScale, 0.66f);  							llPathingLibInstance->renderNavMesh();  						}  						else @@ -4718,8 +4729,8 @@ void LLPipeline::renderDebug()  						if (LLGLSLShader::sNoFixedFunction)  						{  							gPathfindingNoNormalsProgram.bind(); -							gPathfindingNoNormalsProgram.uniform1f("tint", 1.f); -							gPathfindingNoNormalsProgram.uniform1f("alpha_scale", 1.f); +							gPathfindingNoNormalsProgram.uniform1f(sTint, 1.f); +							gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, 1.f);  							llPathingLibInstance->renderNavMeshEdges();  							gPathfindingProgram.bind();  						} @@ -4759,7 +4770,7 @@ void LLPipeline::renderDebug()  							gGL.setColorMask(true, false);  							//render the bookends  							LLGLEnable blend(GL_BLEND); -							gPathfindingProgram.uniform1f("alpha_scale", 0.90f); +							gPathfindingProgram.uniform1f(sAlphaScale, 0.90f);  							llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_START );  							llPathingLibInstance->renderPathBookend( gGL, LLPathingLib::LLPL_END );  							gPathfindingProgram.bind(); @@ -4777,7 +4788,7 @@ void LLPipeline::renderDebug()  						if (LLGLSLShader::sNoFixedFunction)  						{  							LLGLEnable blend(GL_BLEND); -							gPathfindingProgram.uniform1f("alpha_scale", 0.90f); +							gPathfindingProgram.uniform1f(sAlphaScale, 0.90f);  							llPathingLibInstance->renderSimpleShapes( gGL, gAgent.getRegion()->getWaterHeight() );  						}  						else @@ -4825,7 +4836,7 @@ void LLPipeline::renderDebug()  							LLGLEnable blend(GL_BLEND);  							{ -								gPathfindingProgram.uniform1f("ambiance", ambiance); +								gPathfindingProgram.uniform1f(sAmbiance, ambiance);  								{ //draw solid overlay  									LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_LEQUAL); @@ -4840,8 +4851,8 @@ void LLPipeline::renderDebug()  								if (pathfindingConsole->isRenderXRay())  								{ -									gPathfindingProgram.uniform1f("tint", gSavedSettings.getF32("PathfindingXRayTint")); -									gPathfindingProgram.uniform1f("alpha_scale", gSavedSettings.getF32("PathfindingXRayOpacity")); +									gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); +									gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity"));  									LLGLEnable blend(GL_BLEND);  									LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_GREATER); @@ -4849,13 +4860,13 @@ void LLPipeline::renderDebug()  									if (gSavedSettings.getBOOL("PathfindingXRayWireframe"))  									{ //draw hidden wireframe as darker and less opaque -										gPathfindingProgram.uniform1f("ambiance", 1.f); +										gPathfindingProgram.uniform1f(sAmbiance, 1.f);  										llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] );				  									}  									else  									{  										glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );	 -										gPathfindingProgram.uniform1f("ambiance", ambiance); +										gPathfindingProgram.uniform1f(sAmbiance, ambiance);  										llPathingLibInstance->renderNavMeshShapesVBO( render_order[i] );				  										glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);  									} @@ -4863,9 +4874,9 @@ void LLPipeline::renderDebug()  								{ //draw visible wireframe as brighter, thicker and more opaque  									glPolygonOffset(offset, offset); -									gPathfindingProgram.uniform1f("ambiance", 1.f); -									gPathfindingProgram.uniform1f("tint", 1.f); -									gPathfindingProgram.uniform1f("alpha_scale", 1.f); +									gPathfindingProgram.uniform1f(sAmbiance, 1.f); +									gPathfindingProgram.uniform1f(sTint, 1.f); +									gPathfindingProgram.uniform1f(sAlphaScale, 1.f);  									glLineWidth(gSavedSettings.getF32("PathfindingLineWidth"));  									LLGLDisable blendOut(GL_BLEND); @@ -4897,19 +4908,19 @@ void LLPipeline::renderDebug()  						glLineWidth(2.0f);	  						LLGLEnable cull(GL_CULL_FACE); -						gPathfindingProgram.uniform1f("tint", gSavedSettings.getF32("PathfindingXRayTint")); -						gPathfindingProgram.uniform1f("alpha_scale", gSavedSettings.getF32("PathfindingXRayOpacity")); +						gPathfindingProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); +						gPathfindingProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity"));  						if (gSavedSettings.getBOOL("PathfindingXRayWireframe"))  						{ //draw hidden wireframe as darker and less opaque  							glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );	 -							gPathfindingProgram.uniform1f("ambiance", 1.f); +							gPathfindingProgram.uniform1f(sAmbiance, 1.f);  							llPathingLibInstance->renderNavMesh();  							glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );	  						}	  						else  						{ -							gPathfindingProgram.uniform1f("ambiance", ambiance); +							gPathfindingProgram.uniform1f(sAmbiance, ambiance);  							llPathingLibInstance->renderNavMesh();  						} @@ -4917,8 +4928,8 @@ void LLPipeline::renderDebug()  						if (LLGLSLShader::sNoFixedFunction)  						{  							gPathfindingNoNormalsProgram.bind(); -							gPathfindingNoNormalsProgram.uniform1f("tint", gSavedSettings.getF32("PathfindingXRayTint")); -							gPathfindingNoNormalsProgram.uniform1f("alpha_scale", gSavedSettings.getF32("PathfindingXRayOpacity")); +							gPathfindingNoNormalsProgram.uniform1f(sTint, gSavedSettings.getF32("PathfindingXRayTint")); +							gPathfindingNoNormalsProgram.uniform1f(sAlphaScale, gSavedSettings.getF32("PathfindingXRayOpacity"));  							llPathingLibInstance->renderNavMeshEdges();  							gPathfindingProgram.bind();  						} @@ -7273,7 +7284,11 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)  				else  				{  					//focus on alt-zoom target -					focus_point = LLVector3(gAgentCamera.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal()); +					LLViewerRegion* region = gAgent.getRegion(); +					if (region) +					{ +						focus_point = LLVector3(gAgentCamera.getFocusGlobal()-region->getOriginGlobal()); +					}  				}  			} @@ -7880,13 +7895,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, U32 n  	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"); @@ -7995,9 +8003,8 @@ void LLPipeline::renderDeferredLighting()  					}  				} -				gDeferredSunProgram.uniform3fv("offset", slice, offset); -				gDeferredSunProgram.uniform2f("screenRes", mDeferredLight.getWidth(), mDeferredLight.getHeight()); -				 +				gDeferredSunProgram.uniform3fv(sOffset, slice, offset); +								  				{  					LLGLDisable blend(GL_BLEND);  					LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS); @@ -8040,10 +8047,10 @@ void LLPipeline::renderDeferredLighting()  				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)); +			gDeferredBlurLightProgram.uniform2f(sDelta, 1.f, 0.f); +			gDeferredBlurLightProgram.uniform1f(sDistFactor, dist_factor); +			gDeferredBlurLightProgram.uniform3fv(sKern, kern_length, gauss[0].mV); +			gDeferredBlurLightProgram.uniform1f(sKernScale, blur_size * (kern_length/2.f - 0.5f));  			{  				LLGLDisable blend(GL_BLEND); @@ -8060,7 +8067,7 @@ void LLPipeline::renderDeferredLighting()  			mDeferredVB->setBuffer(LLVertexBuffer::MAP_VERTEX);  			mDeferredLight.bindTarget(); -			gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f); +			gDeferredBlurLightProgram.uniform2f(sDelta, 0.f, 1.f);  			{  				LLGLDisable blend(GL_BLEND); @@ -10121,11 +10128,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  	assertInitialized(); -	bool muted = avatar->isVisuallyMuted();		 +	bool visually_muted = avatar->isVisuallyMuted();		  	pushRenderTypeMask(); -	if (muted) +	if (visually_muted)  	{  		andRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, END_RENDER_TYPES);  	} @@ -10267,6 +10274,13 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		avatar->mImpostor.bindTarget();  	} +	F32 old_alpha = LLDrawPoolAvatar::sMinimumAlpha; + +	if (visually_muted) +	{ //disable alpha masking for muted avatars (get whole skin silhouette) +		LLDrawPoolAvatar::sMinimumAlpha = 0.f; +	} +  	if (LLPipeline::sRenderDeferred)  	{  		avatar->mImpostor.clear(); @@ -10281,6 +10295,8 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		renderGeom(camera);  	} +	LLDrawPoolAvatar::sMinimumAlpha = old_alpha; +		  	{ //create alpha mask based on depth buffer (grey out if muted)  		LLFastTimer t(FTM_IMPOSTOR_BACKGROUND);  		if (LLPipeline::sRenderDeferred) @@ -10291,9 +10307,10 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		LLGLDisable blend(GL_BLEND); -		if (muted) +		if (visually_muted)  		{  			gGL.setColorMask(true, true); +  		}  		else  		{ @@ -10312,14 +10329,24 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		gGL.pushMatrix();  		gGL.loadIdentity(); -		static const F32 clip_plane = 0.99999f; +		static const F32 clip_plane = 0.999f;  		if (LLGLSLShader::sNoFixedFunction)  		{ -			gUIProgram.bind(); +			gDebugProgram.bind();  		} -		gGL.color4ub(64,64,64,255); + +		if (LLMuteList::getInstance()->isMuted(avatar->getID())) +		{ //grey muted avatar +			gGL.diffuseColor4ub(64,64,64,255); +		} +		else +		{	// Visually muted avatar +			gGL.diffuseColor4fv( avatar->getMutedAVColor().mV ); +		} + +		{  		gGL.begin(LLRender::QUADS);  		gGL.vertex3f(-1, -1, clip_plane);  		gGL.vertex3f(1, -1, clip_plane); @@ -10327,10 +10354,11 @@ void LLPipeline::generateImpostor(LLVOAvatar* avatar)  		gGL.vertex3f(-1, 1, clip_plane);  		gGL.end();  		gGL.flush(); +		}  		if (LLGLSLShader::sNoFixedFunction)  		{ -			gUIProgram.unbind(); +			gDebugProgram.unbind();  		}  		gGL.popMatrix(); diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png Binary files differindex 0631f16f3b..0631f16f3b 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_add_person.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png Binary files differindex 578482f5ed..578482f5ed 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_ne.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png Binary files differindex 7676131790..7676131790 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_arrow_sw.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png Binary files differindex 2880eb766a..2880eb766a 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_call_log.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png Binary files differindex d009c8f446..d009c8f446 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_close.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png Binary files differindex 8d82960e28..8d82960e28 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_collapse.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png Binary files differindex f718d3fc60..f718d3fc60 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_expand.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png Binary files differindex 315e2c581a..315e2c581a 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_hang_up.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png Binary files differindex 732ab02a20..732ab02a20 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_open_call.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png Binary files differindex 25a32cb2ba..25a32cb2ba 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_plus.png diff --git a/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png Binary files differindex 08debeb91f..08debeb91f 100755..100644 --- a/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png +++ b/indra/newview/skins/default/textures/icons/Conv_toolbar_sort.png diff --git a/indra/newview/skins/default/xui/en/menu_attachment_other.xml b/indra/newview/skins/default/xui/en/menu_attachment_other.xml index a8012656c2..a73ea0cc05 100644 --- a/indra/newview/skins/default/xui/en/menu_attachment_other.xml +++ b/indra/newview/skins/default/xui/en/menu_attachment_other.xml @@ -112,8 +112,43 @@           <menu_item_call.on_enable            function="Object.EnableInspect" />     </menu_item_call> + +   <menu_item_separator /> +     +      <menu_item_check +        name="Normal" +        label="Normal"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="0" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="0" /> +      </menu_item_check> +      <menu_item_check +        name="Always use imposter" +        label="Always use imposter"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="1" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="1" /> +      </menu_item_check> +      <menu_item_check +        name="Never use imposter" +        label="Never use imposter"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="2" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="2" /> +      </menu_item_check> +    <menu_item_separator         layout="topleft" /> +    <menu_item_call       enabled="false"       label="Mute Particle Owner" diff --git a/indra/newview/skins/default/xui/en/menu_avatar_other.xml b/indra/newview/skins/default/xui/en/menu_avatar_other.xml index bca9ba5a56..2ef18dbf90 100644 --- a/indra/newview/skins/default/xui/en/menu_avatar_other.xml +++ b/indra/newview/skins/default/xui/en/menu_avatar_other.xml @@ -39,8 +39,10 @@        <menu_item_call.on_click           function="Avatar.InviteToGroup" />        </menu_item_call> +         <menu_item_separator /> -    <menu_item_call +    +     <menu_item_call       enabled="false"       label="Block"       name="Avatar Mute"> @@ -103,8 +105,43 @@          <menu_item_call.on_enable           function="EnablePayAvatar" />      </menu_item_call> + +   <menu_item_separator /> +     +      <menu_item_check +        name="Normal" +        label="Normal"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="0" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="0" /> +      </menu_item_check> +      <menu_item_check +        name="Always use imposter" +        label="Always use imposter"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="1" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="1" /> +      </menu_item_check> +      <menu_item_check +        name="Never use imposter" +        label="Never use imposter"> +        <menu_item_check.on_check +          function="Avatar.CheckImposterMode" +          parameter="2" /> +	    <menu_item_check.on_click +	      function="Avatar.SetImposterMode" +	      parameter="2" /> +      </menu_item_check> +    <menu_item_separator         layout="topleft" /> +    <menu_item_call       enabled="false"       label="Mute Particle Owner" diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index a11cd13fdb..1197f1ce1f 100644 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -547,6 +547,15 @@              <menu_item_check.on_check                 control="NavBarShowParcelProperties" />            </menu_item_check> +          <menu_item_check +             label="Simple Imposters" +             name="RenderAutoMuteEnabled"> +            <menu_item_check.on_check +               control="RenderAutoMuteEnabled" /> +            <menu_item_check.on_click +               function="ToggleControl" +               parameter="RenderAutoMuteEnabled" /> +          </menu_item_check>            <menu_item_separator />            <menu_item_check               label="Advanced Menu" diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index a627596a15..5ab38c372c 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -203,6 +203,45 @@ Message Template [PATH] not found.    </notification>    <notification +   icon="notify.tga" +   name="ExceededHighDetailRenderCost" +   persist="false" +   type="alertmodal"> +    Your avatar has become too complex to be rendered by even high performance computers.  Almost all Residents will see a low detail stand in instead of your actual avatar. +    <unique/> +    <usetemplate +     ignoretext="Avatar exceeded high detail complexity." +     name="okignore" +     yestext="Close"/> +  </notification> + +  <notification +   icon="notify.tga" +   name="ExceededMidDetailRenderCost" +   persist="false" +   type="alertmodal"> +    Your avatar has become too complex to be rendered by most computers.  Many Residents will see a low detail stand in instead of your actual avatar. +  <unique/> +  <usetemplate +   ignoretext="Avatar exceeded mid detail complexity." +   name="okignore" +   yestext="Close"/> +</notification> + +  <notification + icon="notify.tga" + name="ExceededLowDetailRenderCost" + persist="false" + type="alertmodal"> +    Your avatar has become too complex to be rendered by some computers.  Some Residents will see a low detail stand in instead of your actual avatar. +  <unique/> +  <usetemplate +   ignoretext="Avatar exceeded low detail complexity." +   name="okignore" +   yestext="Close"/> +  </notification> + +  <notification     icon="alertmodal.tga"     name="WearableSave"     type="alertmodal"> @@ -9991,7 +10030,7 @@ An internal error prevented us from properly updating your viewer.  The L$ balan     <tag>fail</tag>  Cannot create large prims that intersect other players.  Please re-try when other players have moved.    </notification> - +      <notification     icon="alertmodal.tga"     name="PreferenceChatClearLog" diff --git a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml index 4ed95f0758..7abc67494f 100644 --- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml @@ -177,10 +177,86 @@       width="80">          Ultra      </text> +  <slider +   control_name="RenderAvatarLODFactor" +   invisiblity_control="ShowAdvancedGraphicsSettings" +   follows="left|top" +   height="16" +   increment="0.125" +   initial_value="160" +   label="Avatar detail:" +   label_width="90" +   layout="topleft" +   left="30" +   name="AvatarMeshDetail2" +   show_text="false" +   top="72" +   width="300"> +    <slider.commit_callback +     function="Pref.UpdateSliderText" +     parameter="AvatarMeshDetailText2" /> +  </slider> +  <text +   type="string" +   invisiblity_control="ShowAdvancedGraphicsSettings" +   length="1" +   follows="left|top" +   height="12" +   layout="topleft" +   name="AvatarMeshDetailText2" +   top_delta="0" +   left_delta="304" +   width="128"> +    Low +  </text> +  <slider +   control_name="RenderFarClip" +   invisiblity_control="ShowAdvancedGraphicsSettings" +   decimal_digits="0" +   follows="left|top" +   height="16" +   increment="8" +   initial_value="160" +   label="Draw distance:" +   label_width="90" +   layout="topleft" +   left="30" +   max_val="512" +   min_val="64" +   name="DrawDistance" +   top="110" +   width="330" /> +  <text +   type="string" +   invisiblity_control="ShowAdvancedGraphicsSettings" +   length="1" +   follows="left|top" +   height="12" +   layout="topleft" +   left_delta="330" +   name="DrawDistanceMeterText2" +   top_delta="0" +   width="128"> +    m +  </text> +  <check_box +		 control_name="RenderDeferred" +     invisiblity_control="ShowAdvancedGraphicsSettings" +		 height="16" +		 initial_value="true" +		 label="Lighting and Shadows" +		 layout="topleft" +		 left="30" +		 name="UseLightShaders2" +		 top="148" +		 width="256"> +    <check_box.commit_callback +      function="Pref.VertexShaderEnable" /> +  </check_box>      <panel -	 visiblity_control="ShowAdvancedGraphicsSettings" +	   visiblity_control="ShowAdvancedGraphicsSettings"       border="false" -	 follows="top|left" +	   follows="top|left"       height="300"       label="CustomGraphics"       layout="topleft" @@ -219,15 +295,15 @@  		 left_delta="0"  		 name="BumpShiny"  		 top_pad="1" -		width="256" /> +		 width="256" />      <check_box -		control_name="RenderLocalLights" -		height="16" -		initial_value="true" -		label="Local Lights" -		layout="topleft" -		left_delta="0" -		name="LocalLights" +		 control_name="RenderLocalLights" +		 height="16" +		 initial_value="true" +		 label="Local Lights" +		 layout="topleft" +		 left_delta="0" +		 name="LocalLights"  		 top_pad="1"  		 width="256" />  		  <check_box diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index f4473dd0b1..cf8bd25600 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -406,10 +406,13 @@ Please try logging in again in a minute.</string>  	<string name="AddAndRemoveJoints">Add and remove joints with other objects</string>  	<string name="ChangePermissions">Change its permissions</string>  	<string name="TrackYourCamera">Track your camera</string> -  <string name="ControlYourCamera">Control your camera</string> +	<string name="ControlYourCamera">Control your camera</string> +	<string name="TeleportYourAgent">Teleport you</string> +	<string name="ManageEstateSilently">Manage your estates silently</string> +	<string name="ChangeYourDefaultAnimations">Change your default animations</string> +	  	<string name="NotConnected">Not Connected</string>  	<string name="AgentNameSubst">(You)</string> <!-- Substitution for agent name --> -  <string name="TeleportYourAgent">Teleport you</string>  	<!-- Sim Access labels -->  	<string name="SIM_ACCESS_PG">General</string> diff --git a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml index b83d9122f7..b83d9122f7 100755..100644 --- a/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml +++ b/indra/newview/skins/default/xui/en/widgets/conversation_view_participant.xml diff --git a/indra/newview/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp index 3ba25f3c10..426ad40342 100644 --- a/indra/newview/tests/llagentaccess_test.cpp +++ b/indra/newview/tests/llagentaccess_test.cpp @@ -40,7 +40,7 @@  static U32 test_preferred_maturity = SIM_ACCESS_PG;  LLControlGroup::LLControlGroup(const std::string& name) -	: LLInstanceTracker<LLControlGroup, std::string>(name) +	: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name)  {  } diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp index 7705b4c567..25da5939f1 100644 --- a/indra/newview/tests/lllogininstance_test.cpp +++ b/indra/newview/tests/lllogininstance_test.cpp @@ -167,7 +167,7 @@ std::string LLGridManager::getAppSLURLBase(const std::string& grid_name)  LLControlGroup gSavedSettings("Global");  LLControlGroup::LLControlGroup(const std::string& name) : -	LLInstanceTracker<LLControlGroup, std::string>(name){} +	INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name){}  LLControlGroup::~LLControlGroup() {}  void LLControlGroup::setBOOL(const std::string& name, BOOL val) {}  BOOL LLControlGroup::getBOOL(const std::string& name) { return FALSE; } diff --git a/indra/newview/tests/llremoteparcelrequest_test.cpp b/indra/newview/tests/llremoteparcelrequest_test.cpp index ed66066b0a..da273132db 100644 --- a/indra/newview/tests/llremoteparcelrequest_test.cpp +++ b/indra/newview/tests/llremoteparcelrequest_test.cpp @@ -69,7 +69,7 @@ void LLAgent::sendReliableMessage(void) { }  LLUUID gAgentSessionID;  LLUUID gAgentID;  LLUIColor::LLUIColor(void) { } -LLControlGroup::LLControlGroup(std::string const & name) : LLInstanceTracker<LLControlGroup, std::string>(name) { } +LLControlGroup::LLControlGroup(std::string const & name) : INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) { }  LLControlGroup::~LLControlGroup(void) { }  void LLUrlEntryParcel::processParcelInfo(const LLUrlEntryParcel::LLParcelData& parcel_data) { } diff --git a/indra/newview/tests/llsecapi_test.cpp b/indra/newview/tests/llsecapi_test.cpp index 703603e2db..83a4149971 100644 --- a/indra/newview/tests/llsecapi_test.cpp +++ b/indra/newview/tests/llsecapi_test.cpp @@ -37,7 +37,7 @@  // Mock objects for the dependencies of the code we're testing                                 LLControlGroup::LLControlGroup(const std::string& name) -: LLInstanceTracker<LLControlGroup, std::string>(name) {} +: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {}  LLControlGroup::~LLControlGroup() {}  BOOL LLControlGroup::declareString(const std::string& name,                                     const std::string& initial_val, diff --git a/indra/newview/tests/llsechandler_basic_test.cpp b/indra/newview/tests/llsechandler_basic_test.cpp index 0235400976..814010028f 100644 --- a/indra/newview/tests/llsechandler_basic_test.cpp +++ b/indra/newview/tests/llsechandler_basic_test.cpp @@ -69,7 +69,7 @@ extern bool _cert_hostname_wildcard_match(const std::string& hostname, const std  std::string gFirstName;  std::string gLastName;  LLControlGroup::LLControlGroup(const std::string& name) -: LLInstanceTracker<LLControlGroup, std::string>(name) {} +: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {}  LLControlGroup::~LLControlGroup() {}  BOOL LLControlGroup::declareString(const std::string& name,                                     const std::string& initial_val, diff --git a/indra/newview/tests/llslurl_test.cpp b/indra/newview/tests/llslurl_test.cpp index 09343ef227..d7debd6c67 100644 --- a/indra/newview/tests/llslurl_test.cpp +++ b/indra/newview/tests/llslurl_test.cpp @@ -35,7 +35,7 @@  // Mock objects for the dependencies of the code we're testing  LLControlGroup::LLControlGroup(const std::string& name) -: LLInstanceTracker<LLControlGroup, std::string>(name) {} +: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {}  LLControlGroup::~LLControlGroup() {}  BOOL LLControlGroup::declareString(const std::string& name,                                     const std::string& initial_val, diff --git a/indra/newview/tests/lltranslate_test.cpp b/indra/newview/tests/lltranslate_test.cpp index fd9527d631..c13660332d 100644 --- a/indra/newview/tests/lltranslate_test.cpp +++ b/indra/newview/tests/lltranslate_test.cpp @@ -295,7 +295,7 @@ LLControlGroup gSavedSettings("test");  std::string LLUI::getLanguage() { return "en"; }  std::string LLTrans::getString(const std::string &xml_desc, const LLStringUtil::format_map_t& args) { return "dummy"; } -LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) {} +LLControlGroup::LLControlGroup(const std::string& name) : INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {}  std::string LLControlGroup::getString(const std::string& name) { return "dummy"; }  LLControlGroup::~LLControlGroup() {} diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp index 710881d811..102cad8852 100644 --- a/indra/newview/tests/llviewerhelputil_test.cpp +++ b/indra/newview/tests/llviewerhelputil_test.cpp @@ -47,7 +47,7 @@ static std::string gOS;  // Mock objects for the dependencies of the code we're testing  LLControlGroup::LLControlGroup(const std::string& name) -	: LLInstanceTracker<LLControlGroup, std::string>(name) {} +	: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {}  LLControlGroup::~LLControlGroup() {}  BOOL LLControlGroup::declareString(const std::string& name,  				   const std::string& initial_val, diff --git a/indra/newview/tests/llviewernetwork_test.cpp b/indra/newview/tests/llviewernetwork_test.cpp index a1e97ea17e..725b5122fb 100644 --- a/indra/newview/tests/llviewernetwork_test.cpp +++ b/indra/newview/tests/llviewernetwork_test.cpp @@ -35,7 +35,7 @@  // Mock objects for the dependencies of the code we're testing  LLControlGroup::LLControlGroup(const std::string& name) -: LLInstanceTracker<LLControlGroup, std::string>(name) {} +: INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) {}  LLControlGroup::~LLControlGroup() {}  BOOL LLControlGroup::declareString(const std::string& name,                                     const std::string& initial_val, diff --git a/indra/newview/tests/llworldmipmap_test.cpp b/indra/newview/tests/llworldmipmap_test.cpp index 142d75bcfd..a6a2f8d7b9 100644 --- a/indra/newview/tests/llworldmipmap_test.cpp +++ b/indra/newview/tests/llworldmipmap_test.cpp @@ -46,7 +46,7 @@ void LLGLTexture::setBoostLevel(S32 ) { }  LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string&, FTType, BOOL, LLGLTexture::EBoostLevel, S8,   																		 LLGLint, LLGLenum, const LLUUID& ) { return NULL; } -LLControlGroup::LLControlGroup(const std::string& name) : LLInstanceTracker<LLControlGroup, std::string>(name) { } +LLControlGroup::LLControlGroup(const std::string& name) : INSTANCE_TRACKER_KEYED(LLControlGroup, std::string)(name) { }  LLControlGroup::~LLControlGroup() { }  std::string LLControlGroup::getString(const std::string& ) { return std::string("test_url"); }  LLControlGroup gSavedSettings("test_settings"); diff --git a/indra/test/io.cpp b/indra/test/io.cpp index 47a67deed0..62e516accb 100644 --- a/indra/test/io.cpp +++ b/indra/test/io.cpp @@ -1141,6 +1141,7 @@ namespace tut  		ensure("Connected to server", connected);  		lldebugs << "connected" << llendl;  		pump_loop(mPump,0.1f); +		(void)elapsed;  		count = mPump->runningChains();  		ensure_equals("server chain onboard", count, 2);  		lldebugs << "** Client is connected." << llendl; diff --git a/indra/test/llstreamtools_tut.cpp b/indra/test/llstreamtools_tut.cpp index 0f6436f0f4..a9bb15d911 100644 --- a/indra/test/llstreamtools_tut.cpp +++ b/indra/test/llstreamtools_tut.cpp @@ -385,15 +385,17 @@ namespace tut  		std::string expected_result;  		std::string actual_result;  		std::istringstream is; -  		is.clear();  		is.str(str = "  First Second \t \r  \n Third  Fourth-ShouldThisBePartOfFourth  Fifth\n");  		actual_result = "";  		get_word(actual_result, is); // First +		(void)ret;  		actual_result = "";  		get_word(actual_result, is); // Second +		(void)ret;  		actual_result = "";  		get_word(actual_result, is); // Third +		(void)ret;  		// the current implementation of get_word seems inconsistent with  		// skip_to_next_word. skip_to_next_word treats any character other @@ -484,6 +486,7 @@ namespace tut  		is.str(str = "First Second \t \r\n Third  Fourth-ShouldThisBePartOfFourth  IsThisFifth\n");  		actual_result = "";  		get_line(actual_result, is); +		(void)ret;  		expected_result = "First Second \t \r\n";  		ensure_equals("get_line: 1", actual_result, expected_result); @@ -548,6 +551,7 @@ namespace tut  		is.str(str = "Should not skip lone \r.\r\n");  		actual_result = "";  		get_line(actual_result, is); +		(void)ret;  		expected_result = "Should not skip lone \r.\r\n";  		ensure_equals("get_line: carriage return skipped even though not followed by newline", actual_result, expected_result);  	} @@ -565,6 +569,7 @@ namespace tut  		is.str(str = "\n");  		actual_result = "";  		get_line(actual_result, is); +		(void)ret;  		expected_result = "\n";  		ensure_equals("get_line: Just newline", actual_result, expected_result);  	} @@ -583,6 +588,7 @@ namespace tut  		is.str(str = "First Line.\nSecond Line.\n");  		actual_result = "";  		get_line(actual_result, is, 255); +		(void)ret;  		expected_result = "First Line.\n";  		ensure_equals("get_line: Basic Operation", actual_result, expected_result); diff --git a/indra/test/lltemplatemessagebuilder_tut.cpp b/indra/test/lltemplatemessagebuilder_tut.cpp index 6c0b70edd2..3d3edab102 100644 --- a/indra/test/lltemplatemessagebuilder_tut.cpp +++ b/indra/test/lltemplatemessagebuilder_tut.cpp @@ -958,10 +958,12 @@ namespace tut  		reader->validateMessage(buffer, builtSize, LLHost());  		reader->readMessage(buffer, LLHost());  		reader->getU32(_PREHASH_Test0, _PREHASH_Test0, outValue); +		(void)outValue;  		char outBuffer[bufferSize];  		memset(buffer, 0xcc, bufferSize);  		reader->getString(_PREHASH_Test1, _PREHASH_Test0, bufferSize,   						  outBuffer); +		(void)outValue2;  		ensure_equals("Ensure present value ", outValue, inValue);  		ensure_equals("Ensure unchanged buffer ", strlen(outBuffer), 0);  		delete reader;  | 
