Merge. Pull in viewer-release after 3.6.7 release.

Fri, 04 Oct 2013 15:36:52 -0400

author
Monty Brandenberg <monty@lindenlab.com>
date
Fri, 04 Oct 2013 15:36:52 -0400
changeset 40732
17bbce4fb7bb
parent 40731
61f491773403
parent 38882
af9300746a85
child 40733
4558989b7313

Merge. Pull in viewer-release after 3.6.7 release.

autobuild.xml file | annotate | diff | revisions
indra/llcommon/CMakeLists.txt file | annotate | diff | revisions
indra/llcommon/llthread.cpp file | annotate | diff | revisions
indra/llcommon/llthread.h file | annotate | diff | revisions
indra/llcorehttp/_httpinternal.h file | annotate | diff | revisions
indra/llcorehttp/_httpoprequest.cpp file | annotate | diff | revisions
indra/llcorehttp/_httpoprequest.h file | annotate | diff | revisions
indra/llcorehttp/_httppolicy.cpp file | annotate | diff | revisions
indra/llcorehttp/httpcommon.cpp file | annotate | diff | revisions
indra/llcorehttp/httpcommon.h file | annotate | diff | revisions
indra/llcorehttp/httpresponse.h file | annotate | diff | revisions
indra/llcorehttp/tests/test_httprequest.hpp file | annotate | diff | revisions
indra/llcorehttp/tests/test_httpstatus.hpp file | annotate | diff | revisions
indra/llcorehttp/tests/test_llcorehttp_peer.py file | annotate | diff | revisions
indra/llmessage/llcurl.cpp file | annotate | diff | revisions
indra/newview/app_settings/settings.xml file | annotate | diff | revisions
indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedF.glsl file | annotate | diff | revisions
indra/newview/app_settings/shaders/class1/deferred/alphaNonIndexedNoColorF.glsl file | annotate | diff | revisions
indra/newview/app_settings/shaders/class1/deferred/alphaSkinnedV.glsl file | annotate | diff | revisions
indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl file | annotate | diff | revisions
indra/newview/app_settings/shaders/class1/deferred/giF.glsl file | annotate | diff | revisions
indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedF.glsl file | annotate | diff | revisions
indra/newview/app_settings/shaders/class2/deferred/alphaNonIndexedNoColorF.glsl file | annotate | diff | revisions
indra/newview/app_settings/shaders/class2/deferred/alphaSkinnedV.glsl file | annotate | diff | revisions
indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl file | annotate | diff | revisions
indra/newview/llmeshrepository.cpp file | annotate | diff | revisions
indra/newview/llviewerregion.cpp file | annotate | diff | revisions
     1.1 --- a/.hgignore	Fri Sep 27 17:22:31 2013 -0400
     1.2 +++ b/.hgignore	Fri Oct 04 15:36:52 2013 -0400
     1.3 @@ -33,6 +33,7 @@
     1.4  indra/newview/browser_profile
     1.5  indra/newview/character
     1.6  indra/newview/fmod.dll
     1.7 +indra/newview/fmod.log
     1.8  indra/newview/mozilla-theme
     1.9  indra/newview/mozilla-universal-darwin.tgz
    1.10  indra/newview/res/ll_icon.*
     2.1 --- a/.hgtags	Fri Sep 27 17:22:31 2013 -0400
     2.2 +++ b/.hgtags	Fri Oct 04 15:36:52 2013 -0400
     2.3 @@ -465,4 +465,4 @@
     2.4  83357f31d8dbf048a8bfdc323f363bf4d588aca1 CHOP-951-a
     2.5  91ed595b716f14f07409595b734fda891a59379e 3.6.4-release
     2.6  bf6d453046011a11de2643fac610cc5258650f82 3.6.5-release
     2.7 -b62e417982d9d4f3ec49d0de3b3c2e37c6d394c1 3.6.6-release
     2.8 +ae457ece77001767ae9613148c495e7b98cc0f4a 3.6.7-release
     3.1 --- a/BuildParams	Fri Sep 27 17:22:31 2013 -0400
     3.2 +++ b/BuildParams	Fri Oct 04 15:36:52 2013 -0400
     3.3 @@ -23,6 +23,7 @@
     3.4  
     3.5  # Override build system default toolchain
     3.6  # Note that this will only affect automated builds.
     3.7 +Linux.distcc_version = 
     3.8  Linux.gcc_version = /usr/bin/gcc-4.6
     3.9  Linux.cxx_version = /usr/bin/g++-4.6
    3.10  
     4.1 --- a/doc/contributions.txt	Fri Sep 27 17:22:31 2013 -0400
     4.2 +++ b/doc/contributions.txt	Fri Oct 04 15:36:52 2013 -0400
     4.3 @@ -924,8 +924,11 @@
     4.4  	MAINT-873
     4.5  	SUN-72
     4.6  	BUG-2432
     4.7 +	STORM-1935
     4.8 +	STORM-1936
     4.9  	BUG-3605
    4.10  	CHUIBUG-197
    4.11 +	STORM-1937
    4.12  Nicky Perian
    4.13  	OPEN-1
    4.14  	STORM-1087
     5.1 --- a/indra/cmake/00-Common.cmake	Fri Sep 27 17:22:31 2013 -0400
     5.2 +++ b/indra/cmake/00-Common.cmake	Fri Oct 04 15:36:52 2013 -0400
     5.3 @@ -131,6 +131,17 @@
     5.4    # Let's actually get a numerical version of gxx's version
     5.5    STRING(REGEX REPLACE ".* ([0-9])\\.([0-9])\\.([0-9]).*" "\\1\\2\\3" CXX_VERSION_NUMBER ${CXX_VERSION})
     5.6  
     5.7 +  # Hacks to work around gcc 4.1 TC build pool machines which can't process pragma warning disables
     5.8 +  # This is pure rubbish; I wish there was another way.
     5.9 +  #
    5.10 +  if(${CXX_VERSION_NUMBER} LESS 420)
    5.11 +    set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-uninitialized -Wno-unused-variable -Wno-unused-function ${CMAKE_CXX_FLAGS}")
    5.12 +  endif (${CXX_VERSION_NUMBER} LESS 420)
    5.13 +
    5.14 +  if(${CXX_VERSION_NUMBER} GREATER 459)
    5.15 +    set(CMAKE_CXX_FLAGS "-Wno-deprecated -Wno-unused-but-set-variable -Wno-unused-variable ${CMAKE_CXX_FLAGS}")
    5.16 +  endif (${CXX_VERSION_NUMBER} GREATER 459)
    5.17 +
    5.18    # gcc 4.3 and above don't like the LL boost and also
    5.19    # cause warnings due to our use of deprecated headers
    5.20    if(${CXX_VERSION_NUMBER} GREATER 429)
     6.1 --- a/indra/cmake/Copy3rdPartyLibs.cmake	Fri Sep 27 17:22:31 2013 -0400
     6.2 +++ b/indra/cmake/Copy3rdPartyLibs.cmake	Fri Oct 04 15:36:52 2013 -0400
     6.3 @@ -270,6 +270,7 @@
     6.4          libdb-5.1.so
     6.5          libexpat.so
     6.6          libexpat.so.1
     6.7 +        libfreetype.so.6
     6.8          libGLOD.so
     6.9          libgmock_main.so
    6.10          libgmock.so.0
     7.1 --- a/indra/cmake/FreeType.cmake	Fri Sep 27 17:22:31 2013 -0400
     7.2 +++ b/indra/cmake/FreeType.cmake	Fri Oct 04 15:36:52 2013 -0400
     7.3 @@ -7,7 +7,7 @@
     7.4    pkg_check_modules(FREETYPE REQUIRED freetype2)
     7.5  else (STANDALONE)
     7.6    use_prebuilt_binary(freetype)
     7.7 -    set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
     7.8 +  set(FREETYPE_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include)
     7.9    set(FREETYPE_LIBRARIES freetype)
    7.10  endif (STANDALONE)
    7.11  
     8.1 --- a/indra/llcharacter/lleditingmotion.cpp	Fri Sep 27 17:22:31 2013 -0400
     8.2 +++ b/indra/llcharacter/lleditingmotion.cpp	Fri Oct 04 15:36:52 2013 -0400
     8.3 @@ -258,3 +258,4 @@
     8.4  
     8.5  
     8.6  // End
     8.7 +
     9.1 --- a/indra/llcharacter/llheadrotmotion.cpp	Fri Sep 27 17:22:31 2013 -0400
     9.2 +++ b/indra/llcharacter/llheadrotmotion.cpp	Fri Oct 04 15:36:52 2013 -0400
     9.3 @@ -530,3 +530,4 @@
     9.4  }
     9.5  
     9.6  // End
     9.7 +
    10.1 --- a/indra/llcharacter/llkeyframemotion.cpp	Fri Sep 27 17:22:31 2013 -0400
    10.2 +++ b/indra/llcharacter/llkeyframemotion.cpp	Fri Oct 04 15:36:52 2013 -0400
    10.3 @@ -672,7 +672,8 @@
    10.4  //-----------------------------------------------------------------------------
    10.5  BOOL LLKeyframeMotion::onUpdate(F32 time, U8* joint_mask)
    10.6  {
    10.7 -	llassert(time >= 0.f);
    10.8 +	// llassert(time >= 0.f);		// This will fire
    10.9 +	time = llmax(0.f, time);
   10.10  
   10.11  	if (mJointMotionList->mLoop)
   10.12  	{
   10.13 @@ -2304,3 +2305,4 @@
   10.14  }
   10.15  
   10.16  // End
   10.17 +
    11.1 --- a/indra/llcharacter/llkeyframewalkmotion.cpp	Fri Sep 27 17:22:31 2013 -0400
    11.2 +++ b/indra/llcharacter/llkeyframewalkmotion.cpp	Fri Oct 04 15:36:52 2013 -0400
    11.3 @@ -390,3 +390,4 @@
    11.4  
    11.5  	return TRUE;
    11.6  }
    11.7 +
    12.1 --- a/indra/llcharacter/llmotion.cpp	Fri Sep 27 17:22:31 2013 -0400
    12.2 +++ b/indra/llcharacter/llmotion.cpp	Fri Oct 04 15:36:52 2013 -0400
    12.3 @@ -169,3 +169,4 @@
    12.4  }
    12.5  
    12.6  // End
    12.7 +
    13.1 --- a/indra/llcharacter/lltargetingmotion.cpp	Fri Sep 27 17:22:31 2013 -0400
    13.2 +++ b/indra/llcharacter/lltargetingmotion.cpp	Fri Oct 04 15:36:52 2013 -0400
    13.3 @@ -169,3 +169,4 @@
    13.4  
    13.5  
    13.6  // End
    13.7 +
    14.1 --- a/indra/llcommon/CMakeLists.txt	Fri Sep 27 17:22:31 2013 -0400
    14.2 +++ b/indra/llcommon/CMakeLists.txt	Fri Oct 04 15:36:52 2013 -0400
    14.3 @@ -124,6 +124,7 @@
    14.4      linden_common.h
    14.5      linked_lists.h
    14.6      llaccountingcost.h
    14.7 +    llalignedarray.h
    14.8      llallocator.h
    14.9      llallocator_heap_profile.h
   14.10      llagentconstants.h
   14.11 @@ -241,6 +242,7 @@
   14.12      llstrider.h
   14.13      llstring.h
   14.14      llstringtable.h
   14.15 +    llstaticstringtable.h
   14.16      llsys.h
   14.17      llthread.h
   14.18      llthreadsafequeue.h
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/indra/llcommon/llalignedarray.h	Fri Oct 04 15:36:52 2013 -0400
    15.3 @@ -0,0 +1,139 @@
    15.4 +/** 
    15.5 + * @file llalignedarray.h
    15.6 + * @brief A static array which obeys alignment restrictions and mimics std::vector accessors.
    15.7 + *
    15.8 + * $LicenseInfo:firstyear=2002&license=viewerlgpl$
    15.9 + * Second Life Viewer Source Code
   15.10 + * Copyright (C) 2010, Linden Research, Inc.
   15.11 + * 
   15.12 + * This library is free software; you can redistribute it and/or
   15.13 + * modify it under the terms of the GNU Lesser General Public
   15.14 + * License as published by the Free Software Foundation;
   15.15 + * version 2.1 of the License only.
   15.16 + * 
   15.17 + * This library is distributed in the hope that it will be useful,
   15.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   15.20 + * Lesser General Public License for more details.
   15.21 + * 
   15.22 + * You should have received a copy of the GNU Lesser General Public
   15.23 + * License along with this library; if not, write to the Free Software
   15.24 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   15.25 + * 
   15.26 + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
   15.27 + * $/LicenseInfo$
   15.28 + */
   15.29 +
   15.30 +#ifndef LL_LLALIGNEDARRAY_H
   15.31 +#define LL_LLALIGNEDARRAY_H
   15.32 +
   15.33 +#include "llmemory.h"
   15.34 +
   15.35 +template <class T, U32 alignment>
   15.36 +class LLAlignedArray
   15.37 +{
   15.38 +public:
   15.39 +	T* mArray;
   15.40 +	U32 mElementCount;
   15.41 +	U32 mCapacity;
   15.42 +
   15.43 +	LLAlignedArray();
   15.44 +	~LLAlignedArray();
   15.45 +
   15.46 +	void push_back(const T& elem);
   15.47 +	U32 size() const { return mElementCount; }
   15.48 +	void resize(U32 size);
   15.49 +	T* append(S32 N);
   15.50 +	T& operator[](int idx);
   15.51 +	const T& operator[](int idx) const;
   15.52 +};
   15.53 +
   15.54 +template <class T, U32 alignment>
   15.55 +LLAlignedArray<T, alignment>::LLAlignedArray()
   15.56 +{
   15.57 +	llassert(alignment >= 16);
   15.58 +	mArray = NULL;
   15.59 +	mElementCount = 0;
   15.60 +	mCapacity = 0;
   15.61 +}
   15.62 +
   15.63 +template <class T, U32 alignment>
   15.64 +LLAlignedArray<T, alignment>::~LLAlignedArray()
   15.65 +{
   15.66 +	ll_aligned_free(mArray);
   15.67 +	mArray = NULL;
   15.68 +	mElementCount = 0;
   15.69 +	mCapacity = 0;
   15.70 +}
   15.71 +
   15.72 +template <class T, U32 alignment>
   15.73 +void LLAlignedArray<T, alignment>::push_back(const T& elem)
   15.74 +{
   15.75 +	T* old_buf = NULL;
   15.76 +	if (mCapacity <= mElementCount)
   15.77 +	{
   15.78 +		mCapacity++;
   15.79 +		mCapacity *= 2;
   15.80 +		T* new_buf = (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment);
   15.81 +		if (mArray)
   15.82 +		{
   15.83 +			ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount);
   15.84 +		}
   15.85 +		old_buf = mArray;
   15.86 +		mArray = new_buf;
   15.87 +	}
   15.88 +
   15.89 +	mArray[mElementCount++] = elem;
   15.90 +
   15.91 +	//delete old array here to prevent error on a.push_back(a[0])
   15.92 +	ll_aligned_free(old_buf);
   15.93 +}
   15.94 +
   15.95 +template <class T, U32 alignment>
   15.96 +void LLAlignedArray<T, alignment>::resize(U32 size)
   15.97 +{
   15.98 +	if (mCapacity < size)
   15.99 +	{
  15.100 +		mCapacity = size+mCapacity*2;
  15.101 +		T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment) : NULL;
  15.102 +		if (mArray)
  15.103 +		{
  15.104 +			ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount);
  15.105 +			ll_aligned_free(mArray);
  15.106 +		}
  15.107 +
  15.108 +		/*for (U32 i = mElementCount; i < mCapacity; ++i)
  15.109 +		{
  15.110 +			new(new_buf+i) T();
  15.111 +		}*/
  15.112 +		mArray = new_buf;
  15.113 +	}
  15.114 +
  15.115 +	mElementCount = size;
  15.116 +}
  15.117 +
  15.118 +
  15.119 +template <class T, U32 alignment>
  15.120 +T& LLAlignedArray<T, alignment>::operator[](int idx)
  15.121 +{
  15.122 +	llassert(idx < mElementCount);
  15.123 +	return mArray[idx];
  15.124 +}
  15.125 +
  15.126 +template <class T, U32 alignment>
  15.127 +const T& LLAlignedArray<T, alignment>::operator[](int idx) const
  15.128 +{
  15.129 +	llassert(idx < mElementCount);
  15.130 +	return mArray[idx];
  15.131 +}
  15.132 +
  15.133 +template <class T, U32 alignment>
  15.134 +T* LLAlignedArray<T, alignment>::append(S32 N)
  15.135 +{
  15.136 +	U32 sz = size();
  15.137 +	resize(sz+N);
  15.138 +	return &((*this)[sz]);
  15.139 +}
  15.140 +
  15.141 +#endif
  15.142 +
    16.1 --- a/indra/llcommon/llapr.h	Fri Sep 27 17:22:31 2013 -0400
    16.2 +++ b/indra/llcommon/llapr.h	Fri Oct 04 15:36:52 2013 -0400
    16.3 @@ -164,14 +164,20 @@
    16.4  	~LLAtomic32<Type>() {};
    16.5  
    16.6  	operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
    16.7 +	
    16.8 +	Type	CurrentValue() const { apr_uint32_t data = apr_atomic_read32(const_cast< volatile apr_uint32_t* >(&mData)); return Type(data); }
    16.9 +
   16.10  	Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }
   16.11  	void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }
   16.12  	void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }
   16.13  	Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++
   16.14  	Type operator --(int) { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
   16.15 +
   16.16 +	Type operator ++() { return apr_atomic_inc32(&mData); } // Type++
   16.17 +	Type operator --() { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
   16.18  	
   16.19  private:
   16.20 -	apr_uint32_t mData;
   16.21 +	volatile apr_uint32_t mData;
   16.22  };
   16.23  
   16.24  typedef LLAtomic32<U32> LLAtomicU32;
    17.1 --- a/indra/llcommon/llcommon.cpp	Fri Sep 27 17:22:31 2013 -0400
    17.2 +++ b/indra/llcommon/llcommon.cpp	Fri Oct 04 15:36:52 2013 -0400
    17.3 @@ -44,6 +44,7 @@
    17.4  	}
    17.5  	LLTimer::initClass();
    17.6  	LLThreadSafeRefCount::initThreadSafeRefCount();
    17.7 +	assert_main_thread();		// Make sure we record the main thread
    17.8  // 	LLWorkerThread::initClass();
    17.9  // 	LLFrameCallbackManager::initClass();
   17.10  }
    18.1 --- a/indra/llcommon/llcriticaldamp.cpp	Fri Sep 27 17:22:31 2013 -0400
    18.2 +++ b/indra/llcommon/llcriticaldamp.cpp	Fri Oct 04 15:36:52 2013 -0400
    18.3 @@ -87,3 +87,4 @@
    18.4  
    18.5  	return interpolant;
    18.6  }
    18.7 +
    19.1 --- a/indra/llcommon/lleventapi.h	Fri Sep 27 17:22:31 2013 -0400
    19.2 +++ b/indra/llcommon/lleventapi.h	Fri Oct 04 15:36:52 2013 -0400
    19.3 @@ -47,6 +47,7 @@
    19.4      typedef LLInstanceTracker<LLEventAPI, std::string> ibase;
    19.5  
    19.6  public:
    19.7 +
    19.8      /**
    19.9       * @param name LLEventPump name on which this LLEventAPI will listen. This
   19.10       * also serves as the LLInstanceTracker instance key.
    20.1 --- a/indra/llcommon/lleventtimer.h	Fri Sep 27 17:22:31 2013 -0400
    20.2 +++ b/indra/llcommon/lleventtimer.h	Fri Oct 04 15:36:52 2013 -0400
    20.3 @@ -36,6 +36,7 @@
    20.4  class LL_COMMON_API LLEventTimer : public LLInstanceTracker<LLEventTimer>
    20.5  {
    20.6  public:
    20.7 +
    20.8  	LLEventTimer(F32 period);	// period is the amount of time between each call to tick() in seconds
    20.9  	LLEventTimer(const LLDate& time);
   20.10  	virtual ~LLEventTimer();
    21.1 --- a/indra/llcommon/llfasttimer.cpp	Fri Sep 27 17:22:31 2013 -0400
    21.2 +++ b/indra/llcommon/llfasttimer.cpp	Fri Oct 04 15:36:52 2013 -0400
    21.3 @@ -107,17 +107,13 @@
    21.4  {
    21.5  public:
    21.6  	NamedTimerFactory()
    21.7 -	:	mTimerRoot(NULL)
    21.8 -	{}
    21.9 -
   21.10 -	/*virtual */ void initSingleton()
   21.11 +	:	mTimerRoot(new LLFastTimer::NamedTimer("root"))
   21.12  	{
   21.13 -		mTimerRoot = new LLFastTimer::NamedTimer("root");
   21.14  		mRootFrameState.setNamedTimer(mTimerRoot);
   21.15  		mTimerRoot->setFrameState(&mRootFrameState);
   21.16  		mTimerRoot->mParent = mTimerRoot;
   21.17  		mTimerRoot->setCollapsed(false);
   21.18 -		mRootFrameState.mParent = &mRootFrameState;
   21.19 +		mRootFrameState.mParent = &mRootFrameState;	
   21.20  	}
   21.21  
   21.22  	~NamedTimerFactory()
    22.1 --- a/indra/llcommon/llfasttimer.h	Fri Sep 27 17:22:31 2013 -0400
    22.2 +++ b/indra/llcommon/llfasttimer.h	Fri Oct 04 15:36:52 2013 -0400
    22.3 @@ -139,10 +139,11 @@
    22.4  
    22.5  	// used to statically declare a new named timer
    22.6  	class LL_COMMON_API DeclareTimer
    22.7 -	:	public LLInstanceTracker<DeclareTimer>
    22.8 +	:	public LLInstanceTracker< DeclareTimer >
    22.9  	{
   22.10  		friend class LLFastTimer;
   22.11  	public:
   22.12 +
   22.13  		DeclareTimer(const std::string& name, bool open);
   22.14  		DeclareTimer(const std::string& name);
   22.15  
    23.1 --- a/indra/llcommon/llinitparam.h	Fri Sep 27 17:22:31 2013 -0400
    23.2 +++ b/indra/llcommon/llinitparam.h	Fri Oct 04 15:36:52 2013 -0400
    23.3 @@ -1952,7 +1952,7 @@
    23.4  		class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>
    23.5  		{
    23.6  			typedef TypedParam<T, NAME_VALUE_LOOKUP, false>		super_t;
    23.7 -			typedef Mandatory<T, NAME_VALUE_LOOKUP>										self_t;
    23.8 +			typedef Mandatory<T, NAME_VALUE_LOOKUP>				self_t;
    23.9  			typedef typename super_t::value_t					value_t;
   23.10  			typedef typename super_t::default_value_t			default_value_t;
   23.11  
    24.1 --- a/indra/llcommon/llinstancetracker.cpp	Fri Sep 27 17:22:31 2013 -0400
    24.2 +++ b/indra/llcommon/llinstancetracker.cpp	Fri Oct 04 15:36:52 2013 -0400
    24.3 @@ -32,18 +32,3 @@
    24.4  // external library headers
    24.5  // other Linden headers
    24.6  
    24.7 -//static 
    24.8 -void * & LLInstanceTrackerBase::getInstances(std::type_info const & info)
    24.9 -{
   24.10 -	typedef std::map<std::string, void *> InstancesMap;
   24.11 -	static InstancesMap instances;
   24.12 -
   24.13 -	// std::map::insert() is just what we want here. You attempt to insert a
   24.14 -	// (key, value) pair. If the specified key doesn't yet exist, it inserts
   24.15 -	// the pair and returns a std::pair of (iterator, true). If the specified
   24.16 -	// key DOES exist, insert() simply returns (iterator, false). One lookup
   24.17 -	// handles both cases.
   24.18 -	return instances.insert(InstancesMap::value_type(info.name(),
   24.19 -													 InstancesMap::mapped_type()))
   24.20 -		.first->second;
   24.21 -}
    25.1 --- a/indra/llcommon/llinstancetracker.h	Fri Sep 27 17:22:31 2013 -0400
    25.2 +++ b/indra/llcommon/llinstancetracker.h	Fri Oct 04 15:36:52 2013 -0400
    25.3 @@ -46,21 +46,7 @@
    25.4  class LL_COMMON_API LLInstanceTrackerBase
    25.5  {
    25.6  protected:
    25.7 -	/// Get a process-unique void* pointer slot for the specified type_info
    25.8 -	static void * & getInstances(std::type_info const & info);
    25.9  
   25.10 -	/// Find or create a STATICDATA instance for the specified TRACKED class.
   25.11 -	/// STATICDATA must be default-constructible.
   25.12 -	template<typename STATICDATA, class TRACKED>
   25.13 -	static STATICDATA& getStatic()
   25.14 -	{
   25.15 -		void *& instances = getInstances(typeid(TRACKED));
   25.16 -		if (! instances)
   25.17 -		{
   25.18 -			instances = new STATICDATA;
   25.19 -		}
   25.20 -		return *static_cast<STATICDATA*>(instances);
   25.21 -	}
   25.22  
   25.23      /// It's not essential to derive your STATICDATA (for use with
   25.24      /// getStatic()) from StaticBase; it's just that both known
   25.25 @@ -74,6 +60,8 @@
   25.26      };
   25.27  };
   25.28  
   25.29 +LL_COMMON_API void assert_main_thread();
   25.30 +
   25.31  /// This mix-in class adds support for tracking all instances of the specified class parameter T
   25.32  /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup
   25.33  /// If KEY is not provided, then instances are stored in a simple set
   25.34 @@ -81,14 +69,18 @@
   25.35  template<typename T, typename KEY = T*>
   25.36  class LLInstanceTracker : public LLInstanceTrackerBase
   25.37  {
   25.38 -	typedef LLInstanceTracker<T, KEY> MyT;
   25.39 +	typedef LLInstanceTracker<T, KEY> self_t;
   25.40  	typedef typename std::map<KEY, T*> InstanceMap;
   25.41  	struct StaticData: public StaticBase
   25.42  	{
   25.43  		InstanceMap sMap;
   25.44  	};
   25.45 -	static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); }
   25.46 -	static InstanceMap& getMap_() { return getStatic().sMap; }
   25.47 +	static StaticData& getStatic() { static StaticData sData; return sData;}
   25.48 +	static InstanceMap& getMap_() 
   25.49 +	{
   25.50 +		// assert_main_thread();   fwiw this class is not thread safe, and it used by multiple threads.  Bad things happen.
   25.51 +		return getStatic().sMap; 
   25.52 +	}
   25.53  
   25.54  public:
   25.55  	class instance_iter : public boost::iterator_facade<instance_iter, T, boost::forward_traversal_tag>
   25.56 @@ -220,7 +212,11 @@
   25.57  	}
   25.58  	void remove_()
   25.59  	{
   25.60 -		getMap_().erase(mInstanceKey);
   25.61 +		typename InstanceMap::iterator iter = getMap_().find(mInstanceKey);
   25.62 +		if (iter != getMap_().end())
   25.63 +		{
   25.64 +			getMap_().erase(iter);
   25.65 +		}
   25.66  	}
   25.67  
   25.68  private:
   25.69 @@ -232,13 +228,13 @@
   25.70  template<typename T>
   25.71  class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase
   25.72  {
   25.73 -	typedef LLInstanceTracker<T, T*> MyT;
   25.74 +	typedef LLInstanceTracker<T, T*> self_t;
   25.75  	typedef typename std::set<T*> InstanceSet;
   25.76  	struct StaticData: public StaticBase
   25.77  	{
   25.78  		InstanceSet sSet;
   25.79  	};
   25.80 -	static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); }
   25.81 +	static StaticData& getStatic() { static StaticData sData; return sData; }
   25.82  	static InstanceSet& getSet_() { return getStatic().sSet; }
   25.83  
   25.84  public:
    26.1 --- a/indra/llcommon/llleap.h	Fri Sep 27 17:22:31 2013 -0400
    26.2 +++ b/indra/llcommon/llleap.h	Fri Oct 04 15:36:52 2013 -0400
    26.3 @@ -32,6 +32,7 @@
    26.4  class LL_COMMON_API LLLeap: public LLInstanceTracker<LLLeap>
    26.5  {
    26.6  public:
    26.7 +
    26.8      /**
    26.9       * Pass a brief string description, mostly for logging purposes. The desc
   26.10       * need not be unique, but obviously the clearer we can make it, the
    27.1 --- a/indra/llcommon/lllslconstants.h	Fri Sep 27 17:22:31 2013 -0400
    27.2 +++ b/indra/llcommon/lllslconstants.h	Fri Oct 04 15:36:52 2013 -0400
    27.3 @@ -67,6 +67,19 @@
    27.4  const S32 LSL_PRIM_POINT_LIGHT	= 23;
    27.5  const S32 LSL_PRIM_CAST_SHADOWS	= 24;
    27.6  const S32 LSL_PRIM_GLOW     	= 25;
    27.7 +const S32 LSL_PRIM_TEXT			= 26;
    27.8 +const S32 LSL_PRIM_NAME			= 27;
    27.9 +const S32 LSL_PRIM_DESC			= 28;
   27.10 +const S32 LSL_PRIM_ROT_LOCAL	= 29;
   27.11 +const S32 LSL_PRIM_PHYSICS_SHAPE_TYPE	= 30;
   27.12 +const S32 LSL_PRIM_OMEGA		= 32;
   27.13 +const S32 LSL_PRIM_POS_LOCAL	= 33;
   27.14 +const S32 LSL_PRIM_LINK_TARGET	= 34;
   27.15 +const S32 LSL_PRIM_SLICE		= 35;
   27.16 +
   27.17 +const S32 LSL_PRIM_PHYSICS_SHAPE_PRIM	= 0;
   27.18 +const S32 LSL_PRIM_PHYSICS_SHAPE_NONE	= 1;
   27.19 +const S32 LSL_PRIM_PHYSICS_SHAPE_CONVEX	= 2;
   27.20  
   27.21  const S32 LSL_PRIM_TYPE_BOX		= 0;
   27.22  const S32 LSL_PRIM_TYPE_CYLINDER= 1;
   27.23 @@ -179,6 +192,22 @@
   27.24  const S32 OBJECT_OWNER = 6;
   27.25  const S32 OBJECT_GROUP = 7;
   27.26  const S32 OBJECT_CREATOR = 8;
   27.27 +const S32 OBJECT_RUNNING_SCRIPT_COUNT = 9;
   27.28 +const S32 OBJECT_TOTAL_SCRIPT_COUNT = 10;
   27.29 +const S32 OBJECT_SCRIPT_MEMORY = 11;
   27.30 +const S32 OBJECT_SCRIPT_TIME = 12;
   27.31 +const S32 OBJECT_PRIM_EQUIVALENCE = 13;
   27.32 +const S32 OBJECT_SERVER_COST = 14;
   27.33 +const S32 OBJECT_STREAMING_COST = 15;
   27.34 +const S32 OBJECT_PHYSICS_COST = 16;
   27.35 +const S32 OBJECT_CHARACTER_TIME = 17;
   27.36 +const S32 OBJECT_ROOT = 18;
   27.37 +const S32 OBJECT_ATTACHED_POINT = 19;
   27.38 +const S32 OBJECT_PATHFINDING_TYPE = 20;
   27.39 +const S32 OBJECT_PHYSICS = 21;
   27.40 +const S32 OBJECT_PHANTOM = 22;
   27.41 +const S32 OBJECT_TEMP_ON_REZ = 23;
   27.42 +const S32 OBJECT_RENDER_WEIGHT = 24;
   27.43  
   27.44  // llTextBox() magic token string - yes this is a hack.  sue me.
   27.45  char const* const TEXTBOX_MAGIC_TOKEN = "!!llTextBox!!";
    28.1 --- a/indra/llcommon/llmemory.h	Fri Sep 27 17:22:31 2013 -0400
    28.2 +++ b/indra/llcommon/llmemory.h	Fri Oct 04 15:36:52 2013 -0400
    28.3 @@ -36,19 +36,68 @@
    28.4  #define LL_CHECK_MEMORY
    28.5  #endif
    28.6  
    28.7 +LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
    28.8 +
    28.9 +#ifdef SHOW_ASSERT
   28.10 +#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment))
   28.11 +#else
   28.12 +#define ll_assert_aligned(ptr,alignment)
   28.13 +#endif
   28.14 +
   28.15 +#include <xmmintrin.h>
   28.16 +
   28.17 +template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address) 
   28.18 +{ 
   28.19 +	return reinterpret_cast<T*>(
   28.20 +		(reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF);
   28.21 +}
   28.22 +
   28.23 +template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) 
   28.24 +{ 
   28.25 +	return reinterpret_cast<T*>(
   28.26 +		(reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F);
   28.27 +}
   28.28 +
   28.29 +#if LL_LINUX || LL_DARWIN
   28.30 +
   28.31 +#define			LL_ALIGN_PREFIX(x)
   28.32 +#define			LL_ALIGN_POSTFIX(x)		__attribute__((aligned(x)))
   28.33 +
   28.34 +#elif LL_WINDOWS
   28.35 +
   28.36 +#define			LL_ALIGN_PREFIX(x)		__declspec(align(x))
   28.37 +#define			LL_ALIGN_POSTFIX(x)
   28.38 +
   28.39 +#else
   28.40 +#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined"
   28.41 +#endif
   28.42 +
   28.43 +#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16)
   28.44 +
   28.45  inline void* ll_aligned_malloc( size_t size, int align )
   28.46  {
   28.47 +#if defined(LL_WINDOWS)
   28.48 +	return _aligned_malloc(size, align);
   28.49 +#else
   28.50  	void* mem = malloc( size + (align - 1) + sizeof(void*) );
   28.51  	char* aligned = ((char*)mem) + sizeof(void*);
   28.52  	aligned += align - ((uintptr_t)aligned & (align - 1));
   28.53  
   28.54  	((void**)aligned)[-1] = mem;
   28.55  	return aligned;
   28.56 +#endif
   28.57  }
   28.58  
   28.59  inline void ll_aligned_free( void* ptr )
   28.60  {
   28.61 -	free( ((void**)ptr)[-1] );
   28.62 +#if defined(LL_WINDOWS)
   28.63 +	_aligned_free(ptr);
   28.64 +#else
   28.65 +	if (ptr)
   28.66 +	{
   28.67 +		free( ((void**)ptr)[-1] );
   28.68 +	}
   28.69 +#endif
   28.70  }
   28.71  
   28.72  #if !LL_USE_TCMALLOC
   28.73 @@ -133,6 +182,78 @@
   28.74  #endif
   28.75  }
   28.76  
   28.77 +
   28.78 +// Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP. 
   28.79 +// Source and dest must be 16-byte aligned and size must be multiple of 16.
   28.80 +//
   28.81 +inline void ll_memcpy_nonaliased_aligned_16(char* __restrict dst, const char* __restrict src, size_t bytes)
   28.82 +{
   28.83 +	assert(src != NULL);
   28.84 +	assert(dst != NULL);
   28.85 +	assert(bytes > 0);
   28.86 +	assert((bytes % sizeof(F32))== 0); 
   28.87 +	ll_assert_aligned(src,16);
   28.88 +	ll_assert_aligned(dst,16);
   28.89 +	assert((src < dst) ? ((src + bytes) < dst) : ((dst + bytes) < src));
   28.90 +	assert(bytes%16==0);
   28.91 +
   28.92 +	char* end = dst + bytes;
   28.93 +
   28.94 +	if (bytes > 64)
   28.95 +	{
   28.96 +
   28.97 +		// Find start of 64b aligned area within block
   28.98 +		//
   28.99 +		void* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst);
  28.100 +		
  28.101 +		//at least 64 bytes before the end of the destination, switch to 16 byte copies
  28.102 +		void* end_64 = end-64;
  28.103 +	
  28.104 +		// Prefetch the head of the 64b area now
  28.105 +		//
  28.106 +		_mm_prefetch((char*)begin_64, _MM_HINT_NTA);
  28.107 +		_mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA);
  28.108 +		_mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA);
  28.109 +		_mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA);
  28.110 +	
  28.111 +		// Copy 16b chunks until we're 64b aligned
  28.112 +		//
  28.113 +		while (dst < begin_64)
  28.114 +		{
  28.115 +
  28.116 +			_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
  28.117 +			dst += 16;
  28.118 +			src += 16;
  28.119 +		}
  28.120 +	
  28.121 +		// Copy 64b chunks up to your tail
  28.122 +		//
  28.123 +		// might be good to shmoo the 512b prefetch offset
  28.124 +		// (characterize performance for various values)
  28.125 +		//
  28.126 +		while (dst < end_64)
  28.127 +		{
  28.128 +			_mm_prefetch((char*)src + 512, _MM_HINT_NTA);
  28.129 +			_mm_prefetch((char*)dst + 512, _MM_HINT_NTA);
  28.130 +			_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
  28.131 +			_mm_store_ps((F32*)(dst + 16), _mm_load_ps((F32*)(src + 16)));
  28.132 +			_mm_store_ps((F32*)(dst + 32), _mm_load_ps((F32*)(src + 32)));
  28.133 +			_mm_store_ps((F32*)(dst + 48), _mm_load_ps((F32*)(src + 48)));
  28.134 +			dst += 64;
  28.135 +			src += 64;
  28.136 +		}
  28.137 +	}
  28.138 +
  28.139 +	// Copy remainder 16b tail chunks (or ALL 16b chunks for sub-64b copies)
  28.140 +	//
  28.141 +	while (dst < end)
  28.142 +	{
  28.143 +		_mm_store_ps((F32*)dst, _mm_load_ps((F32*)src));
  28.144 +		dst += 16;
  28.145 +		src += 16;
  28.146 +	}
  28.147 +}
  28.148 +
  28.149  #ifndef __DEBUG_PRIVATE_MEM__
  28.150  #define __DEBUG_PRIVATE_MEM__  0
  28.151  #endif
  28.152 @@ -541,13 +662,7 @@
  28.153  
  28.154  // LLSingleton moved to llsingleton.h
  28.155  
  28.156 -LL_COMMON_API void ll_assert_aligned_func(uintptr_t ptr,U32 alignment);
  28.157  
  28.158 -#ifdef SHOW_ASSERT
  28.159 -#define ll_assert_aligned(ptr,alignment) ll_assert_aligned_func(reinterpret_cast<uintptr_t>(ptr),((U32)alignment))
  28.160 -#else
  28.161 -#define ll_assert_aligned(ptr,alignment)
  28.162 -#endif
  28.163  
  28.164  
  28.165  #endif
    29.1 --- a/indra/llcommon/llsingleton.cpp	Fri Sep 27 17:22:31 2013 -0400
    29.2 +++ b/indra/llcommon/llsingleton.cpp	Fri Oct 04 15:36:52 2013 -0400
    29.3 @@ -28,5 +28,4 @@
    29.4  
    29.5  #include "llsingleton.h"
    29.6  
    29.7 -std::map<std::string, void *> * LLSingletonRegistry::sSingletonMap = NULL;
    29.8  
    30.1 --- a/indra/llcommon/llsingleton.h	Fri Sep 27 17:22:31 2013 -0400
    30.2 +++ b/indra/llcommon/llsingleton.h	Fri Oct 04 15:36:52 2013 -0400
    30.3 @@ -30,38 +30,6 @@
    30.4  #include <typeinfo>
    30.5  #include <boost/noncopyable.hpp>
    30.6  
    30.7 -/// @brief A global registry of all singletons to prevent duplicate allocations
    30.8 -/// across shared library boundaries
    30.9 -class LL_COMMON_API LLSingletonRegistry {
   30.10 -	private:
   30.11 -		typedef std::map<std::string, void *> TypeMap;
   30.12 -		static TypeMap * sSingletonMap;
   30.13 -
   30.14 -		static void checkInit()
   30.15 -		{
   30.16 -			if(sSingletonMap == NULL)
   30.17 -			{
   30.18 -				sSingletonMap = new TypeMap();
   30.19 -			}
   30.20 -		}
   30.21 -
   30.22 -	public:
   30.23 -		template<typename T> static void * & get()
   30.24 -		{
   30.25 -			std::string name(typeid(T).name());
   30.26 -
   30.27 -			checkInit();
   30.28 -
   30.29 -			// the first entry of the pair returned by insert will be either the existing
   30.30 -			// iterator matching our key, or the newly inserted NULL initialized entry
   30.31 -			// see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
   30.32 -			TypeMap::iterator result =
   30.33 -				sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first;
   30.34 -
   30.35 -			return result->second;
   30.36 -		}
   30.37 -};
   30.38 -
   30.39  // LLSingleton implements the getInstance() method part of the Singleton
   30.40  // pattern. It can't make the derived class constructors protected, though, so
   30.41  // you have to do that yourself.
   30.42 @@ -101,20 +69,23 @@
   30.43  	} EInitState;
   30.44  	
   30.45  	// stores pointer to singleton instance
   30.46 -	// and tracks initialization state of singleton
   30.47 -	struct SingletonInstanceData
   30.48 +	struct SingletonLifetimeManager
   30.49  	{
   30.50 -		EInitState		mInitState;
   30.51 -		DERIVED_TYPE*	mSingletonInstance;
   30.52 -		
   30.53 -		SingletonInstanceData()
   30.54 -		:	mSingletonInstance(NULL),
   30.55 -			mInitState(UNINITIALIZED)
   30.56 -		{}
   30.57 +		SingletonLifetimeManager()
   30.58 +		{
   30.59 +			construct();
   30.60 +		}
   30.61  
   30.62 -		~SingletonInstanceData()
   30.63 +		static void construct()
   30.64  		{
   30.65 -			if (mInitState != DELETED)
   30.66 +			sData.mInitState = CONSTRUCTING;
   30.67 +			sData.mInstance = new DERIVED_TYPE(); 
   30.68 +			sData.mInitState = INITIALIZING;
   30.69 +		}
   30.70 +
   30.71 +		~SingletonLifetimeManager()
   30.72 +		{
   30.73 +			if (sData.mInitState != DELETED)
   30.74  			{
   30.75  				deleteSingleton();
   30.76  			}
   30.77 @@ -124,9 +95,8 @@
   30.78  public:
   30.79  	virtual ~LLSingleton()
   30.80  	{
   30.81 -		SingletonInstanceData& data = getData();
   30.82 -		data.mSingletonInstance = NULL;
   30.83 -		data.mInitState = DELETED;
   30.84 +		sData.mInstance = NULL;
   30.85 +		sData.mInitState = DELETED;
   30.86  	}
   30.87  
   30.88  	/**
   30.89 @@ -151,50 +121,46 @@
   30.90  	 */
   30.91  	static void deleteSingleton()
   30.92  	{
   30.93 -		delete getData().mSingletonInstance;
   30.94 -		getData().mSingletonInstance = NULL;
   30.95 -		getData().mInitState = DELETED;
   30.96 +		delete sData.mInstance;
   30.97 +		sData.mInstance = NULL;
   30.98 +		sData.mInitState = DELETED;
   30.99  	}
  30.100  
  30.101 -	static SingletonInstanceData& getData()
  30.102 -	{
  30.103 -		// this is static to cache the lookup results
  30.104 -		static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>();
  30.105 -
  30.106 -		// *TODO - look into making this threadsafe
  30.107 -		if(NULL == registry)
  30.108 -		{
  30.109 -			static SingletonInstanceData data;
  30.110 -			registry = &data;
  30.111 -		}
  30.112 -
  30.113 -		return *static_cast<SingletonInstanceData *>(registry);
  30.114 -	}
  30.115  
  30.116  	static DERIVED_TYPE* getInstance()
  30.117  	{
  30.118 -		SingletonInstanceData& data = getData();
  30.119 +		static SingletonLifetimeManager sLifeTimeMgr;
  30.120  
  30.121 -		if (data.mInitState == CONSTRUCTING)
  30.122 +		switch (sData.mInitState)
  30.123  		{
  30.124 +		case UNINITIALIZED:
  30.125 +			// should never be uninitialized at this point
  30.126 +			llassert(false);
  30.127 +			return NULL;
  30.128 +		case CONSTRUCTING:
  30.129  			llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl;
  30.130 +			return NULL;
  30.131 +		case INITIALIZING:
  30.132 +			// go ahead and flag ourselves as initialized so we can be reentrant during initialization
  30.133 +			sData.mInitState = INITIALIZED;	
  30.134 +			sData.mInstance->initSingleton(); 
  30.135 +			return sData.mInstance;
  30.136 +		case INITIALIZED:
  30.137 +			return sData.mInstance;
  30.138 +		case DELETED:
  30.139 +			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
  30.140 +			SingletonLifetimeManager::construct();
  30.141 +			sData.mInitState = INITIALIZED;	
  30.142 +			sData.mInstance->initSingleton(); 
  30.143 +			return sData.mInstance;
  30.144  		}
  30.145  
  30.146 -		if (data.mInitState == DELETED)
  30.147 -		{
  30.148 -			llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl;
  30.149 -		}
  30.150 -		
  30.151 -		if (!data.mSingletonInstance) 
  30.152 -		{
  30.153 -			data.mInitState = CONSTRUCTING;
  30.154 -			data.mSingletonInstance = new DERIVED_TYPE(); 
  30.155 -			data.mInitState = INITIALIZING;
  30.156 -			data.mSingletonInstance->initSingleton(); 
  30.157 -			data.mInitState = INITIALIZED;	
  30.158 -		}
  30.159 -		
  30.160 -		return data.mSingletonInstance;
  30.161 +		return NULL;
  30.162 +	}
  30.163 +
  30.164 +	static DERIVED_TYPE* getIfExists()
  30.165 +	{
  30.166 +		return sData.mInstance;
  30.167  	}
  30.168  
  30.169  	// Reference version of getInstance()
  30.170 @@ -208,18 +174,29 @@
  30.171  	// Use this to avoid accessing singletons before the can safely be constructed
  30.172  	static bool instanceExists()
  30.173  	{
  30.174 -		return getData().mInitState == INITIALIZED;
  30.175 +		return sData.mInitState == INITIALIZED;
  30.176  	}
  30.177  	
  30.178  	// Has this singleton already been deleted?
  30.179  	// Use this to avoid accessing singletons from a static object's destructor
  30.180  	static bool destroyed()
  30.181  	{
  30.182 -		return getData().mInitState == DELETED;
  30.183 +		return sData.mInitState == DELETED;
  30.184  	}
  30.185  
  30.186  private:
  30.187 +
  30.188  	virtual void initSingleton() {}
  30.189 +
  30.190 +	struct SingletonData
  30.191 +	{
  30.192 +		EInitState		mInitState;
  30.193 +		DERIVED_TYPE*	mInstance;
  30.194 +	};
  30.195 +	static SingletonData sData;
  30.196  };
  30.197  
  30.198 +template<typename T>
  30.199 +typename LLSingleton<T>::SingletonData LLSingleton<T>::sData;
  30.200 +
  30.201  #endif
    31.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    31.2 +++ b/indra/llcommon/llstaticstringtable.h	Fri Oct 04 15:36:52 2013 -0400
    31.3 @@ -0,0 +1,82 @@
    31.4 +/** 
    31.5 + * @file llstringtable.h
    31.6 + * @brief The LLStringTable class provides a _fast_ method for finding
    31.7 + * unique copies of strings.
    31.8 + *
    31.9 + * $LicenseInfo:firstyear=2001&license=viewerlgpl$
   31.10 + * Second Life Viewer Source Code
   31.11 + * Copyright (C) 2010, Linden Research, Inc.
   31.12 + * 
   31.13 + * This library is free software; you can redistribute it and/or
   31.14 + * modify it under the terms of the GNU Lesser General Public
   31.15 + * License as published by the Free Software Foundation;
   31.16 + * version 2.1 of the License only.
   31.17 + * 
   31.18 + * This library is distributed in the hope that it will be useful,
   31.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   31.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   31.21 + * Lesser General Public License for more details.
   31.22 + * 
   31.23 + * You should have received a copy of the GNU Lesser General Public
   31.24 + * License along with this library; if not, write to the Free Software
   31.25 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
   31.26 + * 
   31.27 + * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
   31.28 + * $/LicenseInfo$
   31.29 + */
   31.30 +
   31.31 +#ifndef LL_STATIC_STRING_TABLE_H
   31.32 +#define LL_STATIC_STRING_TABLE_H
   31.33 +
   31.34 +#include "lldefs.h"
   31.35 +#include <boost/unordered_map.hpp>
   31.36 +#include "llstl.h"
   31.37 +
   31.38 +class LLStaticHashedString
   31.39 +{
   31.40 +public:
   31.41 +
   31.42 +	LLStaticHashedString(const std::string& s)
   31.43 +	{
   31.44 +		string_hash = makehash(s);
   31.45 +		string		= s;
   31.46 +	}
   31.47 +
   31.48 +	const std::string&	String() const { return string;		}
   31.49 +	size_t				Hash()	 const { return string_hash;  }
   31.50 +
   31.51 +	bool operator==(const LLStaticHashedString& b) const { return Hash() == b.Hash(); }
   31.52 +
   31.53 +protected:
   31.54 +
   31.55 +	size_t makehash(const std::string& s)
   31.56 +	{
   31.57 +		size_t len = s.size();
   31.58 +		const char* c = s.c_str();
   31.59 +		size_t hashval = 0;
   31.60 +		for (size_t i=0; i<len; i++)
   31.61 +		{
   31.62 +			hashval = ((hashval<<5) + hashval) + *c++;
   31.63 +		}
   31.64 +		return hashval;
   31.65 +	}
   31.66 +
   31.67 +	std::string string;
   31.68 +	size_t		string_hash;
   31.69 +};
   31.70 +
   31.71 +struct LLStaticStringHasher
   31.72 +{
   31.73 +	enum { bucket_size = 8 };
   31.74 +	size_t operator()(const LLStaticHashedString& key_value) const { return key_value.Hash(); }
   31.75 +	bool   operator()(const LLStaticHashedString& left, const LLStaticHashedString& right) const { return left.Hash() < right.Hash(); }
   31.76 +};
   31.77 +
   31.78 +template< typename MappedObject >
   31.79 +class LL_COMMON_API LLStaticStringTable
   31.80 +	: public boost::unordered_map< LLStaticHashedString, MappedObject, LLStaticStringHasher >
   31.81 +{
   31.82 +};
   31.83 +
   31.84 +#endif
   31.85 +
    32.1 --- a/indra/llcommon/llstringtable.h	Fri Sep 27 17:22:31 2013 -0400
    32.2 +++ b/indra/llcommon/llstringtable.h	Fri Oct 04 15:36:52 2013 -0400
    32.3 @@ -42,14 +42,6 @@
    32.4  //# define STRING_TABLE_HASH_MAP 1
    32.5  #endif
    32.6  
    32.7 -#if STRING_TABLE_HASH_MAP
    32.8 -# if LL_WINDOWS
    32.9 -#  include <hash_map>
   32.10 -# else
   32.11 -#  include <ext/hash_map>
   32.12 -# endif
   32.13 -#endif
   32.14 -
   32.15  const U32 MAX_STRINGS_LENGTH = 256;
   32.16  
   32.17  class LL_COMMON_API LLStringTableEntry
    33.1 --- a/indra/llcommon/llthread.cpp	Fri Sep 27 17:22:31 2013 -0400
    33.2 +++ b/indra/llcommon/llthread.cpp	Fri Oct 04 15:36:52 2013 -0400
    33.3 @@ -67,7 +67,8 @@
    33.4  	static U32 s_thread_id = LLThread::currentID();
    33.5  	if (LLThread::currentID() != s_thread_id)
    33.6  	{
    33.7 -		llerrs << "Illegal execution outside main thread." << llendl;
    33.8 +		llwarns << "Illegal execution from thread id " << (S32) LLThread::currentID()
    33.9 +			<< " outside main thread " << (S32) s_thread_id << llendl;
   33.10  	}
   33.11  }
   33.12  
   33.13 @@ -525,15 +526,7 @@
   33.14  
   33.15  LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)
   33.16  {
   33.17 -	if (sMutex)
   33.18 -	{
   33.19 -		sMutex->lock();
   33.20 -	}
   33.21  	mRef = 0;
   33.22 -	if (sMutex)
   33.23 -	{
   33.24 -		sMutex->unlock();
   33.25 -	}
   33.26  }
   33.27  
   33.28  LLThreadSafeRefCount::~LLThreadSafeRefCount()
    34.1 --- a/indra/llcommon/llthread.h	Fri Sep 27 17:22:31 2013 -0400
    34.2 +++ b/indra/llcommon/llthread.h	Fri Oct 04 15:36:52 2013 -0400
    34.3 @@ -284,49 +284,39 @@
    34.4  	LLThreadSafeRefCount(const LLThreadSafeRefCount&);
    34.5  	LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref) 
    34.6  	{
    34.7 -		if (sMutex)
    34.8 -		{
    34.9 -			sMutex->lock();
   34.10 -		}
   34.11  		mRef = 0;
   34.12 -		if (sMutex)
   34.13 -		{
   34.14 -			sMutex->unlock();
   34.15 -		}
   34.16  		return *this;
   34.17  	}
   34.18  
   34.19 -
   34.20 -	
   34.21  	void ref()
   34.22  	{
   34.23 -		if (sMutex) sMutex->lock();
   34.24  		mRef++; 
   34.25 -		if (sMutex) sMutex->unlock();
   34.26  	} 
   34.27  
   34.28 -	S32 unref()
   34.29 +	void unref()
   34.30  	{
   34.31  		llassert(mRef >= 1);
   34.32 -		if (sMutex) sMutex->lock();
   34.33 -		S32 res = --mRef;
   34.34 -		if (sMutex) sMutex->unlock();
   34.35 -		if (0 == res) 
   34.36 -		{
   34.37 -			delete this; 
   34.38 -			return 0;
   34.39 +		if ((--mRef) == 0)		// See note in llapr.h on atomic decrement operator return value.  
   34.40 +		{	
   34.41 +			// If we hit zero, the caller should be the only smart pointer owning the object and we can delete it.
   34.42 +			// It is technically possible for a vanilla pointer to mess this up, or another thread to
   34.43 +			// jump in, find this object, create another smart pointer and end up dangling, but if
   34.44 +			// the code is that bad and not thread-safe, it's trouble already.
   34.45 +			delete this;
   34.46  		}
   34.47 -		return res;
   34.48 -	}	
   34.49 +	}
   34.50 +
   34.51  	S32 getNumRefs() const
   34.52  	{
   34.53 -		return mRef;
   34.54 +		const S32 currentVal = mRef.CurrentValue();
   34.55 +		return currentVal;
   34.56  	}
   34.57  
   34.58  private: 
   34.59 -	S32	mRef; 
   34.60 +	LLAtomic32< S32	> mRef; 
   34.61  };
   34.62  
   34.63 +
   34.64  /**
   34.65   * intrusive pointer support for LLThreadSafeRefCount
   34.66   * this allows you to use boost::intrusive_ptr with any LLThreadSafeRefCount-derived type
   34.67 @@ -357,4 +347,6 @@
   34.68  
   34.69  //============================================================================
   34.70  
   34.71 +extern LL_COMMON_API void assert_main_thread();
   34.72 +
   34.73  #endif // LL_LLTHREAD_H
    35.1 --- a/indra/llcorehttp/_httpinternal.h	Fri Sep 27 17:22:31 2013 -0400
    35.2 +++ b/indra/llcorehttp/_httpinternal.h	Fri Oct 04 15:36:52 2013 -0400
    35.3 @@ -159,9 +159,6 @@
    35.4  // Block allocation size (a tuning parameter) is found
    35.5  // in bufferarray.h.
    35.6  
    35.7 -// Compatibility controls
    35.8 -const bool HTTP_ENABLE_LINKSYS_WRT54G_V5_DNS_FIX = true;
    35.9 -
   35.10  }  // end namespace LLCore
   35.11  
   35.12  #endif	// _LLCORE_HTTP_INTERNAL_H_
    36.1 --- a/indra/llcorehttp/_httpoprequest.cpp	Fri Sep 27 17:22:31 2013 -0400
    36.2 +++ b/indra/llcorehttp/_httpoprequest.cpp	Fri Oct 04 15:36:52 2013 -0400
    36.3 @@ -204,9 +204,11 @@
    36.4  	if (mReplyLength)
    36.5  	{
    36.6  		// If non-zero, we received and processed a Content-Range
    36.7 -		// header with the response.  Verify that what it says
    36.8 -		// is consistent with the received data.
    36.9 -		if (mReplyLength != mReplyBody->size())
   36.10 +		// header with the response.  If there is received data
   36.11 +		// (and there may not be due to protocol violations,
   36.12 +		// HEAD requests, etc., see BUG-2295) Verify that what it
   36.13 +		// says is consistent with the received data.
   36.14 +		if (mReplyBody && mReplyBody->size() && mReplyLength != mReplyBody->size())
   36.15  		{
   36.16  			// Not as expected, fail the request
   36.17  			mStatus = HttpStatus(HttpStatus::LLCORE, HE_INV_CONTENT_RANGE_HDR);
   36.18 @@ -367,7 +369,6 @@
   36.19  	}
   36.20  }
   36.21  
   36.22 -
   36.23  // Sets all libcurl options and data for a request.
   36.24  //
   36.25  // Used both for initial requests and to 'reload' for
   36.26 @@ -411,7 +412,7 @@
   36.27  	// Get global policy options
   36.28  	HttpPolicyGlobal & policy(service->getPolicy().getGlobalOptions());
   36.29  	
   36.30 -	mCurlHandle = curl_easy_init();
   36.31 +	mCurlHandle = LLCurl::createStandardCurlHandle();
   36.32  	if (! mCurlHandle)
   36.33  	{
   36.34  		// We're in trouble.  We'll continue but it won't go well.
   36.35 @@ -432,26 +433,14 @@
   36.36  	code = curl_easy_setopt(mCurlHandle, CURLOPT_ENCODING, "");
   36.37  	check_curl_easy_code(code, CURLOPT_ENCODING);
   36.38  
   36.39 -	if (HTTP_ENABLE_LINKSYS_WRT54G_V5_DNS_FIX)
   36.40 -	{
   36.41 -		// The Linksys WRT54G V5 router has an issue with frequent
   36.42 -		// DNS lookups from LAN machines.  If they happen too often,
   36.43 -		// like for every HTTP request, the router gets annoyed after
   36.44 -		// about 700 or so requests and starts issuing TCP RSTs to
   36.45 -		// new connections.  Reuse the DNS lookups for even a few
   36.46 -		// seconds and no RSTs.
   36.47 -		code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
   36.48 -		check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
   36.49 -	}
   36.50 -	else
   36.51 -	{
   36.52 -		// *TODO:  Revisit this old DNS timeout setting - may no longer be valid
   36.53 -		// I don't think this is valid anymore, the Multi shared DNS
   36.54 -		// cache is working well.  For the case of naked easy handles,
   36.55 -		// consider using a shared DNS object.
   36.56 -		code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 0);
   36.57 -		check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
   36.58 -	}
   36.59 +	// The Linksys WRT54G V5 router has an issue with frequent
   36.60 +	// DNS lookups from LAN machines.  If they happen too often,
   36.61 +	// like for every HTTP request, the router gets annoyed after
   36.62 +	// about 700 or so requests and starts issuing TCP RSTs to
   36.63 +	// new connections.  Reuse the DNS lookups for even a few
   36.64 +	// seconds and no RSTs.
   36.65 +	code = curl_easy_setopt(mCurlHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
   36.66 +	check_curl_easy_code(code, CURLOPT_DNS_CACHE_TIMEOUT);
   36.67  	code = curl_easy_setopt(mCurlHandle, CURLOPT_AUTOREFERER, 1);
   36.68  	check_curl_easy_code(code, CURLOPT_AUTOREFERER);
   36.69  	code = curl_easy_setopt(mCurlHandle, CURLOPT_FOLLOWLOCATION, 1);
   36.70 @@ -831,7 +820,7 @@
   36.71  	std::string safe_line;
   36.72  	std::string tag;
   36.73  	bool logit(false);
   36.74 -	len = (std::min)(len, size_t(256));					// Keep things reasonable in all cases
   36.75 +	const size_t log_len((std::min)(len, size_t(256)));		// Keep things reasonable in all cases
   36.76  	
   36.77  	switch (info)
   36.78  	{
   36.79 @@ -839,7 +828,7 @@
   36.80  		if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
   36.81  		{
   36.82  			tag = "TEXT";
   36.83 -			escape_libcurl_debug_data(buffer, len, true, safe_line);
   36.84 +			escape_libcurl_debug_data(buffer, log_len, true, safe_line);
   36.85  			logit = true;
   36.86  		}
   36.87  		break;
   36.88 @@ -848,7 +837,7 @@
   36.89  		if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
   36.90  		{
   36.91  			tag = "HEADERIN";
   36.92 -			escape_libcurl_debug_data(buffer, len, true, safe_line);
   36.93 +			escape_libcurl_debug_data(buffer, log_len, true, safe_line);
   36.94  			logit = true;
   36.95  		}
   36.96  		break;
   36.97 @@ -857,7 +846,7 @@
   36.98  		if (op->mTracing >= HTTP_TRACE_CURL_HEADERS)
   36.99  		{
  36.100  			tag = "HEADEROUT";
  36.101 -			escape_libcurl_debug_data(buffer, 2 * len, true, safe_line);		// Goes out as one line
  36.102 +			escape_libcurl_debug_data(buffer, log_len, true, safe_line);	// Goes out as one line unlike header_in
  36.103  			logit = true;
  36.104  		}
  36.105  		break;
  36.106 @@ -869,7 +858,7 @@
  36.107  			logit = true;
  36.108  			if (op->mTracing >= HTTP_TRACE_CURL_BODIES)
  36.109  			{
  36.110 -				escape_libcurl_debug_data(buffer, len, false, safe_line);
  36.111 +				escape_libcurl_debug_data(buffer, log_len, false, safe_line);
  36.112  			}
  36.113  			else
  36.114  			{
  36.115 @@ -887,7 +876,7 @@
  36.116  			logit = true;
  36.117  			if (op->mTracing >= HTTP_TRACE_CURL_BODIES)
  36.118  			{
  36.119 -				escape_libcurl_debug_data(buffer, len, false, safe_line);
  36.120 +				escape_libcurl_debug_data(buffer, log_len, false, safe_line);
  36.121  			}
  36.122  			else
  36.123  			{
    37.1 --- a/indra/llcorehttp/_httpoprequest.h	Fri Sep 27 17:22:31 2013 -0400
    37.2 +++ b/indra/llcorehttp/_httpoprequest.h	Fri Oct 04 15:36:52 2013 -0400
    37.3 @@ -60,7 +60,6 @@
    37.4  /// the information needed to make a working request which can
    37.5  /// then be enqueued to a request queue.
    37.6  ///
    37.7 -
    37.8  class HttpOpRequest : public HttpOperation
    37.9  {
   37.10  public:
    38.1 --- a/indra/llcorehttp/_httppolicy.cpp	Fri Sep 27 17:22:31 2013 -0400
    38.2 +++ b/indra/llcorehttp/_httppolicy.cpp	Fri Oct 04 15:36:52 2013 -0400
    38.3 @@ -388,33 +388,13 @@
    38.4  
    38.5  bool HttpPolicy::stageAfterCompletion(HttpOpRequest * op)
    38.6  {
    38.7 -	static const HttpStatus cant_connect(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);
    38.8 -	static const HttpStatus cant_res_proxy(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_PROXY);
    38.9 -	static const HttpStatus cant_res_host(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_HOST);
   38.10 -	static const HttpStatus send_error(HttpStatus::EXT_CURL_EASY, CURLE_SEND_ERROR);
   38.11 -	static const HttpStatus recv_error(HttpStatus::EXT_CURL_EASY, CURLE_RECV_ERROR);
   38.12 -	static const HttpStatus upload_failed(HttpStatus::EXT_CURL_EASY, CURLE_UPLOAD_FAILED);
   38.13 -	static const HttpStatus op_timedout(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);
   38.14 -	static const HttpStatus post_error(HttpStatus::EXT_CURL_EASY, CURLE_HTTP_POST_ERROR);
   38.15 -
   38.16  	// Retry or finalize
   38.17  	if (! op->mStatus)
   38.18  	{
   38.19 -		// If this failed, we might want to retry.  Have to inspect
   38.20 -		// the status a little more deeply for those reasons worth retrying...
   38.21 -		if (op->mPolicyRetries < op->mPolicyRetryLimit &&
   38.22 -			((op->mStatus.isHttpStatus() && op->mStatus.mType >= 499 && op->mStatus.mType <= 599) ||
   38.23 -			 cant_connect == op->mStatus ||
   38.24 -			 cant_res_proxy == op->mStatus ||
   38.25 -			 cant_res_host == op->mStatus ||
   38.26 -			 send_error == op->mStatus ||
   38.27 -			 recv_error == op->mStatus ||
   38.28 -			 upload_failed == op->mStatus ||
   38.29 -			 op_timedout == op->mStatus ||
   38.30 -			 post_error == op->mStatus))
   38.31 +		// If this failed, we might want to retry.
   38.32 +		if (op->mPolicyRetries < op->mPolicyRetryLimit && op->mStatus.isRetryable())
   38.33  		{
   38.34 -			// Okay, worth a retry.  We include 499 in this test as
   38.35 -			// it's the old 'who knows?' error from many grid services...
   38.36 +			// Okay, worth a retry.
   38.37  			retryOp(op);
   38.38  			return true;				// still active/ready
   38.39  		}
    39.1 --- a/indra/llcorehttp/httpcommon.cpp	Fri Sep 27 17:22:31 2013 -0400
    39.2 +++ b/indra/llcorehttp/httpcommon.cpp	Fri Oct 04 15:36:52 2013 -0400
    39.3 @@ -117,6 +117,7 @@
    39.4  			{ 415, "Unsupported Media Type" },
    39.5  			{ 416, "Requested range not satisfiable" },
    39.6  			{ 417, "Expectation Failed" },
    39.7 +			{ 499, "Linden Catch-All" },
    39.8  			{ 500, "Internal Server Error" },
    39.9  			{ 501, "Not Implemented" },
   39.10  			{ 502, "Bad Gateway" },
   39.11 @@ -215,6 +216,34 @@
   39.12  }
   39.13  
   39.14  
   39.15 -		
   39.16 +// Pass true on statuses that might actually be cleared by a
   39.17 +// retry.  Library failures, calling problems, etc. aren't
   39.18 +// going to be fixed by squirting bits all over the Net.
   39.19 +bool HttpStatus::isRetryable() const
   39.20 +{
   39.21 +	static const HttpStatus cant_connect(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_CONNECT);
   39.22 +	static const HttpStatus cant_res_proxy(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_PROXY);
   39.23 +	static const HttpStatus cant_res_host(HttpStatus::EXT_CURL_EASY, CURLE_COULDNT_RESOLVE_HOST);
   39.24 +	static const HttpStatus send_error(HttpStatus::EXT_CURL_EASY, CURLE_SEND_ERROR);
   39.25 +	static const HttpStatus recv_error(HttpStatus::EXT_CURL_EASY, CURLE_RECV_ERROR);
   39.26 +	static const HttpStatus upload_failed(HttpStatus::EXT_CURL_EASY, CURLE_UPLOAD_FAILED);
   39.27 +	static const HttpStatus op_timedout(HttpStatus::EXT_CURL_EASY, CURLE_OPERATION_TIMEDOUT);
   39.28 +	static const HttpStatus post_error(HttpStatus::EXT_CURL_EASY, CURLE_HTTP_POST_ERROR);
   39.29 +	static const HttpStatus partial_file(HttpStatus::EXT_CURL_EASY, CURLE_PARTIAL_FILE);
   39.30 +	static const HttpStatus inv_cont_range(HttpStatus::LLCORE, HE_INV_CONTENT_RANGE_HDR);
   39.31 +
   39.32 +	return ((isHttpStatus() && mType >= 499 && mType <= 599) ||	// Include special 499 in retryables
   39.33 +			*this == cant_connect ||	// Connection reset/endpoint problems
   39.34 +			*this == cant_res_proxy ||	// DNS problems
   39.35 +			*this == cant_res_host ||	// DNS problems
   39.36 +			*this == send_error ||		// General socket problems 
   39.37 +			*this == recv_error ||		// General socket problems 
   39.38 +			*this == upload_failed ||	// Transport problem
   39.39 +			*this == op_timedout ||		// Timer expired
   39.40 +			*this == post_error ||		// Transport problem
   39.41 +			*this == partial_file ||	// Data inconsistency in response
   39.42 +			*this == inv_cont_range);	// Short data read disagrees with content-range
   39.43 +}
   39.44 +
   39.45  } // end namespace LLCore
   39.46  
    40.1 --- a/indra/llcorehttp/httpcommon.h	Fri Sep 27 17:22:31 2013 -0400
    40.2 +++ b/indra/llcorehttp/httpcommon.h	Fri Oct 04 15:36:52 2013 -0400
    40.3 @@ -397,6 +397,12 @@
    40.4  	{
    40.5  		return 	mType >= type_enum_t(100) && mType <= type_enum_t(999);
    40.6  	}
    40.7 +
    40.8 +	/// Returns true if the status is one that will be retried
    40.9 +	/// internally.  Provided for external consumption for cases
   40.10 +	/// where that logic needs to be replicated.  Only applies
   40.11 +	/// to failed statuses, successful statuses will return false.
   40.12 +	bool isRetryable() const;
   40.13  	
   40.14  }; // end struct HttpStatus
   40.15  
    41.1 --- a/indra/llcorehttp/httpresponse.h	Fri Sep 27 17:22:31 2013 -0400
    41.2 +++ b/indra/llcorehttp/httpresponse.h	Fri Oct 04 15:36:52 2013 -0400
    41.3 @@ -48,8 +48,9 @@
    41.4  /// individual pieces of the response.
    41.5  ///
    41.6  /// Typical usage will have the caller interrogate the object
    41.7 -/// and return from the handler callback.  Instances are refcounted
    41.8 -/// and callers can bump the count and retain the object as needed.
    41.9 +/// during the handler callback and then simply returning.
   41.10 +/// But instances are refcounted and and callers can add a
   41.11 +/// reference and hold onto the object after the callback.
   41.12  ///
   41.13  /// Threading:  Not intrinsically thread-safe.
   41.14  ///
   41.15 @@ -119,6 +120,10 @@
   41.16  	/// caller is going to have to make assumptions on receipt of
   41.17  	/// a 206 status.  The @full value may also be zero in cases of
   41.18  	/// parsing problems or a wild-carded length response.
   41.19 +	///
   41.20 +	/// These values will not necessarily agree with the data in
   41.21 +	/// the body itself (if present).  The BufferArray object
   41.22 +	/// is authoritative for actual data length.
   41.23  	void getRange(unsigned int * offset, unsigned int * length, unsigned int * full) const
   41.24  		{
   41.25  			*offset = mReplyOffset;
    42.1 --- a/indra/llcorehttp/tests/test_httprequest.hpp	Fri Sep 27 17:22:31 2013 -0400
    42.2 +++ b/indra/llcorehttp/tests/test_httprequest.hpp	Fri Oct 04 15:36:52 2013 -0400
    42.3 @@ -45,6 +45,15 @@
    42.4  
    42.5  using namespace LLCoreInt;
    42.6  
    42.7 +// spin/sleep waiting times for client/server exchange tests
    42.8 +//
    42.9 +// These are now fairly generous to try to get around timeout
   42.10 +// ('reasonable time') failures during execution on a heavily-
   42.11 +// loaded system where the unit test is in competition with
   42.12 +// other programs.
   42.13 +static const int LOOP_SLEEP_INTERVAL(10000);
   42.14 +static const int LOOP_COUNT_SHORT(500);			// 5-second dwell time
   42.15 +static const int LOOP_COUNT_LONG(3000);			// 30-second dwell time
   42.16  
   42.17  namespace
   42.18  {
   42.19 @@ -305,11 +314,11 @@
   42.20  
   42.21  		// Run the notification pump.
   42.22  		int count(0);
   42.23 -		int limit(20);
   42.24 +		int limit(LOOP_COUNT_SHORT);
   42.25  		while (count++ < limit && mHandlerCalls < 1)
   42.26  		{
   42.27  			req->update(1000000);
   42.28 -			usleep(100000);
   42.29 +			usleep(LOOP_SLEEP_INTERVAL);
   42.30  		}
   42.31  		ensure("Request executed in reasonable time", count < limit);
   42.32  		ensure("One handler invocation for request", mHandlerCalls == 1);
   42.33 @@ -320,21 +329,21 @@
   42.34  	
   42.35  		// Run the notification pump again
   42.36  		count = 0;
   42.37 -		limit = 100;
   42.38 +		limit = LOOP_COUNT_LONG;
   42.39  		while (count++ < limit && mHandlerCalls < 2)
   42.40  		{
   42.41  			req->update(1000000);
   42.42 -			usleep(100000);
   42.43 +			usleep(LOOP_SLEEP_INTERVAL);
   42.44  		}
   42.45  		ensure("Second request executed in reasonable time", count < limit);
   42.46  		ensure("Second handler invocation", mHandlerCalls == 2);
   42.47  
   42.48  		// See that we actually shutdown the thread
   42.49  		count = 0;
   42.50 -		limit = 10;
   42.51 +		limit = LOOP_COUNT_SHORT;
   42.52  		while (count++ < limit && ! HttpService::isStopped())
   42.53  		{
   42.54 -			usleep(100000);
   42.55 +			usleep(LOOP_SLEEP_INTERVAL);
   42.56  		}
   42.57  		ensure("Thread actually stopped running", HttpService::isStopped());
   42.58  	
   42.59 @@ -403,12 +412,12 @@
   42.60  
   42.61  		// Run the notification pump.
   42.62  		int count(0);
   42.63 -		int limit(20);
   42.64 +		int limit(LOOP_COUNT_LONG);
   42.65  		while (count++ < limit && mHandlerCalls < 2)
   42.66  		{
   42.67  			req1->update(1000000);
   42.68  			req2->update(1000000);
   42.69 -			usleep(100000);
   42.70 +			usleep(LOOP_SLEEP_INTERVAL);
   42.71  		}
   42.72  		ensure("Request executed in reasonable time", count < limit);
   42.73  		ensure("One handler invocation for request", mHandlerCalls == 2);
   42.74 @@ -420,22 +429,22 @@
   42.75  	
   42.76  		// Run the notification pump again
   42.77  		count = 0;
   42.78 -		limit = 100;
   42.79 +		limit = LOOP_COUNT_LONG;
   42.80  		while (count++ < limit && mHandlerCalls < 3)
   42.81  		{
   42.82  			req1->update(1000000);
   42.83  			req2->update(1000000);
   42.84 -			usleep(100000);
   42.85 +			usleep(LOOP_SLEEP_INTERVAL);
   42.86  		}
   42.87  		ensure("Second request executed in reasonable time", count < limit);
   42.88  		ensure("Second handler invocation", mHandlerCalls == 3);
   42.89  
   42.90  		// See that we actually shutdown the thread
   42.91  		count = 0;
   42.92 -		limit = 10;
   42.93 +		limit = LOOP_COUNT_SHORT;
   42.94  		while (count++ < limit && ! HttpService::isStopped())
   42.95  		{
   42.96 -			usleep(100000);
   42.97 +			usleep(LOOP_SLEEP_INTERVAL);
   42.98  		}
   42.99  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.100  	
  42.101 @@ -504,11 +513,11 @@
  42.102  
  42.103  		// Run the notification pump.
  42.104  		int count(0);
  42.105 -		int limit(10);
  42.106 +		int limit(LOOP_COUNT_SHORT);
  42.107  		while (count++ < limit && mHandlerCalls < 1)
  42.108  		{
  42.109  			req->update(1000000);
  42.110 -			usleep(100000);
  42.111 +			usleep(LOOP_SLEEP_INTERVAL);
  42.112  		}
  42.113  		ensure("NoOp notification received", mHandlerCalls == 1);
  42.114  
  42.115 @@ -580,11 +589,11 @@
  42.116  
  42.117  		// Run the notification pump.
  42.118  		int count(0);
  42.119 -		int limit(10);
  42.120 +		int limit(LOOP_COUNT_SHORT);
  42.121  		while (count++ < limit && mHandlerCalls < 1)
  42.122  		{
  42.123  			req->update(1000000);
  42.124 -			usleep(100000);
  42.125 +			usleep(LOOP_SLEEP_INTERVAL);
  42.126  		}
  42.127  		ensure("No notifications received", mHandlerCalls == 0);
  42.128  
  42.129 @@ -661,11 +670,11 @@
  42.130  
  42.131  		// Run the notification pump.
  42.132  		int count(0);
  42.133 -		int limit(50);				// With one retry, should fail quickish
  42.134 +		int limit(LOOP_COUNT_LONG);
  42.135  		while (count++ < limit && mHandlerCalls < 1)
  42.136  		{
  42.137  			req->update(1000000);
  42.138 -			usleep(100000);
  42.139 +			usleep(LOOP_SLEEP_INTERVAL);
  42.140  		}
  42.141  		ensure("Request executed in reasonable time", count < limit);
  42.142  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.143 @@ -677,21 +686,21 @@
  42.144  	
  42.145  		// Run the notification pump again
  42.146  		count = 0;
  42.147 -		limit = 100;
  42.148 +		limit = LOOP_COUNT_LONG;
  42.149  		while (count++ < limit && mHandlerCalls < 2)
  42.150  		{
  42.151  			req->update(1000000);
  42.152 -			usleep(100000);
  42.153 +			usleep(LOOP_SLEEP_INTERVAL);
  42.154  		}
  42.155  		ensure("Second request executed in reasonable time", count < limit);
  42.156  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.157  
  42.158  		// See that we actually shutdown the thread
  42.159  		count = 0;
  42.160 -		limit = 10;
  42.161 +		limit = LOOP_COUNT_SHORT;
  42.162  		while (count++ < limit && ! HttpService::isStopped())
  42.163  		{
  42.164 -			usleep(100000);
  42.165 +			usleep(LOOP_SLEEP_INTERVAL);
  42.166  		}
  42.167  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.168  
  42.169 @@ -777,11 +786,11 @@
  42.170  
  42.171  		// Run the notification pump.
  42.172  		int count(0);
  42.173 -		int limit(10);
  42.174 +		int limit(LOOP_COUNT_LONG);
  42.175  		while (count++ < limit && mHandlerCalls < 1)
  42.176  		{
  42.177  			req->update(1000000);
  42.178 -			usleep(100000);
  42.179 +			usleep(LOOP_SLEEP_INTERVAL);
  42.180  		}
  42.181  		ensure("Request executed in reasonable time", count < limit);
  42.182  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.183 @@ -793,21 +802,21 @@
  42.184  	
  42.185  		// Run the notification pump again
  42.186  		count = 0;
  42.187 -		limit = 10;
  42.188 +		limit = LOOP_COUNT_LONG;
  42.189  		while (count++ < limit && mHandlerCalls < 2)
  42.190  		{
  42.191  			req->update(1000000);
  42.192 -			usleep(100000);
  42.193 +			usleep(LOOP_SLEEP_INTERVAL);
  42.194  		}
  42.195  		ensure("Second request executed in reasonable time", count < limit);
  42.196  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.197  
  42.198  		// See that we actually shutdown the thread
  42.199  		count = 0;
  42.200 -		limit = 10;
  42.201 +		limit = LOOP_COUNT_SHORT;
  42.202  		while (count++ < limit && ! HttpService::isStopped())
  42.203  		{
  42.204 -			usleep(100000);
  42.205 +			usleep(LOOP_SLEEP_INTERVAL);
  42.206  		}
  42.207  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.208  	
  42.209 @@ -887,11 +896,11 @@
  42.210  
  42.211  		// Run the notification pump.
  42.212  		int count(0);
  42.213 -		int limit(10);
  42.214 +		int limit(LOOP_COUNT_LONG);
  42.215  		while (count++ < limit && mHandlerCalls < 1)
  42.216  		{
  42.217  			req->update(1000000);
  42.218 -			usleep(100000);
  42.219 +			usleep(LOOP_SLEEP_INTERVAL);
  42.220  		}
  42.221  		ensure("Request executed in reasonable time", count < limit);
  42.222  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.223 @@ -903,21 +912,21 @@
  42.224  	
  42.225  		// Run the notification pump again
  42.226  		count = 0;
  42.227 -		limit = 10;
  42.228 +		limit = LOOP_COUNT_LONG;
  42.229  		while (count++ < limit && mHandlerCalls < 2)
  42.230  		{
  42.231  			req->update(1000000);
  42.232 -			usleep(100000);
  42.233 +			usleep(LOOP_SLEEP_INTERVAL);
  42.234  		}
  42.235  		ensure("Second request executed in reasonable time", count < limit);
  42.236  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.237  
  42.238  		// See that we actually shutdown the thread
  42.239  		count = 0;
  42.240 -		limit = 10;
  42.241 +		limit = LOOP_COUNT_SHORT;
  42.242  		while (count++ < limit && ! HttpService::isStopped())
  42.243  		{
  42.244 -			usleep(100000);
  42.245 +			usleep(LOOP_SLEEP_INTERVAL);
  42.246  		}
  42.247  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.248  	
  42.249 @@ -999,11 +1008,11 @@
  42.250  
  42.251  		// Run the notification pump.
  42.252  		int count(0);
  42.253 -		int limit(10);
  42.254 +		int limit(LOOP_COUNT_LONG);
  42.255  		while (count++ < limit && mHandlerCalls < 1)
  42.256  		{
  42.257  			req->update(1000000);
  42.258 -			usleep(100000);
  42.259 +			usleep(LOOP_SLEEP_INTERVAL);
  42.260  		}
  42.261  		ensure("Request executed in reasonable time", count < limit);
  42.262  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.263 @@ -1015,21 +1024,21 @@
  42.264  	
  42.265  		// Run the notification pump again
  42.266  		count = 0;
  42.267 -		limit = 10;
  42.268 +		limit = LOOP_COUNT_LONG;
  42.269  		while (count++ < limit && mHandlerCalls < 2)
  42.270  		{
  42.271  			req->update(1000000);
  42.272 -			usleep(100000);
  42.273 +			usleep(LOOP_SLEEP_INTERVAL);
  42.274  		}
  42.275  		ensure("Second request executed in reasonable time", count < limit);
  42.276  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.277  
  42.278  		// See that we actually shutdown the thread
  42.279  		count = 0;
  42.280 -		limit = 10;
  42.281 +		limit = LOOP_COUNT_SHORT;
  42.282  		while (count++ < limit && ! HttpService::isStopped())
  42.283  		{
  42.284 -			usleep(100000);
  42.285 +			usleep(LOOP_SLEEP_INTERVAL);
  42.286  		}
  42.287  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.288  
  42.289 @@ -1117,11 +1126,11 @@
  42.290  
  42.291  		// Run the notification pump.
  42.292  		int count(0);
  42.293 -		int limit(10);
  42.294 +		int limit(LOOP_COUNT_LONG);
  42.295  		while (count++ < limit && mHandlerCalls < 1)
  42.296  		{
  42.297  			req->update(1000000);
  42.298 -			usleep(100000);
  42.299 +			usleep(LOOP_SLEEP_INTERVAL);
  42.300  		}
  42.301  		ensure("Request executed in reasonable time", count < limit);
  42.302  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.303 @@ -1133,21 +1142,21 @@
  42.304  	
  42.305  		// Run the notification pump again
  42.306  		count = 0;
  42.307 -		limit = 10;
  42.308 +		limit = LOOP_COUNT_LONG;
  42.309  		while (count++ < limit && mHandlerCalls < 2)
  42.310  		{
  42.311  			req->update(1000000);
  42.312 -			usleep(100000);
  42.313 +			usleep(LOOP_SLEEP_INTERVAL);
  42.314  		}
  42.315  		ensure("Second request executed in reasonable time", count < limit);
  42.316  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.317  
  42.318  		// See that we actually shutdown the thread
  42.319  		count = 0;
  42.320 -		limit = 10;
  42.321 +		limit = LOOP_COUNT_SHORT;
  42.322  		while (count++ < limit && ! HttpService::isStopped())
  42.323  		{
  42.324 -			usleep(100000);
  42.325 +			usleep(LOOP_SLEEP_INTERVAL);
  42.326  		}
  42.327  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.328  
  42.329 @@ -1237,11 +1246,11 @@
  42.330  
  42.331  		// Run the notification pump.
  42.332  		int count(0);
  42.333 -		int limit(10);
  42.334 +		int limit(LOOP_COUNT_LONG);
  42.335  		while (count++ < limit && mHandlerCalls < 1)
  42.336  		{
  42.337  			req->update(1000000);
  42.338 -			usleep(100000);
  42.339 +			usleep(LOOP_SLEEP_INTERVAL);
  42.340  		}
  42.341  		ensure("Request executed in reasonable time", count < limit);
  42.342  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.343 @@ -1253,21 +1262,21 @@
  42.344  	
  42.345  		// Run the notification pump again
  42.346  		count = 0;
  42.347 -		limit = 10;
  42.348 +		limit = LOOP_COUNT_LONG;
  42.349  		while (count++ < limit && mHandlerCalls < 2)
  42.350  		{
  42.351  			req->update(1000000);
  42.352 -			usleep(100000);
  42.353 +			usleep(LOOP_SLEEP_INTERVAL);
  42.354  		}
  42.355  		ensure("Second request executed in reasonable time", count < limit);
  42.356  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.357  
  42.358  		// See that we actually shutdown the thread
  42.359  		count = 0;
  42.360 -		limit = 10;
  42.361 +		limit = LOOP_COUNT_SHORT;
  42.362  		while (count++ < limit && ! HttpService::isStopped())
  42.363  		{
  42.364 -			usleep(100000);
  42.365 +			usleep(LOOP_SLEEP_INTERVAL);
  42.366  		}
  42.367  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.368  	
  42.369 @@ -1352,8 +1361,8 @@
  42.370  		HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
  42.371  													 0U,
  42.372  													 url_base,
  42.373 -													 0,
  42.374 -													 0,
  42.375 +													 0,	
  42.376 +												 0,
  42.377  													 opts,
  42.378  													 NULL,
  42.379  													 &handler);
  42.380 @@ -1365,11 +1374,11 @@
  42.381  
  42.382  		// Run the notification pump.
  42.383  		int count(0);
  42.384 -		int limit(10);
  42.385 +		int limit(LOOP_COUNT_LONG);
  42.386  		while (count++ < limit && mHandlerCalls < 1)
  42.387  		{
  42.388  			req->update(1000000);
  42.389 -			usleep(100000);
  42.390 +			usleep(LOOP_SLEEP_INTERVAL);
  42.391  		}
  42.392  		ensure("Request executed in reasonable time", count < limit);
  42.393  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.394 @@ -1382,21 +1391,21 @@
  42.395  	
  42.396  		// Run the notification pump again
  42.397  		count = 0;
  42.398 -		limit = 10;
  42.399 +		limit = LOOP_COUNT_LONG;
  42.400  		while (count++ < limit && mHandlerCalls < 2)
  42.401  		{
  42.402  			req->update(1000000);
  42.403 -			usleep(100000);
  42.404 +			usleep(LOOP_SLEEP_INTERVAL);
  42.405  		}
  42.406  		ensure("Second request executed in reasonable time", count < limit);
  42.407  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.408  
  42.409  		// See that we actually shutdown the thread
  42.410  		count = 0;
  42.411 -		limit = 10;
  42.412 +		limit = LOOP_COUNT_SHORT;
  42.413  		while (count++ < limit && ! HttpService::isStopped())
  42.414  		{
  42.415 -			usleep(100000);
  42.416 +			usleep(LOOP_SLEEP_INTERVAL);
  42.417  		}
  42.418  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.419  	
  42.420 @@ -1484,11 +1493,11 @@
  42.421  
  42.422  		// Run the notification pump.
  42.423  		int count(0);
  42.424 -		int limit(50);				// With one retry, should fail quickish
  42.425 +		int limit(LOOP_COUNT_LONG);
  42.426  		while (count++ < limit && mHandlerCalls < 1)
  42.427  		{
  42.428  			req->update(1000000);
  42.429 -			usleep(100000);
  42.430 +			usleep(LOOP_SLEEP_INTERVAL);
  42.431  		}
  42.432  		ensure("Request executed in reasonable time", count < limit);
  42.433  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.434 @@ -1500,21 +1509,21 @@
  42.435  	
  42.436  		// Run the notification pump again
  42.437  		count = 0;
  42.438 -		limit = 100;
  42.439 +		limit = LOOP_COUNT_LONG;
  42.440  		while (count++ < limit && mHandlerCalls < 2)
  42.441  		{
  42.442  			req->update(1000000);
  42.443 -			usleep(100000);
  42.444 +			usleep(LOOP_SLEEP_INTERVAL);
  42.445  		}
  42.446  		ensure("Second request executed in reasonable time", count < limit);
  42.447  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.448  
  42.449  		// See that we actually shutdown the thread
  42.450  		count = 0;
  42.451 -		limit = 10;
  42.452 +		limit = LOOP_COUNT_SHORT;
  42.453  		while (count++ < limit && ! HttpService::isStopped())
  42.454  		{
  42.455 -			usleep(100000);
  42.456 +			usleep(LOOP_SLEEP_INTERVAL);
  42.457  		}
  42.458  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.459  
  42.460 @@ -1607,11 +1616,11 @@
  42.461  
  42.462  		// Run the notification pump.
  42.463  		int count(0);
  42.464 -		int limit(10);
  42.465 +		int limit(LOOP_COUNT_LONG);
  42.466  		while (count++ < limit && mHandlerCalls < 1)
  42.467  		{
  42.468  			req->update(1000000);
  42.469 -			usleep(100000);
  42.470 +			usleep(LOOP_SLEEP_INTERVAL);
  42.471  		}
  42.472  		ensure("Request executed in reasonable time", count < limit);
  42.473  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.474 @@ -1624,21 +1633,21 @@
  42.475  	
  42.476  		// Run the notification pump again
  42.477  		count = 0;
  42.478 -		limit = 10;
  42.479 +		limit = LOOP_COUNT_LONG;
  42.480  		while (count++ < limit && mHandlerCalls < 2)
  42.481  		{
  42.482  			req->update(1000000);
  42.483 -			usleep(100000);
  42.484 +			usleep(LOOP_SLEEP_INTERVAL);
  42.485  		}
  42.486  		ensure("Second request executed in reasonable time", count < limit);
  42.487  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.488  
  42.489  		// See that we actually shutdown the thread
  42.490  		count = 0;
  42.491 -		limit = 10;
  42.492 +		limit = LOOP_COUNT_SHORT;
  42.493  		while (count++ < limit && ! HttpService::isStopped())
  42.494  		{
  42.495 -			usleep(100000);
  42.496 +			usleep(LOOP_SLEEP_INTERVAL);
  42.497  		}
  42.498  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.499  	
  42.500 @@ -1773,11 +1782,11 @@
  42.501  
  42.502  		// Run the notification pump.
  42.503  		int count(0);
  42.504 -		int limit(10);
  42.505 +		int limit(LOOP_COUNT_LONG);
  42.506  		while (count++ < limit && mHandlerCalls < 1)
  42.507  		{
  42.508  			req->update(1000000);
  42.509 -			usleep(100000);
  42.510 +			usleep(LOOP_SLEEP_INTERVAL);
  42.511  		}
  42.512  		ensure("Request executed in reasonable time", count < limit);
  42.513  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.514 @@ -1850,11 +1859,11 @@
  42.515  
  42.516  		// Run the notification pump.
  42.517  		count = 0;
  42.518 -		limit = 10;
  42.519 +		limit = LOOP_COUNT_LONG;
  42.520  		while (count++ < limit && mHandlerCalls < 2)
  42.521  		{
  42.522  			req->update(1000000);
  42.523 -			usleep(100000);
  42.524 +			usleep(LOOP_SLEEP_INTERVAL);
  42.525  		}
  42.526  		ensure("Request executed in reasonable time", count < limit);
  42.527  		ensure("One handler invocation for request", mHandlerCalls == 2);
  42.528 @@ -1869,21 +1878,21 @@
  42.529  	
  42.530  		// Run the notification pump again
  42.531  		count = 0;
  42.532 -		limit = 10;
  42.533 +		limit = LOOP_COUNT_LONG;
  42.534  		while (count++ < limit && mHandlerCalls < 3)
  42.535  		{
  42.536  			req->update(1000000);
  42.537 -			usleep(100000);
  42.538 +			usleep(LOOP_SLEEP_INTERVAL);
  42.539  		}
  42.540  		ensure("Second request executed in reasonable time", count < limit);
  42.541  		ensure("Second handler invocation", mHandlerCalls == 3);
  42.542  
  42.543  		// See that we actually shutdown the thread
  42.544  		count = 0;
  42.545 -		limit = 10;
  42.546 +		limit = LOOP_COUNT_SHORT;
  42.547  		while (count++ < limit && ! HttpService::isStopped())
  42.548  		{
  42.549 -			usleep(100000);
  42.550 +			usleep(LOOP_SLEEP_INTERVAL);
  42.551  		}
  42.552  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.553  	
  42.554 @@ -2048,11 +2057,11 @@
  42.555  			
  42.556  		// Run the notification pump.
  42.557  		int count(0);
  42.558 -		int limit(10);
  42.559 +		int limit(LOOP_COUNT_LONG);
  42.560  		while (count++ < limit && mHandlerCalls < 1)
  42.561  		{
  42.562  			req->update(1000000);
  42.563 -			usleep(100000);
  42.564 +			usleep(LOOP_SLEEP_INTERVAL);
  42.565  		}
  42.566  		ensure("Request executed in reasonable time", count < limit);
  42.567  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.568 @@ -2067,21 +2076,21 @@
  42.569  	
  42.570  		// Run the notification pump again
  42.571  		count = 0;
  42.572 -		limit = 10;
  42.573 +		limit = LOOP_COUNT_LONG;
  42.574  		while (count++ < limit && mHandlerCalls < 2)
  42.575  		{
  42.576  			req->update(1000000);
  42.577 -			usleep(100000);
  42.578 +			usleep(LOOP_SLEEP_INTERVAL);
  42.579  		}
  42.580  		ensure("Second request executed in reasonable time", count < limit);
  42.581  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.582  
  42.583  		// See that we actually shutdown the thread
  42.584  		count = 0;
  42.585 -		limit = 10;
  42.586 +		limit = LOOP_COUNT_SHORT;
  42.587  		while (count++ < limit && ! HttpService::isStopped())
  42.588  		{
  42.589 -			usleep(100000);
  42.590 +			usleep(LOOP_SLEEP_INTERVAL);
  42.591  		}
  42.592  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.593  	
  42.594 @@ -2252,11 +2261,11 @@
  42.595  			
  42.596  		// Run the notification pump.
  42.597  		int count(0);
  42.598 -		int limit(10);
  42.599 +		int limit(LOOP_COUNT_LONG);
  42.600  		while (count++ < limit && mHandlerCalls < 1)
  42.601  		{
  42.602  			req->update(1000000);
  42.603 -			usleep(100000);
  42.604 +			usleep(LOOP_SLEEP_INTERVAL);
  42.605  		}
  42.606  		ensure("Request executed in reasonable time", count < limit);
  42.607  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.608 @@ -2271,21 +2280,21 @@
  42.609  	
  42.610  		// Run the notification pump again
  42.611  		count = 0;
  42.612 -		limit = 10;
  42.613 +		limit = LOOP_COUNT_LONG;
  42.614  		while (count++ < limit && mHandlerCalls < 2)
  42.615  		{
  42.616  			req->update(1000000);
  42.617 -			usleep(100000);
  42.618 +			usleep(LOOP_SLEEP_INTERVAL);
  42.619  		}
  42.620  		ensure("Second request executed in reasonable time", count < limit);
  42.621  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.622  
  42.623  		// See that we actually shutdown the thread
  42.624  		count = 0;
  42.625 -		limit = 10;
  42.626 +		limit = LOOP_COUNT_SHORT;
  42.627  		while (count++ < limit && ! HttpService::isStopped())
  42.628  		{
  42.629 -			usleep(100000);
  42.630 +			usleep(LOOP_SLEEP_INTERVAL);
  42.631  		}
  42.632  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.633  	
  42.634 @@ -2456,11 +2465,11 @@
  42.635  
  42.636  		// Run the notification pump.
  42.637  		int count(0);
  42.638 -		int limit(10);
  42.639 +		int limit(LOOP_COUNT_LONG);
  42.640  		while (count++ < limit && mHandlerCalls < 1)
  42.641  		{
  42.642  			req->update(1000000);
  42.643 -			usleep(100000);
  42.644 +			usleep(LOOP_SLEEP_INTERVAL);
  42.645  		}
  42.646  		ensure("Request executed in reasonable time", count < limit);
  42.647  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.648 @@ -2474,21 +2483,21 @@
  42.649  	
  42.650  		// Run the notification pump again
  42.651  		count = 0;
  42.652 -		limit = 10;
  42.653 +		limit = LOOP_COUNT_LONG;
  42.654  		while (count++ < limit && mHandlerCalls < 2)
  42.655  		{
  42.656  			req->update(1000000);
  42.657 -			usleep(100000);
  42.658 +			usleep(LOOP_SLEEP_INTERVAL);
  42.659  		}
  42.660  		ensure("Second request executed in reasonable time", count < limit);
  42.661  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.662  
  42.663  		// See that we actually shutdown the thread
  42.664  		count = 0;
  42.665 -		limit = 10;
  42.666 +		limit = LOOP_COUNT_SHORT;
  42.667  		while (count++ < limit && ! HttpService::isStopped())
  42.668  		{
  42.669 -			usleep(100000);
  42.670 +			usleep(LOOP_SLEEP_INTERVAL);
  42.671  		}
  42.672  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.673  	
  42.674 @@ -2673,11 +2682,11 @@
  42.675  			
  42.676  		// Run the notification pump.
  42.677  		int count(0);
  42.678 -		int limit(10);
  42.679 +		int limit(LOOP_COUNT_LONG);
  42.680  		while (count++ < limit && mHandlerCalls < 1)
  42.681  		{
  42.682  			req->update(1000000);
  42.683 -			usleep(100000);
  42.684 +			usleep(LOOP_SLEEP_INTERVAL);
  42.685  		}
  42.686  		ensure("Request executed in reasonable time", count < limit);
  42.687  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.688 @@ -2692,21 +2701,21 @@
  42.689  	
  42.690  		// Run the notification pump again
  42.691  		count = 0;
  42.692 -		limit = 10;
  42.693 +		limit = LOOP_COUNT_LONG;
  42.694  		while (count++ < limit && mHandlerCalls < 2)
  42.695  		{
  42.696  			req->update(1000000);
  42.697 -			usleep(100000);
  42.698 +			usleep(LOOP_SLEEP_INTERVAL);
  42.699  		}
  42.700  		ensure("Second request executed in reasonable time", count < limit);
  42.701  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.702  
  42.703  		// See that we actually shutdown the thread
  42.704  		count = 0;
  42.705 -		limit = 10;
  42.706 +		limit = LOOP_COUNT_SHORT;
  42.707  		while (count++ < limit && ! HttpService::isStopped())
  42.708  		{
  42.709 -			usleep(100000);
  42.710 +			usleep(LOOP_SLEEP_INTERVAL);
  42.711  		}
  42.712  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.713  	
  42.714 @@ -2890,11 +2899,11 @@
  42.715  			
  42.716  		// Run the notification pump.
  42.717  		int count(0);
  42.718 -		int limit(10);
  42.719 +		int limit(LOOP_COUNT_LONG);
  42.720  		while (count++ < limit && mHandlerCalls < 1)
  42.721  		{
  42.722  			req->update(1000000);
  42.723 -			usleep(100000);
  42.724 +			usleep(LOOP_SLEEP_INTERVAL);
  42.725  		}
  42.726  		ensure("Request executed in reasonable time", count < limit);
  42.727  		ensure("One handler invocation for request", mHandlerCalls == 1);
  42.728 @@ -2909,21 +2918,21 @@
  42.729  	
  42.730  		// Run the notification pump again
  42.731  		count = 0;
  42.732 -		limit = 10;
  42.733 +		limit = LOOP_COUNT_LONG;
  42.734  		while (count++ < limit && mHandlerCalls < 2)
  42.735  		{
  42.736  			req->update(1000000);
  42.737 -			usleep(100000);
  42.738 +			usleep(LOOP_SLEEP_INTERVAL);
  42.739  		}
  42.740  		ensure("Second request executed in reasonable time", count < limit);
  42.741  		ensure("Second handler invocation", mHandlerCalls == 2);
  42.742  
  42.743  		// See that we actually shutdown the thread
  42.744  		count = 0;
  42.745 -		limit = 10;
  42.746 +		limit = LOOP_COUNT_SHORT;
  42.747  		while (count++ < limit && ! HttpService::isStopped())
  42.748  		{
  42.749 -			usleep(100000);
  42.750 +			usleep(LOOP_SLEEP_INTERVAL);
  42.751  		}
  42.752  		ensure("Thread actually stopped running", HttpService::isStopped());
  42.753  	
  42.754 @@ -2971,12 +2980,206 @@
  42.755  	}
  42.756  }
  42.757  
  42.758 -
  42.759 +// BUG-2295 Tests - Content-Range header received but no body
  42.760  template <> template <>
  42.761  void HttpRequestTestObjectType::test<22>()
  42.762  {
  42.763  	ScopedCurlInit ready;
  42.764  
  42.765 +	std::string url_base(get_base_url());
  42.766 +	// std::cerr << "Base:  "  << url_base << std::endl;
  42.767 +	
  42.768 +	set_test_name("BUG-2295");
  42.769 +
  42.770 +	// Handler can be stack-allocated *if* there are no dangling
  42.771 +	// references to it after completion of this method.
  42.772 +	// Create before memory record as the string copy will bump numbers.
  42.773 +	TestHandler2 handler(this, "handler");
  42.774 +		
  42.775 +	// record the total amount of dynamically allocated memory
  42.776 +	mMemTotal = GetMemTotal();
  42.777 +	mHandlerCalls = 0;
  42.778 +
  42.779 +	HttpOptions * options = NULL;
  42.780 +	HttpRequest * req = NULL;
  42.781 +
  42.782 +	try
  42.783 +	{
  42.784 +		// options set
  42.785 +		options = new HttpOptions();
  42.786 +		options->setRetries(1);			// Partial_File is retryable and can timeout in here
  42.787 +
  42.788 +		// Get singletons created
  42.789 +		HttpRequest::createService();
  42.790 +		
  42.791 +		// Start threading early so that thread memory is invariant
  42.792 +		// over the test.
  42.793 +		HttpRequest::startThread();
  42.794 +
  42.795 +		// create a new ref counted object with an implicit reference
  42.796 +		req = new HttpRequest();
  42.797 +		ensure("Memory allocated on construction", mMemTotal < GetMemTotal());
  42.798 +
  42.799 +		// ======================================
  42.800 +		// Issue bug2295 GETs that will get a 206
  42.801 +		// ======================================
  42.802 +		mStatus = HttpStatus(206);
  42.803 +		static const int test_count(3);
  42.804 +		for (int i(0); i < test_count; ++i)
  42.805 +		{
  42.806 +			char buffer[128];
  42.807 +			sprintf(buffer, "/bug2295/%d/", i);
  42.808 +			HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
  42.809 +														 0U,
  42.810 +														 url_base + buffer,
  42.811 +														 0,
  42.812 +														 25,
  42.813 +														 options,
  42.814 +														 NULL,
  42.815 +														 &handler);
  42.816 +			ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
  42.817 +		}
  42.818 +		
  42.819 +		// Run the notification pump.
  42.820 +		int count(0);
  42.821 +		int limit(LOOP_COUNT_LONG);
  42.822 +		while (count++ < limit && mHandlerCalls < test_count)
  42.823 +		{
  42.824 +			req->update(1000000);
  42.825 +			usleep(LOOP_SLEEP_INTERVAL);
  42.826 +		}
  42.827 +		ensure("Request executed in reasonable time - ms1", count < limit);
  42.828 +		ensure("One handler invocation for each request - ms1", mHandlerCalls == test_count);
  42.829 +
  42.830 +		// ======================================
  42.831 +		// Issue bug2295 GETs that will get a libcurl 18 (PARTIAL_FILE)
  42.832 +		// ======================================
  42.833 +		mHandlerCalls = 0;
  42.834 +		mStatus = HttpStatus(HttpStatus::EXT_CURL_EASY, CURLE_PARTIAL_FILE);
  42.835 +		static const int test2_count(1);
  42.836 +		for (int i(0); i < test2_count; ++i)
  42.837 +		{
  42.838 +			char buffer[128];
  42.839 +			sprintf(buffer, "/bug2295/00000012/%d/", i);
  42.840 +			HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
  42.841 +														 0U,
  42.842 +														 url_base + buffer,
  42.843 +														 0,
  42.844 +														 25,
  42.845 +														 options,
  42.846 +														 NULL,
  42.847 +														 &handler);
  42.848 +			ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
  42.849 +		}
  42.850 +		
  42.851 +		// Run the notification pump.
  42.852 +		count = 0;
  42.853 +		limit = LOOP_COUNT_LONG;
  42.854 +		while (count++ < limit && mHandlerCalls < test2_count)
  42.855 +		{
  42.856 +			req->update(1000000);
  42.857 +			usleep(LOOP_SLEEP_INTERVAL);
  42.858 +		}
  42.859 +		ensure("Request executed in reasonable time - ms2", count < limit);
  42.860 +		ensure("One handler invocation for each request - ms2", mHandlerCalls == test2_count);
  42.861 +
  42.862 +		// ======================================
  42.863 +		// Issue bug2295 GETs that will get an llcorehttp HE_INV_CONTENT_RANGE_HDR status
  42.864 +		// ======================================
  42.865 +		mHandlerCalls = 0;
  42.866 +		mStatus = HttpStatus(HttpStatus::LLCORE, HE_INV_CONTENT_RANGE_HDR);
  42.867 +		static const int test3_count(1);
  42.868 +		for (int i(0); i < test3_count; ++i)
  42.869 +		{
  42.870 +			char buffer[128];
  42.871 +			sprintf(buffer, "/bug2295/inv_cont_range/%d/", i);
  42.872 +			HttpHandle handle = req->requestGetByteRange(HttpRequest::DEFAULT_POLICY_ID,
  42.873 +														 0U,
  42.874 +														 url_base + buffer,
  42.875 +														 0,
  42.876 +														 25,
  42.877 +														 options,
  42.878 +														 NULL,
  42.879 +														 &handler);
  42.880 +			ensure("Valid handle returned for ranged request", handle != LLCORE_HTTP_HANDLE_INVALID);
  42.881 +		}
  42.882 +		
  42.883 +		// Run the notification pump.
  42.884 +		count = 0;
  42.885 +		limit = LOOP_COUNT_LONG;
  42.886 +		while (count++ < limit && mHandlerCalls < test3_count)
  42.887 +		{
  42.888 +			req->update(1000000);
  42.889 +			usleep(LOOP_SLEEP_INTERVAL);
  42.890 +		}
  42.891 +		ensure("Request executed in reasonable time - ms3", count < limit);
  42.892 +		ensure("One handler invocation for each request - ms3", mHandlerCalls == test3_count);
  42.893 +
  42.894 +		// ======================================
  42.895 +		// Okay, request a shutdown of the servicing thread
  42.896 +		// ======================================
  42.897 +		mStatus = HttpStatus();
  42.898 +		mHandlerCalls = 0;
  42.899 +		HttpHandle handle = req->requestStopThread(&handler);
  42.900 +		ensure("Valid handle returned for second request", handle != LLCORE_HTTP_HANDLE_INVALID);
  42.901 +	
  42.902 +		// Run the notification pump again
  42.903 +		count = 0;
  42.904 +		limit = LOOP_COUNT_LONG;
  42.905 +		while (count++ < limit && mHandlerCalls < 1)
  42.906 +		{
  42.907 +			req->update(1000000);
  42.908 +			usleep(LOOP_SLEEP_INTERVAL);
  42.909 +		}
  42.910 +		ensure("Shutdown request executed in reasonable time", count < limit);
  42.911 +		ensure("Shutdown handler invocation", mHandlerCalls == 1);
  42.912 +
  42.913 +		// See that we actually shutdown the thread
  42.914 +		count = 0;
  42.915 +		limit = LOOP_COUNT_SHORT;
  42.916 +		while (count++ < limit && ! HttpService::isStopped())
  42.917 +		{
  42.918 +			usleep(LOOP_SLEEP_INTERVAL);
  42.919 +		}
  42.920 +		ensure("Thread actually stopped running", HttpService::isStopped());
  42.921 +
  42.922 +		// release options
  42.923 +		if (options)
  42.924 +		{
  42.925 +			options->release();
  42.926 +			options = NULL;
  42.927 +		}
  42.928 +		
  42.929 +		// release the request object
  42.930 +		delete req;
  42.931 +		req = NULL;
  42.932 +
  42.933 +		// Shut down service
  42.934 +		HttpRequest::destroyService();
  42.935 +	
  42.936 +#if defined(WIN32)
  42.937 +		// Can only do this memory test on Windows.  On other platforms,
  42.938 +		// the LL logging system holds on to memory and produces what looks
  42.939 +		// like memory leaks...
  42.940 +	
  42.941 +		// printf("Old mem:  %d, New mem:  %d\n", mMemTotal, GetMemTotal());
  42.942 +		ensure("Memory usage back to that at entry", mMemTotal == GetMemTotal());
  42.943 +#endif
  42.944 +	}
  42.945 +	catch (...)
  42.946 +	{
  42.947 +		stop_thread(req);
  42.948 +		delete req;
  42.949 +		HttpRequest::destroyService();
  42.950 +		throw;
  42.951 +	}
  42.952 +}
  42.953 +
  42.954 +template <> template <>
  42.955 +void HttpRequestTestObjectType::test<23>()
  42.956 +{
  42.957 +	ScopedCurlInit ready;
  42.958 +
  42.959  	set_test_name("HttpRequest GET 503s with 'Retry-After'");
  42.960  
  42.961  	// This tests mainly that the code doesn't fall over if
    43.1 --- a/indra/llcorehttp/tests/test_httpstatus.hpp	Fri Sep 27 17:22:31 2013 -0400
    43.2 +++ b/indra/llcorehttp/tests/test_httpstatus.hpp	Fri Oct 04 15:36:52 2013 -0400
    43.3 @@ -91,9 +91,6 @@
    43.4  void HttpStatusTestObjectType::test<2>()
    43.5  {
    43.6  	set_test_name("HttpStatus memory structure");
    43.7 -#if LL_WINDOWS
    43.8 -	skip("MAINT-2302: This frequently (though not always) fails on Windows.");
    43.9 -#endif
   43.10  
   43.11  	// Require that an HttpStatus object can be trivially
   43.12  	// returned as a function return value in registers.
   43.13 @@ -106,10 +103,7 @@
   43.14  template <> template <>
   43.15  void HttpStatusTestObjectType::test<3>()
   43.16  {
   43.17 -	set_test_name("HttpStatus valid error string conversion");
   43.18 -#if LL_WINDOWS
   43.19 -	skip("MAINT-2302: This frequently (though not always) fails on Windows.");
   43.20 -#endif
   43.21 +	set_test_name("HttpStatus valid status string conversion");
   43.22  	
   43.23  	HttpStatus status;
   43.24  	status.mType = HttpStatus::EXT_CURL_EASY;
   43.25 @@ -141,10 +135,7 @@
   43.26  template <> template <>
   43.27  void HttpStatusTestObjectType::test<4>()
   43.28  {
   43.29 -	set_test_name("HttpStatus invalid error string conversion");
   43.30 -#if LL_WINDOWS
   43.31 -	skip("MAINT-2302: This frequently (though not always) fails on Windows.");
   43.32 -#endif
   43.33 +	set_test_name("HttpStatus invalid status string conversion");
   43.34  	
   43.35  	HttpStatus status;
   43.36  	status.mType = HttpStatus::EXT_CURL_EASY;
   43.37 @@ -170,9 +161,6 @@
   43.38  void HttpStatusTestObjectType::test<5>()
   43.39  {
   43.40  	set_test_name("HttpStatus equality/inequality testing");
   43.41 -#if LL_WINDOWS
   43.42 -	skip("MAINT-2302: This frequently (though not always) fails on Windows.");
   43.43 -#endif
   43.44  
   43.45  	// Make certain equality/inequality tests do not pass
   43.46  	// through the bool conversion.  Distinct successful
   43.47 @@ -193,9 +181,6 @@
   43.48  void HttpStatusTestObjectType::test<6>()
   43.49  {
   43.50  	set_test_name("HttpStatus basic HTTP status encoding");
   43.51 -#if LL_WINDOWS
   43.52 -	skip("MAINT-2302: This frequently (though not always) fails on Windows.");
   43.53 -#endif
   43.54  	
   43.55  	HttpStatus status;
   43.56  	status.mType = 200;
   43.57 @@ -242,10 +227,7 @@
   43.58  template <> template <>
   43.59  void HttpStatusTestObjectType::test<7>()
   43.60  {
   43.61 -	set_test_name("HttpStatus HTTP error text strings");
   43.62 -#if LL_WINDOWS
   43.63 -	skip("MAINT-2302: This frequently (though not always) fails on Windows.");
   43.64 -#endif
   43.65 +	set_test_name("HttpStatus HTTP status text strings");
   43.66  
   43.67  	HttpStatus status(100, HE_REPLY_ERROR);
   43.68  	std::string msg(status.toString());
    44.1 --- a/indra/llcorehttp/tests/test_llcorehttp_peer.py	Fri Sep 27 17:22:31 2013 -0400
    44.2 +++ b/indra/llcorehttp/tests/test_llcorehttp_peer.py	Fri Oct 04 15:36:52 2013 -0400
    44.3 @@ -35,6 +35,10 @@
    44.4  import select
    44.5  import getopt
    44.6  from threading import Thread
    44.7 +try:
    44.8 +    from cStringIO import StringIO
    44.9 +except ImportError:
   44.10 +    from StringIO import StringIO
   44.11  from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
   44.12  from SocketServer import ThreadingMixIn
   44.13  
   44.14 @@ -48,7 +52,23 @@
   44.15      """This subclass of BaseHTTPRequestHandler is to receive and echo
   44.16      LLSD-flavored messages sent by the C++ LLHTTPClient.
   44.17  
   44.18 -    [Merge with viewer-cat later]
   44.19 +    Target URLs are fairly free-form and are assembled by 
   44.20 +    concatinating fragments.  Currently defined fragments
   44.21 +    are:
   44.22 +    - '/reflect/'       Request headers are bounced back to caller
   44.23 +                        after prefixing with 'X-Reflect-'
   44.24 +    - '/fail/'          Body of request can contain LLSD with 
   44.25 +                        'reason' string and 'status' integer
   44.26 +                        which will become response header.
   44.27 +    - '/bug2295/'       206 response, no data in body:
   44.28 +    -- '/bug2295/0/'       "Content-Range: bytes 0-75/2983"
   44.29 +    -- '/bug2295/1/'       "Content-Range: bytes 0-75/*"
   44.30 +    -- '/bug2295/2/'       "Content-Range: bytes 0-75/2983",
   44.31 +                           "Content-Length: 0"
   44.32 +    -- '/bug2295/00000018/0/'  Generates PARTIAL_FILE (18) error in libcurl.
   44.33 +                           "Content-Range: bytes 0-75/2983",
   44.34 +                           "Content-Length: 76"
   44.35 +    -- '/bug2295/inv_cont_range/0/'  Generates HE_INVALID_CONTENT_RANGE error in llcorehttp.
   44.36      - '/503/'           Generate 503 responses with various kinds
   44.37                          of 'retry-after' headers
   44.38      -- '/503/0/'            "Retry-After: 2"   
   44.39 @@ -58,7 +78,12 @@
   44.40      -- '/503/4/'            "Retry-After: (*#*(@*(@(")"
   44.41      -- '/503/5/'            "Retry-After: aklsjflajfaklsfaklfasfklasdfklasdgahsdhgasdiogaioshdgo"
   44.42      -- '/503/6/'            "Retry-After: 1 2 3 4 5 6 7 8 9 10"
   44.43 +
   44.44 +    Some combinations make no sense, there's no effort to protect
   44.45 +    you from that.
   44.46      """
   44.47 +    ignore_exceptions = (Exception,)
   44.48 +
   44.49      def read(self):
   44.50          # The following logic is adapted from the library module
   44.51          # SimpleXMLRPCServer.py.
   44.52 @@ -98,20 +123,29 @@
   44.53  
   44.54      def do_GET(self, withdata=True):
   44.55          # Of course, don't attempt to read data.
   44.56 -        self.answer(dict(reply="success", status=200,
   44.57 -                         reason="Your GET operation worked"))
   44.58 +        try:
   44.59 +            self.answer(dict(reply="success", status=200,
   44.60 +                             reason="Your GET operation worked"))
   44.61 +        except self.ignore_exceptions, e:
   44.62 +            print >> sys.stderr, "Exception during GET (ignoring): %s" % str(e)
   44.63  
   44.64      def do_POST(self):
   44.65          # Read the provided POST data.
   44.66          # self.answer(self.read())
   44.67 -        self.answer(dict(reply="success", status=200,
   44.68 -                         reason=self.read()))
   44.69 +        try:
   44.70 +            self.answer(dict(reply="success", status=200,
   44.71 +                             reason=self.read()))
   44.72 +        except self.ignore_exceptions, e:
   44.73 +            print >> sys.stderr, "Exception during POST (ignoring): %s" % str(e)
   44.74  
   44.75      def do_PUT(self):
   44.76          # Read the provided PUT data.
   44.77          # self.answer(self.read())
   44.78 -        self.answer(dict(reply="success", status=200,
   44.79 -                         reason=self.read()))
   44.80 +        try:
   44.81 +            self.answer(dict(reply="success", status=200,
   44.82 +                             reason=self.read()))
   44.83 +        except self.ignore_exceptions, e:
   44.84 +            print >> sys.stderr, "Exception during PUT (ignoring): %s" % str(e)
   44.85  
   44.86      def answer(self, data, withdata=True):
   44.87          debug("%s.answer(%s): self.path = %r", self.__class__.__name__, data, self.path)
   44.88 @@ -152,6 +186,41 @@
   44.89              self.end_headers()
   44.90              if body:
   44.91                  self.wfile.write(body)
   44.92 +        elif "/bug2295/" in self.path:
   44.93 +            # Test for https://jira.secondlife.com/browse/BUG-2295
   44.94 +            #
   44.95 +            # Client can receive a header indicating data should
   44.96 +            # appear in the body without actually getting the body.
   44.97 +            # Library needs to defend against this case.
   44.98 +            #
   44.99 +            body = None
  44.100 +            if "/bug2295/0/" in self.path:
  44.101 +                self.send_response(206)
  44.102 +                self.send_header("Content-Range", "bytes 0-75/2983")
  44.103 +            elif "/bug2295/1/" in self.path:
  44.104 +                self.send_response(206)
  44.105 +                self.send_header("Content-Range", "bytes 0-75/*")
  44.106 +            elif "/bug2295/2/" in self.path:
  44.107 +                self.send_response(206)
  44.108 +                self.send_header("Content-Range", "bytes 0-75/2983")
  44.109 +                self.send_header("Content-Length", "0")
  44.110 +            elif "/bug2295/00000012/0/" in self.path:
  44.111 +                self.send_response(206)
  44.112 +                self.send_header("Content-Range", "bytes 0-75/2983")
  44.113 +                self.send_header("Content-Length", "76")
  44.114 +            elif "/bug2295/inv_cont_range/0/" in self.path:
  44.115 +                self.send_response(206)
  44.116 +                self.send_header("Content-Range", "bytes 0-75/2983")
  44.117 +                body = "Some text, but not enough."
  44.118 +            else:
  44.119 +                # Unknown request
  44.120 +                self.send_response(400)
  44.121 +            if "/reflect/" in self.path:
  44.122 +                self.reflect_headers()
  44.123 +            self.send_header("Content-type", "text/plain")
  44.124 +            self.end_headers()
  44.125 +            if body:
  44.126 +                self.wfile.write(body)
  44.127          elif "fail" not in self.path:
  44.128              data = data.copy()          # we're going to modify
  44.129              # Ensure there's a "reply" key in data, even if there wasn't before
  44.130 @@ -207,6 +276,17 @@
  44.131      # operation of freeport() absolutely depends on it being off.
  44.132      allow_reuse_address = False
  44.133  
  44.134 +    # Override of BaseServer.handle_error().  Not too interested
  44.135 +    # in errors and the default handler emits a scary traceback
  44.136 +    # to stderr which annoys some.  Disable this override to get
  44.137 +    # default behavior which *shouldn't* cause the program to return
  44.138 +    # a failure status.
  44.139 +    def handle_error(self, request, client_address):
  44.140 +        print '-'*40
  44.141 +        print 'Ignoring exception during processing of request from',
  44.142 +        print client_address
  44.143 +        print '-'*40
  44.144 +
  44.145  if __name__ == "__main__":
  44.146      do_valgrind = False
  44.147      path_search = False
  44.148 @@ -233,3 +313,4 @@
  44.149          args = ["valgrind", "--log-file=./valgrind.log"] + args
  44.150          path_search = True
  44.151      sys.exit(run(server=Thread(name="httpd", target=httpd.serve_forever), use_path=path_search, *args))
  44.152 +
    45.1 --- a/indra/llmath/llmatrix4a.h	Fri Sep 27 17:22:31 2013 -0400
    45.2 +++ b/indra/llmath/llmatrix4a.h	Fri Oct 04 15:36:52 2013 -0400
    45.3 @@ -107,15 +107,14 @@
    45.4  
    45.5  	inline void rotate(const LLVector4a& v, LLVector4a& res)
    45.6  	{
    45.7 +		LLVector4a y,z;
    45.8 +
    45.9  		res = _mm_shuffle_ps(v, v, _MM_SHUFFLE(0, 0, 0, 0));
   45.10 +		y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
   45.11 +		z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
   45.12 +		
   45.13  		res.mul(mMatrix[0]);
   45.14 -		
   45.15 -		LLVector4a y;
   45.16 -		y = _mm_shuffle_ps(v, v, _MM_SHUFFLE(1, 1, 1, 1));
   45.17  		y.mul(mMatrix[1]);
   45.18 -
   45.19 -		LLVector4a z;
   45.20 -		z = _mm_shuffle_ps(v, v, _MM_SHUFFLE(2, 2, 2, 2));
   45.21  		z.mul(mMatrix[2]);
   45.22  
   45.23  		res.add(y);
    46.1 --- a/indra/llmath/llsimdmath.h	Fri Sep 27 17:22:31 2013 -0400
    46.2 +++ b/indra/llmath/llsimdmath.h	Fri Oct 04 15:36:52 2013 -0400
    46.3 @@ -39,34 +39,6 @@
    46.4  #include <stdint.h>
    46.5  #endif
    46.6  
    46.7 -template <typename T> T* LL_NEXT_ALIGNED_ADDRESS(T* address) 
    46.8 -{ 
    46.9 -	return reinterpret_cast<T*>(
   46.10 -		(reinterpret_cast<uintptr_t>(address) + 0xF) & ~0xF);
   46.11 -}
   46.12 -
   46.13 -template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address) 
   46.14 -{ 
   46.15 -	return reinterpret_cast<T*>(
   46.16 -		(reinterpret_cast<uintptr_t>(address) + 0x3F) & ~0x3F);
   46.17 -}
   46.18 -
   46.19 -#if LL_LINUX || LL_DARWIN
   46.20 -
   46.21 -#define			LL_ALIGN_PREFIX(x)
   46.22 -#define			LL_ALIGN_POSTFIX(x)		__attribute__((aligned(x)))
   46.23 -
   46.24 -#elif LL_WINDOWS
   46.25 -
   46.26 -#define			LL_ALIGN_PREFIX(x)		__declspec(align(x))
   46.27 -#define			LL_ALIGN_POSTFIX(x)
   46.28 -
   46.29 -#else
   46.30 -#error "LL_ALIGN_PREFIX and LL_ALIGN_POSTFIX undefined"
   46.31 -#endif
   46.32 -
   46.33 -#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16)
   46.34 -
   46.35  #include <xmmintrin.h>
   46.36  #include <emmintrin.h>
   46.37  
    47.1 --- a/indra/llmath/llvector4a.cpp	Fri Sep 27 17:22:31 2013 -0400
    47.2 +++ b/indra/llmath/llvector4a.cpp	Fri Oct 04 15:36:52 2013 -0400
    47.3 @@ -41,55 +41,7 @@
    47.4  
    47.5  /*static */void LLVector4a::memcpyNonAliased16(F32* __restrict dst, const F32* __restrict src, size_t bytes)
    47.6  {
    47.7 -	assert(src != NULL);
    47.8 -	assert(dst != NULL);
    47.9 -	assert(bytes > 0);
   47.10 -	assert((bytes % sizeof(F32))== 0); 
   47.11 -	ll_assert_aligned(src,16);
   47.12 -	ll_assert_aligned(dst,16);
   47.13 -	assert(bytes%16==0);
   47.14 -
   47.15 -	F32* end = dst + (bytes / sizeof(F32) );
   47.16 -
   47.17 -	if (bytes > 64)
   47.18 -	{
   47.19 -		F32* begin_64 = LL_NEXT_ALIGNED_ADDRESS_64(dst);
   47.20 -		
   47.21 -		//at least 64 (16*4) bytes before the end of the destination, switch to 16 byte copies
   47.22 -		F32* end_64 = end-16;
   47.23 -		
   47.24 -		_mm_prefetch((char*)begin_64, _MM_HINT_NTA);
   47.25 -		_mm_prefetch((char*)begin_64 + 64, _MM_HINT_NTA);
   47.26 -		_mm_prefetch((char*)begin_64 + 128, _MM_HINT_NTA);
   47.27 -		_mm_prefetch((char*)begin_64 + 192, _MM_HINT_NTA);
   47.28 -		
   47.29 -		while (dst < begin_64)
   47.30 -		{
   47.31 -			copy4a(dst, src);
   47.32 -			dst += 4;
   47.33 -			src += 4;
   47.34 -		}
   47.35 -		
   47.36 -		while (dst < end_64)
   47.37 -		{
   47.38 -			_mm_prefetch((char*)src + 512, _MM_HINT_NTA);
   47.39 -			_mm_prefetch((char*)dst + 512, _MM_HINT_NTA);
   47.40 -			copy4a(dst, src);
   47.41 -			copy4a(dst+4, src+4);
   47.42 -			copy4a(dst+8, src+8);
   47.43 -			copy4a(dst+12, src+12);
   47.44 -			
   47.45 -			dst += 16;
   47.46 -			src += 16;
   47.47 -		}
   47.48 -	}
   47.49 -
   47.50 -	while (dst < end)
   47.51 -	{
   47.52 -		copy4a(dst, src);
   47.53 -		dst += 4;
   47.54 -		src += 4;
   47.55 -	}
   47.56 +        ll_memcpy_nonaliased_aligned_16((char*)dst, (char*)src, bytes);
   47.57  }
   47.58  
   47.59  void LLVector4a::setRotated( const LLRotation& rot, const LLVector4a& vec )
    48.1 --- a/indra/llmath/llvector4a.inl	Fri Sep 27 17:22:31 2013 -0400
    48.2 +++ b/indra/llmath/llvector4a.inl	Fri Oct 04 15:36:52 2013 -0400
    48.3 @@ -480,16 +480,13 @@
    48.4  	mQ = _mm_max_ps(lhs.mQ, rhs.mQ);
    48.5  }
    48.6  
    48.7 -// Set this to  (c * lhs) + rhs * ( 1 - c)
    48.8 +// Set this to  lhs + (rhs-lhs)*c
    48.9  inline void LLVector4a::setLerp(const LLVector4a& lhs, const LLVector4a& rhs, F32 c)
   48.10  {
   48.11 -	LLVector4a a = lhs;
   48.12 -	a.mul(c);
   48.13 -	
   48.14 -	LLVector4a b = rhs;
   48.15 -	b.mul(1.f-c);
   48.16 -	
   48.17 -	setAdd(a, b);
   48.18 +	LLVector4a t;
   48.19 +	t.setSub(rhs,lhs);
   48.20 +	t.mul(c);
   48.21 +	setAdd(lhs, t);
   48.22  }
   48.23  
   48.24  inline LLBool32 LLVector4a::isFinite3() const
    49.1 --- a/indra/llmath/llvolume.cpp	Fri Sep 27 17:22:31 2013 -0400
    49.2 +++ b/indra/llmath/llvolume.cpp	Fri Oct 04 15:36:52 2013 -0400
    49.3 @@ -550,7 +550,7 @@
    49.4  	const F32 tableScale[] = { 1, 1, 1, 0.5f, 0.707107f, 0.53f, 0.525f, 0.5f };
    49.5  	F32 scale = 0.5f;
    49.6  	F32 t, t_step, t_first, t_fraction, ang, ang_step;
    49.7 -	LLVector3 pt1,pt2;
    49.8 +	LLVector4a pt1,pt2;
    49.9  
   49.10  	F32 begin  = params.getBegin();
   49.11  	F32 end    = params.getEnd();
   49.12 @@ -573,20 +573,21 @@
   49.13  	// Starting t and ang values for the first face
   49.14  	t = t_first;
   49.15  	ang = 2.0f*F_PI*(t*ang_scale + offset);
   49.16 -	pt1.setVec(cos(ang)*scale,sin(ang)*scale, t);
   49.17 +	pt1.set(cos(ang)*scale,sin(ang)*scale, t);
   49.18  
   49.19  	// Increment to the next point.
   49.20  	// pt2 is the end point on the fractional face
   49.21  	t += t_step;
   49.22  	ang += ang_step;
   49.23 -	pt2.setVec(cos(ang)*scale,sin(ang)*scale,t);
   49.24 +	pt2.set(cos(ang)*scale,sin(ang)*scale,t);
   49.25  
   49.26  	t_fraction = (begin - t_first)*sides;
   49.27  
   49.28  	// Only use if it's not almost exactly on an edge.
   49.29  	if (t_fraction < 0.9999f)
   49.30  	{
   49.31 -		LLVector3 new_pt = lerp(pt1, pt2, t_fraction);
   49.32 +		LLVector4a new_pt;
   49.33 +		new_pt.setLerp(pt1, pt2, t_fraction);
   49.34  		mProfile.push_back(new_pt);
   49.35  	}
   49.36  
   49.37 @@ -594,12 +595,17 @@
   49.38  	while (t < end)
   49.39  	{
   49.40  		// Iterate through all the integer steps of t.
   49.41 -		pt1.setVec(cos(ang)*scale,sin(ang)*scale,t);
   49.42 +		pt1.set(cos(ang)*scale,sin(ang)*scale,t);
   49.43  
   49.44  		if (mProfile.size() > 0) {
   49.45 -			LLVector3 p = mProfile[mProfile.size()-1];
   49.46 +			LLVector4a p = mProfile[mProfile.size()-1];
   49.47  			for (S32 i = 0; i < split && mProfile.size() > 0; i++) {
   49.48 -				mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1));
   49.49 +				//mProfile.push_back(p+(pt1-p) * 1.0f/(float)(split+1) * (float)(i+1));
   49.50 +				LLVector4a new_pt;
   49.51 +				new_pt.setSub(pt1, p);
   49.52 +				new_pt.mul(1.0f/(float)(split+1) * (float)(i+1));
   49.53 +				new_pt.add(p);
   49.54 +				mProfile.push_back(new_pt);
   49.55  			}
   49.56  		}
   49.57  		mProfile.push_back(pt1);
   49.58 @@ -612,18 +618,25 @@
   49.59  
   49.60  	// pt1 is the first point on the fractional face
   49.61  	// pt2 is the end point on the fractional face
   49.62 -	pt2.setVec(cos(ang)*scale,sin(ang)*scale,t);
   49.63 +	pt2.set(cos(ang)*scale,sin(ang)*scale,t);
   49.64  
   49.65  	// Find the fraction that we need to add to the end point.
   49.66  	t_fraction = (end - (t - t_step))*sides;
   49.67  	if (t_fraction > 0.0001f)
   49.68  	{
   49.69 -		LLVector3 new_pt = lerp(pt1, pt2, t_fraction);
   49.70 +		LLVector4a new_pt;
   49.71 +		new_pt.setLerp(pt1, pt2, t_fraction);
   49.72  		
   49.73  		if (mProfile.size() > 0) {
   49.74 -			LLVector3 p = mProfile[mProfile.size()-1];
   49.75 +			LLVector4a p = mProfile[mProfile.size()-1];
   49.76  			for (S32 i = 0; i < split && mProfile.size() > 0; i++) {
   49.77 -				mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1));
   49.78 +				//mProfile.push_back(p+(new_pt-p) * 1.0f/(float)(split+1) * (float)(i+1));
   49.79 +
   49.80 +				LLVector4a pt1;
   49.81 +				pt1.setSub(new_pt, p);
   49.82 +				pt1.mul(1.0f/(float)(split+1) * (float)(i+1));
   49.83 +				pt1.add(p);
   49.84 +				mProfile.push_back(pt1);
   49.85  			}
   49.86  		}
   49.87  		mProfile.push_back(new_pt);
   49.88 @@ -644,7 +657,7 @@
   49.89  		if (params.getHollow() <= 0)
   49.90  		{
   49.91  			// put center point if not hollow.
   49.92 -			mProfile.push_back(LLVector3(0,0,0));
   49.93 +			mProfile.push_back(LLVector4a(0,0,0));
   49.94  		}
   49.95  	}
   49.96  	else
   49.97 @@ -657,103 +670,6 @@
   49.98  	mTotal = mProfile.size();
   49.99  }
  49.100  
  49.101 -void LLProfile::genNormals(const LLProfileParams& params)
  49.102 -{
  49.103 -	S32 count = mProfile.size();
  49.104 -
  49.105 -	S32 outer_count;
  49.106 -	if (mTotalOut)
  49.107 -	{
  49.108 -		outer_count = mTotalOut;
  49.109 -	}
  49.110 -	else
  49.111 -	{
  49.112 -		outer_count = mTotal / 2;
  49.113 -	}
  49.114 -
  49.115 -	mEdgeNormals.resize(count * 2);
  49.116 -	mEdgeCenters.resize(count * 2);
  49.117 -	mNormals.resize(count);
  49.118 -
  49.119 -	LLVector2 pt0,pt1;
  49.120 -
  49.121 -	BOOL hollow = (params.getHollow() > 0);
  49.122 -
  49.123 -	S32 i0, i1, i2, i3, i4;
  49.124 -
  49.125 -	// Parametrically generate normal
  49.126 -	for (i2 = 0; i2 < count; i2++)
  49.127 -	{
  49.128 -		mNormals[i2].mV[0] = mProfile[i2].mV[0];
  49.129 -		mNormals[i2].mV[1] = mProfile[i2].mV[1];
  49.130 -		if (hollow && (i2 >= outer_count))
  49.131 -		{
  49.132 -			mNormals[i2] *= -1.f;
  49.133 -		}
  49.134 -		if (mNormals[i2].magVec() < 0.001)
  49.135 -		{
  49.136 -			// Special case for point at center, get adjacent points.
  49.137 -			i1 = (i2 - 1) >= 0 ? i2 - 1 : count - 1;
  49.138 -			i0 = (i1 - 1) >= 0 ? i1 - 1 : count - 1;
  49.139 -			i3 = (i2 + 1) < count ? i2 + 1 : 0;
  49.140 -			i4 = (i3 + 1) < count ? i3 + 1 : 0;
  49.141 -
  49.142 -			pt0.setVec(mProfile[i1].mV[VX] + mProfile[i1].mV[VX] - mProfile[i0].mV[VX], 
  49.143 -				mProfile[i1].mV[VY] + mProfile[i1].mV[VY] - mProfile[i0].mV[VY]);
  49.144 -			pt1.setVec(mProfile[i3].mV[VX] + mProfile[i3].mV[VX] - mProfile[i4].mV[VX], 
  49.145 -				mProfile[i3].mV[VY] + mProfile[i3].mV[VY] - mProfile[i4].mV[VY]);
  49.146 -
  49.147 -			mNormals[i2] = pt0 + pt1;
  49.148 -			mNormals[i2] *= 0.5f;
  49.149 -		}
  49.150 -		mNormals[i2].normVec();
  49.151 -	}
  49.152 -
  49.153 -	S32 num_normal_sets = isConcave() ? 2 : 1;
  49.154 -	for (S32 normal_set = 0; normal_set < num_normal_sets; normal_set++)
  49.155 -	{
  49.156 -		S32 point_num;
  49.157 -		for (point_num = 0; point_num < mTotal; point_num++)
  49.158 -		{
  49.159 -			LLVector3 point_1 = mProfile[point_num];
  49.160 -			point_1.mV[VZ] = 0.f;
  49.161 -
  49.162 -			LLVector3 point_2;
  49.163 -			
  49.164 -			if (isConcave() && normal_set == 0 && point_num == (mTotal - 1) / 2)
  49.165 -			{
  49.166 -				point_2 = mProfile[mTotal - 1];
  49.167 -			}
  49.168 -			else if (isConcave() && normal_set == 1 && point_num == mTotal - 1)
  49.169 -			{
  49.170 -				point_2 = mProfile[(mTotal - 1) / 2];
  49.171 -			}
  49.172 -			else
  49.173 -			{
  49.174 -				LLVector3 delta_pos;
  49.175 -				S32 neighbor_point = (point_num + 1) % mTotal;
  49.176 -				while(delta_pos.magVecSquared() < 0.01f * 0.01f)
  49.177 -				{
  49.178 -					point_2 = mProfile[neighbor_point];
  49.179 -					delta_pos = point_2 - point_1;
  49.180 -					neighbor_point = (neighbor_point + 1) % mTotal;
  49.181 -					if (neighbor_point == point_num)
  49.182 -					{
  49.183 -						break;
  49.184 -					}
  49.185 -				}
  49.186 -			}
  49.187 -
  49.188 -			point_2.mV[VZ] = 0.f;
  49.189 -			LLVector3 face_normal = (point_2 - point_1) % LLVector3::z_axis;
  49.190 -			face_normal.normVec();
  49.191 -			mEdgeNormals[normal_set * count + point_num] = face_normal;
  49.192 -			mEdgeCenters[normal_set * count + point_num] = lerp(point_1, point_2, 0.5f);
  49.193 -		}
  49.194 -	}
  49.195 -}
  49.196 -
  49.197 -
  49.198  // Hollow is percent of the original bounding box, not of this particular
  49.199  // profile's geometry.  Thus, a swept triangle needs lower hollow values than
  49.200  // a swept square.
  49.201 @@ -769,12 +685,13 @@
  49.202  
  49.203  	Face *face = addFace(mTotalOut, mTotal-mTotalOut,0,LL_FACE_INNER_SIDE, flat);
  49.204  
  49.205 -	std::vector<LLVector3> pt;
  49.206 +	static LLAlignedArray<LLVector4a,64> pt;
  49.207  	pt.resize(mTotal) ;
  49.208  
  49.209  	for (S32 i=mTotalOut;i<mTotal;i++)
  49.210  	{
  49.211 -		pt[i] = mProfile[i] * box_hollow;
  49.212 +		pt[i] = mProfile[i];
  49.213 +		pt[i].mul(box_hollow);
  49.214  	}
  49.215  
  49.216  	S32 j=mTotal-1;
  49.217 @@ -920,8 +837,8 @@
  49.218  		detail = MIN_LOD;
  49.219  	}
  49.220  
  49.221 -	mProfile.clear();
  49.222 -	mFaces.clear();
  49.223 +	mProfile.resize(0);
  49.224 +	mFaces.resize(0);
  49.225  
  49.226  	// Generate the face data
  49.227  	S32 i;
  49.228 @@ -953,10 +870,13 @@
  49.229  				addFace((face_num++) * (split +1), split+2, 1, LL_FACE_OUTER_SIDE_0 << i, TRUE);
  49.230  			}
  49.231  
  49.232 +			LLVector4a scale(1,1,4,1);
  49.233 +
  49.234  			for (i = 0; i <(S32) mProfile.size(); i++)
  49.235  			{
  49.236  				// Scale by 4 to generate proper tex coords.
  49.237 -				mProfile[i].mV[2] *= 4.f;
  49.238 +				mProfile[i].mul(scale);
  49.239 +				llassert(mProfile[i].isFinite3());
  49.240  			}
  49.241  
  49.242  			if (hollow)
  49.243 @@ -989,10 +909,12 @@
  49.244  	case  LL_PCODE_PROFILE_EQUALTRI:
  49.245  		{
  49.246  			genNGon(params, 3,0, 0, 1, split);
  49.247 +			LLVector4a scale(1,1,3,1);
  49.248  			for (i = 0; i <(S32) mProfile.size(); i++)
  49.249  			{
  49.250  				// Scale by 3 to generate proper tex coords.
  49.251 -				mProfile[i].mV[2] *= 3.f;
  49.252 +				mProfile[i].mul(scale);
  49.253 +				llassert(mProfile[i].isFinite3());
  49.254  			}
  49.255  
  49.256  			if (path_open)
  49.257 @@ -1171,8 +1093,6 @@
  49.258  		}
  49.259  	}
  49.260  	
  49.261 -	//genNormals(params);
  49.262 -
  49.263  	return TRUE;
  49.264  }
  49.265  
  49.266 @@ -1455,25 +1375,29 @@
  49.267  	// the path begins at the correct cut.
  49.268  	F32 step= 1.0f / sides;
  49.269  	F32 t	= params.getBegin();
  49.270 -	pt		= vector_append(mPath, 1);
  49.271 +	pt		= mPath.append(1);
  49.272  	ang		= 2.0f*F_PI*revolutions * t;
  49.273  	s		= sin(ang)*lerp(radius_start, radius_end, t);	
  49.274  	c		= cos(ang)*lerp(radius_start, radius_end, t);
  49.275  
  49.276  
  49.277 -	pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s)
  49.278 +	pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)
  49.279  					  + lerp(-skew ,skew, t) * 0.5f,
  49.280  					c + lerp(0,params.getShear().mV[1],s), 
  49.281  					s);
  49.282 -	pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t);
  49.283 -	pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t);
  49.284 +	pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t),
  49.285 +		hole_y * lerp(taper_y_begin, taper_y_end, t),
  49.286 +		0,1);
  49.287  	pt->mTexT  = t;
  49.288  
  49.289  	// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02
  49.290  	twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);
  49.291  	// Rotate the point around the circle's center.
  49.292  	qang.setQuat   (ang,path_axis);
  49.293 -	pt->mRot   = twist * qang;
  49.294 +
  49.295 +	LLMatrix3 rot(twist * qang);
  49.296 +
  49.297 +	pt->mRot.loadu(rot);
  49.298  
  49.299  	t+=step;
  49.300  
  49.301 @@ -1484,50 +1408,54 @@
  49.302  	// Run through the non-cut dependent points.
  49.303  	while (t < params.getEnd())
  49.304  	{
  49.305 -		pt		= vector_append(mPath, 1);
  49.306 +		pt		= mPath.append(1);
  49.307  
  49.308  		ang = 2.0f*F_PI*revolutions * t;
  49.309  		c   = cos(ang)*lerp(radius_start, radius_end, t);
  49.310  		s   = sin(ang)*lerp(radius_start, radius_end, t);
  49.311  
  49.312 -		pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s)
  49.313 +		pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)
  49.314  					      + lerp(-skew ,skew, t) * 0.5f,
  49.315  						c + lerp(0,params.getShear().mV[1],s), 
  49.316  						s);
  49.317  
  49.318 -		pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t);
  49.319 -		pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t);
  49.320 +		pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t),
  49.321 +					hole_y * lerp(taper_y_begin, taper_y_end, t),
  49.322 +					0,1);
  49.323  		pt->mTexT  = t;
  49.324  
  49.325  		// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02
  49.326  		twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);
  49.327  		// Rotate the point around the circle's center.
  49.328  		qang.setQuat   (ang,path_axis);
  49.329 -		pt->mRot	= twist * qang;
  49.330 +		LLMatrix3 tmp(twist*qang);
  49.331 +		pt->mRot.loadu(tmp);
  49.332  
  49.333  		t+=step;
  49.334  	}
  49.335  
  49.336  	// Make one final pass for the end cut.
  49.337  	t = params.getEnd();
  49.338 -	pt		= vector_append(mPath, 1);
  49.339 +	pt		= mPath.append(1);
  49.340  	ang = 2.0f*F_PI*revolutions * t;
  49.341  	c   = cos(ang)*lerp(radius_start, radius_end, t);
  49.342  	s   = sin(ang)*lerp(radius_start, radius_end, t);
  49.343  
  49.344 -	pt->mPos.setVec(0 + lerp(0,params.getShear().mV[0],s)
  49.345 +	pt->mPos.set(0 + lerp(0,params.getShear().mV[0],s)
  49.346  					  + lerp(-skew ,skew, t) * 0.5f,
  49.347  					c + lerp(0,params.getShear().mV[1],s), 
  49.348  					s);
  49.349 -	pt->mScale.mV[VX] = hole_x * lerp(taper_x_begin, taper_x_end, t);
  49.350 -	pt->mScale.mV[VY] = hole_y * lerp(taper_y_begin, taper_y_end, t);
  49.351 +	pt->mScale.set(hole_x * lerp(taper_x_begin, taper_x_end, t),
  49.352 +				   hole_y * lerp(taper_y_begin, taper_y_end, t),
  49.353 +				   0,1);
  49.354  	pt->mTexT  = t;
  49.355  
  49.356  	// Twist rotates the path along the x,y plane (I think) - DJS 04/05/02
  49.357  	twist.setQuat  (lerp(twist_begin,twist_end,t) * 2.f * F_PI - F_PI,0,0,1);
  49.358  	// Rotate the point around the circle's center.
  49.359  	qang.setQuat   (ang,path_axis);
  49.360 -	pt->mRot   = twist * qang;
  49.361 +	LLMatrix3 tmp(twist*qang);
  49.362 +	pt->mRot.loadu(tmp);
  49.363  
  49.364  	mTotal = mPath.size();
  49.365  }
  49.366 @@ -1625,7 +1553,7 @@
  49.367  	mDirty = FALSE;
  49.368  	S32 np = 2; // hardcode for line
  49.369  
  49.370 -	mPath.clear();
  49.371 +	mPath.resize(0);
  49.372  	mOpen = TRUE;
  49.373  
  49.374  	// Is this 0xf0 mask really necessary?  DK 03/02/05
  49.375 @@ -1651,12 +1579,16 @@
  49.376  			for (S32 i=0;i<np;i++)
  49.377  			{
  49.378  				F32 t = lerp(params.getBegin(),params.getEnd(),(F32)i * mStep);
  49.379 -				mPath[i].mPos.setVec(lerp(0,params.getShear().mV[0],t),
  49.380 +				mPath[i].mPos.set(lerp(0,params.getShear().mV[0],t),
  49.381  									 lerp(0,params.getShear().mV[1],t),
  49.382  									 t - 0.5f);
  49.383 -				mPath[i].mRot.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1);
  49.384 -				mPath[i].mScale.mV[0] = lerp(start_scale.mV[0],end_scale.mV[0],t);
  49.385 -				mPath[i].mScale.mV[1] = lerp(start_scale.mV[1],end_scale.mV[1],t);
  49.386 +				LLQuaternion quat;
  49.387 +				quat.setQuat(lerp(F_PI * params.getTwistBegin(),F_PI * params.getTwist(),t),0,0,1);
  49.388 +				LLMatrix3 tmp(quat);
  49.389 +				mPath[i].mRot.loadu(tmp);
  49.390 +				mPath[i].mScale.set(lerp(start_scale.mV[0],end_scale.mV[0],t),
  49.391 +									lerp(start_scale.mV[1],end_scale.mV[1],t),
  49.392 +									0,1);
  49.393  				mPath[i].mTexT        = t;
  49.394  			}
  49.395  		}
  49.396 @@ -1693,7 +1625,7 @@
  49.397  			F32 toggle = 0.5f;
  49.398  			for (S32 i=0;i<(S32)mPath.size();i++)
  49.399  			{
  49.400 -				mPath[i].mPos.mV[0] = toggle;
  49.401 +				mPath[i].mPos.getF32ptr()[0] = toggle;
  49.402  				if (toggle == 0.5f)
  49.403  					toggle = -0.5f;
  49.404  				else
  49.405 @@ -1714,14 +1646,16 @@
  49.406  		for (S32 i=0;i<np;i++)
  49.407  		{
  49.408  			F32 t = (F32)i * mStep;
  49.409 -			mPath[i].mPos.setVec(0,
  49.410 +			mPath[i].mPos.set(0,
  49.411  								lerp(0,   -sin(F_PI*params.getTwist()*t)*0.5f,t),
  49.412  								lerp(-0.5, cos(F_PI*params.getTwist()*t)*0.5f,t));
  49.413 -			mPath[i].mScale.mV[0] = lerp(1,params.getScale().mV[0],t);
  49.414 -			mPath[i].mScale.mV[1] = lerp(1,params.getScale().mV[1],t);
  49.415 +			mPath[i].mScale.set(lerp(1,params.getScale().mV[0],t),
  49.416 +								lerp(1,params.getScale().mV[1],t), 0,1);
  49.417  			mPath[i].mTexT  = t;
  49.418 -
  49.419 -			mPath[i].mRot.setQuat(F_PI * params.getTwist() * t,1,0,0);
  49.420 +			LLQuaternion quat;
  49.421 +			quat.setQuat(F_PI * params.getTwist() * t,1,0,0);
  49.422 +			LLMatrix3 tmp(quat);
  49.423 +			mPath[i].mRot.loadu(tmp);
  49.424  		}
  49.425  
  49.426  		break;
  49.427 @@ -1745,11 +1679,15 @@
  49.428  		// Path hasn't been generated yet.
  49.429  		// Some algorithms later assume at least TWO path points.
  49.430  		resizePath(2);
  49.431 +		LLQuaternion quat;
  49.432 +		quat.setQuat(0,0,0);
  49.433 +		LLMatrix3 tmp(quat);
  49.434 +
  49.435  		for (U32 i = 0; i < 2; i++)
  49.436  		{
  49.437 -			mPath[i].mPos.setVec(0, 0, 0);
  49.438 -			mPath[i].mRot.setQuat(0, 0, 0);
  49.439 -			mPath[i].mScale.setVec(1, 1);
  49.440 +			mPath[i].mPos.set(0, 0, 0);
  49.441 +			mPath[i].mRot.loadu(tmp);
  49.442 +			mPath[i].mScale.set(1, 1, 0, 1);
  49.443  			mPath[i].mTexT = 0;
  49.444  		}
  49.445  	}
  49.446 @@ -2182,6 +2120,7 @@
  49.447  
  49.448  BOOL LLVolume::generate()
  49.449  {
  49.450 +	LL_CHECK_MEMORY
  49.451  	llassert_always(mProfilep);
  49.452  	
  49.453  	//Added 10.03.05 Dave Parks
  49.454 @@ -2218,20 +2157,6 @@
  49.455  		mLODScaleBias.setVec(0.6f, 0.6f, 0.6f);
  49.456  	}
  49.457  	
  49.458 -	//********************************************************************
  49.459 -	//debug info, to be removed
  49.460 -	if((U32)(mPathp->mPath.size() * mProfilep->mProfile.size()) > (1u << 20))
  49.461 -	{
  49.462 -		llinfos << "sizeS: " << mPathp->mPath.size() << " sizeT: " << mProfilep->mProfile.size() << llendl ;
  49.463 -		llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ;
  49.464 -		llinfos << mParams << llendl ;
  49.465 -		llinfos << "more info to check if mProfilep is deleted or not." << llendl ;
  49.466 -		llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ;
  49.467 -
  49.468 -		llerrs << "LLVolume corrupted!" << llendl ;
  49.469 -	}
  49.470 -	//********************************************************************
  49.471 -
  49.472  	BOOL regenPath = mPathp->generate(mParams.getPathParams(), path_detail, split);
  49.473  	BOOL regenProf = mProfilep->generate(mParams.getProfileParams(), mPathp->isOpen(),profile_detail, split);
  49.474  
  49.475 @@ -2240,21 +2165,6 @@
  49.476  		S32 sizeS = mPathp->mPath.size();
  49.477  		S32 sizeT = mProfilep->mProfile.size();
  49.478  
  49.479 -		//********************************************************************
  49.480 -		//debug info, to be removed
  49.481 -		if((U32)(sizeS * sizeT) > (1u << 20))
  49.482 -		{
  49.483 -			llinfos << "regenPath: " << (S32)regenPath << " regenProf: " << (S32)regenProf << llendl ;
  49.484 -			llinfos << "sizeS: " << sizeS << " sizeT: " << sizeT << llendl ;
  49.485 -			llinfos << "path_detail : " << path_detail << " split: " << split << " profile_detail: " << profile_detail << llendl ;
  49.486 -			llinfos << mParams << llendl ;
  49.487 -			llinfos << "more info to check if mProfilep is deleted or not." << llendl ;
  49.488 -			llinfos << mProfilep->mNormals.size() << " : " << mProfilep->mFaces.size() << " : " << mProfilep->mEdgeNormals.size() << " : " << mProfilep->mEdgeCenters.size() << llendl ;
  49.489 -
  49.490 -			llerrs << "LLVolume corrupted!" << llendl ;
  49.491 -		}
  49.492 -		//********************************************************************
  49.493 -
  49.494  		sNumMeshPoints -= mMesh.size();
  49.495  		mMesh.resize(sizeT * sizeS);
  49.496  		sNumMeshPoints += mMesh.size();		
  49.497 @@ -2262,22 +2172,39 @@
  49.498  		//generate vertex positions
  49.499  
  49.500  		// Run along the path.
  49.501 +		LLVector4a* dst = mMesh.mArray;
  49.502 +
  49.503  		for (S32 s = 0; s < sizeS; ++s)
  49.504  		{
  49.505 -			LLVector2  scale = mPathp->mPath[s].mScale;
  49.506 -			LLQuaternion rot = mPathp->mPath[s].mRot;
  49.507 +			F32* scale = mPathp->mPath[s].mScale.getF32ptr();
  49.508 +			
  49.509 +			F32 sc [] = 
  49.510 +			{ scale[0], 0, 0, 0,
  49.511 +				0, scale[1], 0, 0,
  49.512 +				0, 0, scale[2], 0,
  49.513 +					0, 0, 0, 1 };
  49.514 +			
  49.515 +			LLMatrix4 rot((F32*) mPathp->mPath[s].mRot.mMatrix);
  49.516 +			LLMatrix4 scale_mat(sc);
  49.517 +			
  49.518 +			scale_mat *= rot;
  49.519 +			
  49.520 +			LLMatrix4a rot_mat;
  49.521 +			rot_mat.loadu(scale_mat);
  49.522 +			
  49.523 +			LLVector4a* profile = mProfilep->mProfile.mArray;
  49.524 +			LLVector4a* end_profile = profile+sizeT;
  49.525 +			LLVector4a offset = mPathp->mPath[s].mPos;
  49.526 +
  49.527 +			LLVector4a tmp;
  49.528  
  49.529  			// Run along the profile.
  49.530 -			for (S32 t = 0; t < sizeT; ++t)
  49.531 +			while (profile < end_profile)
  49.532  			{
  49.533 -				S32 m = s*sizeT + t;
  49.534 -				Point& pt = mMesh[m];
  49.535 -				
  49.536 -				pt.mPos.mV[0] = mProfilep->mProfile[t].mV[0] * scale.mV[0];
  49.537 -				pt.mPos.mV[1] = mProfilep->mProfile[t].mV[1] * scale.mV[1];
  49.538 -				pt.mPos.mV[2] = 0.0f;
  49.539 -				pt.mPos       = pt.mPos * rot;
  49.540 -				pt.mPos      += mPathp->mPath[s].mPos;
  49.541 +				rot_mat.rotate(*profile++, tmp);
  49.542 +				dst->setAdd(tmp,offset);
  49.543 +				llassert(dst->isFinite3());
  49.544 +				++dst;
  49.545  			}
  49.546  		}
  49.547  
  49.548 @@ -2287,9 +2214,11 @@
  49.549  			LLFaceID id = iter->mFaceID;
  49.550  			mFaceMask |= id;
  49.551  		}
  49.552 -		
  49.553 +		LL_CHECK_MEMORY
  49.554  		return TRUE;
  49.555  	}
  49.556 +
  49.557 +	LL_CHECK_MEMORY
  49.558  	return FALSE;
  49.559  }
  49.560  
  49.561 @@ -2868,13 +2797,15 @@
  49.562  }
  49.563  
  49.564  
  49.565 -inline LLVector3 sculpt_rgb_to_vector(U8 r, U8 g, U8 b)
  49.566 +inline LLVector4a sculpt_rgb_to_vector(U8 r, U8 g, U8 b)
  49.567  {
  49.568  	// maps RGB values to vector values [0..255] -> [-0.5..0.5]
  49.569 -	LLVector3 value;
  49.570 -	value.mV[VX] = r / 255.f - 0.5f;
  49.571 -	value.mV[VY] = g / 255.f - 0.5f;
  49.572 -	value.mV[VZ] = b / 255.f - 0.5f;
  49.573 +	LLVector4a value;
  49.574 +	LLVector4a sub(0.5f, 0.5f, 0.5f);
  49.575 +
  49.576 +	value.set(r,g,b);
  49.577 +	value.mul(1.f/255.f);
  49.578 +	value.sub(sub);
  49.579  
  49.580  	return value;
  49.581  }
  49.582 @@ -2895,21 +2826,21 @@
  49.583  }
  49.584  
  49.585  
  49.586 -inline LLVector3 sculpt_index_to_vector(U32 index, const U8* sculpt_data)
  49.587 -{
  49.588 -	LLVector3 v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]);
  49.589 +inline LLVector4a sculpt_index_to_vector(U32 index, const U8* sculpt_data)
  49.590 +{
  49.591 +	LLVector4a v = sculpt_rgb_to_vector(sculpt_data[index], sculpt_data[index+1], sculpt_data[index+2]);
  49.592  
  49.593  	return v;
  49.594  }
  49.595  
  49.596 -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)
  49.597 +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)
  49.598  {
  49.599  	U32 index = sculpt_st_to_index(s, t, size_s, size_t, sculpt_width, sculpt_height, sculpt_components);
  49.600  
  49.601  	return sculpt_index_to_vector(index, sculpt_data);
  49.602  }
  49.603  
  49.604 -inline LLVector3 sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)
  49.605 +inline LLVector4a sculpt_xy_to_vector(U32 x, U32 y, U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data)
  49.606  {
  49.607  	U32 index = sculpt_xy_to_index(x, y, sculpt_width, sculpt_height, sculpt_components);
  49.608  
  49.609 @@ -2931,15 +2862,26 @@
  49.610  		for (S32 t = 0; t < sizeT-1; t++)
  49.611  		{
  49.612  			// get four corners of quad
  49.613 -			LLVector3 p1 = mMesh[(s  )*sizeT + (t  )].mPos;
  49.614 -			LLVector3 p2 = mMesh[(s+1)*sizeT + (t  )].mPos;
  49.615 -			LLVector3 p3 = mMesh[(s  )*sizeT + (t+1)].mPos;
  49.616 -			LLVector3 p4 = mMesh[(s+1)*sizeT + (t+1)].mPos;
  49.617 +			LLVector4a& p1 = mMesh[(s  )*sizeT + (t  )];
  49.618 +			LLVector4a& p2 = mMesh[(s+1)*sizeT + (t  )];
  49.619 +			LLVector4a& p3 = mMesh[(s  )*sizeT + (t+1)];
  49.620 +			LLVector4a& p4 = mMesh[(s+1)*sizeT + (t+1)];
  49.621  
  49.622  			// compute the area of the quad by taking the length of the cross product of the two triangles
  49.623 -			LLVector3 cross1 = (p1 - p2) % (p1 - p3);
  49.624 -			LLVector3 cross2 = (p4 - p2) % (p4 - p3);
  49.625 -			area += (cross1.magVec() + cross2.magVec()) / 2.f;
  49.626 +			LLVector4a v0,v1,v2,v3;
  49.627 +			v0.setSub(p1,p2);
  49.628 +			v1.setSub(p1,p3);
  49.629 +			v2.setSub(p4,p2);
  49.630 +			v3.setSub(p4,p3);
  49.631 +
  49.632 +			LLVector4a cross1, cross2;
  49.633 +			cross1.setCross3(v0,v1);
  49.634 +			cross2.setCross3(v2,v3);
  49.635 +
  49.636 +			//LLVector3 cross1 = (p1 - p2) % (p1 - p3);
  49.637 +			//LLVector3 cross2 = (p4 - p2) % (p4 - p3);
  49.638 +			
  49.639 +			area += (cross1.getLength3() + cross2.getLength3()).getF32() / 2.f;
  49.640  		}
  49.641  	}
  49.642  
  49.643 @@ -2960,7 +2902,7 @@
  49.644  		for (S32 t = 0; t < sizeT; t++)
  49.645  		{
  49.646  			S32 i = t + line;
  49.647 -			Point& pt = mMesh[i];
  49.648 +			LLVector4a& pt = mMesh[i];
  49.649  
  49.650  			
  49.651  			F32 u = (F32)s/(sizeS-1);
  49.652 @@ -2968,9 +2910,13 @@
  49.653  
  49.654  			const F32 RADIUS = (F32) 0.3;
  49.655  					
  49.656 -			pt.mPos.mV[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS);
  49.657 -			pt.mPos.mV[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS);
  49.658 -			pt.mPos.mV[2] = (F32)(cos(F_PI * v) * RADIUS);
  49.659 +			F32* p = pt.getF32ptr();
  49.660 +
  49.661 +			p[0] = (F32)(sin(F_PI * v) * cos(2.0 * F_PI * u) * RADIUS);
  49.662 +			p[1] = (F32)(sin(F_PI * v) * sin(2.0 * F_PI * u) * RADIUS);
  49.663 +			p[2] = (F32)(cos(F_PI * v) * RADIUS);
  49.664 +
  49.665 +			llassert(pt.isFinite3());
  49.666  
  49.667  		}
  49.668  		line += sizeT;
  49.669 @@ -2995,7 +2941,7 @@
  49.670  		for (S32 t = 0; t < sizeT; t++)
  49.671  		{
  49.672  			S32 i = t + line;
  49.673 -			Point& pt = mMesh[i];
  49.674 +			LLVector4a& pt = mMesh[i];
  49.675  
  49.676  			S32 reversed_t = t;
  49.677  
  49.678 @@ -3052,12 +2998,15 @@
  49.679  				}
  49.680  			}
  49.681  
  49.682 -			pt.mPos = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
  49.683 +			pt = sculpt_xy_to_vector(x, y, sculpt_width, sculpt_height, sculpt_components, sculpt_data);
  49.684  
  49.685  			if (sculpt_mirror)
  49.686  			{
  49.687 -				pt.mPos.mV[VX] *= -1.f;
  49.688 +				LLVector4a scale(-1.f,1,1,1);
  49.689 +				pt.mul(scale);
  49.690  			}
  49.691 +
  49.692 +			llassert(pt.isFinite3());
  49.693  		}
  49.694  		
  49.695  		line += sizeT;
  49.696 @@ -3638,627 +3587,6 @@
  49.697  	return true;
  49.698  }
  49.699  
  49.700 -S32 *LLVolume::getTriangleIndices(U32 &num_indices) const
  49.701 -{
  49.702 -	S32 expected_num_triangle_indices = getNumTriangleIndices();
  49.703 -	if (expected_num_triangle_indices > MAX_VOLUME_TRIANGLE_INDICES)
  49.704 -	{
  49.705 -		// we don't allow LLVolumes with this many vertices
  49.706 -		llwarns << "Couldn't allocate triangle indices" << llendl;
  49.707 -		num_indices = 0;
  49.708 -		return NULL;
  49.709 -	}
  49.710 -
  49.711 -	S32* index = new S32[expected_num_triangle_indices];
  49.712 -	S32 count = 0;
  49.713 -
  49.714 -	// Let's do this totally diffently, as we don't care about faces...
  49.715 -	// Counter-clockwise triangles are forward facing...
  49.716 -
  49.717 -	BOOL open = getProfile().isOpen();
  49.718 -	BOOL hollow = (mParams.getProfileParams().getHollow() > 0);
  49.719 -	BOOL path_open = getPath().isOpen();
  49.720 -	S32 size_s, size_s_out, size_t;
  49.721 -	S32 s, t, i;
  49.722 -	size_s = getProfile().getTotal();
  49.723 -	size_s_out = getProfile().getTotalOut();
  49.724 -	size_t = getPath().mPath.size();
  49.725 -
  49.726 -	// NOTE -- if the construction of the triangles below ever changes
  49.727 -	// then getNumTriangleIndices() method may also have to be updated.
  49.728 -
  49.729 -	if (open)		/* Flawfinder: ignore */
  49.730 -	{
  49.731 -		if (hollow)
  49.732 -		{
  49.733 -			// Open hollow -- much like the closed solid, except we 
  49.734 -			// we need to stitch up the gap between s=0 and s=size_s-1
  49.735 -
  49.736 -			for (t = 0; t < size_t - 1; t++)
  49.737 -			{
  49.738 -				// The outer face, first cut, and inner face
  49.739 -				for (s = 0; s < size_s - 1; s++)
  49.740 -				{
  49.741 -					i  = s + t*size_s;
  49.742 -					index[count++]  = i;				// x,y
  49.743 -					index[count++]  = i + 1;			// x+1,y
  49.744 -					index[count++]  = i + size_s;		// x,y+1
  49.745 -	
  49.746 -					index[count++]  = i + size_s;		// x,y+1
  49.747 -					index[count++]  = i + 1;			// x+1,y
  49.748 -					index[count++]  = i + size_s + 1;	// x+1,y+1
  49.749 -				}
  49.750 -
  49.751 -				// The other cut face
  49.752 -				index[count++]  = s + t*size_s;		// x,y
  49.753 -				index[count++]  = 0 + t*size_s;		// x+1,y
  49.754 -				index[count++]  = s + (t+1)*size_s;	// x,y+1
  49.755 -	
  49.756 -				index[count++]  = s + (t+1)*size_s;	// x,y+1
  49.757 -				index[count++]  = 0 + t*size_s;		// x+1,y
  49.758 -				index[count++]  = 0 + (t+1)*size_s;	// x+1,y+1
  49.759 -			}
  49.760 -
  49.761 -			// Do the top and bottom caps, if necessary
  49.762 -			if (path_open)
  49.763 -			{
  49.764 -				// Top cap
  49.765 -				S32 pt1 = 0;
  49.766 -				S32 pt2 = size_s-1;
  49.767 -				S32 i   = (size_t - 1)*size_s;
  49.768 -
  49.769 -				while (pt2 - pt1 > 1)
  49.770 -				{
  49.771 -					// Use the profile points instead of the mesh, since you want
  49.772 -					// the un-transformed profile distances.
  49.773 -					LLVector3 p1 = getProfile().mProfile[pt1];
  49.774 -					LLVector3 p2 = getProfile().mProfile[pt2];
  49.775 -					LLVector3 pa = getProfile().mProfile[pt1+1];
  49.776 -					LLVector3 pb = getProfile().mProfile[pt2-1];
  49.777 -
  49.778 -					p1.mV[VZ] = 0.f;
  49.779 -					p2.mV[VZ] = 0.f;
  49.780 -					pa.mV[VZ] = 0.f;
  49.781 -					pb.mV[VZ] = 0.f;
  49.782 -
  49.783 -					// Use area of triangle to determine backfacing
  49.784 -					F32 area_1a2, area_1ba, area_21b, area_2ab;
  49.785 -					area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
  49.786 -								(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
  49.787 -								(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
  49.788 -
  49.789 -					area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  49.790 -								(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
  49.791 -								(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
  49.792 -
  49.793 -					area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
  49.794 -								(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  49.795 -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  49.796 -
  49.797 -					area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
  49.798 -								(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
  49.799 -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  49.800 -
  49.801 -					BOOL use_tri1a2 = TRUE;
  49.802 -					BOOL tri_1a2 = TRUE;
  49.803 -					BOOL tri_21b = TRUE;
  49.804 -
  49.805 -					if (area_1a2 < 0)
  49.806 -					{
  49.807 -						tri_1a2 = FALSE;
  49.808 -					}
  49.809 -					if (area_2ab < 0)
  49.810 -					{
  49.811 -						// Can't use, because it contains point b
  49.812 -						tri_1a2 = FALSE;
  49.813 -					}
  49.814 -					if (area_21b < 0)
  49.815 -					{
  49.816 -						tri_21b = FALSE;
  49.817 -					}
  49.818 -					if (area_1ba < 0)
  49.819 -					{
  49.820 -						// Can't use, because it contains point b
  49.821 -						tri_21b = FALSE;
  49.822 -					}
  49.823 -
  49.824 -					if (!tri_1a2)
  49.825 -					{
  49.826 -						use_tri1a2 = FALSE;
  49.827 -					}
  49.828 -					else if (!tri_21b)
  49.829 -					{
  49.830 -						use_tri1a2 = TRUE;
  49.831 -					}
  49.832 -					else
  49.833 -					{
  49.834 -						LLVector3 d1 = p1 - pa;
  49.835 -						LLVector3 d2 = p2 - pb;
  49.836 -
  49.837 -						if (d1.magVecSquared() < d2.magVecSquared())
  49.838 -						{
  49.839 -							use_tri1a2 = TRUE;
  49.840 -						}
  49.841 -						else
  49.842 -						{
  49.843 -							use_tri1a2 = FALSE;
  49.844 -						}
  49.845 -					}
  49.846 -
  49.847 -					if (use_tri1a2)
  49.848 -					{
  49.849 -						index[count++] = pt1 + i;
  49.850 -						index[count++] = pt1 + 1 + i;
  49.851 -						index[count++] = pt2 + i;
  49.852 -						pt1++;
  49.853 -					}
  49.854 -					else
  49.855 -					{
  49.856 -						index[count++] = pt1 + i;
  49.857 -						index[count++] = pt2 - 1 + i;
  49.858 -						index[count++] = pt2 + i;
  49.859 -						pt2--;
  49.860 -					}
  49.861 -				}
  49.862 -
  49.863 -				// Bottom cap
  49.864 -				pt1          = 0;
  49.865 -				pt2          = size_s-1;
  49.866 -				while (pt2 - pt1 > 1)
  49.867 -				{
  49.868 -					// Use the profile points instead of the mesh, since you want
  49.869 -					// the un-transformed profile distances.
  49.870 -					LLVector3 p1 = getProfile().mProfile[pt1];
  49.871 -					LLVector3 p2 = getProfile().mProfile[pt2];
  49.872 -					LLVector3 pa = getProfile().mProfile[pt1+1];
  49.873 -					LLVector3 pb = getProfile().mProfile[pt2-1];
  49.874 -
  49.875 -					p1.mV[VZ] = 0.f;
  49.876 -					p2.mV[VZ] = 0.f;
  49.877 -					pa.mV[VZ] = 0.f;
  49.878 -					pb.mV[VZ] = 0.f;
  49.879 -
  49.880 -					// Use area of triangle to determine backfacing
  49.881 -					F32 area_1a2, area_1ba, area_21b, area_2ab;
  49.882 -					area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
  49.883 -								(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
  49.884 -								(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
  49.885 -
  49.886 -					area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  49.887 -								(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
  49.888 -								(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
  49.889 -
  49.890 -					area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
  49.891 -								(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
  49.892 -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  49.893 -
  49.894 -					area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
  49.895 -								(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
  49.896 -								(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
  49.897 -
  49.898 -					BOOL use_tri1a2 = TRUE;
  49.899 -					BOOL tri_1a2 = TRUE;
  49.900 -					BOOL tri_21b = TRUE;
  49.901 -
  49.902 -					if (area_1a2 < 0)
  49.903 -					{
  49.904 -						tri_1a2 = FALSE;
  49.905 -					}
  49.906 -					if (area_2ab < 0)
  49.907 -					{
  49.908 -						// Can't use, because it contains point b
  49.909 -						tri_1a2 = FALSE;
  49.910 -					}
  49.911 -					if (area_21b < 0)
  49.912 -					{
  49.913 -						tri_21b = FALSE;
  49.914 -					}
  49.915 -					if (area_1ba < 0)
  49.916 -					{
  49.917 -						// Can't use, because it contains point b
  49.918 -						tri_21b = FALSE;
  49.919 -					}
  49.920 -
  49.921 -					if (!tri_1a2)
  49.922 -					{
  49.923 -						use_tri1a2 = FALSE;
  49.924 -					}
  49.925 -					else if (!tri_21b)
  49.926 -					{
  49.927 -						use_tri1a2 = TRUE;
  49.928 -					}
  49.929 -					else
  49.930 -					{
  49.931 -						LLVector3 d1 = p1 - pa;
  49.932 -						LLVector3 d2 = p2 - pb;
  49.933 -
  49.934 -						if (d1.magVecSquared() < d2.magVecSquared())
  49.935 -						{
  49.936 -							use_tri1a2 = TRUE;
  49.937 -						}
  49.938 -						else
  49.939 -						{
  49.940 -							use_tri1a2 = FALSE;
  49.941 -						}
  49.942 -					}
  49.943 -
  49.944 -					if (use_tri1a2)
  49.945 -					{
  49.946 -						index[count++] = pt1;
  49.947 -						index[count++] = pt2;
  49.948 -						index[count++] = pt1 + 1;
  49.949 -						pt1++;
  49.950 -					}
  49.951 -					else
  49.952 -					{
  49.953 -						index[count++] = pt1;
  49.954 -						index[count++] = pt2;
  49.955 -						index[count++] = pt2 - 1;
  49.956 -						pt2--;
  49.957 -					}
  49.958 -				}
  49.959 -			}
  49.960 -		}
  49.961 -		else
  49.962 -		{
  49.963 -			// Open solid
  49.964 -
  49.965 -			for (t = 0; t < size_t - 1; t++)
  49.966 -			{
  49.967 -				// Outer face + 1 cut face
  49.968 -				for (s = 0; s < size_s - 1; s++)
  49.969 -				{
  49.970 -					i  = s + t*size_s;
  49.971 -
  49.972 -					index[count++]  = i;				// x,y
  49.973 -					index[count++]  = i + 1;			// x+1,y
  49.974 -					index[count++]  = i + size_s;		// x,y+1
  49.975 -
  49.976 -					index[count++]  = i + size_s;		// x,y+1
  49.977 -					index[count++]  = i + 1;			// x+1,y
  49.978 -					index[count++]  = i + size_s + 1;	// x+1,y+1
  49.979 -				}
  49.980 -
  49.981 -				// The other cut face
  49.982 -				index[count++] = (size_s - 1) + (t*size_s);		// x,y
  49.983 -				index[count++] = 0 + t*size_s;					// x+1,y
  49.984 -				index[count++] = (size_s - 1) + (t+1)*size_s;	// x,y+1
  49.985 -
  49.986 -				index[count++] = (size_s - 1) + (t+1)*size_s;	// x,y+1
  49.987 -				index[count++] = 0 + (t*size_s);				// x+1,y
  49.988 -				index[count++] = 0 + (t+1)*size_s;				// x+1,y+1
  49.989 -			}
  49.990 -
  49.991 -			// Do the top and bottom caps, if necessary
  49.992 -			if (path_open)
  49.993 -			{
  49.994 -				for (s = 0; s < size_s - 2; s++)
  49.995 -				{
  49.996 -					index[count++] = s+1;
  49.997 -					index[count++] = s;
  49.998 -					index[count++] = size_s - 1;
  49.999 -				}
 49.1000 -
 49.1001 -				// We've got a top cap
 49.1002 -				S32 offset = (size_t - 1)*size_s;
 49.1003 -				for (s = 0; s < size_s - 2; s++)
 49.1004 -				{
 49.1005 -					// Inverted ordering from bottom cap.
 49.1006 -					index[count++] = offset + size_s - 1;
 49.1007 -					index[count++] = offset + s;
 49.1008 -					index[count++] = offset + s + 1;
 49.1009 -				}
 49.1010 -			}
 49.1011 -		}
 49.1012 -	}
 49.1013 -	else if (hollow)
 49.1014 -	{
 49.1015 -		// Closed hollow
 49.1016 -		// Outer face
 49.1017 -		
 49.1018 -		for (t = 0; t < size_t - 1; t++)
 49.1019 -		{
 49.1020 -			for (s = 0; s < size_s_out - 1; s++)
 49.1021 -			{
 49.1022 -				i  = s + t*size_s;
 49.1023 -
 49.1024 -				index[count++]  = i;				// x,y
 49.1025 -				index[count++]  = i + 1;			// x+1,y
 49.1026 -				index[count++]  = i + size_s;		// x,y+1
 49.1027 -
 49.1028 -				index[count++]  = i + size_s;		// x,y+1
 49.1029 -				index[count++]  = i + 1;			// x+1,y
 49.1030 -				index[count++]  = i + 1 + size_s;	// x+1,y+1
 49.1031 -			}
 49.1032 -		}
 49.1033 -
 49.1034 -		// Inner face
 49.1035 -		// Invert facing from outer face
 49.1036 -		for (t = 0; t < size_t - 1; t++)
 49.1037 -		{
 49.1038 -			for (s = size_s_out; s < size_s - 1; s++)
 49.1039 -			{
 49.1040 -				i  = s + t*size_s;
 49.1041 -
 49.1042 -				index[count++]  = i;				// x,y
 49.1043 -				index[count++]  = i + 1;			// x+1,y
 49.1044 -				index[count++]  = i + size_s;		// x,y+1
 49.1045 -
 49.1046 -				index[count++]  = i + size_s;		// x,y+1
 49.1047 -				index[count++]  = i + 1;			// x+1,y
 49.1048 -				index[count++]  = i + 1 + size_s;	// x+1,y+1
 49.1049 -			}
 49.1050 -		}
 49.1051 -
 49.1052 -		// Do the top and bottom caps, if necessary
 49.1053 -		if (path_open)
 49.1054 -		{
 49.1055 -			// Top cap
 49.1056 -			S32 pt1 = 0;
 49.1057 -			S32 pt2 = size_s-1;
 49.1058 -			S32 i   = (size_t - 1)*size_s;
 49.1059 -
 49.1060 -			while (pt2 - pt1 > 1)
 49.1061 -			{
 49.1062 -				// Use the profile points instead of the mesh, since you want
 49.1063 -				// the un-transformed profile distances.
 49.1064 -				LLVector3 p1 = getProfile().mProfile[pt1];
 49.1065 -				LLVector3 p2 = getProfile().mProfile[pt2];
 49.1066 -				LLVector3 pa = getProfile().mProfile[pt1+1];
 49.1067 -				LLVector3 pb = getProfile().mProfile[pt2-1];
 49.1068 -
 49.1069 -				p1.mV[VZ] = 0.f;
 49.1070 -				p2.mV[VZ] = 0.f;
 49.1071 -				pa.mV[VZ] = 0.f;
 49.1072 -				pb.mV[VZ] = 0.f;
 49.1073 -
 49.1074 -				// Use area of triangle to determine backfacing
 49.1075 -				F32 area_1a2, area_1ba, area_21b, area_2ab;
 49.1076 -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
 49.1077 -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
 49.1078 -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
 49.1079 -
 49.1080 -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
 49.1081 -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
 49.1082 -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
 49.1083 -
 49.1084 -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
 49.1085 -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
 49.1086 -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
 49.1087 -
 49.1088 -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
 49.1089 -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
 49.1090 -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
 49.1091 -
 49.1092 -				BOOL use_tri1a2 = TRUE;
 49.1093 -				BOOL tri_1a2 = TRUE;
 49.1094 -				BOOL tri_21b = TRUE;
 49.1095 -
 49.1096 -				if (area_1a2 < 0)
 49.1097 -				{
 49.1098 -					tri_1a2 = FALSE;
 49.1099 -				}
 49.1100 -				if (area_2ab < 0)
 49.1101 -				{
 49.1102 -					// Can't use, because it contains point b
 49.1103 -					tri_1a2 = FALSE;
 49.1104 -				}
 49.1105 -				if (area_21b < 0)
 49.1106 -				{
 49.1107 -					tri_21b = FALSE;
 49.1108 -				}
 49.1109 -				if (area_1ba < 0)
 49.1110 -				{
 49.1111 -					// Can't use, because it contains point b
 49.1112 -					tri_21b = FALSE;
 49.1113 -				}
 49.1114 -
 49.1115 -				if (!tri_1a2)
 49.1116 -				{
 49.1117 -					use_tri1a2 = FALSE;
 49.1118 -				}
 49.1119 -				else if (!tri_21b)
 49.1120 -				{
 49.1121 -					use_tri1a2 = TRUE;
 49.1122 -				}
 49.1123 -				else
 49.1124 -				{
 49.1125 -					LLVector3 d1 = p1 - pa;
 49.1126 -					LLVector3 d2 = p2 - pb;
 49.1127 -
 49.1128 -					if (d1.magVecSquared() < d2.magVecSquared())
 49.1129 -					{
 49.1130 -						use_tri1a2 = TRUE;
 49.1131 -					}
 49.1132 -					else
 49.1133 -					{
 49.1134 -						use_tri1a2 = FALSE;
 49.1135 -					}
 49.1136 -				}
 49.1137 -
 49.1138 -				if (use_tri1a2)
 49.1139 -				{
 49.1140 -					index[count++] = pt1 + i;
 49.1141 -					index[count++] = pt1 + 1 + i;
 49.1142 -					index[count++] = pt2 + i;
 49.1143 -					pt1++;
 49.1144 -				}
 49.1145 -				else
 49.1146 -				{
 49.1147 -					index[count++] = pt1 + i;
 49.1148 -					index[count++] = pt2 - 1 + i;
 49.1149 -					index[count++] = pt2 + i;
 49.1150 -					pt2--;
 49.1151 -				}
 49.1152 -			}
 49.1153 -
 49.1154 -			// Bottom cap
 49.1155 -			pt1          = 0;
 49.1156 -			pt2          = size_s-1;
 49.1157 -			while (pt2 - pt1 > 1)
 49.1158 -			{
 49.1159 -				// Use the profile points instead of the mesh, since you want
 49.1160 -				// the un-transformed profile distances.
 49.1161 -				LLVector3 p1 = getProfile().mProfile[pt1];
 49.1162 -				LLVector3 p2 = getProfile().mProfile[pt2];
 49.1163 -				LLVector3 pa = getProfile().mProfile[pt1+1];
 49.1164 -				LLVector3 pb = getProfile().mProfile[pt2-1];
 49.1165 -
 49.1166 -				p1.mV[VZ] = 0.f;
 49.1167 -				p2.mV[VZ] = 0.f;
 49.1168 -				pa.mV[VZ] = 0.f;
 49.1169 -				pb.mV[VZ] = 0.f;
 49.1170 -
 49.1171 -				// Use area of triangle to determine backfacing
 49.1172 -				F32 area_1a2, area_1ba, area_21b, area_2ab;
 49.1173 -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
 49.1174 -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
 49.1175 -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
 49.1176 -
 49.1177 -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
 49.1178 -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
 49.1179 -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
 49.1180 -
 49.1181 -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
 49.1182 -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
 49.1183 -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
 49.1184 -
 49.1185 -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
 49.1186 -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
 49.1187 -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
 49.1188 -
 49.1189 -				BOOL use_tri1a2 = TRUE;
 49.1190 -				BOOL tri_1a2 = TRUE;
 49.1191 -				BOOL tri_21b = TRUE;
 49.1192 -
 49.1193 -				if (area_1a2 < 0)
 49.1194 -				{
 49.1195 -					tri_1a2 = FALSE;
 49.1196 -				}
 49.1197 -				if (area_2ab < 0)
 49.1198 -				{
 49.1199 -					// Can't use, because it contains point b
 49.1200 -					tri_1a2 = FALSE;
 49.1201 -				}
 49.1202 -				if (area_21b < 0)
 49.1203 -				{
 49.1204 -					tri_21b = FALSE;
 49.1205 -				}
 49.1206 -				if (area_1ba < 0)
 49.1207 -				{
 49.1208 -					// Can't use, because it contains point b
 49.1209 -					tri_21b = FALSE;
 49.1210 -				}
 49.1211 -
 49.1212 -				if (!tri_1a2)
 49.1213 -				{
 49.1214 -					use_tri1a2 = FALSE;
 49.1215 -				}
 49.1216 -				else if (!tri_21b)
 49.1217 -				{
 49.1218 -					use_tri1a2 = TRUE;
 49.1219 -				}
 49.1220 -				else
 49.1221 -				{
 49.1222 -					LLVector3 d1 = p1 - pa;
 49.1223 -					LLVector3 d2 = p2 - pb;
 49.1224 -
 49.1225 -					if (d1.magVecSquared() < d2.magVecSquared())
 49.1226 -					{
 49.1227 -						use_tri1a2 = TRUE;
 49.1228 -					}
 49.1229 -					else
 49.1230 -					{
 49.1231 -						use_tri1a2 = FALSE;
 49.1232 -					}
 49.1233 -				}
 49.1234 -
 49.1235 -				if (use_tri1a2)
 49.1236 -				{
 49.1237 -					index[count++] = pt1;
 49.1238 -					index[count++] = pt2;
 49.1239 -					index[count++] = pt1 + 1;
 49.1240 -					pt1++;
 49.1241 -				}
 49.1242 -				else
 49.1243 -				{
 49.1244 -					index[count++] = pt1;
 49.1245 -					index[count++] = pt2;
 49.1246 -					index[count++] = pt2 - 1;
 49.1247 -					pt2--;
 49.1248 -				}
 49.1249 -			}
 49.1250 -		}		
 49.1251 -	}
 49.1252 -	else
 49.1253 -	{
 49.1254 -		// Closed solid.  Easy case.
 49.1255 -		for (t = 0; t < size_t - 1; t++)
 49.1256 -		{
 49.1257 -			for (s = 0; s < size_s - 1; s++)
 49.1258 -			{
 49.1259 -				// Should wrap properly, but for now...
 49.1260 -				i  = s + t*size_s;
 49.1261 -
 49.1262 -				index[count++]  = i;				// x,y
 49.1263 -				index[count++]  = i + 1;			// x+1,y
 49.1264 -				index[count++]  = i + size_s;		// x,y+1
 49.1265 -
 49.1266 -				index[count++]  = i + size_s;		// x,y+1
 49.1267 -				index[count++]  = i + 1;			// x+1,y
 49.1268 -				index[count++]  = i + size_s + 1;	// x+1,y+1
 49.1269 -			}
 49.1270 -		}
 49.1271 -
 49.1272 -		// Do the top and bottom caps, if necessary
 49.1273 -		if (path_open)
 49.1274 -		{
 49.1275 -			// bottom cap
 49.1276 -			for (s = 1; s < size_s - 2; s++)
 49.1277 -			{
 49.1278 -				index[count++] = s+1;
 49.1279 -				index[count++] = s;
 49.1280 -				index[count++] = 0;
 49.1281 -			}
 49.1282 -
 49.1283 -			// top cap
 49.1284 -			S32 offset = (size_t - 1)*size_s;
 49.1285 -			for (s = 1; s < size_s - 2; s++)
 49.1286 -			{
 49.1287 -				// Inverted ordering from bottom cap.
 49.1288 -				index[count++] = offset;
 49.1289 -				index[count++] = offset + s;
 49.1290 -				index[count++] = offset + s + 1;
 49.1291 -			}
 49.1292 -		}
 49.1293 -	}
 49.1294 -
 49.1295 -#ifdef LL_DEBUG
 49.1296 -	// assert that we computed the correct number of indices
 49.1297 -	if (count != expected_num_triangle_indices )
 49.1298 -	{
 49.1299 -		llerrs << "bad index count prediciton:"
 49.1300 -			<< "  expected=" << expected_num_triangle_indices 
 49.1301 -			<< " actual=" << count << llendl;
 49.1302 -	}
 49.1303 -#endif
 49.1304 -
 49.1305 -#if 0
 49.1306 -	// verify that each index does not point beyond the size of the mesh
 49.1307 -	S32 num_vertices = mMesh.size();
 49.1308 -	for (i = 0; i < count; i+=3)
 49.1309 -	{
 49.1310 -		llinfos << index[i] << ":" << index[i+1] << ":" << index[i+2] << llendl;
 49.1311 -		llassert(index[i] < num_vertices);
 49.1312 -		llassert(index[i+1] < num_vertices);
 49.1313 -		llassert(index[i+2] < num_vertices);
 49.1314 -	}
 49.1315 -#endif
 49.1316 -
 49.1317 -	num_indices = count;
 49.1318 -	return index;
 49.1319 -}
 49.1320 -
 49.1321  void LLVolume::getLoDTriangleCounts(const LLVolumeParams& params, S32* counts)
 49.1322  { //attempt to approximate the number of triangles that will result from generating a volume LoD set for the 
 49.1323  	//supplied LLVolumeParams -- inaccurate, but a close enough approximation for determining streaming cost
 49.1324 @@ -4276,63 +3604,6 @@
 49.1325  	}
 49.1326  }
 49.1327  
 49.1328 -S32 LLVolume::getNumTriangleIndices() const
 49.1329 -{
 49.1330 -	BOOL profile_open = getProfile().isOpen();
 49.1331 -	BOOL hollow = (mParams.getProfileParams().getHollow() > 0);
 49.1332 -	BOOL path_open = getPath().isOpen();
 49.1333 -
 49.1334 -	S32 size_s, size_s_out, size_t;
 49.1335 -	size_s = getProfile().getTotal();
 49.1336 -	size_s_out = getProfile().getTotalOut();
 49.1337 -	size_t = getPath().mPath.size();
 49.1338 -
 49.1339 -	S32 count = 0;
 49.1340 -	if (profile_open)		/* Flawfinder: ignore */
 49.1341 -	{
 49.1342 -		if (hollow)
 49.1343 -		{
 49.1344 -			// Open hollow -- much like the closed solid, except we 
 49.1345 -			// we need to stitch up the gap between s=0 and s=size_s-1
 49.1346 -			count = (size_t - 1) * (((size_s -1) * 6) + 6);
 49.1347 -		}
 49.1348 -		else
 49.1349 -		{
 49.1350 -			count = (size_t - 1) * (((size_s -1) * 6) + 6); 
 49.1351 -		}
 49.1352 -	}
 49.1353 -	else if (hollow)
 49.1354 -	{
 49.1355 -		// Closed hollow
 49.1356 -		// Outer face
 49.1357 -		count = (size_t - 1) * (size_s_out - 1) * 6;
 49.1358 -
 49.1359 -		// Inner face
 49.1360 -		count += (size_t - 1) * ((size_s - 1) - size_s_out) * 6;
 49.1361 -	}
 49.1362 -	else
 49.1363 -	{
 49.1364 -		// Closed solid.  Easy case.
 49.1365 -		count = (size_t - 1) * (size_s - 1) * 6;
 49.1366 -	}
 49.1367 -
 49.1368 -	if (path_open)
 49.1369 -	{
 49.1370 -		S32 cap_triangle_count = size_s - 3;
 49.1371 -		if ( profile_open
 49.1372 -			|| hollow )
 49.1373 -		{
 49.1374 -			cap_triangle_count = size_s - 2;
 49.1375 -		}
 49.1376 -		if ( cap_triangle_count > 0 )
 49.1377 -		{
 49.1378 -			// top and bottom caps
 49.1379 -			count += cap_triangle_count * 2 * 3;
 49.1380 -		}
 49.1381 -	}
 49.1382 -	return count;
 49.1383 -}
 49.1384 -
 49.1385  
 49.1386  S32 LLVolume::getNumTriangles(S32* vcount) const
 49.1387  {
 49.1388 @@ -5268,6 +4539,7 @@
 49.1389  	mNumS(0),
 49.1390  	mNumT(0),
 49.1391  	mNumVertices(0),
 49.1392 +	mNumAllocatedVertices(0),
 49.1393  	mNumIndices(0),
 49.1394  	mPositions(NULL),
 49.1395  	mNormals(NULL),
 49.1396 @@ -5275,7 +4547,8 @@
 49.1397  	mTexCoords(NULL),
 49.1398  	mIndices(NULL),
 49.1399  	mWeights(NULL),
 49.1400 -	mOctree(NULL)
 49.1401 +	mOctree(NULL),
 49.1402 +	mOptimized(FALSE)
 49.1403  {
 49.1404  	mExtents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*3);
 49.1405  	mExtents[0].splat(-0.5f);
 49.1406 @@ -5291,6 +4564,7 @@
 49.1407  	mNumS(0),
 49.1408  	mNumT(0),
 49.1409  	mNumVertices(0),
 49.1410 +	mNumAllocatedVertices(0),
 49.1411  	mNumIndices(0),
 49.1412  	mPositions(NULL),
 49.1413  	mNormals(NULL),
 49.1414 @@ -5328,8 +4602,6 @@
 49.1415  
 49.1416  	freeData();
 49.1417  	
 49.1418 -	LLVector4a::memcpyNonAliased16((F32*) mExtents, (F32*) src.mExtents, 3*sizeof(LLVector4a));
 49.1419 -
 49.1420  	resizeVertices(src.mNumVertices);
 49.1421  	resizeIndices(src.mNumIndices);
 49.1422  
 49.1423 @@ -5339,18 +4611,16 @@
 49.1424  		S32 tc_size = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF;
 49.1425  			
 49.1426  		LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) src.mPositions, vert_size);
 49.1427 +
 49.1428 +		if (src.mNormals)
 49.1429 +		{
 49.1430  		LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size);
 49.1431 +		}
 49.1432  
 49.1433  		if(src.mTexCoords)
 49.1434  		{
 49.1435  			LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
 49.1436  		}
 49.1437 -		else
 49.1438 -		{
 49.1439 -			ll_aligned_free_16(mTexCoords) ;
 49.1440 -			mTexCoords = NULL ;
 49.1441 -		}
 49.1442 -
 49.1443  
 49.1444  		if (src.mTangents)
 49.1445  		{
 49.1446 @@ -5382,6 +4652,8 @@
 49.1447  		LLVector4a::memcpyNonAliased16((F32*) mIndices, (F32*) src.mIndices, idx_size);
 49.1448  	}
 49.1449  	
 49.1450 +	mOptimized = src.mOptimized;
 49.1451 +
 49.1452  	//delete 
 49.1453  	return *this;
 49.1454  }
 49.1455 @@ -5396,12 +4668,13 @@
 49.1456  
 49.1457  void LLVolumeFace::freeData()
 49.1458  {
 49.1459 -	ll_aligned_free_16(mPositions);
 49.1460 +	ll_aligned_free(mPositions);
 49.1461  	mPositions = NULL;
 49.1462 -	ll_aligned_free_16( mNormals);
 49.1463 +
 49.1464 +	//normals and texture coordinates are part of the same buffer as mPositions, do not free them separately
 49.1465  	mNormals = NULL;
 49.1466 -	ll_aligned_free_16(mTexCoords);
 49.1467  	mTexCoords = NULL;
 49.1468 +
 49.1469  	ll_aligned_free_16(mIndices);
 49.1470  	mIndices = NULL;
 49.1471  	ll_aligned_free_16(mTangents);
 49.1472 @@ -5419,52 +4692,23 @@
 49.1473  	delete mOctree;
 49.1474  	mOctree = NULL;
 49.1475  
 49.1476 +	LL_CHECK_MEMORY
 49.1477  	BOOL ret = FALSE ;
 49.1478  	if (mTypeMask & CAP_MASK)
 49.1479  	{
 49.1480  		ret = createCap(volume, partial_build);
 49.1481 +		LL_CHECK_MEMORY
 49.1482  	}
 49.1483  	else if ((mTypeMask & END_MASK) || (mTypeMask & SIDE_MASK))
 49.1484  	{
 49.1485  		ret = createSide(volume, partial_build);
 49.1486 +		LL_CHECK_MEMORY
 49.1487  	}
 49.1488  	else
 49.1489  	{
 49.1490  		llerrs << "Unknown/uninitialized face type!" << llendl;
 49.1491  	}
 49.1492  
 49.1493 -	//update the range of the texture coordinates
 49.1494 -	if(ret)
 49.1495 -	{
 49.1496 -		mTexCoordExtents[0].setVec(1.f, 1.f) ;
 49.1497 -		mTexCoordExtents[1].setVec(0.f, 0.f) ;
 49.1498 -
 49.1499 -		for(U32 i = 0 ; i < mNumVertices ; i++)
 49.1500 -		{
 49.1501 -			if(mTexCoordExtents[0].mV[0] > mTexCoords[i].mV[0])
 49.1502 -			{
 49.1503 -				mTexCoordExtents[0].mV[0] = mTexCoords[i].mV[0] ;
 49.1504 -			}
 49.1505 -			if(mTexCoordExtents[1].mV[0] < mTexCoords[i].mV[0])
 49.1506 -			{
 49.1507 -				mTexCoordExtents[1].mV[0] = mTexCoords[i].mV[0] ;
 49.1508 -			}
 49.1509 -
 49.1510 -			if(mTexCoordExtents[0].mV[1] > mTexCoords[i].mV[1])
 49.1511 -			{
 49.1512 -				mTexCoordExtents[0].mV[1] = mTexCoords[i].mV[1] ;
 49.1513 -			}
 49.1514 -			if(mTexCoordExtents[1].mV[1] < mTexCoords[i].mV[1])
 49.1515 -			{
 49.1516 -				mTexCoordExtents[1].mV[1] = mTexCoords[i].mV[1] ;
 49.1517 -			}			
 49.1518 -		}
 49.1519 -		mTexCoordExtents[0].mV[0] = llmax(0.f, mTexCoordExtents[0].mV[0]) ;
 49.1520 -		mTexCoordExtents[0].mV[1] = llmax(0.f, mTexCoordExtents[0].mV[1]) ;
 49.1521 -		mTexCoordExtents[1].mV[0] = llmin(1.f, mTexCoordExtents[1].mV[0]) ;
 49.1522 -		mTexCoordExtents[1].mV[1] = llmin(1.f, mTexCoordExtents[1].mV[1]) ;
 49.1523 -	}
 49.1524 -
 49.1525  	return ret ;
 49.1526  }
 49.1527  
 49.1528 @@ -5580,22 +4824,29 @@
 49.1529  		}
 49.1530  	}
 49.1531  
 49.1532 +
 49.1533 +	if (angle_cutoff > 1.f && !mNormals)
 49.1534 +	{
 49.1535 +		// Now alloc'd with positions
 49.1536 +		//ll_aligned_free_16(new_face.mNormals);
 49.1537 +		new_face.mNormals = NULL;
 49.1538 +	}
 49.1539 +
 49.1540 +	if (!mTexCoords)
 49.1541 +	{
 49.1542 +		// Now alloc'd with positions
 49.1543 +		//ll_aligned_free_16(new_face.mTexCoords);
 49.1544 +		new_face.mTexCoords = NULL;
 49.1545 +	}
 49.1546 +
 49.1547 +	// Only swap data if we've actually optimized the mesh
 49.1548 +	//
 49.1549 +	if (new_face.mNumVertices <= mNumVertices)
 49.1550 +	{
 49.1551  	llassert(new_face.mNumIndices == mNumIndices);
 49.1552 -	llassert(new_face.mNumVertices <= mNumVertices);
 49.1553 -
 49.1554 -	if (angle_cutoff > 1.f && !mNormals)
 49.1555 -	{
 49.1556 -		ll_aligned_free_16(new_face.mNormals);
 49.1557 -		new_face.mNormals = NULL;
 49.1558 -	}
 49.1559 -
 49.1560 -	if (!mTexCoords)
 49.1561 -	{
 49.1562 -		ll_aligned_free_16(new_face.mTexCoords);
 49.1563 -		new_face.mTexCoords = NULL;
 49.1564 -	}
 49.1565 -
 49.1566 -	swapData(new_face);
 49.1567 +		swapData(new_face);
 49.1568 +	}
 49.1569 +
 49.1570  }
 49.1571  
 49.1572  class LLVCacheTriangleData;
 49.1573 @@ -5605,14 +4856,14 @@
 49.1574  public:
 49.1575  	S32 mIdx;
 49.1576  	S32 mCacheTag;
 49.1577 -	F32 mScore;
 49.1578 +	F64 mScore;
 49.1579  	U32 mActiveTriangles;
 49.1580  	std::vector<LLVCacheTriangleData*> mTriangles;
 49.1581  
 49.1582  	LLVCacheVertexData()
 49.1583  	{
 49.1584  		mCacheTag = -1;
 49.1585 -		mScore = 0.f;
 49.1586 +		mScore = 0.0;
 49.1587  		mActiveTriangles = 0;
 49.1588  		mIdx = -1;
 49.1589  	}
 49.1590 @@ -5622,13 +4873,13 @@
 49.1591  {
 49.1592  public:
 49.1593  	bool mActive;
 49.1594 -	F32 mScore;
 49.1595 +	F64 mScore;
 49.1596  	LLVCacheVertexData* mVertex[3];
 49.1597  
 49.1598  	LLVCacheTriangleData()
 49.1599  	{
 49.1600  		mActive = true;
 49.1601 -		mScore = 0.f;
 49.1602 +		mScore = 0.0;
 49.1603  		mVertex[0] = mVertex[1] = mVertex[2] = NULL;
 49.1604  	}
 49.1605  
 49.1606 @@ -5639,7 +4890,7 @@
 49.1607  		{
 49.1608  			if (mVertex[i])
 49.1609  			{
 49.1610 -				llassert_always(mVertex[i]->mActiveTriangles > 0);
 49.1611 +				llassert(mVertex[i]->mActiveTriangles > 0);
 49.1612  				mVertex[i]->mActiveTriangles--;
 49.1613  			}
 49.1614  		}
 49.1615 @@ -5651,20 +4902,20 @@
 49.1616  	}
 49.1617  };
 49.1618  
 49.1619 -const F32 FindVertexScore_CacheDecayPower = 1.5f;
 49.1620 -const F32 FindVertexScore_LastTriScore = 0.75f;
 49.1621 -const F32 FindVertexScore_ValenceBoostScale = 2.0f;
 49.1622 -const F32 FindVertexScore_ValenceBoostPower = 0.5f;
 49.1623 +const F64 FindVertexScore_CacheDecayPower = 1.5;
 49.1624 +const F64 FindVertexScore_LastTriScore = 0.75;
 49.1625 +const F64 FindVertexScore_ValenceBoostScale = 2.0;
 49.1626 +const F64 FindVertexScore_ValenceBoostPower = 0.5;
 49.1627  const U32 MaxSizeVertexCache = 32;
 49.1628 -
 49.1629 -F32 find_vertex_score(LLVCacheVertexData& data)
 49.1630 -{
 49.1631 -	if (data.mActiveTriangles == 0)
 49.1632 -	{ //no triangle references this vertex
 49.1633 -		return -1.f;
 49.1634 -	}
 49.1635 -
 49.1636 -	F32 score = 0.f;
 49.1637 +const F64 FindVertexScore_Scaler = 1.0/(MaxSizeVertexCache-3);
 49.1638 +
 49.1639 +F64 find_vertex_score(LLVCacheVertexData& data)
 49.1640 +{
 49.1641 +	F64 score = -1.0;
 49.1642 +
 49.1643 +	if (data.mActiveTriangles >= 0)
 49.1644 +	{ 
 49.1645 +		score = 0.0;
 49.1646  
 49.1647  	S32 cache_idx = data.mCacheTag;
 49.1648  
 49.1649 @@ -5680,15 +4931,15 @@
 49.1650  		}
 49.1651  		else
 49.1652  		{ //more points for being higher in the cache
 49.1653 -			F32 scaler = 1.f/(MaxSizeVertexCache-3);
 49.1654 -			score = 1.f-((cache_idx-3)*scaler);
 49.1655 -			score = powf(score, FindVertexScore_CacheDecayPower);
 49.1656 +				score = 1.0-((cache_idx-3)*FindVertexScore_Scaler);
 49.1657 +				score = pow(score, FindVertexScore_CacheDecayPower);
 49.1658  		}
 49.1659  	}
 49.1660  
 49.1661  	//bonus points for having low valence
 49.1662 -	F32 valence_boost = powf((F32)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower);
 49.1663 +		F64 valence_boost = pow((F64)data.mActiveTriangles, -FindVertexScore_ValenceBoostPower);
 49.1664  	score += FindVertexScore_ValenceBoostScale * valence_boost;
 49.1665 +	}
 49.1666  
 49.1667  	return score;
 49.1668  }
 49.1669 @@ -5795,32 +5046,44 @@
 49.1670  
 49.1671  	void updateScores()
 49.1672  	{
 49.1673 -		for (U32 i = MaxSizeVertexCache; i < MaxSizeVertexCache+3; ++i)
 49.1674 -		{ //trailing 3 vertices aren't actually in the cache for scoring purposes
 49.1675 -			if (mCache[i])
 49.1676 +		LLVCacheVertexData** data_iter = mCache+MaxSizeVertexCache;
 49.1677 +		LLVCacheVertexData** end_data = mCache+MaxSizeVertexCache+3;
 49.1678 +
 49.1679 +		while(data_iter != end_data)
 49.1680 +		{
 49.1681 +			LLVCacheVertexData* data = *data_iter++;
 49.1682 +			//trailing 3 vertices aren't actually in the cache for scoring purposes
 49.1683 +			if (data)
 49.1684  			{
 49.1685 -				mCache[i]->mCacheTag = -1;
 49.1686 +				data->mCacheTag = -1;
 49.1687  			}
 49.1688  		}
 49.1689  
 49.1690 -		for (U32 i = 0; i < MaxSizeVertexCache; ++i)
 49.1691 +		data_iter = mCache;
 49.1692 +		end_data = mCache+MaxSizeVertexCache;
 49.1693 +
 49.1694 +		while (data_iter != end_data)
 49.1695  		{ //update scores of vertices in cache
 49.1696 -			if (mCache[i])
 49.1697 +			LLVCacheVertexData* data = *data_iter++;
 49.1698 +			if (data)
 49.1699  			{
 49.1700 -				mCache[i]->mScore = find_vertex_score(*(mCache[i]));
 49.1701 -				llassert_always(mCache[i]->mCacheTag == i);
 49.1702 +				data->mScore = find_vertex_score(*data);
 49.1703  			}
 49.1704  		}
 49.1705  
 49.1706  		mBestTriangle = NULL;
 49.1707  		//update triangle scores
 49.1708 -		for (U32 i = 0; i < MaxSizeVertexCache+3; ++i)
 49.1709 -		{
 49.1710 -			if (mCache[i])
 49.1711 +		data_iter = mCache;
 49.1712 +		end_data = mCache+MaxSizeVertexCache+3;
 49.1713 +
 49.1714 +		while (data_iter != end_data)
 49.1715 +		{
 49.1716 +			LLVCacheVertexData* data = *data_iter++;
 49.1717 +			if (data)
 49.1718  			{
 49.1719 -				for (U32 j = 0; j < mCache[i]->mTriangles.size(); ++j)
 49.1720 +				for (std::vector<LLVCacheTriangleData*>::iterator iter = data->mTriangles.begin(), end_iter = data->mTriangles.end(); iter != end_iter; ++iter)
 49.1721  				{
 49.1722 -					LLVCacheTriangleData* tri = mCache[i]->mTriangles[j];
 49.1723 +					LLVCacheTriangleData* tri = *iter;
 49.1724  					if (tri->mActive)
 49.1725  					{
 49.1726  						tri->mScore = tri->mVertex[0]->mScore;
 49.1727 @@ -5837,13 +5100,17 @@
 49.1728  		}
 49.1729  
 49.1730  		//knock trailing 3 vertices off the cache
 49.1731 -		for (U32 i = MaxSizeVertexCache; i < MaxSizeVertexCache+3; ++i)
 49.1732 -		{
 49.1733 -			if (mCache[i])
 49.1734 +		data_iter = mCache+MaxSizeVertexCache;
 49.1735 +		end_data = mCache+MaxSizeVertexCache+3;
 49.1736 +		while (data_iter != end_data)
 49.1737 +		{
 49.1738 +			LLVCacheVertexData* data = *data_iter;
 49.1739 +			if (data)
 49.1740  			{
 49.1741 -				llassert_always(mCache[i]->mCacheTag == -1);
 49.1742 -				mCache[i] = NULL;
 49.1743 +				llassert(data->mCacheTag == -1);
 49.1744 +				*data_iter = NULL;
 49.1745  			}
 49.1746 +			++data_iter;
 49.1747  		}
 49.1748  	}
 49.1749  };
 49.1750 @@ -5853,6 +5120,9 @@
 49.1751  { //optimize for vertex cache according to Forsyth method: 
 49.1752    // http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
 49.1753  	
 49.1754 +	llassert(!mOptimized);
 49.1755 +	mOptimized = TRUE;
 49.1756 +
 49.1757  	LLVCacheLRU cache;
 49.1758  	
 49.1759  	if (mNumVertices < 3)
 49.1760 @@ -5898,12 +5168,14 @@
 49.1761  
 49.1762  	for (U32 i = 0; i < mNumVertices; i++)
 49.1763  	{ //initialize score values (no cache -- might try a fifo cache here)
 49.1764 -		vertex_data[i].mScore = find_vertex_score(vertex_data[i]);
 49.1765 -		vertex_data[i].mActiveTriangles = vertex_data[i].mTriangles.size();
 49.1766 -
 49.1767 -		for (U32 j = 0; j < vertex_data[i].mTriangles.size(); ++j)
 49.1768 -		{
 49.1769 -			vertex_data[i].mTriangles[j]->mScore += vertex_data[i].mScore;
 49.1770 +		LLVCacheVertexData& data = vertex_data[i];
 49.1771 +
 49.1772 +		data.mScore = find_vertex_score(data);
 49.1773 +		data.mActiveTriangles = data.mTriangles.size();
 49.1774 +
 49.1775 +		for (U32 j = 0; j < data.mActiveTriangles; ++j)
 49.1776 +		{
 49.1777 +			data.mTriangles[j]->mScore += data.mScore;
 49.1778  		}
 49.1779  	}
 49.1780  
 49.1781 @@ -5973,10 +5245,10 @@
 49.1782  	
 49.1783  	//allocate space for new buffer
 49.1784  	S32 num_verts = mNumVertices;
 49.1785 -	LLVector4a* pos = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
 49.1786 -	LLVector4a* norm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
 49.1787  	S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
 49.1788 -	LLVector2* tc = (LLVector2*) ll_aligned_malloc_16(size);
 49.1789 +	LLVector4a* pos = (LLVector4a*) ll_aligned_malloc(sizeof(LLVector4a)*2*num_verts+size, 64);
 49.1790 +	LLVector4a* norm = pos + num_verts;
 49.1791 +	LLVector2* tc = (LLVector2*) (norm + num_verts);
 49.1792  
 49.1793  	LLVector4a* wght = NULL;
 49.1794  	if (mWeights)
 49.1795 @@ -5984,10 +5256,10 @@
 49.1796  		wght = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
 49.1797  	}
 49.1798  
 49.1799 -	LLVector4a* tangent = NULL;
 49.1800 +	LLVector4a* binorm = NULL;
 49.1801  	if (mTangents)
 49.1802  	{
 49.1803 -		tangent = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
 49.1804 +		binorm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
 49.1805  	}
 49.1806  
 49.1807  	//allocate mapping of old indices to new indices
 49.1808 @@ -6012,7 +5284,7 @@
 49.1809  			}
 49.1810  			if (mTangents)
 49.1811  			{
 49.1812 -				tangent[cur_idx] = mTangents[idx];
 49.1813 +				binorm[cur_idx] = mTangents[idx];
 49.1814  			}
 49.1815  
 49.1816  			cur_idx++;
 49.1817 @@ -6024,9 +5296,8 @@
 49.1818  		mIndices[i] = new_idx[mIndices[i]];
 49.1819  	}
 49.1820  	
 49.1821 -	ll_aligned_free_16(mPositions);
 49.1822 -	ll_aligned_free_16(mNormals);
 49.1823 -	ll_aligned_free_16(mTexCoords);
 49.1824 +	ll_aligned_free(mPositions);
 49.1825 +	// DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
 49.1826  	ll_aligned_free_16(mWeights);
 49.1827  	ll_aligned_free_16(mTangents);
 49.1828  
 49.1829 @@ -6034,7 +5305,7 @@
 49.1830  	mNormals = norm;
 49.1831  	mTexCoords = tc;
 49.1832  	mWeights = wght;
 49.1833 -	mTangents = tangent;
 49.1834 +	mTangents = binorm;
 49.1835  
 49.1836  	//std::string result = llformat("ACMR pre/post: %.3f/%.3f  --  %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);
 49.1837  	//llinfos << result << llendl;
 49.1838 @@ -6148,8 +5419,10 @@
 49.1839  
 49.1840  BOOL LLVolumeFace::createUnCutCubeCap(LLVolume* volume, BOOL partial_build)
 49.1841  {
 49.1842 -	const std::vector<LLVolume::Point>& mesh = volume->getMesh();
 49.1843 -	const std::vector<LLVector3>& profile = volume->getProfile().mProfile;
 49.1844 +	LL_CHECK_MEMORY		
 49.1845 +
 49.1846 +	const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh();
 49.1847 +	const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile;
 49.1848  	S32 max_s = volume->getProfile().getTotal();
 49.1849  	S32 max_t = volume->getPath().mPath.size();
 49.1850  
 49.1851 @@ -6174,9 +5447,9 @@
 49.1852  		VertexData baseVert;
 49.1853  		for(S32 t = 0; t < 4; t++)
 49.1854  		{
 49.1855 -			corners[t].getPosition().load3( mesh[offset + (grid_size*t)].mPos.mV);
 49.1856 -			corners[t].mTexCoord.mV[0] = profile[grid_size*t].mV[0]+0.5f;
 49.1857 -			corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t].mV[1];
 49.1858 +			corners[t].getPosition().load4a(mesh[offset + (grid_size*t)].getF32ptr());
 49.1859 +			corners[t].mTexCoord.mV[0] = profile[grid_size*t][0]+0.5f;
 49.1860 +			corners[t].mTexCoord.mV[1] = 0.5f - profile[grid_size*t][1];
 49.1861  		}
 49.1862  
 49.1863  		{
 49.1864 @@ -6275,6 +5548,7 @@
 49.1865  		}
 49.1866  	}
 49.1867  		
 49.1868 +	LL_CHECK_MEMORY
 49.1869  	return TRUE;
 49.1870  }
 49.1871  
 49.1872 @@ -6293,8 +5567,8 @@
 49.1873  
 49.1874  	S32 num_vertices = 0, num_indices = 0;
 49.1875  
 49.1876 -	const std::vector<LLVolume::Point>& mesh = volume->getMesh();
 49.1877 -	const std::vector<LLVector3>& profile = volume->getProfile().mProfile;
 49.1878 +	const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh();
 49.1879 +	const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile;
 49.1880  
 49.1881  	// All types of caps have the same number of vertices and indices
 49.1882  	num_vertices = profile.size();
 49.1883 @@ -6312,13 +5586,14 @@
 49.1884  	else
 49.1885  	{
 49.1886  		resizeVertices(num_vertices);
 49.1887 -		
 49.1888  		if (!partial_build)
 49.1889  		{
 49.1890  			resizeIndices(num_indices);
 49.1891  		}
 49.1892  	}
 49.1893  
 49.1894 +	LL_CHECK_MEMORY;
 49.1895 +
 49.1896  	S32 max_s = volume->getProfile().getTotal();
 49.1897  	S32 max_t = volume->getPath().mPath.size();
 49.1898  
 49.1899 @@ -6348,34 +5623,71 @@
 49.1900  	LLVector4a* norm = (LLVector4a*) mNormals;
 49.1901  	
 49.1902  	// Copy the vertices into the array
 49.1903 -	for (S32 i = 0; i < num_vertices; i++)
 49.1904 -	{
 49.1905 -		if (mTypeMask & TOP_MASK)
 49.1906 -		{
 49.1907 -			tc[i].mV[0] = profile[i].mV[0]+0.5f;
 49.1908 -			tc[i].mV[1] = profile[i].mV[1]+0.5f;
 49.1909 +
 49.1910 +	const LLVector4a* src = mesh.mArray+offset;
 49.1911 +	const LLVector4a* end = src+num_vertices;
 49.1912 +	
 49.1913 +	min = *src;
 49.1914 +	max = min;
 49.1915 +	
 49.1916 +	
 49.1917 +	const LLVector4a* p = profile.mArray;
 49.1918 +
 49.1919 +	if (mTypeMask & TOP_MASK)
 49.1920 +	{
 49.1921 +		min_uv.set((*p)[0]+0.5f,
 49.1922 +					(*p)[1]+0.5f);
 49.1923 +
 49.1924 +		max_uv = min_uv;
 49.1925 +
 49.1926 +		while(src < end)
 49.1927 +		{
 49.1928 +			tc->mV[0] = (*p)[0]+0.5f;
 49.1929 +			tc->mV[1] = (*p)[1]+0.5f;
 49.1930 +
 49.1931 +			llassert(src->isFinite3());
 49.1932 +			update_min_max(min,max,*src);
 49.1933 +			update_min_max(min_uv, max_uv, *tc);
 49.1934 +		
 49.1935 +			*pos = *src;
 49.1936 +		
 49.1937 +			llassert(pos->isFinite3());
 49.1938 +
 49.1939 +			++p;
 49.1940 +			++tc;
 49.1941 +			++src;
 49.1942 +			++pos;
 49.1943 +		}
 49.1944  		}
 49.1945  		else
 49.1946  		{
 49.1947 +
 49.1948 +		min_uv.set((*p)[0]+0.5f,
 49.1949 +				   0.5f - (*p)[1]);
 49.1950 +		max_uv = min_uv;
 49.1951 +
 49.1952 +		while(src < end)
 49.1953 +		{
 49.1954  			// Mirror for underside.
 49.1955 -			tc[i].mV[0] = profile[i].mV[0]+0.5f;
 49.1956 -			tc[i].mV[1] = 0.5f - profile[i].mV[1];
 49.1957 -		}
 49.1958 -
 49.1959 -		pos[i].load3(mesh[i + offset].mPos.mV);
 49.1960 +			tc->mV[0] = (*p)[0]+0.5f;
 49.1961 +			tc->mV[1] = 0.5f - (*p)[1];
 49.1962  		
 49.1963 -		if (i == 0)
 49.1964 -		{
 49.1965 -			max = pos[i];
 49.1966 -			min = max;
 49.1967 -			min_uv = max_uv = tc[i];
 49.1968 -		}
 49.1969 -		else
 49.1970 -		{
 49.1971 -			update_min_max(min,max,pos[i]);
 49.1972 -			update_min_max(min_uv, max_uv, tc[i]);
 49.1973 -		}
 49.1974 -	}
 49.1975 +			llassert(src->isFinite3());
 49.1976 +			update_min_max(min,max,*src);
 49.1977 +			update_min_max(min_uv, max_uv, *tc);
 49.1978 +
 49.1979 +			*pos = *src;
 49.1980 +		
 49.1981 +			llassert(pos->isFinite3());
 49.1982 +		
 49.1983 +			++p;
 49.1984 +			++tc;
 49.1985 +			++src;
 49.1986 +			++pos;
 49.1987 +		}
 49.1988 +	}
 49.1989 +
 49.1990 +	LL_CHECK_MEMORY
 49.1991  
 49.1992  	mCenter->setAdd(min, max);
 49.1993  	mCenter->mul(0.5f); 
 49.1994 @@ -6383,62 +5695,19 @@
 49.1995  	cuv = (min_uv + max_uv)*0.5f;
 49.1996  
 49.1997  
 49.1998 -	LLVector4a tangent;
 49.1999 -	calc_tangent_from_triangle(
 49.2000 -			*norm,
 49.2001 -			tangent,
 49.2002 -			*mCenter, cuv,
 49.2003 -			pos[0], tc[0],
 49.2004 -			pos[1], tc[1]);
 49.2005 -
 49.2006 -	if (tangent.getLength3() < 0.01)
 49.2007 -	{
 49.2008 -		tangent.set(1,0,0,1);
 49.2009 -	}
 49.2010 -	else
 49.2011 -	{
 49.2012 -		LLVector4a default_tangent;
 49.2013 -		default_tangent.set(1,0,0,1);
 49.2014 -		tangent.normalize3fast_checked(&default_tangent);
 49.2015 -	}
 49.2016 -
 49.2017 -	LLVector4a normal;
 49.2018 -	LLVector4a d0, d1;
 49.2019 -
 49.2020 -	d0.setSub(*mCenter, pos[0]);
 49.2021 -	d1.setSub(*mCenter, pos[1]);
 49.2022 -	
 49.2023 -	if (mTypeMask & TOP_MASK)
 49.2024 -	{
 49.2025 -		normal.setCross3(d0, d1);
 49.2026 -	}
 49.2027 -	else
 49.2028 -	{
 49.2029 -		normal.setCross3(d1, d0);
 49.2030 -	}
 49.2031 -
 49.2032 -	normal.normalize3fast_checked();
 49.2033 -
 49.2034  	VertexData vd;
 49.2035  	vd.setPosition(*mCenter);
 49.2036  	vd.mTexCoord = cuv;
 49.2037  	
 49.2038  	if (!(mTypeMask & HOLLOW_MASK) && !(mTypeMask & OPEN_MASK))
 49.2039  	{
 49.2040 -		pos[num_vertices] = *mCenter;
 49.2041 -		tc[num_vertices] = cuv;
 49.2042 -
 49.2043 +		*pos++ = *mCenter;
 49.2044 +		*tc++ = cuv;
 49.2045  		num_vertices++;
 49.2046  	}
 49.2047  		
 49.2048 -	allocateTangents(num_vertices);		
 49.2049 -
 49.2050 -	for (S32 i = 0; i < num_vertices; i++)
 49.2051 -	{
 49.2052 -		mTangents[i].load4a(tangent.getF32ptr());
 49.2053 -		norm[i].load4a(normal.getF32ptr());
 49.2054 -	}	
 49.2055 -
 49.2056 +	LL_CHECK_MEMORY
 49.2057 +		
 49.2058  	if (partial_build)
 49.2059  	{
 49.2060  		return TRUE;
 49.2061 @@ -6457,33 +5726,38 @@
 49.2062  			{
 49.2063  				// Use the profile points instead of the mesh, since you want
 49.2064  				// the un-transformed profile distances.
 49.2065 -				LLVector3 p1 = profile[pt1];
 49.2066 -				LLVector3 p2 = profile[pt2];
 49.2067 -				LLVector3 pa = profile[pt1+1];
 49.2068 -				LLVector3 pb = profile[pt2-1];
 49.2069 -
 49.2070 -				p1.mV[VZ] = 0.f;
 49.2071 -				p2.mV[VZ] = 0.f;
 49.2072 -				pa.mV[VZ] = 0.f;
 49.2073 -				pb.mV[VZ] = 0.f;
 49.2074 +				const LLVector4a& p1 = profile[pt1];
 49.2075 +				const LLVector4a& p2 = profile[pt2];
 49.2076 +				const LLVector4a& pa = profile[pt1+1];
 49.2077 +				const LLVector4a& pb = profile[pt2-1];
 49.2078 +
 49.2079 +				const F32* p1V = p1.getF32ptr();
 49.2080 +				const F32* p2V = p2.getF32ptr();
 49.2081 +				const F32* paV = pa.getF32ptr();
 49.2082 +				const F32* pbV = pb.getF32ptr();
 49.2083 +
 49.2084 +				//p1.mV[VZ] = 0.f;
 49.2085 +				//p2.mV[VZ] = 0.f;
 49.2086 +				//pa.mV[VZ] = 0.f;
 49.2087 +				//pb.mV[VZ] = 0.f;
 49.2088  
 49.2089  				// Use area of triangle to determine backfacing
 49.2090  				F32 area_1a2, area_1ba, area_21b, area_2ab;
 49.2091 -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
 49.2092 -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
 49.2093 -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
 49.2094 -
 49.2095 -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
 49.2096 -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
 49.2097 -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
 49.2098 -
 49.2099 -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
 49.2100 -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
 49.2101 -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
 49.2102 -
 49.2103 -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
 49.2104 -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
 49.2105 -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
 49.2106 +				area_1a2 =  (p1V[0]*paV[1] - paV[0]*p1V[1]) +
 49.2107 +							(paV[0]*p2V[1] - p2V[0]*paV[1]) +
 49.2108 +							(p2V[0]*p1V[1] - p1V[0]*p2V[1]);
 49.2109 +
 49.2110 +				area_1ba =  (p1V[0]*pbV[1] - pbV[0]*p1V[1]) +
 49.2111 +							(pbV[0]*paV[1] - paV[0]*pbV[1]) +
 49.2112 +							(paV[0]*p1V[1] - p1V[0]*paV[1]);
 49.2113 +
 49.2114 +				area_21b =  (p2V[0]*p1V[1] - p1V[0]*p2V[1]) +
 49.2115 +							(p1V[0]*pbV[1] - pbV[0]*p1V[1]) +
 49.2116 +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]);
 49.2117 +
 49.2118 +				area_2ab =  (p2V[0]*paV[1] - paV[0]*p2V[1]) +
 49.2119 +							(paV[0]*pbV[1] - pbV[0]*paV[1]) +
 49.2120 +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]);
 49.2121  
 49.2122  				BOOL use_tri1a2 = TRUE;
 49.2123  				BOOL tri_1a2 = TRUE;
 49.2124 @@ -6518,10 +5792,13 @@
 49.2125  				}
 49.2126  				else
 49.2127  				{
 49.2128 -					LLVector3 d1 = p1 - pa;
 49.2129 -					LLVector3 d2 = p2 - pb;
 49.2130 -
 49.2131 -					if (d1.magVecSquared() < d2.magVecSquared())
 49.2132 +					LLVector4a d1;
 49.2133 +					d1.setSub(p1, pa);
 49.2134 +					
 49.2135 +					LLVector4a d2; 
 49.2136 +					d2.setSub(p2, pb);
 49.2137 +
 49.2138 +					if (d1.dot3(d1) < d2.dot3(d2))
 49.2139  					{
 49.2140  						use_tri1a2 = TRUE;
 49.2141  					}
 49.2142 @@ -6560,33 +5837,33 @@
 49.2143  			{
 49.2144  				// Use the profile points instead of the mesh, since you want
 49.2145  				// the un-transformed profile distances.
 49.2146 -				LLVector3 p1 = profile[pt1];
 49.2147 -				LLVector3 p2 = profile[pt2];
 49.2148 -				LLVector3 pa = profile[pt1+1];
 49.2149 -				LLVector3 pb = profile[pt2-1];
 49.2150 -
 49.2151 -				p1.mV[VZ] = 0.f;
 49.2152 -				p2.mV[VZ] = 0.f;
 49.2153 -				pa.mV[VZ] = 0.f;
 49.2154 -				pb.mV[VZ] = 0.f;
 49.2155 +				const LLVector4a& p1 = profile[pt1];
 49.2156 +				const LLVector4a& p2 = profile[pt2];
 49.2157 +				const LLVector4a& pa = profile[pt1+1];
 49.2158 +				const LLVector4a& pb = profile[pt2-1];
 49.2159 +
 49.2160 +				const F32* p1V = p1.getF32ptr();
 49.2161 +				const F32* p2V = p2.getF32ptr();
 49.2162 +				const F32* paV = pa.getF32ptr();
 49.2163 +				const F32* pbV = pb.getF32ptr();
 49.2164  
 49.2165  				// Use area of triangle to determine backfacing
 49.2166  				F32 area_1a2, area_1ba, area_21b, area_2ab;
 49.2167 -				area_1a2 =  (p1.mV[0]*pa.mV[1] - pa.mV[0]*p1.mV[1]) +
 49.2168 -							(pa.mV[0]*p2.mV[1] - p2.mV[0]*pa.mV[1]) +
 49.2169 -							(p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]);
 49.2170 -
 49.2171 -				area_1ba =  (p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
 49.2172 -							(pb.mV[0]*pa.mV[1] - pa.mV[0]*pb.mV[1]) +
 49.2173 -							(pa.mV[0]*p1.mV[1] - p1.mV[0]*pa.mV[1]);
 49.2174 -
 49.2175 -				area_21b =  (p2.mV[0]*p1.mV[1] - p1.mV[0]*p2.mV[1]) +
 49.2176 -							(p1.mV[0]*pb.mV[1] - pb.mV[0]*p1.mV[1]) +
 49.2177 -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
 49.2178 -
 49.2179 -				area_2ab =  (p2.mV[0]*pa.mV[1] - pa.mV[0]*p2.mV[1]) +
 49.2180 -							(pa.mV[0]*pb.mV[1] - pb.mV[0]*pa.mV[1]) +
 49.2181 -							(pb.mV[0]*p2.mV[1] - p2.mV[0]*pb.mV[1]);
 49.2182 +				area_1a2 =  (p1V[0]*paV[1] - paV[0]*p1V[1]) +
 49.2183 +							(paV[0]*p2V[1] - p2V[0]*paV[1]) +
 49.2184 +							(p2V[0]*p1V[1] - p1V[0]*p2V[1]);
 49.2185 +
 49.2186 +				area_1ba =  (p1V[0]*pbV[1] - pbV[0]*p1V[1]) +
 49.2187 +							(pbV[0]*paV[1] - paV[0]*pbV[1]) +
 49.2188 +							(paV[0]*p1V[1] - p1V[0]*paV[1]);
 49.2189 +
 49.2190 +				area_21b =  (p2V[0]*p1V[1] - p1V[0]*p2V[1]) +
 49.2191 +							(p1V[0]*pbV[1] - pbV[0]*p1V[1]) +
 49.2192 +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]);
 49.2193 +
 49.2194 +				area_2ab =  (p2V[0]*paV[1] - paV[0]*p2V[1]) +
 49.2195 +							(paV[0]*pbV[1] - pbV[0]*paV[1]) +
 49.2196 +							(pbV[0]*p2V[1] - p2V[0]*pbV[1]);
 49.2197  
 49.2198  				BOOL use_tri1a2 = TRUE;
 49.2199  				BOOL tri_1a2 = TRUE;
 49.2200 @@ -6621,10 +5898,12 @@
 49.2201  				}
 49.2202  				else
 49.2203  				{
 49.2204 -					LLVector3 d1 = p1 - pa;
 49.2205 -					LLVector3 d2 = p2 - pb;
 49.2206 -
 49.2207 -					if (d1.magVecSquared() < d2.magVecSquared())
 49.2208 +					LLVector4a d1;
 49.2209 +					d1.setSub(p1,pa);
 49.2210 +					LLVector4a d2;
 49.2211 +					d2.setSub(p2,pb);
 49.2212 +
 49.2213 +					if (d1.dot3(d1) < d2.dot3(d2))
 49.2214  					{
 49.2215  						use_tri1a2 = TRUE;
 49.2216  					}
 49.2217 @@ -6674,6 +5953,38 @@
 49.2218  
 49.2219  	}
 49.2220  
 49.2221 +	LLVector4a d0,d1;
 49.2222 +	LL_CHECK_MEMORY
 49.2223 +		
 49.2224 +
 49.2225 +	d0.setSub(mPositions[mIndices[1]], mPositions[mIndices[0]]);
 49.2226 +	d1.setSub(mPositions[mIndices[2]], mPositions[mIndices[0]]);
 49.2227 +
 49.2228 +	LLVector4a normal;
 49.2229 +	normal.setCross3(d0,d1);
 49.2230 +
 49.2231 +	if (normal.dot3(normal).getF32() > F_APPROXIMATELY_ZERO)
 49.2232 +	{
 49.2233 +		normal.normalize3fast();
 49.2234 +	}
 49.2235 +	else
 49.2236 +	{ //degenerate, make up a value
 49.2237 +		normal.set(0,0,1);
 49.2238 +	}
 49.2239 +
 49.2240 +	llassert(llfinite(normal.getF32ptr()[0]));
 49.2241 +	llassert(llfinite(normal.getF32ptr()[1]));
 49.2242 +	llassert(llfinite(normal.getF32ptr()[2]));
 49.2243 +
 49.2244 +	llassert(!llisnan(normal.getF32ptr()[0]));
 49.2245 +	llassert(!llisnan(normal.getF32ptr()[1]));
 49.2246 +	llassert(!llisnan(normal.getF32ptr()[2]));
 49.2247 +	
 49.2248 +	for (S32 i = 0; i < num_vertices; i++)
 49.2249 +	{
 49.2250 +		norm[i].load4a(normal.getF32ptr());
 49.2251 +	}
 49.2252 +
 49.2253  	return TRUE;
 49.2254  }
 49.2255  
 49.2256 @@ -6702,37 +6013,33 @@
 49.2257  		CalculateTangentArray(mNumVertices, mPositions, mNormals, mTexCoords, mNumIndices/3, mIndices, mTangents);
 49.2258  
 49.2259  		//normalize tangents
 49.2260 -		LLVector4a default_norm;
 49.2261 -		default_norm.set(0,1,0,1);
 49.2262  		for (U32 i = 0; i < mNumVertices; i++) 
 49.2263  		{
 49.2264 -			//tangent[i].normalize3fast();
 49.2265 +			//binorm[i].normalize3fast();
 49.2266  			//bump map/planar projection code requires normals to be normalized
 49.2267 -			mNormals[i].normalize3fast_checked();
 49.2268 +			mNormals[i].normalize3fast();
 49.2269  		}
 49.2270  	}
 49.2271  }
 49.2272  
 49.2273  void LLVolumeFace::resizeVertices(S32 num_verts)
 49.2274  {
 49.2275 -	ll_aligned_free_16(mPositions);
 49.2276 -	ll_aligned_free_16(mNormals);
 49.2277 +	ll_aligned_free(mPositions);
 49.2278 +	//DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
 49.2279  	ll_aligned_free_16(mTangents);
 49.2280 -	ll_aligned_free_16(mTexCoords);
 49.2281  
 49.2282  	mTangents = NULL;
 49.2283  
 49.2284  	if (num_verts)
 49.2285  	{
 49.2286 -		mPositions = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
 49.2287 -		ll_assert_aligned(mPositions, 16);
 49.2288 -		mNormals = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
 49.2289 -		ll_assert_aligned(mNormals, 16);
 49.2290 -
 49.2291  		//pad texture coordinate block end to allow for QWORD reads
 49.2292  		S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
 49.2293 -		mTexCoords = (LLVector2*) ll_aligned_malloc_16(size);
 49.2294 -		ll_assert_aligned(mTexCoords, 16);
 49.2295 +
 49.2296 +		mPositions = (LLVector4a*) ll_aligned_malloc(sizeof(LLVector4a)*2*num_verts+size, 64);
 49.2297 +		mNormals = mPositions+num_verts;
 49.2298 +		mTexCoords = (LLVector2*) (mNormals+num_verts);
 49.2299 +
 49.2300 +		ll_assert_aligned(mPositions, 64);
 49.2301  	}
 49.2302  	else
 49.2303  	{
 49.2304 @@ -6742,6 +6049,7 @@
 49.2305  	}
 49.2306  
 49.2307  	mNumVertices = num_verts;
 49.2308 +	mNumAllocatedVertices = num_verts;
 49.2309  }
 49.2310  
 49.2311  void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv)
 49.2312 @@ -6752,27 +6060,42 @@
 49.2313  void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, const LLVector2& tc)
 49.2314  {
 49.2315  	S32 new_verts = mNumVertices+1;
 49.2316 -	S32 new_size = new_verts*16;
 49.2317 -	S32 old_size = mNumVertices*16;
 49.2318 +
 49.2319 +	if (new_verts > mNumAllocatedVertices)
 49.2320 +	{ 
 49.2321 +		//double buffer size on expansion
 49.2322 +		new_verts *= 2;
 49.2323 +
 49.2324 +		S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF;
 49.2325 +		S32 old_tc_size = ((mNumVertices*8)+0xF) & ~0xF;
 49.2326 +
 49.2327 +		S32 old_vsize = mNumVertices*16;
 49.2328 +		
 49.2329 +		S32 new_size = new_verts*16*2+new_tc_size;
 49.2330 +
 49.2331 +		LLVector4a* old_buf = mPositions;
 49.2332 +
 49.2333 +		mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64);
 49.2334 +		mNormals = mPositions+new_verts;
 49.2335 +		mTexCoords = (LLVector2*) (mNormals+new_verts);
 49.2336  
 49.2337  	//positions
 49.2338 -	mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_size, old_size);
 49.2339 -	ll_assert_aligned(mPositions,16);
 49.2340 +		LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize);
 49.2341  	
 49.2342  	//normals
 49.2343 -	mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_size, old_size);
 49.2344 -	ll_assert_aligned(mNormals,16);
 49.2345 +		LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize);
 49.2346  
 49.2347  	//tex coords
 49.2348 -	new_size = ((new_verts*8)+0xF) & ~0xF;
 49.2349 -	old_size = ((mNumVertices*8)+0xF) & ~0xF;
 49.2350 -	mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, new_size, old_size);
 49.2351 -	ll_assert_aligned(mTexCoords,16);
 49.2352 -	
 49.2353 +		LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tc_size);
 49.2354  
 49.2355  	//just clear tangents
 49.2356  	ll_aligned_free_16(mTangents);
 49.2357  	mTangents = NULL;
 49.2358 +		ll_aligned_free(old_buf);
 49.2359 +
 49.2360 +		mNumAllocatedVertices = new_verts;
 49.2361 +
 49.2362 +	}
 49.2363  
 49.2364  	mPositions[mNumVertices] = pos;
 49.2365  	mNormals[mNumVertices] = norm;
 49.2366 @@ -6861,13 +6184,23 @@
 49.2367  		llerrs << "Cannot append empty face." << llendl;
 49.2368  	}
 49.2369  
 49.2370 +	U32 old_vsize = mNumVertices*16;
 49.2371 +	U32 new_vsize = new_count * 16;
 49.2372 +	U32 old_tcsize = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF;
 49.2373 +	U32 new_tcsize = (new_count*sizeof(LLVector2)+0xF) & ~0xF;
 49.2374 +	U32 new_size = new_vsize * 2 + new_tcsize;
 49.2375 +
 49.2376  	//allocate new buffer space
 49.2377 -	mPositions = (LLVector4a*) ll_aligned_realloc_16(mPositions, new_count*sizeof(LLVector4a), mNumVertices*sizeof(LLVector4a));
 49.2378 -	ll_assert_aligned(mPositions, 16);
 49.2379 -	mNormals = (LLVector4a*) ll_aligned_realloc_16(mNormals, new_count*sizeof(LLVector4a), mNumVertices*sizeof(LLVector4a));
 49.2380 -	ll_assert_aligned(mNormals, 16);
 49.2381 -	mTexCoords = (LLVector2*) ll_aligned_realloc_16(mTexCoords, (new_count*sizeof(LLVector2)+0xF) & ~0xF, (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF);
 49.2382 -	ll_assert_aligned(mTexCoords, 16);
 49.2383 +	LLVector4a* old_buf = mPositions;
 49.2384 +	mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64);
 49.2385 +	mNormals = mPositions + new_count;
 49.2386 +	mTexCoords = (LLVector2*) (mNormals+new_count);
 49.2387 +
 49.2388 +	mNumAllocatedVertices = new_count;
 49.2389 +
 49.2390 +	LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize);
 49.2391 +	LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize);
 49.2392 +	LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tcsize);
 49.2393  	
 49.2394  	mNumVertices = new_count;
 49.2395  
 49.2396 @@ -6893,7 +6226,7 @@
 49.2397  
 49.2398  		//transform appended face normal and store
 49.2399  		norm_mat.rotate(src_norm[i], dst_norm[i]);
 49.2400 -		dst_norm[i].normalize3fast_checked();
 49.2401 +		dst_norm[i].normalize3fast();
 49.2402  
 49.2403  		//copy appended face texture coordinate
 49.2404  		dst_tc[i] = src_tc[i];
 49.2405 @@ -6927,6 +6260,7 @@
 49.2406  
 49.2407  BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
 49.2408  {
 49.2409 +	LL_CHECK_MEMORY
 49.2410  	BOOL flat = mTypeMask & FLAT_MASK;
 49.2411  
 49.2412  	U8 sculpt_type = volume->getParams().getSculptType();
 49.2413 @@ -6937,9 +6271,9 @@
 49.2414  	
 49.2415  	S32 num_vertices, num_indices;
 49.2416  
 49.2417 -	const std::vector<LLVolume::Point>& mesh = volume->getMesh();
 49.2418 -	const std::vector<LLVector3>& profile = volume->getProfile().mProfile;
 49.2419 -	const std::vector<LLPath::PathPt>& path_data = volume->getPath().mPath;
 49.2420 +	const LLAlignedArray<LLVector4a,64>& mesh = volume->getMesh();
 49.2421 +	const LLAlignedArray<LLVector4a,64>& profile = volume->getProfile().mProfile;
 49.2422 +	const LLAlignedArray<LLPath::PathPt,64>& path_data = volume->getPath().mPath;
 49.2423  
 49.2424  	S32 max_s = volume->getProfile().getTotal();
 49.2425  
 49.2426 @@ -6960,15 +6294,19 @@
 49.2427  		}
 49.2428  	}
 49.2429  
 49.2430 +	LL_CHECK_MEMORY
 49.2431 +
 49.2432  	LLVector4a* pos = (LLVector4a*) mPositions;
 49.2433 -	LLVector4a* norm = (LLVector4a*) mNormals;
 49.2434  	LLVector2* tc = (LLVector2*) mTexCoords;
 49.2435 -	S32 begin_stex = llfloor( profile[mBeginS].mV[2] );
 49.2436 +	F32 begin_stex = floorf(profile[mBeginS][2]);
 49.2437  	S32 num_s = ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2) ? mNumS/2 : mNumS;
 49.2438  
 49.2439  	S32 cur_vertex = 0;
 49.2440 +	S32 end_t = mBeginT+mNumT;
 49.2441 +	bool test = (mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2;
 49.2442 +
 49.2443  	// Copy the vertices into the array
 49.2444 -	for (t = mBeginT; t < mBeginT + mNumT; t++)
 49.2445 +	for (t = mBeginT; t < end_t; t++)
 49.2446  	{
 49.2447  		tt = path_data[t].mTexT;
 49.2448  		for (s = 0; s < num_s; s++)
 49.2449 @@ -6989,11 +6327,11 @@
 49.2450  				// Get s value for tex-coord.
 49.2451  				if (!flat)
 49.2452  				{
 49.2453 -					ss = profile[mBeginS + s].mV[2];
 49.2454 +					ss = profile[mBeginS + s][2];
 49.2455  				}
 49.2456  				else
 49.2457  				{
 49.2458 -					ss = profile[mBeginS + s].mV[2] - begin_stex;
 49.2459 +					ss = profile[mBeginS + s][2] - begin_stex;
 49.2460  				}
 49.2461  			}
 49.2462  
 49.2463 @@ -7013,19 +6351,15 @@
 49.2464  				i = mBeginS + s + max_s*t;
 49.2465  			}
 49.2466  
 49.2467 -			pos[cur_vertex].load3(mesh[i].mPos.mV);
 49.2468 -			tc[cur_vertex] = LLVector2(ss,tt);
 49.2469 +			mesh[i].store4a((F32*)(pos+cur_vertex));
 49.2470 +			tc[cur_vertex].set(ss,tt);
 49.2471  		
 49.2472 -			norm[cur_vertex].clear();
 49.2473  			cur_vertex++;
 49.2474  
 49.2475 -			if ((mTypeMask & INNER_MASK) && (mTypeMask & FLAT_MASK) && mNumS > 2 && s > 0)
 49.2476 +			if (test && s > 0)
 49.2477  			{
 49.2478 -				pos[cur_vertex].load3(mesh[i].mPos.mV);
 49.2479 -				tc[cur_vertex] = LLVector2(ss,tt);
 49.2480 -			
 49.2481 -				norm[cur_vertex].clear();
 49.2482 -				
 49.2483 +				mesh[i].store4a((F32*)(pos+cur_vertex));
 49.2484 +				tc[cur_vertex].set(ss,tt);
 49.2485  				cur_vertex++;
 49.2486  			}
 49.2487  		}
 49.2488 @@ -7042,26 +6376,62 @@
 49.2489  			}
 49.2490  
 49.2491  			i = mBeginS + s + max_s*t;
 49.2492 -			ss = profile[mBeginS + s].mV[2] - begin_stex;
 49.2493 -			pos[cur_vertex].load3(mesh[i].mPos.mV);
 49.2494 -			tc[cur_vertex] = LLVector2(ss,tt);
 49.2495 -			norm[cur_vertex].clear(); 
 49.2496 +			ss = profile[mBeginS + s][2] - begin_stex;
 49.2497 +
 49.2498 +			mesh[i].store4a((F32*)(pos+cur_vertex));
 49.2499 +			tc[cur_vertex].set(ss,tt);
 49.2500  			
 49.2501  			cur_vertex++;
 49.2502  		}
 49.2503 -	}
 49.2504 +	}	
 49.2505 +	LL_CHECK_MEMORY
 49.2506  	
 49.2507 +	mCenter->clear();
 49.2508 +
 49.2509 +	LLVector4a* cur_pos = pos;
 49.2510 +	LLVector4a* end_pos = pos + mNumVertices;
 49.2511 +
 49.2512  	//get bounding box for this side
 49.2513 -	LLVector4a& face_min = mExtents[0];
 49.2514 -	LLVector4a& face_max = mExtents[1];
 49.2515 -	mCenter->clear();
 49.2516 -
 49.2517 -	face_min = face_max = pos[0];
 49.2518 -
 49.2519 -	for (U32 i = 1; i < mNumVertices; ++i)
 49.2520 -	{
 49.2521 -		update_min_max(face_min, face_max, pos[i]);
 49.2522 -	}
 49.2523 +	LLVector4a face_min;
 49.2524 +	LLVector4a face_max;
 49.2525 +	
 49.2526 +	face_min = face_max = *cur_pos++;
 49.2527 +		
 49.2528 +	while (cur_pos < end_pos)
 49.2529 +	{
 49.2530 +		update_min_max(face_min, face_max, *cur_pos++);
 49.2531 +	}
 49.2532 +
 49.2533 +	mExtents[0] = face_min;
 49.2534 +	mExtents[1] = face_max;
 49.2535 +
 49.2536 +	U32 tc_count = mNumVertices;
 49.2537 +	if (tc_count%2 == 1)
 49.2538 +	{ //odd number of texture coordinates, duplicate last entry to padded end of array
 49.2539 +		tc_count++;
 49.2540 +		mTexCoords[mNumVertices] = mTexCoords[mNumVertices-1];
 49.2541 +	}
 49.2542 +
 49.2543 +	LLVector4a* cur_tc = (LLVector4a*) mTexCoords;
 49.2544 +	LLVector4a* end_tc = (LLVector4a*) (mTexCoords+tc_count);
 49.2545 +
 49.2546 +	LLVector4a tc_min; 
 49.2547 +	LLVector4a tc_max; 
 49.2548 +
 49.2549 +	tc_min = tc_max = *cur_tc++;
 49.2550 +
 49.2551 +	while (cur_tc < end_tc)
 49.2552 +	{
 49.2553 +		update_min_max(tc_min, tc_max, *cur_tc++);
 49.2554 +	}
 49.2555 +
 49.2556 +	F32* minp = tc_min.getF32ptr();
 49.2557 +	F32* maxp = tc_max.getF32ptr();
 49.2558 +
 49.2559 +	mTexCoordExtents[0].mV[0] = llmin(minp[0], minp[2]);
 49.2560 +	mTexCoordExtents[0].mV[1] = llmin(minp[1], minp[3]);
 49.2561 +	mTexCoordExtents[1].mV[0] = llmax(maxp[0], maxp[2]);
 49.2562 +	mTexCoordExtents[1].mV[1] = llmax(maxp[1], maxp[3]);
 49.2563  
 49.2564  	mCenter->setAdd(face_min, face_max);
 49.2565  	mCenter->mul(0.5f);
 49.2566 @@ -7127,47 +6497,119 @@
 49.2567  		}
 49.2568  	}
 49.2569  
 49.2570 +	LL_CHECK_MEMORY
 49.2571 +
 49.2572  	//clear normals
 49.2573 -	for (U32 i = 0; i < mNumVertices; i++)
 49.2574 -	{
 49.2575 -		mNormals[i].clear();
 49.2576 -	}
 49.2577 +	F32* dst = (F32*) mNormals;
 49.2578 +	F32* end = (F32*) (mNormals+mNumVertices);
 49.2579 +	LLVector4a zero = LLVector4a::getZero();
 49.2580 +
 49.2581 +	while (dst < end)
 49.2582 +	{
 49.2583 +		zero.store4a(dst);
 49.2584 +		dst += 4;
 49.2585 +	}
 49.2586 +
 49.2587 +	LL_CHECK_MEMORY
 49.2588  
 49.2589  	//generate normals 
 49.2590 -	for (U32 i = 0; i < mNumIndices/3; i++) //for each triangle
 49.2591 -	{
 49.2592 -		const U16* idx = &(mIndices[i*3]);
 49.2593 -		
 49.2594 -
 49.2595 -		LLVector4a* v[] = 
 49.2596 -		{	pos+idx[0], pos+idx[1], pos+idx[2] };
 49.2597 -		
 49.2598 -		LLVector4a* n[] = 
 49.2599 -		{	norm+idx[0], norm+idx[1], norm+idx[2] };
 49.2600 +	U32 count = mNumIndices/3;
 49.2601 +
 49.2602 +	LLVector4a* norm = mNormals;
 49.2603 +
 49.2604 +	static LLAlignedArray<LLVector4a, 64> triangle_normals;
 49.2605 +	triangle_normals.resize(count);
 49.2606 +	LLVector4a* output = triangle_normals.mArray;
 49.2607 +	LLVector4a* end_output = output+count;
 49.2608 +
 49.2609 +	U16* idx = mIndices;
 49.2610 +
 49.2611 +	while (output < end_output)
 49.2612 +	{
 49.2613 +		LLVector4a b,v1,v2;
 49.2614 +		b.load4a((F32*) (pos+idx[0]));
 49.2615 +		v1.load4a((F32*) (pos+idx[1]));
 49.2616 +		v2.load4a((F32*) (pos+idx[2]));
 49.2617  		
 49.2618  		//calculate triangle normal
 49.2619 -		LLVector4a a, b, c;
 49.2620 +		LLVector4a a;
 49.2621  		
 49.2622 -		a.setSub(*v[0], *v[1]);
 49.2623 -		b.setSub(*v[0], *v[2]);
 49.2624 -		c.setCross3(a,b);
 49.2625 -
 49.2626 -		n[0]->add(c);
 49.2627 -		n[1]->add(c);
 49.2628 -		n[2]->add(c);
 49.2629 +		a.setSub(b, v1);
 49.2630 +		b.sub(v2);
 49.2631 +
 49.2632 +
 49.2633 +		LLQuad& vector1 = *((LLQuad*) &v1);
 49.2634 +		LLQuad& vector2 = *((LLQuad*) &v2);
 49.2635  		
 49.2636 -		llassert(llfinite(c.getF32ptr()[0]));
 49.2637 -		llassert(llfinite(c.getF32ptr()[1]));
 49.2638 -		llassert(llfinite(c.getF32ptr()[2]));
 49.2639 -
 49.2640 -		llassert(!llisnan(c.getF32ptr()[0]));
 49.2641 -		llassert(!llisnan(c.getF32ptr()[1]));
 49.2642 -		llassert(!llisnan(c.getF32ptr()[2]));
 49.2643 +		LLQuad& amQ = *((LLQuad*) &a);
 49.2644 +		LLQuad& bmQ = *((LLQuad*) &b);
 49.2645 +
 49.2646 +		//v1.setCross3(t,v0);
 49.2647 +		//setCross3(const LLVector4a& a, const LLVector4a& b)
 49.2648 +		// Vectors are stored in memory in w, z, y, x order from high to low
 49.2649 +		// Set vector1 = { a[W], a[X], a[Z], a[Y] }
 49.2650 +		vector1 = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 0, 2, 1 ));
 49.2651 +		// Set vector2 = { b[W], b[Y], b[X], b[Z] }
 49.2652 +		vector2 = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 1, 0, 2 ));
 49.2653 +		// mQ = { a[W]*b[W], a[X]*b[Y], a[Z]*b[X], a[Y]*b[Z] }
 49.2654 +		vector2 = _mm_mul_ps( vector1, vector2 );
 49.2655 +		// vector3 = { a[W], a[Y], a[X], a[Z] }
 49.2656 +		amQ = _mm_shuffle_ps( amQ, amQ, _MM_SHUFFLE( 3, 1, 0, 2 ));
 49.2657 +		// vector4 = { b[W], b[X], b[Z], b[Y] }
 49.2658 +		bmQ = _mm_shuffle_ps( bmQ, bmQ, _MM_SHUFFLE( 3, 0, 2, 1 ));
 49.2659 +		// 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] }
 49.2660 +		vector1 = _mm_sub_ps( vector2, _mm_mul_ps( amQ, bmQ ));
 49.2661 +
 49.2662 +		llassert(v1.isFinite3());
 49.2663 +
 49.2664 +		v1.store4a((F32*) output);
 49.2665 +		
 49.2666 +		
 49.2667 +		output++;
 49.2668 +		idx += 3;
 49.2669 +	}
 49.2670 +
 49.2671 +	idx = mIndices;
 49.2672 +
 49.2673 +	LLVector4a* src = triangle_normals.mArray;
 49.2674 +	
 49.2675 +	for (U32 i = 0; i < count; i++) //for each triangle
 49.2676 +	{
 49.2677 +		LLVector4a c;
 49.2678 +		c.load4a((F32*) (src++));
 49.2679 +
 49.2680 +		LLVector4a* n0p = norm+idx[0];
 49.2681 +		LLVector4a* n1p = norm+idx[1];
 49.2682 +		LLVector4a* n2p = norm+idx[2];
 49.2683 +		
 49.2684 +		idx += 3;
 49.2685 +
 49.2686 +		LLVector4a n0,n1,n2;
 49.2687 +		n0.load4a((F32*) n0p);
 49.2688 +		n1.load4a((F32*) n1p);
 49.2689 +		n2.load4a((F32*) n2p);
 49.2690 +		
 49.2691 +		n0.add(c);
 49.2692 +		n1.add(c);
 49.2693 +		n2.add(c);
 49.2694 +
 49.2695 +		llassert(c.isFinite3());
 49.2696  
 49.2697  		//even out quad contributions
 49.2698 -		n[i%2+1]->add(c);
 49.2699 +		switch (i%2+1)
 49.2700 +		{
 49.2701 +			case 0: n0.add(c); break;
 49.2702 +			case 1: n1.add(c); break;
 49.2703 +			case 2: n2.add(c); break;
 49.2704 +		};
 49.2705 +
 49.2706 +		n0.store4a((F32*) n0p);
 49.2707 +		n1.store4a((F32*) n1p);
 49.2708 +		n2.store4a((F32*) n2p);
 49.2709  	}
 49.2710  	
 49.2711 +	LL_CHECK_MEMORY
 49.2712 +
 49.2713  	// adjust normals based on wrapping and stitching
 49.2714  	
 49.2715  	LLVector4a top;
 49.2716 @@ -7299,64 +6741,16 @@
 49.2717  
 49.2718  	}
 49.2719  
 49.2720 +	LL_CHECK_MEMORY
 49.2721 +
 49.2722  	return TRUE;
 49.2723  }
 49.2724  
 49.2725 -// Finds binormal based on three vertices with texture coordinates.
 49.2726 -// Fills in dummy values if the triangle has degenerate texture coordinates.
 49.2727 -void calc_binormal_from_triangle(LLVector4a& binormal,
 49.2728 -
 49.2729 -	const LLVector4a& pos0,
 49.2730 -	const LLVector2& tex0,
 49.2731 -	const LLVector4a& pos1,
 49.2732 -	const LLVector2& tex1,
 49.2733 -	const LLVector4a& pos2,
 49.2734 -	const LLVector2& tex2)
 49.2735 -{
 49.2736 -	LLVector4a rx0( pos0[VX], tex0.mV[VX], tex0.mV[VY] );
 49.2737 -	LLVector4a rx1( pos1[VX], tex1.mV[VX], tex1.mV[VY] );
 49.2738 -	LLVector4a rx2( pos2[VX], tex2.mV[VX], tex2.mV[VY] );
 49.2739 -	
 49.2740 -	LLVector4a ry0( pos0[VY], tex0.mV[VX], tex0.mV[VY] );
 49.2741 -	LLVector4a ry1( pos1[VY], tex1.mV[VX], tex1.mV[VY] );
 49.2742 -	LLVector4a ry2( pos2[VY], tex2.mV[VX], tex2.mV[VY] );
 49.2743 -
 49.2744 -	LLVector4a rz0( pos0[VZ], tex0.mV[VX], tex0.mV[VY] );
 49.2745 -	LLVector4a rz1( pos1[VZ], tex1.mV[VX], tex1.mV[VY] );
 49.2746 -	LLVector4a rz2( pos2[VZ], tex2.mV[VX], tex2.mV[VY] );
 49.2747 -	
 49.2748 -	LLVector4a lhs, rhs;
 49.2749 -
 49.2750 -	LLVector4a r0; 
 49.2751 -	lhs.setSub(rx0, rx1); rhs.setSub(rx0, rx2);
 49.2752 -	r0.setCross3(lhs, rhs);
 49.2753 -		
 49.2754 -	LLVector4a r1;
 49.2755 -	lhs.setSub(ry0, ry1); rhs.setSub(ry0, ry2);
 49.2756 -	r1.setCross3(lhs, rhs);
 49.2757 -
 49.2758 -	LLVector4a r2;
 49.2759 -	lhs.setSub(rz0, rz1); rhs.setSub(rz0, rz2);
 49.2760 -	r2.setCross3(lhs, rhs);
 49.2761 -
 49.2762 -	if( r0[VX] && r1[VX] && r2[VX] )
 49.2763 -	{
 49.2764 -		binormal.set(
 49.2765 -				-r0[VZ] / r0[VX],
 49.2766 -				-r1[VZ] / r1[VX],
 49.2767 -				-r2[VZ] / r2[VX]);
 49.2768 -		// binormal.normVec();
 49.2769 -	}
 49.2770 -	else
 49.2771 -	{
 49.2772 -		binormal.set( 0, 1 , 0 );
 49.2773 -	}
 49.2774 -}
 49.2775 -
 49.2776  //adapted from Lengyel, Eric. “Computing Tangent Space Basis Vectors for an Arbitrary Mesh”. Terathon Software 3D Graphics Library, 2001. http://www.terathon.com/code/tangent.html
 49.2777  void CalculateTangentArray(U32 vertexCount, const LLVector4a *vertex, const LLVector4a *normal,
 49.2778          const LLVector2 *texcoord, U32 triangleCount, const U16* index_array, LLVector4a *tangent)
 49.2779  {
 49.2780 +    //LLVector4a *tan1 = new LLVector4a[vertexCount * 2];
 49.2781  	LLVector4a* tan1 = (LLVector4a*) ll_aligned_malloc_16(vertexCount*2*sizeof(LLVector4a));
 49.2782  
 49.2783      LLVector4a* tan2 = tan1 + vertexCount;
    50.1 --- a/indra/llmath/llvolume.h	Fri Sep 27 17:22:31 2013 -0400
    50.2 +++ b/indra/llmath/llvolume.h	Fri Oct 04 15:36:52 2013 -0400
    50.3 @@ -37,7 +37,6 @@
    50.4  
    50.5  template <class T> class LLOctreeNode;
    50.6  
    50.7 -class LLVector4a;
    50.8  class LLVolumeFace;
    50.9  class LLVolume;
   50.10  class LLVolumeTriangle;
   50.11 @@ -50,12 +49,15 @@
   50.12  #include "v3math.h"
   50.13  #include "v3dmath.h"
   50.14  #include "v4math.h"
   50.15 +#include "llvector4a.h"
   50.16 +#include "llmatrix4a.h"
   50.17  #include "llquaternion.h"
   50.18  #include "llstrider.h"
   50.19  #include "v4coloru.h"
   50.20  #include "llrefcount.h"
   50.21  #include "llpointer.h"
   50.22  #include "llfile.h"
   50.23 +#include "llalignedarray.h"
   50.24  
   50.25  //============================================================================
   50.26  
   50.27 @@ -708,16 +710,16 @@
   50.28  		LLFaceID  mFaceID;
   50.29  	};
   50.30  	
   50.31 -	std::vector<LLVector3> mProfile;	
   50.32 -	std::vector<LLVector2> mNormals;
   50.33 +	LLAlignedArray<LLVector4a, 64> mProfile;	
   50.34 +	//LLAlignedArray<LLVector4a, 64> mNormals;
   50.35  	std::vector<Face>      mFaces;
   50.36 -	std::vector<LLVector3> mEdgeNormals;
   50.37 -	std::vector<LLVector3> mEdgeCenters;
   50.38 +
   50.39 +	//LLAlignedArray<LLVector4a, 64> mEdgeNormals;
   50.40 +	//LLAlignedArray<LLVector4a, 64> mEdgeCenters;
   50.41  
   50.42  	friend std::ostream& operator<<(std::ostream &s, const LLProfile &profile);
   50.43  
   50.44  protected:
   50.45 -	void genNormals(const LLProfileParams& params);
   50.46  	static S32 getNumNGonPoints(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
   50.47  	void genNGon(const LLProfileParams& params, S32 sides, F32 offset=0.0f, F32 bevel = 0.0f, F32 ang_scale = 1.f, S32 split = 0);
   50.48  
   50.49 @@ -741,13 +743,29 @@
   50.50  class LLPath
   50.51  {
   50.52  public:
   50.53 -	struct PathPt
   50.54 +	class PathPt
   50.55  	{
   50.56 -		LLVector3	 mPos;
   50.57 -		LLVector2    mScale;
   50.58 -		LLQuaternion mRot;
   50.59 +	public:
   50.60 +		LLMatrix4a   mRot;
   50.61 +		LLVector4a	 mPos;
   50.62 +		
   50.63 +		LLVector4a   mScale;
   50.64  		F32			 mTexT;
   50.65 -		PathPt() { mPos.setVec(0,0,0); mTexT = 0; mScale.setVec(0,0); mRot.loadIdentity(); }
   50.66 +		F32 pad[3]; //for alignment
   50.67 +		PathPt() 
   50.68 +		{ 
   50.69 +			mPos.clear(); 
   50.70 +			mTexT = 0; 
   50.71 +			mScale.clear(); 
   50.72 +			mRot.setRows(LLVector4a(1,0,0,0),
   50.73 +						LLVector4a(0,1,0,0),
   50.74 +						LLVector4a(0,0,1,0));
   50.75 +
   50.76 +			//distinguished data in the pad for debugging
   50.77 +			pad[0] = 3.14159f;
   50.78 +			pad[1] = -3.14159f;
   50.79 +			pad[2] = 0.585f;
   50.80 +		}
   50.81  	};
   50.82  
   50.83  public:
   50.84 @@ -779,7 +797,7 @@
   50.85  	friend std::ostream& operator<<(std::ostream &s, const LLPath &path);
   50.86  
   50.87  public:
   50.88 -	std::vector<PathPt> mPath;
   50.89 +	LLAlignedArray<PathPt, 64> mPath;
   50.90  
   50.91  protected:
   50.92  	BOOL		  mOpen;
   50.93 @@ -912,6 +930,7 @@
   50.94  	LLVector2   mTexCoordExtents[2]; //minimum and maximum of texture coordinates of the face.
   50.95  
   50.96  	S32 mNumVertices;
   50.97 +	S32 mNumAllocatedVertices;
   50.98  	S32 mNumIndices;
   50.99  
  50.100  	LLVector4a* mPositions;
  50.101 @@ -933,6 +952,9 @@
  50.102  
  50.103  	LLOctreeNode<LLVolumeTriangle>* mOctree;
  50.104  
  50.105 +	//whether or not face has been cache optimized
  50.106 +	BOOL mOptimized;
  50.107 +
  50.108  private:
  50.109  	BOOL createUnCutCubeCap(LLVolume* volume, BOOL partial_build = FALSE);
  50.110  	BOOL createCap(LLVolume* volume, BOOL partial_build = FALSE);
  50.111 @@ -947,11 +969,7 @@
  50.112  	~LLVolume(); // use unref
  50.113  
  50.114  public:
  50.115 -	struct Point
  50.116 -	{
  50.117 -		LLVector3 mPos;
  50.118 -	};
  50.119 -
  50.120 +		
  50.121  	struct FaceParams
  50.122  	{
  50.123  		LLFaceID mFaceID;
  50.124 @@ -974,8 +992,8 @@
  50.125  	const LLProfile& getProfile() const						{ return *mProfilep; }
  50.126  	LLPath& getPath() const									{ return *mPathp; }
  50.127  	void resizePath(S32 length);
  50.128 -	const std::vector<Point>& getMesh() const				{ return mMesh; }
  50.129 -	const LLVector3& getMeshPt(const U32 i) const			{ return mMesh[i].mPos; }
  50.130 +	const LLAlignedArray<LLVector4a,64>&	getMesh() const				{ return mMesh; }
  50.131 +	const LLVector4a& getMeshPt(const U32 i) const			{ return mMesh[i]; }
  50.132  
  50.133  	void setDirty() { mPathp->setDirty(); mProfilep->setDirty(); }
  50.134  
  50.135 @@ -990,10 +1008,7 @@
  50.136  	S32 getSculptLevel() const                              { return mSculptLevel; }
  50.137  	void setSculptLevel(S32 level)							{ mSculptLevel = level; }
  50.138  
  50.139 -	S32 *getTriangleIndices(U32 &num_indices) const;
  50.140 -
  50.141 -	// returns number of triangle indeces required for path/profile mesh
  50.142 -	S32 getNumTriangleIndices() const;
  50.143 +	
  50.144  	static void getLoDTriangleCounts(const LLVolumeParams& params, S32* counts);
  50.145  
  50.146  	S32 getNumTriangles(S32* vcount = NULL) const;
  50.147 @@ -1059,7 +1074,8 @@
  50.148  	LLVolumeParams mParams;
  50.149  	LLPath *mPathp;
  50.150  	LLProfile *mProfilep;
  50.151 -	std::vector<Point> mMesh;
  50.152 +	LLAlignedArray<LLVector4a,64> mMesh;
  50.153 +	
  50.154  	
  50.155  	BOOL mGenerateSingleFace;
  50.156  	typedef std::vector<LLVolumeFace> face_list_t;
    51.1 --- a/indra/llmessage/llcurl.cpp	Fri Sep 27 17:22:31 2013 -0400
    51.2 +++ b/indra/llmessage/llcurl.cpp	Fri Oct 04 15:36:52 2013 -0400
    51.3 @@ -92,6 +92,7 @@
    51.4  bool     LLCurl::sNotQuitting = true;
    51.5  F32      LLCurl::sCurlRequestTimeOut = 120.f; //seonds
    51.6  S32      LLCurl::sMaxHandles = 256; //max number of handles, (multi handles and easy handles combined).
    51.7 +CURL*	 LLCurl::sCurlTemplateStandardHandle = NULL;
    51.8  
    51.9  void check_curl_code(CURLcode code)
   51.10  {
   51.11 @@ -1818,10 +1819,10 @@
   51.12  	}
   51.13  	sTotalHandles++;
   51.14  
   51.15 -	CURL* ret = curl_easy_init() ;
   51.16 +	CURL* ret = createStandardCurlHandle();
   51.17  	if(!ret)
   51.18  	{
   51.19 -		llwarns << "curl_easy_init failed." << llendl ;
   51.20 +		llwarns << "failed to create curl handle." << llendl ;
   51.21  	}
   51.22  
   51.23  	return ret ;
   51.24 @@ -1851,3 +1852,47 @@
   51.25  {
   51.26  	check_curl_multi_code(code);
   51.27  }
   51.28 +
   51.29 +
   51.30 +// Static
   51.31 +CURL* LLCurl::createStandardCurlHandle()
   51.32 +{
   51.33 +	if (sCurlTemplateStandardHandle == NULL)
   51.34 +	{	// Late creation of the template curl handle
   51.35 +		sCurlTemplateStandardHandle = curl_easy_init();
   51.36 +		if (sCurlTemplateStandardHandle == NULL)
   51.37 +		{
   51.38 +			llwarns << "curl error calling curl_easy_init()" << llendl;
   51.39 +		}
   51.40 +		else
   51.41 +		{
   51.42 +			CURLcode result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
   51.43 +			check_curl_code(result);
   51.44 +			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_NOSIGNAL, 1);
   51.45 +			check_curl_code(result);
   51.46 +			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_NOPROGRESS, 1);
   51.47 +			check_curl_code(result);
   51.48 +			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_ENCODING, "");	
   51.49 +			check_curl_code(result);
   51.50 +			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_AUTOREFERER, 1);
   51.51 +			check_curl_code(result);
   51.52 +			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_FOLLOWLOCATION, 1);	
   51.53 +			check_curl_code(result);
   51.54 +			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_SSL_VERIFYPEER, 1);
   51.55 +			check_curl_code(result);
   51.56 +			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_SSL_VERIFYHOST, 0);
   51.57 +			check_curl_code(result);
   51.58 +
   51.59 +			// The Linksys WRT54G V5 router has an issue with frequent
   51.60 +			// DNS lookups from LAN machines.  If they happen too often,
   51.61 +			// like for every HTTP request, the router gets annoyed after
   51.62 +			// about 700 or so requests and starts issuing TCP RSTs to
   51.63 +			// new connections.  Reuse the DNS lookups for even a few
   51.64 +			// seconds and no RSTs.
   51.65 +			result = curl_easy_setopt(sCurlTemplateStandardHandle, CURLOPT_DNS_CACHE_TIMEOUT, 15);
   51.66 +			check_curl_code(result);
   51.67 +		}
   51.68 +	}
   51.69 +
   51.70 +	return curl_easy_duphandle(sCurlTemplateStandardHandle);
   51.71 +}
    52.1 --- a/indra/llmessage/llcurl.h	Fri Sep 27 17:22:31 2013 -0400
    52.2 +++ b/indra/llmessage/llcurl.h	Fri Oct 04 15:36:52 2013 -0400
    52.3 @@ -45,7 +45,7 @@
    52.4  #include "llqueuedthread.h"
    52.5  #include "llframetimer.h"
    52.6  #include "llpointer.h"
    52.7 -
    52.8 +#include "llsingleton.h"
    52.9  
   52.10  class LLMutex;
   52.11  class LLCurlThread;
   52.12 @@ -188,6 +188,8 @@
   52.13  	static CURL*  newEasyHandle() ;
   52.14  	static void   deleteEasyHandle(CURL* handle) ;
   52.15  
   52.16 +	static CURL*	createStandardCurlHandle();
   52.17 +
   52.18  private:
   52.19  	static std::string sCAPath;
   52.20  	static std::string sCAFile;
   52.21 @@ -197,6 +199,7 @@
   52.22  	static LLMutex* sHandleMutexp ;
   52.23  	static S32      sTotalHandles ;
   52.24  	static S32      sMaxHandles;
   52.25 +	static CURL*	sCurlTemplateStandardHandle;
   52.26  public:
   52.27  	static bool     sNotQuitting;
   52.28  	static F32      sCurlRequestTimeOut;	
    53.1 --- a/indra/llmessage/llpartdata.cpp	Fri Sep 27 17:22:31 2013 -0400
    53.2 +++ b/indra/llmessage/llpartdata.cpp	Fri Oct 04 15:36:52 2013 -0400
    53.3 @@ -37,53 +37,46 @@
    53.4  
    53.5  
    53.6  
    53.7 -const S32 PS_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; // 18
    53.8 -const S32 PS_DATA_BLOCK_SIZE = 68 + PS_PART_DATA_BLOCK_SIZE; // 68 + 18 = 86
    53.9 +const S32 PS_PART_DATA_GLOW_SIZE = 2;
   53.10 +const S32 PS_PART_DATA_BLEND_SIZE = 2;
   53.11 +const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18
   53.12 +const S32 PS_SYS_DATA_BLOCK_SIZE = 68;
   53.13 +const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+
   53.14 +									PS_LEGACY_PART_DATA_BLOCK_SIZE +
   53.15 +									PS_PART_DATA_BLEND_SIZE +
   53.16 +									PS_PART_DATA_GLOW_SIZE+
   53.17 +									8; //two S32 size fields
   53.18 +
   53.19 +const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE;
   53.20 +
   53.21 +
   53.22 +const U32 PART_DATA_MASK = LLPartData::LL_PART_DATA_GLOW | LLPartData::LL_PART_DATA_BLEND;
   53.23 +
   53.24  
   53.25  
   53.26  const F32 MAX_PART_SCALE = 4.f;
   53.27  
   53.28 -BOOL LLPartData::pack(LLDataPacker &dp)
   53.29 +bool LLPartData::hasGlow() const
   53.30  {
   53.31 -	LLColor4U coloru;
   53.32 -	dp.packU32(mFlags, "pdflags");
   53.33 -	dp.packFixed(mMaxAge, "pdmaxage", FALSE, 8, 8);
   53.34 -	coloru.setVec(mStartColor);
   53.35 -	dp.packColor4U(coloru, "pdstartcolor");
   53.36 -	coloru.setVec(mEndColor);
   53.37 -	dp.packColor4U(coloru, "pdendcolor");
   53.38 -	dp.packFixed(mStartScale.mV[0], "pdstartscalex", FALSE, 3, 5);
   53.39 -	dp.packFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5);
   53.40 -	dp.packFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5);
   53.41 -	dp.packFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5);
   53.42 -	return TRUE;
   53.43 +	return mStartGlow > 0.f || mEndGlow > 0.f;
   53.44  }
   53.45  
   53.46 -LLSD LLPartData::asLLSD() const
   53.47 +bool LLPartData::hasBlendFunc() const
   53.48  {
   53.49 -	LLSD sd = LLSD();
   53.50 -	sd["pdflags"] = ll_sd_from_U32(mFlags);
   53.51 -	sd["pdmaxage"] = mMaxAge;
   53.52 -	sd["pdstartcolor"] = ll_sd_from_color4(mStartColor);
   53.53 -	sd["pdendcolor"] = ll_sd_from_color4(mEndColor);
   53.54 -	sd["pdstartscale"] = ll_sd_from_vector2(mStartScale);
   53.55 -	sd["pdendscale"] = ll_sd_from_vector2(mEndScale);
   53.56 -	return sd;
   53.57 +	return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
   53.58  }
   53.59  
   53.60 -bool LLPartData::fromLLSD(LLSD& sd)
   53.61 +S32 LLPartData::getSize() const
   53.62  {
   53.63 -	mFlags = ll_U32_from_sd(sd["pdflags"]);
   53.64 -	mMaxAge = (F32)sd["pdmaxage"].asReal();
   53.65 -	mStartColor = ll_color4_from_sd(sd["pdstartcolor"]);
   53.66 -	mEndColor = ll_color4_from_sd(sd["pdendcolor"]);
   53.67 -	mStartScale = ll_vector2_from_sd(sd["pdstartscale"]);
   53.68 -	mEndScale = ll_vector2_from_sd(sd["pdendscale"]);
   53.69 -	return true;
   53.70 +	S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE;
   53.71 +	if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE;
   53.72 +	if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE;
   53.73 +
   53.74 +	return size;
   53.75  }
   53.76  
   53.77  
   53.78 -BOOL LLPartData::unpack(LLDataPacker &dp)
   53.79 +BOOL LLPartData::unpackLegacy(LLDataPacker &dp)
   53.80  {
   53.81  	LLColor4U coloru;
   53.82  
   53.83 @@ -98,9 +91,70 @@
   53.84  	dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", FALSE, 3, 5);
   53.85  	dp.unpackFixed(mEndScale.mV[0], "pdendscalex", FALSE, 3, 5);
   53.86  	dp.unpackFixed(mEndScale.mV[1], "pdendscaley", FALSE, 3, 5);
   53.87 +
   53.88 +	mStartGlow = 0.f;
   53.89 +	mEndGlow = 0.f;
   53.90 +	mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
   53.91 +	mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
   53.92 +
   53.93  	return TRUE;
   53.94  }
   53.95  
   53.96 +BOOL LLPartData::unpack(LLDataPacker &dp)
   53.97 +{
   53.98 +	S32 size = 0;
   53.99 +	dp.unpackS32(size, "partsize");
  53.100 +
  53.101 +	unpackLegacy(dp);
  53.102 +	size -= PS_LEGACY_PART_DATA_BLOCK_SIZE;
  53.103 +
  53.104 +	if (mFlags & LL_PART_DATA_GLOW)
  53.105 +	{
  53.106 +		if (size < PS_PART_DATA_GLOW_SIZE) return FALSE;
  53.107 +
  53.108 +		U8 tmp_glow = 0;
  53.109 +		dp.unpackU8(tmp_glow,"pdstartglow");
  53.110 +		mStartGlow = tmp_glow / 255.f;
  53.111 +		dp.unpackU8(tmp_glow,"pdendglow");
  53.112 +		mEndGlow = tmp_glow / 255.f;
  53.113 +
  53.114 +		size -= PS_PART_DATA_GLOW_SIZE;
  53.115 +	}
  53.116 +	else
  53.117 +	{
  53.118 +		mStartGlow = 0.f;
  53.119 +		mEndGlow = 0.f;
  53.120 +	}
  53.121 +
  53.122 +	if (mFlags & LL_PART_DATA_BLEND)
  53.123 +	{
  53.124 +		if (size < PS_PART_DATA_BLEND_SIZE) return FALSE;
  53.125 +		dp.unpackU8(mBlendFuncSource,"pdblendsource");
  53.126 +		dp.unpackU8(mBlendFuncDest,"pdblenddest");
  53.127 +		size -= PS_PART_DATA_BLEND_SIZE;
  53.128 +	}
  53.129 +	else
  53.130 +	{
  53.131 +		mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
  53.132 +		mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
  53.133 +	}
  53.134 +
  53.135 +	if (size > 0)
  53.136 +	{ //leftover bytes, unrecognized parameters
  53.137 +		U8 feh = 0;
  53.138 +		while (size > 0)
  53.139 +		{ //read remaining bytes in block
  53.140 +			dp.unpackU8(feh, "whippang");
  53.141 +			size--;
  53.142 +		}
  53.143 +
  53.144 +		//this particle system won't display properly, better to not show anything
  53.145 +		return FALSE;
  53.146 +	}
  53.147 +
  53.148 +
  53.149 +	return TRUE;
  53.150 +}
  53.151  
  53.152  void LLPartData::setFlags(const U32 flags)
  53.153  {
  53.154 @@ -148,6 +202,18 @@
  53.155  	mEndColor.mV[3] = alpha;
  53.156  }
  53.157  
  53.158 +// static
  53.159 +bool LLPartData::validBlendFunc(S32 func)
  53.160 +{
  53.161 +	if (func >= 0
  53.162 +		&& func < LL_PART_BF_COUNT
  53.163 +		&& func != UNSUPPORTED_DEST_ALPHA
  53.164 +		&& func != UNSUPPORTED_ONE_MINUS_DEST_ALPHA)
  53.165 +	{
  53.166 +		return true;
  53.167 +	}
  53.168 +	return false;
  53.169 +}
  53.170  
  53.171  LLPartSysData::LLPartSysData()
  53.172  {
  53.173 @@ -160,6 +226,10 @@
  53.174  	mPartData.mStartScale = LLVector2(1.f, 1.f);
  53.175  	mPartData.mEndScale = LLVector2(1.f, 1.f);
  53.176  	mPartData.mMaxAge = 10.0;
  53.177 +	mPartData.mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
  53.178 +	mPartData.mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
  53.179 +	mPartData.mStartGlow = 0.f;
  53.180 +	mPartData.mEndGlow = 0.f;
  53.181  
  53.182  	mMaxAge = 0.0;
  53.183  	mStartAge = 0.0;
  53.184 @@ -175,38 +245,7 @@
  53.185  	mNumParticles = 0;
  53.186  }
  53.187  
  53.188 -
  53.189 -BOOL LLPartSysData::pack(LLDataPacker &dp)
  53.190 -{
  53.191 -	dp.packU32(mCRC, "pscrc");
  53.192 -	dp.packU32(mFlags, "psflags");
  53.193 -	dp.packU8(mPattern, "pspattern");
  53.194 -	dp.packFixed(mMaxAge, "psmaxage", FALSE, 8, 8);
  53.195 -	dp.packFixed(mStartAge, "psstartage", FALSE, 8, 8);
  53.196 -	dp.packFixed(mInnerAngle, "psinnerangle", FALSE, 3, 5);
  53.197 -	dp.packFixed(mOuterAngle, "psouterangle", FALSE, 3, 5);
  53.198 -	dp.packFixed(mBurstRate, "psburstrate", FALSE, 8, 8);
  53.199 -	dp.packFixed(mBurstRadius, "psburstradius", FALSE, 8, 8);
  53.200 -	dp.packFixed(mBurstSpeedMin, "psburstspeedmin", FALSE, 8, 8);
  53.201 -	dp.packFixed(mBurstSpeedMax, "psburstspeedmax", FALSE, 8, 8);
  53.202 -	dp.packU8(mBurstPartCount, "psburstpartcount");
  53.203 -
  53.204 -	dp.packFixed(mAngularVelocity.mV[0], "psangvelx", TRUE, 8, 7);
  53.205 -	dp.packFixed(mAngularVelocity.mV[1], "psangvely", TRUE, 8, 7);
  53.206 -	dp.packFixed(mAngularVelocity.mV[2], "psangvelz", TRUE, 8, 7);
  53.207 -
  53.208 -	dp.packFixed(mPartAccel.mV[0], "psaccelx", TRUE, 8, 7);
  53.209 -	dp.packFixed(mPartAccel.mV[1], "psaccely", TRUE, 8, 7);
  53.210 -	dp.packFixed(mPartAccel.mV[2], "psaccelz", TRUE, 8, 7);
  53.211 -
  53.212 -	dp.packUUID(mPartImageID, "psuuid");
  53.213 -	dp.packUUID(mTargetUUID, "pstargetuuid");
  53.214 -	mPartData.pack(dp);
  53.215 -	return TRUE;
  53.216 -}
  53.217 -
  53.218 -
  53.219 -BOOL LLPartSysData::unpack(LLDataPacker &dp)
  53.220 +BOOL LLPartSysData::unpackSystem(LLDataPacker &dp)
  53.221  {
  53.222  	dp.unpackU32(mCRC, "pscrc");
  53.223  	dp.unpackU32(mFlags, "psflags");
  53.224 @@ -232,10 +271,48 @@
  53.225  
  53.226  	dp.unpackUUID(mPartImageID, "psuuid");
  53.227  	dp.unpackUUID(mTargetUUID, "pstargetuuid");
  53.228 -	mPartData.unpack(dp);
  53.229  	return TRUE;
  53.230  }
  53.231  
  53.232 +BOOL LLPartSysData::unpackLegacy(LLDataPacker &dp)
  53.233 +{
  53.234 +	unpackSystem(dp);
  53.235 +	mPartData.unpackLegacy(dp);
  53.236 +
  53.237 +	return TRUE;
  53.238 +}
  53.239 +
  53.240 +BOOL LLPartSysData::unpack(LLDataPacker &dp)
  53.241 +{
  53.242 +	// syssize is currently unused.  Adding now when modifying the 'version to make extensible in the future
  53.243 +	S32 size = 0;
  53.244 +	dp.unpackS32(size, "syssize");
  53.245 +	
  53.246 +	if (size != PS_SYS_DATA_BLOCK_SIZE)
  53.247 +	{ //unexpected size, this viewer doesn't know how to parse this particle system
  53.248 +		
  53.249 +		//skip to LLPartData block
  53.250 +		U8 feh = 0;
  53.251 +		
  53.252 +		for (U32 i = 0; i < size; ++i)
  53.253 +		{
  53.254 +			dp.unpackU8(feh, "whippang");
  53.255 +		}
  53.256 +				
  53.257 +		dp.unpackS32(size, "partsize");
  53.258 +		//skip LLPartData block
  53.259 +		for (U32 i = 0; i < size; ++i)
  53.260 +		{
  53.261 +			dp.unpackU8(feh, "whippang");
  53.262 +		}
  53.263 +		return FALSE;
  53.264 +	}
  53.265 +
  53.266 +	unpackSystem(dp);
  53.267 +	
  53.268 +	return mPartData.unpack(dp);
  53.269 +}
  53.270 +
  53.271  std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
  53.272  {
  53.273  	s << "Flags: " << std::hex << data.mFlags;
  53.274 @@ -253,7 +330,7 @@
  53.275  
  53.276  BOOL LLPartSysData::isNullPS(const S32 block_num)
  53.277  {
  53.278 -	U8 ps_data_block[PS_DATA_BLOCK_SIZE];
  53.279 +	U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
  53.280  	U32 crc;
  53.281  
  53.282  	S32 size;
  53.283 @@ -264,14 +341,28 @@
  53.284  	{
  53.285  		return TRUE;
  53.286  	}
  53.287 -	else if (size != PS_DATA_BLOCK_SIZE)
  53.288 +	
  53.289 +	if (size > PS_MAX_DATA_BLOCK_SIZE)
  53.290  	{
  53.291 -		llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl;
  53.292 +		//size is too big, newer particle version unsupported
  53.293  		return TRUE;
  53.294  	}
  53.295 -	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE);
  53.296  
  53.297 -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE);
  53.298 +	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
  53.299 +
  53.300 +	LLDataPackerBinaryBuffer dp(ps_data_block, size);
  53.301 +	if (size > PS_LEGACY_DATA_BLOCK_SIZE)
  53.302 +	{
  53.303 +		// non legacy systems pack a size before the CRC
  53.304 +		S32 tmp = 0;
  53.305 +		dp.unpackS32(tmp, "syssize");
  53.306 +
  53.307 +		if (tmp > PS_SYS_DATA_BLOCK_SIZE)
  53.308 +		{ //unknown system data block size, don't know how to parse it, treat as NULL
  53.309 +			return TRUE;
  53.310 +		}
  53.311 +	}
  53.312 +
  53.313  	dp.unpackU32(crc, "crc");
  53.314  
  53.315  	if (crc == 0)
  53.316 @@ -281,50 +372,37 @@
  53.317  	return FALSE;
  53.318  }
  53.319  
  53.320 -
  53.321 -//static
  53.322 -BOOL LLPartSysData::packNull()
  53.323 -{
  53.324 -	U8 ps_data_block[PS_DATA_BLOCK_SIZE];
  53.325 -	gMessageSystem->addBinaryData("PSBlock", ps_data_block, 0);
  53.326 -	return TRUE;
  53.327 -}
  53.328 -
  53.329 -
  53.330 -BOOL LLPartSysData::packBlock()
  53.331 -{
  53.332 -	U8 ps_data_block[PS_DATA_BLOCK_SIZE];
  53.333 -
  53.334 -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE);
  53.335 -	pack(dp);
  53.336 -
  53.337 -	// Add to message
  53.338 -	gMessageSystem->addBinaryData("PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE);
  53.339 -
  53.340 -	return TRUE;
  53.341 -}                                         
  53.342 -
  53.343 -
  53.344  BOOL LLPartSysData::unpackBlock(const S32 block_num)
  53.345  {
  53.346 -	U8 ps_data_block[PS_DATA_BLOCK_SIZE];
  53.347 +	U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
  53.348  
  53.349  	// Check size of block
  53.350  	S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
  53.351  
  53.352 -	if (size != PS_DATA_BLOCK_SIZE)
  53.353 +	if (size > PS_MAX_DATA_BLOCK_SIZE)
  53.354  	{
  53.355 -		llwarns << "PSBlock is wrong size for particle system data - got " << size << ", expecting " << PS_DATA_BLOCK_SIZE << llendl;
  53.356 +		// Larger packets are newer and unsupported
  53.357  		return FALSE;
  53.358  	}
  53.359  
  53.360  	// Get from message
  53.361 -	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, PS_DATA_BLOCK_SIZE, block_num, PS_DATA_BLOCK_SIZE);
  53.362 +	gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
  53.363  
  53.364 -	LLDataPackerBinaryBuffer dp(ps_data_block, PS_DATA_BLOCK_SIZE);
  53.365 -	unpack(dp);
  53.366 +	LLDataPackerBinaryBuffer dp(ps_data_block, size);
  53.367  
  53.368 -	return TRUE;
  53.369 +	if (size == PS_LEGACY_DATA_BLOCK_SIZE)
  53.370 +	{
  53.371 +		return unpackLegacy(dp);
  53.372 +	}
  53.373 +	else
  53.374 +	{
  53.375 +		return unpack(dp);
  53.376 +	}
  53.377 +}
  53.378 +
  53.379 +bool LLPartSysData::isLegacyCompatible() const
  53.380 +{
  53.381 +	return !mPartData.hasGlow() && !mPartData.hasBlendFunc();
  53.382  }
  53.383  
  53.384  void LLPartSysData::clampSourceParticleRate()
    54.1 --- a/indra/llmessage/llpartdata.h	Fri Sep 27 17:22:31 2013 -0400
    54.2 +++ b/indra/llmessage/llpartdata.h	Fri Oct 04 15:36:52 2013 -0400
    54.3 @@ -70,7 +70,12 @@
    54.4  	LLPS_SRC_TARGET_UUID,
    54.5  	LLPS_SRC_OMEGA,
    54.6  	LLPS_SRC_ANGLE_BEGIN,
    54.7 -	LLPS_SRC_ANGLE_END
    54.8 +	LLPS_SRC_ANGLE_END,
    54.9 +
   54.10 +	LLPS_PART_BLEND_FUNC_SOURCE,
   54.11 +	LLPS_PART_BLEND_FUNC_DEST,
   54.12 +	LLPS_PART_START_GLOW,
   54.13 +	LLPS_PART_END_GLOW
   54.14  };
   54.15  
   54.16  
   54.17 @@ -83,11 +88,13 @@
   54.18  		mParameter(0.f)
   54.19  	{
   54.20  	}
   54.21 +	BOOL unpackLegacy(LLDataPacker &dp);
   54.22  	BOOL unpack(LLDataPacker &dp);
   54.23 +
   54.24  	BOOL pack(LLDataPacker &dp);
   54.25 -	LLSD asLLSD() const;
   54.26 -	operator LLSD() const {return asLLSD(); }
   54.27 -	bool fromLLSD(LLSD& sd);
   54.28 +	
   54.29 +	bool hasGlow() const;
   54.30 +	bool hasBlendFunc() const;
   54.31  
   54.32  	// Masks for the different particle flags
   54.33  	enum
   54.34 @@ -102,17 +109,39 @@
   54.35  		LL_PART_TARGET_LINEAR_MASK =	0x80,		// Particle uses a direct linear interpolation
   54.36  		LL_PART_EMISSIVE_MASK =			0x100,		// Particle is "emissive", instead of being lit
   54.37  		LL_PART_BEAM_MASK =				0x200,		// Particle is a "beam" connecting source and target
   54.38 +		LL_PART_RIBBON_MASK =			0x400,		// Particles are joined together into one continuous triangle strip
   54.39  
   54.40  		// Not implemented yet!
   54.41  		//LL_PART_RANDOM_ACCEL_MASK =		0x100,		// Particles have random acceleration
   54.42  		//LL_PART_RANDOM_VEL_MASK =		0x200,		// Particles have random velocity shifts"
   54.43  		//LL_PART_TRAIL_MASK =			0x400,		// Particles have historical "trails"
   54.44  
   54.45 +		//sYSTEM SET FLAGS
   54.46 +		LL_PART_DATA_GLOW =				0x10000,
   54.47 +		LL_PART_DATA_BLEND =			0x20000,
   54.48 +
   54.49  		// Viewer side use only!
   54.50  		LL_PART_HUD =					0x40000000,
   54.51  		LL_PART_DEAD_MASK =				0x80000000,
   54.52  	};
   54.53  
   54.54 +	enum
   54.55 +	{
   54.56 +		LL_PART_BF_ONE = 0,
   54.57 +		LL_PART_BF_ZERO = 1,
   54.58 +		LL_PART_BF_DEST_COLOR = 2,
   54.59 +		LL_PART_BF_SOURCE_COLOR = 3,
   54.60 +		LL_PART_BF_ONE_MINUS_DEST_COLOR = 4,
   54.61 +		LL_PART_BF_ONE_MINUS_SOURCE_COLOR = 5,
   54.62 +		UNSUPPORTED_DEST_ALPHA = 6,
   54.63 +		LL_PART_BF_SOURCE_ALPHA = 7,
   54.64 +		UNSUPPORTED_ONE_MINUS_DEST_ALPHA = 8,
   54.65 +		LL_PART_BF_ONE_MINUS_SOURCE_ALPHA = 9,
   54.66 +		LL_PART_BF_COUNT = 10
   54.67 +	};
   54.68 +
   54.69 +	static bool validBlendFunc(S32 func);
   54.70 +
   54.71  	void setFlags(const U32 flags);
   54.72  	void setMaxAge(const F32 max_age);
   54.73  	void setStartScale(const F32 xs, F32 ys);
   54.74 @@ -126,6 +155,9 @@
   54.75  	friend class LLPartSysData;
   54.76  	friend class LLViewerPartSourceScript;
   54.77  
   54.78 +private:
   54.79 +	S32 getSize() const;
   54.80 +
   54.81  	// These are public because I'm really lazy...
   54.82  public:
   54.83  	U32					mFlags;						// Particle state/interpolators in effect
   54.84 @@ -137,6 +169,12 @@
   54.85  
   54.86  	LLVector3			mPosOffset;					// Offset from source if using FOLLOW_SOURCE
   54.87  	F32					mParameter;					// A single floating point parameter
   54.88 +
   54.89 +	F32					mStartGlow;
   54.90 +	F32					mEndGlow;
   54.91 +	
   54.92 +	U8					mBlendFuncSource;
   54.93 +	U8					mBlendFuncDest;
   54.94  };
   54.95  
   54.96  
   54.97 @@ -146,14 +184,12 @@
   54.98  	LLPartSysData();
   54.99  
  54.100  	BOOL unpack(LLDataPacker &dp);
  54.101 -	BOOL pack(LLDataPacker &dp);
  54.102 +	BOOL unpackLegacy(LLDataPacker &dp);
  54.103 +	BOOL unpackBlock(const S32 block_num);
  54.104 +		
  54.105 +	static BOOL isNullPS(const S32 block_num); // Returns FALSE if this is a "NULL" particle system (i.e. no system)
  54.106  
  54.107 -	
  54.108 -	BOOL unpackBlock(const S32 block_num);
  54.109 -	BOOL packBlock();
  54.110 -
  54.111 -	static BOOL packNull();
  54.112 -	static BOOL isNullPS(const S32 block_num); // Returns FALSE if this is a "NULL" particle system (i.e. no system)
  54.113 +	bool isLegacyCompatible() const;
  54.114  
  54.115  	// Different masks for effects on the source
  54.116  	enum
  54.117 @@ -187,7 +223,12 @@
  54.118  	void clampSourceParticleRate();
  54.119  	
  54.120  	friend std::ostream&	 operator<<(std::ostream& s, const LLPartSysData &data);		// Stream a
  54.121 +
  54.122 +	S32 getdataBlockSize() const;
  54.123  	
  54.124 +private:
  54.125 +	BOOL unpackSystem(LLDataPacker &dp);
  54.126 +
  54.127  public:
  54.128  	// Public because I'm lazy....
  54.129  
    55.1 --- a/indra/llmessage/lltransfermanager.cpp	Fri Sep 27 17:22:31 2013 -0400
    55.2 +++ b/indra/llmessage/lltransfermanager.cpp	Fri Oct 04 15:36:52 2013 -0400
    55.3 @@ -606,16 +606,21 @@
    55.4  void LLTransferManager::reliablePacketCallback(void **user_data, S32 result)
    55.5  {
    55.6  	LLUUID *transfer_idp = (LLUUID *)user_data;
    55.7 -	if (result)
    55.8 +	if (result &&
    55.9 +		transfer_idp != NULL)
   55.10  	{
   55.11 -		llwarns << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << llendl;
   55.12  		LLTransferSource *tsp = gTransferManager.findTransferSource(*transfer_idp);
   55.13  		if (tsp)
   55.14  		{
   55.15 +			llwarns << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << llendl;
   55.16  			LLTransferSourceChannel *tscp = tsp->mChannelp;
   55.17  			tsp->abortTransfer();
   55.18  			tscp->deleteTransfer(tsp);
   55.19  		}
   55.20 +		else
   55.21 +		{
   55.22 +			llwarns << "Aborting reliable transfer " << *transfer_idp << " but can't find the LLTransferSource object" << llendl;
   55.23 +		}
   55.24  	}
   55.25  	delete transfer_idp;
   55.26  }
   55.27 @@ -892,22 +897,26 @@
   55.28  }
   55.29  
   55.30  
   55.31 -BOOL LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)
   55.32 +void LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)
   55.33  {
   55.34 +	if (tsp)
   55.35 +	{
   55.36 +		LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
   55.37 +		for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
   55.38 +		{
   55.39 +			if (iter->second == tsp)
   55.40 +			{
   55.41 +				delete tsp;
   55.42 +				mTransferSources.mMap.erase(iter);
   55.43 +				return;
   55.44 +			}
   55.45 +		}
   55.46  
   55.47 -	LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
   55.48 -	for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
   55.49 -	{
   55.50 -		if (iter->second == tsp)
   55.51 -		{
   55.52 -			delete tsp;
   55.53 -			mTransferSources.mMap.erase(iter);
   55.54 -			return TRUE;
   55.55 -		}
   55.56 +		llwarns << "Unable to find transfer source id " 
   55.57 +			<< tsp->getID()
   55.58 +			<< " to delete!" 
   55.59 +			<< llendl;
   55.60  	}
   55.61 -
   55.62 -	llerrs << "Unable to find transfer source to delete!" << llendl;
   55.63 -	return FALSE;
   55.64  }
   55.65  
   55.66  
   55.67 @@ -1008,21 +1017,26 @@
   55.68  }
   55.69  
   55.70  
   55.71 -BOOL LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)
   55.72 +void LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)
   55.73  {
   55.74 -	tt_iter iter;
   55.75 -	for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
   55.76 +	if (ttp)
   55.77  	{
   55.78 -		if (*iter == ttp)
   55.79 +		tt_iter iter;
   55.80 +		for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
   55.81  		{
   55.82 -			delete ttp;
   55.83 -			mTransferTargets.erase(iter);
   55.84 -			return TRUE;
   55.85 +			if (*iter == ttp)
   55.86 +			{
   55.87 +				delete ttp;
   55.88 +				mTransferTargets.erase(iter);
   55.89 +				return;
   55.90 +			}
   55.91  		}
   55.92 +
   55.93 +		llwarns << "Unable to find transfer target id " 
   55.94 +			<< ttp->getID()
   55.95 +			<< " to delete!" 
   55.96 +			<< llendl;
   55.97  	}
   55.98 -
   55.99 -	llerrs << "Unable to find transfer target to delete!" << llendl;
  55.100 -	return FALSE;
  55.101  }
  55.102  
  55.103  
    56.1 --- a/indra/llmessage/lltransfermanager.h	Fri Sep 27 17:22:31 2013 -0400
    56.2 +++ b/indra/llmessage/lltransfermanager.h	Fri Oct 04 15:36:52 2013 -0400
    56.3 @@ -199,7 +199,7 @@
    56.4  
    56.5  	void				addTransferSource(LLTransferSource *sourcep);
    56.6  	LLTransferSource	*findTransferSource(const LLUUID &transfer_id);
    56.7 -	BOOL				deleteTransfer(LLTransferSource *tsp);
    56.8 +	void				deleteTransfer(LLTransferSource *tsp);
    56.9  
   56.10  	void					setThrottleID(const S32 throttle_id)	{ mThrottleID = throttle_id; }
   56.11  
   56.12 @@ -232,7 +232,7 @@
   56.13  						 const F32 priority);
   56.14  
   56.15  	LLTransferTarget		*findTransferTarget(const LLUUID &transfer_id);
   56.16 -	BOOL					deleteTransfer(LLTransferTarget *ttp);
   56.17 +	void					deleteTransfer(LLTransferTarget *ttp);
   56.18  
   56.19  
   56.20  	LLTransferChannelType	getChannelType() const		{ return mChannelType; }
    57.1 --- a/indra/llmessage/tests/llpartdata_test.cpp	Fri Sep 27 17:22:31 2013 -0400
    57.2 +++ b/indra/llmessage/tests/llpartdata_test.cpp	Fri Oct 04 15:36:52 2013 -0400
    57.3 @@ -38,10 +38,34 @@
    57.4  
    57.5  namespace tut
    57.6  {
    57.7 +
    57.8 +	//bunch of sniffed data that *should* be a valid particle system
    57.9 +	static U8 msg[] = { 
   57.10 +		0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
   57.11 +		0x00, 0x00, 0x00, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x00, 0x80, 0x00, 0x80, 
   57.12 +		0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x5e, 0x12, 0x0b, 0xa1, 0x58, 0x05, 0xdc, 0x57, 0x66, 
   57.13 +		0xb7, 0xf5, 0xac, 0x4b, 0xd1, 0x8f, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
   57.14 +		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x02, 0x05, 0x02, 0x00, 0x00, 0x0a, 0xff, 
   57.15 +		0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x20, 0x20, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 
   57.16 +		0x00, 0x7e, 0xc6, 0x81, 0xdc, 0x7e, 0xc6, 0x81, 0xdc, 0x77, 0xcf, 0xef, 0xd4, 0xce, 0x64, 0x1a, 0x7e, 
   57.17 +		0x26, 0x87, 0x55, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0xdd, 0x65, 0x22, 0x7f, 0x77, 0xcf, 0x98, 0xa3, 0xab, 
   57.18 +		0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd1, 0xf2, 
   57.19 +		0xf1, 0x65, 0x32, 0x1b, 0xef, 0x18, 0x70, 0x66, 0xba, 0x30, 0xa0, 0x11, 0xaa, 0x2f, 0xb0, 0xab, 0xd0, 
   57.20 +		0x30, 0x7d, 0xbd, 0x01, 0x00, 0xf8, 0x0d, 0xb8, 0x30, 0x01, 0x00, 0x00, 0x00, 0xce, 0xc6, 0x81, 0xdc, 
   57.21 +		0xce, 0xc6, 0x81, 0xdc, 0xc7, 0xcf, 0xef, 0xd4, 0x75, 0x65, 0x1a, 0x7f, 0x62, 0x6f, 0x55, 0x7f, 0x6d, 
   57.22 +		0x65, 0x22, 0x7f, 0x6d, 0x65, 0x22, 0x7f, 0xc7, 0xcf, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 
   57.23 +		0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd6, 0xf2, 0xf1, 0x62, 0x12, 0x1b, 0xef, 
   57.24 +		0x18, 0x7e, 0xbd, 0x01, 0x00, 0x16, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
   57.25 +		0x00, 0x00, 0x00, 0x00, 0x7c, 0xac, 0x28, 0x03, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 
   57.26 +		0xe0, 0xb9, 0x30, 0x03, 0xe1, 0xb9, 0x30, 0xbb, 0x00, 0x00, 0x00, 0x48, 0xe0, 0xb9, 0x30, 0x36, 0xd9, 
   57.27 +		0x81, 0xdc, 0x36, 0xd9, 0x81, 0xdc, 0x3f, 0xd0, 0xef, 0xd4, 0xa5, 0x7a, 0x72, 0x7f, 0x26, 0x30, 0x55, 
   57.28 +		0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x95, 0x7a, 0x22, 0x7f, 0x3f, 0xd0, 0x98, 0xa3, 0xab, 0xab, 0xab, 0xab, 
   57.29 +		0xab, 0xab, 0xab, 0xab, 0x00, 0x00, 0x00, 0x00, 0x00 };
   57.30  	
   57.31  	struct partdata_test
   57.32  	{
   57.33  	};
   57.34 +
   57.35  	typedef test_group<partdata_test> partdata_test_t;
   57.36  	typedef partdata_test_t::object partdata_test_object_t;
   57.37  	tut::partdata_test_t tut_partdata_test("LLPartData");
   57.38 @@ -49,168 +73,82 @@
   57.39  	template<> template<>
   57.40  	void partdata_test_object_t::test<1>()
   57.41  	{
   57.42 -		LLPartData llpdata,llpdata1;
   57.43 -		U8 pkbuf[128];
   57.44 +		LLPartSysData llpsysdata;
   57.45 +		LLDataPackerBinaryBuffer dp1(msg, sizeof(msg));
   57.46  
   57.47 -		llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK |
   57.48 -		LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK |
   57.49 -		LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK |
   57.50 -		LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK);
   57.51 +		ensure("LLPartSysData::unpack failed.", llpsysdata.unpack(dp1));
   57.52  
   57.53 -		llpdata.setMaxAge(29.3f);
   57.54 +		
   57.55 +		//mCRC	1	unsigned int
   57.56 +		ensure("mCRC different after unpacking", llpsysdata.mCRC == (U32) 1);
   57.57 +		//mFlags	0	unsigned int
   57.58 +		ensure ("mFlags different after unpacking", llpsysdata.mFlags == (U32) 0);
   57.59 +		//mPattern	1 ''	unsigned char
   57.60 +		ensure ("mPattern different after unpacking", llpsysdata.mPattern == (U8) 1);
   57.61 +		//mInnerAngle	0.00000000	float
   57.62 +		ensure_approximately_equals("mInnerAngle different after unpacking", llpsysdata.mInnerAngle, 0.f, 8);
   57.63 +		//mOuterAngle	0.00000000	float
   57.64 +		ensure_approximately_equals("mOuterAngle different after unpacking", llpsysdata.mOuterAngle, 0.f, 8);
   57.65 +		//mAngularVelocity	0,0,0
   57.66 +		ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[0], 0.f, 8);
   57.67 +		ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[1], 0.f, 8);
   57.68 +		ensure_approximately_equals("mAngularVelocity.mV[0] different after unpacking", llpsysdata.mAngularVelocity.mV[2], 0.f, 8);
   57.69 +		//mBurstRate	0.097656250	float
   57.70 +		ensure_approximately_equals("mBurstRate different after unpacking", llpsysdata.mBurstRate, 0.097656250f, 8);
   57.71 +		//mBurstPartCount	1 ''	unsigned char
   57.72 +		ensure("mBurstPartCount different after unpacking", llpsysdata.mBurstPartCount == (U8) 1);
   57.73 +		//mBurstRadius	0.00000000	float
   57.74 +		ensure_approximately_equals("mBurstRadius different after unpacking", llpsysdata.mBurstRadius, 0.f, 8);
   57.75 +		//mBurstSpeedMin	1.0000000	float
   57.76 +		ensure_approximately_equals("mBurstSpeedMin different after unpacking", llpsysdata.mBurstSpeedMin, 1.f, 8);
   57.77 +		//mBurstSpeedMax	1.0000000	float
   57.78 +		ensure_approximately_equals("mBurstSpeedMax different after unpacking", llpsysdata.mBurstSpeedMax, 1.f, 8);
   57.79 +		//mMaxAge	0.00000000	float
   57.80 +		ensure_approximately_equals("mMaxAge different after unpacking", llpsysdata.mMaxAge, 0.f, 8);
   57.81 +		//mStartAge	0.00000000	float
   57.82 +		ensure_approximately_equals("mStartAge different after unpacking", llpsysdata.mStartAge, 0.f, 8);
   57.83 +		//mPartAccel	<0,0,0>
   57.84 +		ensure_approximately_equals("mPartAccel.mV[0] different after unpacking", llpsysdata.mPartAccel.mV[0], 0.f, 7);
   57.85 +		ensure_approximately_equals("mPartAccel.mV[1] different after unpacking", llpsysdata.mPartAccel.mV[1], 0.f, 7);
   57.86 +		ensure_approximately_equals("mPartAccel.mV[2] different after unpacking", llpsysdata.mPartAccel.mV[2], 0.f, 7);
   57.87  
   57.88 -		LLVector3 llvec1(1.0f, .5f, .25f);
   57.89 -		llpdata.setStartColor(llvec1);
   57.90 -		llpdata.setStartAlpha(.7f);
   57.91 +		//mPartData
   57.92 +		LLPartData& data = llpsysdata.mPartData;
   57.93  
   57.94 -		LLVector3 llvec2(.2f, .3f, 1.0f);
   57.95 -		llpdata.setEndColor(llvec2);
   57.96 -		llpdata.setEndAlpha(1.0f);
   57.97 -
   57.98 -		llpdata.setStartScale(3.23f, 4.0f);
   57.99 -		llpdata.setEndScale(2.4678f, 1.0f);
  57.100 -
  57.101 -		LLDataPackerBinaryBuffer dp((U8*)pkbuf, 128);
  57.102 -		llpdata.pack(dp);
  57.103 +		//mFlags	132354	unsigned int
  57.104 +		ensure ("mPartData.mFlags different after unpacking", data.mFlags == (U32) 132354);
  57.105 +		//mMaxAge	10.000000	float
  57.106 +		ensure_approximately_equals("mPartData.mMaxAge different after unpacking", data.mMaxAge, 10.f, 8); 
  57.107 +		//mStartColor	<1,1,1,1>
  57.108 +		ensure_approximately_equals("mPartData.mStartColor.mV[0] different after unpacking", data.mStartColor.mV[0], 1.f, 8);
  57.109 +		ensure_approximately_equals("mPartData.mStartColor.mV[1] different after unpacking", data.mStartColor.mV[1], 1.f, 8);
  57.110 +		ensure_approximately_equals("mPartData.mStartColor.mV[2] different after unpacking", data.mStartColor.mV[2], 1.f, 8);
  57.111 +		ensure_approximately_equals("mPartData.mStartColor.mV[3] different after unpacking", data.mStartColor.mV[3], 1.f, 8);
  57.112 +		//mEndColor	<1,1,0,0>
  57.113 +		ensure_approximately_equals("mPartData.mEndColor.mV[0] different after unpacking", data.mEndColor.mV[0], 1.f, 8);
  57.114 +		ensure_approximately_equals("mPartData.mEndColor.mV[1] different after unpacking", data.mEndColor.mV[1], 1.f, 8);
  57.115 +		ensure_approximately_equals("mPartData.mEndColor.mV[2] different after unpacking", data.mEndColor.mV[2], 0.f, 8);
  57.116 +		ensure_approximately_equals("mPartData.mEndColor.mV[3] different after unpacking", data.mEndColor.mV[3], 0.f, 8);
  57.117 +		//mStartScale	<1,1>
  57.118 +		ensure_approximately_equals("mPartData.mStartScale.mV[0] different after unpacking", data.mStartScale.mV[0], 1.f, 8);
  57.119 +		ensure_approximately_equals("mPartData.mStartScale.mV[1] different after unpacking", data.mStartScale.mV[1], 1.f, 8);
  57.120 +		//mEndScale	<0,0>
  57.121 +		ensure_approximately_equals("mPartData.mEndScale.mV[0] different after unpacking", data.mEndScale.mV[0], 0.f, 8);
  57.122 +		ensure_approximately_equals("mPartData.mEndScale.mV[1] different after unpacking", data.mEndScale.mV[1], 0.f, 8);
  57.123 +		//mPosOffset	<0,0,0>
  57.124 +		ensure_approximately_equals("mPartData.mPosOffset.mV[0] different after unpacking", data.mPosOffset.mV[0], 0.f, 8);
  57.125 +		ensure_approximately_equals("mPartData.mPosOffset.mV[1] different after unpacking", data.mPosOffset.mV[1], 0.f, 8);
  57.126 +		ensure_approximately_equals("mPartData.mPosOffset.mV[2] different after unpacking", data.mPosOffset.mV[2], 0.f, 8);
  57.127 +		//mParameter	0.00000000	float
  57.128 +		ensure_approximately_equals("mPartData.mParameter different after unpacking", data.mParameter, 0.f, 8);
  57.129  		
  57.130 -		S32 cur_size = dp.getCurrentSize();
  57.131 -		
  57.132 -		LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size);
  57.133 -		llpdata1.unpack(dp1);
  57.134 -
  57.135 -		ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags);
  57.136 -		ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8);
  57.137 -
  57.138 -		ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8);
  57.139 -		ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8);
  57.140 -		ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8);
  57.141 -		ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8);
  57.142 -
  57.143 -		ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8);
  57.144 -		ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8);
  57.145 -		ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8);
  57.146 -		ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8);
  57.147 -
  57.148 -		ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5);
  57.149 -		ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5);
  57.150 -
  57.151 -		ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5);
  57.152 -		ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5);
  57.153 -	}
  57.154 -
  57.155 -
  57.156 -	template<> template<>
  57.157 -	void partdata_test_object_t::test<2>()
  57.158 -	{
  57.159 -		LLPartData llpdata,llpdata1;
  57.160 -
  57.161 -		llpdata.setFlags(LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK |
  57.162 -		LLPartData::LL_PART_BOUNCE_MASK | LLPartData::LL_PART_WIND_MASK | LLPartData::LL_PART_FOLLOW_SRC_MASK |
  57.163 -		LLPartData::LL_PART_FOLLOW_VELOCITY_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_TARGET_LINEAR_MASK |
  57.164 -		LLPartData::LL_PART_EMISSIVE_MASK | LLPartData::LL_PART_BEAM_MASK | LLPartData::LL_PART_DEAD_MASK);
  57.165 -		
  57.166 -		llpdata.setMaxAge(29.3f);
  57.167 -
  57.168 -		LLVector3 llvec1(1.0f, .5f, .25f);
  57.169 -		llpdata.setStartColor(llvec1);
  57.170 -		llpdata.setStartAlpha(.7f);
  57.171 -
  57.172 -		LLVector3 llvec2(.2f, .3f, 1.0f);
  57.173 -		llpdata.setEndColor(llvec2);
  57.174 -		llpdata.setEndAlpha(1.0f);
  57.175 -
  57.176 -		llpdata.setStartScale(3.23f, 4.0f);
  57.177 -		llpdata.setEndScale(2.4678f, 1.0f);
  57.178 -
  57.179 -		LLSD llsd = llpdata.asLLSD();
  57.180 -
  57.181 -		llpdata1.fromLLSD(llsd);
  57.182 -
  57.183 -		ensure("1.mFlags values are different after unpacking", llpdata1.mFlags == llpdata.mFlags);
  57.184 -		ensure_approximately_equals("2.mMaxAge values are different after unpacking", llpdata1.mMaxAge, llpdata.mMaxAge, 8);
  57.185 -
  57.186 -		ensure_approximately_equals("3.mStartColor[0] values are different after unpacking", llpdata1.mStartColor.mV[0], llpdata.mStartColor.mV[0], 8);
  57.187 -		ensure_approximately_equals("4.mStartColor[1] values are different after unpacking", llpdata1.mStartColor.mV[1], llpdata.mStartColor.mV[1], 8);
  57.188 -		ensure_approximately_equals("5.mStartColor[2] values are different after unpacking", llpdata1.mStartColor.mV[2], llpdata.mStartColor.mV[2], 8);
  57.189 -		ensure_approximately_equals("6.mStartColor[3] values are different after unpacking", llpdata1.mStartColor.mV[3], llpdata.mStartColor.mV[3], 8);
  57.190 -
  57.191 -		ensure_approximately_equals("7.mEndColor[0] values are different after unpacking", llpdata1.mEndColor.mV[0], llpdata.mEndColor.mV[0], 8);
  57.192 -		ensure_approximately_equals("8.mEndColor[1] values are different after unpacking", llpdata1.mEndColor.mV[1], llpdata.mEndColor.mV[1], 8);
  57.193 -		ensure_approximately_equals("9.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[2], llpdata.mEndColor.mV[2], 8);
  57.194 -		ensure_approximately_equals("10.mEndColor[2] values are different after unpacking", llpdata1.mEndColor.mV[3], llpdata.mEndColor.mV[3], 8);
  57.195 -
  57.196 -		ensure_approximately_equals("11.mStartScale[0] values are different after unpacking", llpdata1.mStartScale.mV[0], llpdata.mStartScale.mV[0], 5);
  57.197 -		ensure_approximately_equals("12.mStartScale[1] values are different after unpacking", llpdata1.mStartScale.mV[1], llpdata.mStartScale.mV[1], 5);
  57.198 -
  57.199 -		ensure_approximately_equals("13.mEndScale[0] values are different after unpacking", llpdata1.mEndScale.mV[0], llpdata.mEndScale.mV[0], 5);
  57.200 -		ensure_approximately_equals("14.mEndScale[1] values are different after unpacking", llpdata1.mEndScale.mV[1], llpdata.mEndScale.mV[1], 5);
  57.201 -	}
  57.202 -
  57.203 -
  57.204 -//*********llpartsysdata***********
  57.205 -
  57.206 -	template<> template<>
  57.207 -	void partdata_test_object_t::test<3>()
  57.208 -	{
  57.209 -		LLPartSysData llpsysdata, llpsysdata1;
  57.210 -		U8 pkbuf[256];
  57.211 -		llpsysdata.setBurstSpeedMin(33.33f);
  57.212 -		ensure("1.mBurstSpeedMin coudnt be set", 33.33f == llpsysdata.mBurstSpeedMin);
  57.213 -
  57.214 -		llpsysdata.setBurstSpeedMax(44.44f); 
  57.215 -		ensure("2.mBurstSpeedMax coudnt be set", 44.44f == llpsysdata.mBurstSpeedMax);
  57.216 -
  57.217 -		llpsysdata.setBurstRadius(45.55f);
  57.218 -		ensure("3.mBurstRadius coudnt be set", 45.55f == llpsysdata.mBurstRadius);
  57.219 -
  57.220 -		LLVector3 llvec(44.44f, 111.11f, -40.4f);
  57.221 -		llpsysdata.setPartAccel(llvec);
  57.222 -
  57.223 -		llpsysdata.mCRC = 0xFFFFFFFF;
  57.224 -		llpsysdata.mFlags = 0x20;
  57.225 -
  57.226 -		llpsysdata.mPattern = LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE_EMPTY;
  57.227 -
  57.228 -		llpsysdata.mMaxAge = 99.99f;
  57.229 -		llpsysdata.mStartAge = 18.5f;
  57.230 -		llpsysdata.mInnerAngle = 4.234f;
  57.231 -		llpsysdata.mOuterAngle = 7.123f;
  57.232 -		llpsysdata.mBurstRate  = 245.53f;
  57.233 -		llpsysdata.mBurstPartCount = 0xFF;
  57.234 -		llpsysdata.mAngularVelocity = llvec;
  57.235 -
  57.236 -		llpsysdata.mPartImageID.generate();
  57.237 -		llpsysdata.mTargetUUID.generate();
  57.238 -		
  57.239 -		LLDataPackerBinaryBuffer dp((U8*)pkbuf, 256);
  57.240 -		llpsysdata.pack(dp);
  57.241 -		S32 cur_size = dp.getCurrentSize();
  57.242 -		LLDataPackerBinaryBuffer dp1((U8*)pkbuf, cur_size);
  57.243 -		llpsysdata1.unpack(dp1);
  57.244 -
  57.245 -		ensure("1.mCRC's not equal", llpsysdata.mCRC == llpsysdata1.mCRC);
  57.246 -		ensure("2.mFlags's not equal", llpsysdata.mFlags == llpsysdata1.mFlags);
  57.247 -		ensure("3.mPattern's not equal", llpsysdata.mPattern == llpsysdata1.mPattern);
  57.248 -		ensure_approximately_equals("4.mMaxAge's not equal", llpsysdata.mMaxAge , llpsysdata1.mMaxAge, 8);
  57.249 -		ensure_approximately_equals("5.mStartAge's not equal", llpsysdata.mStartAge, llpsysdata1.mStartAge, 8);
  57.250 -		ensure_approximately_equals("6.mOuterAngle's not equal", llpsysdata.mOuterAngle, llpsysdata1.mOuterAngle, 5);
  57.251 -		ensure_approximately_equals("7.mInnerAngles's not equal", llpsysdata.mInnerAngle, llpsysdata1.mInnerAngle, 5);
  57.252 -		ensure_approximately_equals("8.mBurstRate's not equal", llpsysdata.mBurstRate, llpsysdata1.mBurstRate, 8);
  57.253 -		ensure("9.mBurstPartCount's not equal", llpsysdata.mBurstPartCount == llpsysdata1.mBurstPartCount);
  57.254 -
  57.255 -		ensure_approximately_equals("10.mBurstSpeedMin's not equal", llpsysdata.mBurstSpeedMin, llpsysdata1.mBurstSpeedMin, 8);
  57.256 -		ensure_approximately_equals("11.mBurstSpeedMax's not equal", llpsysdata.mBurstSpeedMax, llpsysdata1.mBurstSpeedMax, 8);
  57.257 -
  57.258 -		ensure_approximately_equals("12.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[0], llpsysdata1.mAngularVelocity.mV[0], 7);
  57.259 -		ensure_approximately_equals("13.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[1], llpsysdata1.mAngularVelocity.mV[1], 7);
  57.260 -		ensure_approximately_equals("14.mAngularVelocity's not equal", llpsysdata.mAngularVelocity.mV[2], llpsysdata1.mAngularVelocity.mV[2], 7);
  57.261 -			
  57.262 -		ensure_approximately_equals("15.mPartAccel's not equal", llpsysdata.mPartAccel.mV[0], llpsysdata1.mPartAccel.mV[0], 7);
  57.263 -		ensure_approximately_equals("16.mPartAccel's not equal", llpsysdata.mPartAccel.mV[1], llpsysdata1.mPartAccel.mV[1], 7);
  57.264 -		ensure_approximately_equals("17.mPartAccel's not equal", llpsysdata.mPartAccel.mV[2], llpsysdata1.mPartAccel.mV[2], 7);
  57.265 -
  57.266 -		ensure("18.mPartImageID's not equal", llpsysdata.mPartImageID == llpsysdata1.mPartImageID);
  57.267 -		ensure("19.mTargetUUID's not equal", llpsysdata.mTargetUUID == llpsysdata1.mTargetUUID);
  57.268 -		ensure_approximately_equals("20.mBurstRadius's not equal", llpsysdata.mBurstRadius, llpsysdata1.mBurstRadius, 8);
  57.269 +		//mStartGlow	0.00000000	float
  57.270 +		ensure_approximately_equals("mPartData.mStartGlow different after unpacking", data.mStartGlow, 0.f, 8);
  57.271 +		//mEndGlow	0.00000000	float
  57.272 +		ensure_approximately_equals("mPartData.mEndGlow different after unpacking", data.mEndGlow, 0.f, 8);
  57.273 +		//mBlendFuncSource	2 ''	unsigned char
  57.274 +		ensure("mPartData.mBlendFuncSource different after unpacking", data.mBlendFuncSource == (U8) 2);
  57.275 +		//mBlendFuncDest	1 ''	unsigned char 
  57.276 +		ensure("mPartData.mBlendFuncDest different after unpacking", data.mBlendFuncDest == (U8) 1);
  57.277  	}
  57.278  }
    58.1 --- a/indra/llplugin/slplugin/CMakeLists.txt	Fri Sep 27 17:22:31 2013 -0400
    58.2 +++ b/indra/llplugin/slplugin/CMakeLists.txt	Fri Oct 04 15:36:52 2013 -0400
    58.3 @@ -50,10 +50,17 @@
    58.4      ${SLPlugin_SOURCE_FILES}
    58.5  )
    58.6  
    58.7 +if (WINDOWS)
    58.8 +set_target_properties(SLPlugin
    58.9 +  PROPERTIES
   58.10 +  LINK_FLAGS_DEBUG "/NODEFAULTLIB:\"LIBCMTD\""
   58.11 +  )
   58.12 +else ()
   58.13  set_target_properties(SLPlugin
   58.14    PROPERTIES
   58.15    MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/slplugin_info.plist
   58.16    )
   58.17 +endif ()
   58.18  
   58.19  target_link_libraries(SLPlugin
   58.20    ${LLPLUGIN_LIBRARIES}
    59.1 --- a/indra/llprimitive/llmodel.cpp	Fri Sep 27 17:22:31 2013 -0400
    59.2 +++ b/indra/llprimitive/llmodel.cpp	Fri Oct 04 15:36:52 2013 -0400
    59.3 @@ -166,6 +166,7 @@
    59.4  
    59.5  	if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source )
    59.6  	{
    59.7 +		llwarns << "Could not find dom sources for basic geo data; invalid model." << llendl;
    59.8  		return LLModel::BAD_ELEMENT;
    59.9  	}
   59.10  
   59.11 @@ -186,27 +187,78 @@
   59.12  	
   59.13  	LLVolumeFace::VertexMapData::PointMap point_map;
   59.14  	
   59.15 -	for (U32 i = 0; i < idx.getCount(); i += idx_stride)
   59.16 +	U32 index_count  = idx.getCount();
   59.17 +	U32 vertex_count = pos_source  ? v.getCount()  : 0;
   59.18 +	U32 tc_count     = tc_source   ? tc.getCount() : 0;
   59.19 +	U32 norm_count   = norm_source ? n.getCount()  : 0;
   59.20 +
   59.21 +	for (U32 i = 0; i < index_count; i += idx_stride)
   59.22  	{
   59.23  		LLVolumeFace::VertexData cv;
   59.24  		if (pos_source)
   59.25  		{
   59.26 +			// guard against model data specifiying out of range indices or verts
   59.27 +			//
   59.28 +			if (((i + pos_offset) > index_count)
   59.29 +			 || ((idx[i+pos_offset]*3+2) > vertex_count))
   59.30 +			{
   59.31 +				llwarns << "Out of range index data; invalid model." << llendl;
   59.32 +				return LLModel::BAD_ELEMENT;
   59.33 +			}
   59.34 +
   59.35  			cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0],
   59.36  								v[idx[i+pos_offset]*3+1],
   59.37  								v[idx[i+pos_offset]*3+2]));
   59.38 +
   59.39 +			if (!cv.getPosition().isFinite3())
   59.40 +			{
   59.41 +				llwarns << "Nan positional data, invalid model." << llendl;
   59.42 +				return LLModel::BAD_ELEMENT;
   59.43 +			}
   59.44  		}
   59.45  
   59.46  		if (tc_source)
   59.47  		{
   59.48 +			// guard against model data specifiying out of range indices or tcs
   59.49 +			//
   59.50 +			
   59.51 +			if (((i + tc_offset) > index_count)
   59.52 +			 || ((idx[i+tc_offset]*2+1) > tc_count))
   59.53 +			{
   59.54 +				llwarns << "Out of range TC indices." << llendl;
   59.55 +				return LLModel::BAD_ELEMENT;
   59.56 +			}
   59.57 +
   59.58  			cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0],
   59.59  								tc[idx[i+tc_offset]*2+1]);
   59.60 +
   59.61 +			if (!cv.mTexCoord.isFinite())
   59.62 +			{
   59.63 +				llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
   59.64 +				return LLModel::BAD_ELEMENT;
   59.65 +			}
   59.66  		}
   59.67  		
   59.68  		if (norm_source)
   59.69  		{
   59.70 +			// guard against model data specifiying out of range indices or norms
   59.71 +			//
   59.72 +			if (((i + norm_offset) > index_count)
   59.73 +				|| ((idx[i+norm_offset]*3+2) > norm_count))
   59.74 +			{
   59.75 +				llwarns << "Found out of range norm indices, invalid model." << llendl;
   59.76 +				return LLModel::BAD_ELEMENT;
   59.77 +			}
   59.78 +
   59.79  			cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0],
   59.80  								n[idx[i+norm_offset]*3+1],
   59.81  								n[idx[i+norm_offset]*3+2]));
   59.82 +
   59.83 +			if (!cv.getNormal().isFinite3())
   59.84 +			{
   59.85 +				llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
   59.86 +				return LLModel::BAD_ELEMENT;
   59.87 +			}
   59.88  		}
   59.89  		
   59.90  		BOOL found = FALSE;
   59.91 @@ -261,13 +313,13 @@
   59.92  			LLVolumeFace& new_face = *face_list.rbegin();
   59.93  			if (!norm_source)
   59.94  			{
   59.95 -				ll_aligned_free_16(new_face.mNormals);
   59.96 +				//ll_aligned_free_16(new_face.mNormals);
   59.97  				new_face.mNormals = NULL;
   59.98  			}
   59.99  
  59.100  			if (!tc_source)
  59.101  			{
  59.102 -				ll_aligned_free_16(new_face.mTexCoords);
  59.103 +				//ll_aligned_free_16(new_face.mTexCoords);
  59.104  				new_face.mTexCoords = NULL;
  59.105  			}
  59.106  
  59.107 @@ -292,13 +344,13 @@
  59.108  		LLVolumeFace& new_face = *face_list.rbegin();
  59.109  		if (!norm_source)
  59.110  		{
  59.111 -			ll_aligned_free_16(new_face.mNormals);
  59.112 +			//ll_aligned_free_16(new_face.mNormals);
  59.113  			new_face.mNormals = NULL;
  59.114  		}
  59.115  
  59.116  		if (!tc_source)
  59.117  		{
  59.118 -			ll_aligned_free_16(new_face.mTexCoords);
  59.119 +			//ll_aligned_free_16(new_face.mTexCoords);
  59.120  			new_face.mTexCoords = NULL;
  59.121  		}
  59.122  	}
  59.123 @@ -333,6 +385,7 @@
  59.124  
  59.125  	if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source))
  59.126  	{
  59.127 +		llwarns << "Could not get DOM sources for basic geo data, invalid model." << llendl;
  59.128  		return LLModel::BAD_ELEMENT;
  59.129  	}
  59.130  
  59.131 @@ -364,6 +417,11 @@
  59.132  	
  59.133  	LLVolumeFace::VertexMapData::PointMap point_map;
  59.134  
  59.135 +	U32 index_count  = idx.getCount();
  59.136 +	U32 vertex_count = pos_source  ? v.getCount()  : 0;
  59.137 +	U32 tc_count     = tc_source   ? tc.getCount() : 0;
  59.138 +	U32 norm_count   = norm_source ? n.getCount()  : 0;
  59.139 +
  59.140  	U32 cur_idx = 0;
  59.141  	for (U32 i = 0; i < vcount.getCount(); ++i)
  59.142  	{ //for each polygon
  59.143 @@ -376,22 +434,68 @@
  59.144  
  59.145  			if (pos_source)
  59.146  			{
  59.147 +				// guard against model data specifiying out of range indices or verts
  59.148 +				//
  59.149 +				if (((cur_idx + pos_offset) > index_count)
  59.150 +				 || ((idx[cur_idx+pos_offset]*3+2) > vertex_count))
  59.151 +				{
  59.152 +					llwarns << "Out of range position indices, invalid model." << llendl;
  59.153 +					return LLModel::BAD_ELEMENT;
  59.154 +				}
  59.155 +
  59.156  				cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0],
  59.157  									v[idx[cur_idx+pos_offset]*3+1],
  59.158  									v[idx[cur_idx+pos_offset]*3+2]);
  59.159 +
  59.160 +				if (!cv.getPosition().isFinite3())
  59.161 +				{
  59.162 +					llwarns << "Found NaN while loading positions from DAE-Model, invalid model." << llendl;
  59.163 +					return LLModel::BAD_ELEMENT;
  59.164 +				}
  59.165 +
  59.166  			}
  59.167  
  59.168  			if (tc_source)
  59.169  			{
  59.170 +				// guard against model data specifiying out of range indices or tcs
  59.171 +				//
  59.172 +				if (((cur_idx + tc_offset) > index_count)
  59.173 +				 || ((idx[cur_idx+tc_offset]*2+1) > tc_count))
  59.174 +				{
  59.175 +					llwarns << "Out of range TC indices, invalid model." << llendl;
  59.176 +					return LLModel::BAD_ELEMENT;
  59.177 +				}
  59.178 +
  59.179  				cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0],
  59.180  									tc[idx[cur_idx+tc_offset]*2+1]);
  59.181 +
  59.182 +				if (!cv.mTexCoord.isFinite())
  59.183 +				{
  59.184 +					llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
  59.185 +					return LLModel::BAD_ELEMENT;
  59.186 +				}
  59.187  			}
  59.188  			
  59.189  			if (norm_source)
  59.190  			{
  59.191 +				// guard against model data specifiying out of range indices or norms
  59.192 +				//
  59.193 +				if (((cur_idx + norm_offset) > index_count)
  59.194 +				 || ((idx[cur_idx+norm_offset]*3+2) > norm_count))
  59.195 +				{
  59.196 +					llwarns << "Out of range norm indices, invalid model." << llendl;
  59.197 +					return LLModel::BAD_ELEMENT;
  59.198 +				}
  59.199 +
  59.200  				cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0],
  59.201  									n[idx[cur_idx+norm_offset]*3+1],
  59.202  									n[idx[cur_idx+norm_offset]*3+2]);
  59.203 +
  59.204 +				if (!cv.getNormal().isFinite3())
  59.205 +				{
  59.206 +					llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
  59.207 +					return LLModel::BAD_ELEMENT;
  59.208 +				}
  59.209  			}
  59.210  			
  59.211  			cur_idx += idx_stride;
  59.212 @@ -480,13 +584,13 @@
  59.213  				LLVolumeFace& new_face = *face_list.rbegin();
  59.214  				if (!norm_source)
  59.215  				{
  59.216 -					ll_aligned_free_16(new_face.mNormals);
  59.217 +					//ll_aligned_free_16(new_face.mNormals);
  59.218  					new_face.mNormals = NULL;
  59.219  				}
  59.220  
  59.221  				if (!tc_source)
  59.222  				{
  59.223 -					ll_aligned_free_16(new_face.mTexCoords);
  59.224 +					//ll_aligned_free_16(new_face.mTexCoords);
  59.225  					new_face.mTexCoords = NULL;
  59.226  				}
  59.227  
  59.228 @@ -514,13 +618,13 @@
  59.229  		LLVolumeFace& new_face = *face_list.rbegin();
  59.230  		if (!norm_source)
  59.231  		{
  59.232 -			ll_aligned_free_16(new_face.mNormals);
  59.233 +			//ll_aligned_free_16(new_face.mNormals);
  59.234  			new_face.mNormals = NULL;
  59.235  		}
  59.236  
  59.237  		if (!tc_source)
  59.238  		{
  59.239 -			ll_aligned_free_16(new_face.mTexCoords);
  59.240 +			//ll_aligned_free_16(new_face.mTexCoords);
  59.241  			new_face.mTexCoords = NULL;
  59.242  		}
  59.243  	}
  59.244 @@ -558,6 +662,7 @@
  59.245  			domVertices* vertices = (domVertices*) elem.cast();
  59.246  			if (!vertices)
  59.247  			{
  59.248 +				llwarns << "Could not find vertex source, invalid model." << llendl;
  59.249  				return LLModel::BAD_ELEMENT;
  59.250  			}
  59.251  			domInputLocal_Array& v_inp = vertices->getInput_array();
  59.252 @@ -571,6 +676,7 @@
  59.253  					domSource* src = (domSource*) elem.cast();
  59.254  					if (!src)
  59.255  					{
  59.256 +						llwarns << "Could not find DOM source, invalid model." << llendl;
  59.257  						return LLModel::BAD_ELEMENT;
  59.258  					}
  59.259  					v = &(src->getFloat_array()->getValue());
  59.260 @@ -586,6 +692,7 @@
  59.261  			domSource* src = (domSource*) elem.cast();
  59.262  			if (!src)
  59.263  			{
  59.264 +				llwarns << "Could not find DOM source, invalid model." << llendl;
  59.265  				return LLModel::BAD_ELEMENT;
  59.266  			}
  59.267  			n = &(src->getFloat_array()->getValue());
  59.268 @@ -598,6 +705,7 @@
  59.269  			domSource* src = (domSource*) elem.cast();
  59.270  			if (!src)
  59.271  			{
  59.272 +				llwarns << "Could not find DOM source, invalid model." << llendl;
  59.273  				return LLModel::BAD_ELEMENT;
  59.274  			}
  59.275  			t = &(src->getFloat_array()->getValue());
  59.276 @@ -632,6 +740,12 @@
  59.277  				vert.getPosition().set(v->get(v_idx),
  59.278  								v->get(v_idx+1),
  59.279  								v->get(v_idx+2));
  59.280 +
  59.281 +				if (!vert.getPosition().isFinite3())
  59.282 +				{
  59.283 +					llwarns << "Found NaN while loading position data from DAE-Model, invalid model." << llendl;
  59.284 +					return LLModel::BAD_ELEMENT;
  59.285 +				}
  59.286  			}
  59.287  			
  59.288  			//bounds check n and t lookups because some FBX to DAE converters
  59.289 @@ -644,6 +758,12 @@
  59.290  				vert.getNormal().set(n->get(n_idx),
  59.291  								n->get(n_idx+1),
  59.292  								n->get(n_idx+2));
  59.293 +
  59.294 +				if (!vert.getNormal().isFinite3())
  59.295 +				{
  59.296 +					llwarns << "Found NaN while loading normals from DAE-Model, invalid model." << llendl;
  59.297 +					return LLModel::BAD_ELEMENT;
  59.298 +				}
  59.299  			}
  59.300  			else
  59.301  			{
  59.302 @@ -657,6 +777,12 @@
  59.303  				t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount());
  59.304  				vert.mTexCoord.setVec(t->get(t_idx),
  59.305  								t->get(t_idx+1));								
  59.306 +
  59.307 +				if (!vert.mTexCoord.isFinite())
  59.308 +				{
  59.309 +					llwarns << "Found NaN while loading tex coords from DAE-Model, invalid model." << llendl;
  59.310 +					return LLModel::BAD_ELEMENT;
  59.311 +				}
  59.312  			}
  59.313  			else
  59.314  			{
  59.315 @@ -730,13 +856,13 @@
  59.316  		LLVolumeFace& new_face = *face_list.rbegin();
  59.317  		if (!n)
  59.318  		{
  59.319 -			ll_aligned_free_16(new_face.mNormals);
  59.320 +			//ll_aligned_free_16(new_face.mNormals);
  59.321  			new_face.mNormals = NULL;
  59.322  		}
  59.323  
  59.324  		if (!t)
  59.325  		{
  59.326 -			ll_aligned_free_16(new_face.mTexCoords);
  59.327 +			//ll_aligned_free_16(new_face.mTexCoords);
  59.328  			new_face.mTexCoords = NULL;
  59.329  		}
  59.330  	}
  59.331 @@ -1010,6 +1136,43 @@
  59.332  	translation_out = mNormalizedTranslation;
  59.333  }
  59.334  
  59.335 +LLVector3 LLModel::getTransformedCenter(const LLMatrix4& mat)
  59.336 +{
  59.337 +	LLVector3 ret;
  59.338 +
  59.339 +	if (!mVolumeFaces.empty())
  59.340 +	{
  59.341 +		LLMatrix4a m;
  59.342 +		m.loadu(mat);
  59.343 +
  59.344 +		LLVector4a minv,maxv;
  59.345 +
  59.346 +		LLVector4a t;
  59.347 +		m.affineTransform(mVolumeFaces[0].mPositions[0], t);
  59.348 +		minv = maxv = t;
  59.349 +
  59.350 +		for (S32 i = 0; i < mVolumeFaces.size(); ++i)
  59.351 +		{
  59.352 +			LLVolumeFace& face = mVolumeFaces[i];
  59.353 +
  59.354 +			for (U32 j = 0; j < face.mNumVertices; ++j)
  59.355 +			{
  59.356 +				m.affineTransform(face.mPositions[j],t);
  59.357 +				update_min_max(minv, maxv, t);
  59.358 +			}
  59.359 +		}
  59.360 +
  59.361 +		minv.add(maxv);
  59.362 +		minv.mul(0.5f);
  59.363 +
  59.364 +		ret.set(minv.getF32ptr());
  59.365 +	}
  59.366 +
  59.367 +	return ret;
  59.368 +}
  59.369 +
  59.370 +
  59.371 +
  59.372  void LLModel::setNumVolumeFaces(S32 count)
  59.373  {
  59.374  	mVolumeFaces.resize(count);
  59.375 @@ -1036,7 +1199,7 @@
  59.376  	}
  59.377  	else
  59.378  	{
  59.379 -		ll_aligned_free_16(face.mNormals);
  59.380 +		//ll_aligned_free_16(face.mNormals);
  59.381  		face.mNormals = NULL;
  59.382  	}
  59.383  
  59.384 @@ -1047,7 +1210,7 @@
  59.385  	}
  59.386  	else
  59.387  	{
  59.388 -		ll_aligned_free_16(face.mTexCoords);
  59.389 +		//ll_aligned_free_16(face.mTexCoords);
  59.390  		face.mTexCoords = NULL;
  59.391  	}
  59.392  
  59.393 @@ -1246,7 +1409,7 @@
  59.394  		}
  59.395  		else
  59.396  		{
  59.397 -			ll_aligned_free_16(new_face.mTexCoords);
  59.398 +			//ll_aligned_free_16(new_face.mTexCoords);
  59.399  			new_face.mTexCoords = NULL;
  59.400  		}
  59.401  
    60.1 --- a/indra/llprimitive/llmodel.h	Fri Sep 27 17:22:31 2013 -0400
    60.2 +++ b/indra/llprimitive/llmodel.h	Fri Oct 04 15:36:52 2013 -0400
    60.3 @@ -173,13 +173,15 @@
    60.4  	void optimizeVolumeFaces();
    60.5  	void offsetMesh( const LLVector3& pivotPoint );
    60.6  	void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out);
    60.7 -	
    60.8 +	LLVector3 getTransformedCenter(const LLMatrix4& mat);
    60.9 +
   60.10  	//reorder face list based on mMaterialList in this and reference so 
   60.11  	//order matches that of reference (material ordering touchup)
   60.12  	bool matchMaterialOrder(LLModel* ref, int& refFaceCnt, int& modelFaceCnt );
   60.13  	bool isMaterialListSubset( LLModel* ref );
   60.14  	bool needToAddFaces( LLModel* ref, int& refFaceCnt, int& modelFaceCnt );
   60.15  	
   60.16 +	
   60.17  	std::vector<std::string> mMaterialList;
   60.18  
   60.19  	//data used for skin weights
    61.1 --- a/indra/llrender/llgl.cpp	Fri Sep 27 17:22:31 2013 -0400
    61.2 +++ b/indra/llrender/llgl.cpp	Fri Oct 04 15:36:52 2013 -0400
    61.3 @@ -59,6 +59,7 @@
    61.4  BOOL gClothRipple = FALSE;
    61.5  BOOL gHeadlessClient = FALSE;
    61.6  BOOL gGLActive = FALSE;
    61.7 +BOOL gGLDebugLoggingEnabled = TRUE;
    61.8  
    61.9  static const std::string HEADLESS_VENDOR_STRING("Linden Lab");
   61.10  static const std::string HEADLESS_RENDERER_STRING("Headless");
   61.11 @@ -80,6 +81,8 @@
   61.12                                  const GLchar* message,
   61.13                                  GLvoid* userParam)
   61.14  {
   61.15 +	if (gGLDebugLoggingEnabled)
   61.16 +	{
   61.17  	if (severity == GL_DEBUG_SEVERITY_HIGH_ARB)
   61.18  	{
   61.19  		llwarns << "----- GL ERROR --------" << llendl;
   61.20 @@ -98,6 +101,7 @@
   61.21  		llerrs << "Halting on GL Error" << llendl;
   61.22  	}
   61.23  }
   61.24 +}
   61.25  #endif
   61.26  
   61.27  void parse_glsl_version(S32& major, S32& minor);
   61.28 @@ -258,6 +262,7 @@
   61.29  PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback = NULL;
   61.30  PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings = NULL;
   61.31  PFNGLBINDBUFFERRANGEPROC glBindBufferRange = NULL;
   61.32 +PFNGLBINDBUFFERBASEPROC glBindBufferBase = NULL;
   61.33  
   61.34  //GL_ARB_debug_output
   61.35  PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB = NULL;
   61.36 @@ -1156,7 +1161,7 @@
   61.37  	glGetIntegerv(GL_MAX_ELEMENTS_VERTICES, (GLint*) &mGLMaxVertexRange);
   61.38  	glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange);
   61.39  	glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*) &mGLMaxTextureSize);
   61.40 -	
   61.41 +
   61.42  #if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS
   61.43  	LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL;
   61.44  	if (mHasVertexBufferObject)
   61.45 @@ -1247,6 +1252,7 @@
   61.46  		glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) GLH_EXT_GET_PROC_ADDRESS("glEndTransformFeedback");
   61.47  		glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) GLH_EXT_GET_PROC_ADDRESS("glTransformFeedbackVaryings");
   61.48  		glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferRange");
   61.49 +		glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) GLH_EXT_GET_PROC_ADDRESS("glBindBufferBase");
   61.50  	}
   61.51  	if (mHasDebugOutput)
   61.52  	{
   61.53 @@ -1501,7 +1507,7 @@
   61.54  
   61.55  void assert_glerror()
   61.56  {
   61.57 -	if (!gGLActive)
   61.58 +/*	if (!gGLActive)
   61.59  	{
   61.60  		//llwarns << "GL used while not active!" << llendl;
   61.61  
   61.62 @@ -1510,8 +1516,13 @@
   61.63  			//ll_fail("GL used while not active");
   61.64  		}
   61.65  	}
   61.66 +*/
   61.67  
   61.68 -	if (gDebugGL) 
   61.69 +	if (!gDebugGL) 
   61.70 +	{
   61.71 +		//funny looking if for branch prediction -- gDebugGL is almost always false and assert_glerror is called often
   61.72 +	}
   61.73 +	else
   61.74  	{
   61.75  		do_assert_glerror();
   61.76  	}
    62.1 --- a/indra/llrender/llglheaders.h	Fri Sep 27 17:22:31 2013 -0400
    62.2 +++ b/indra/llrender/llglheaders.h	Fri Oct 04 15:36:52 2013 -0400
    62.3 @@ -543,6 +543,7 @@
    62.4  extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
    62.5  extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
    62.6  extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
    62.7 +extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
    62.8  
    62.9  
   62.10  #elif LL_WINDOWS
   62.11 @@ -787,6 +788,7 @@
   62.12  extern PFNGLENDTRANSFORMFEEDBACKPROC glEndTransformFeedback;
   62.13  extern PFNGLTRANSFORMFEEDBACKVARYINGSPROC glTransformFeedbackVaryings;
   62.14  extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange;
   62.15 +extern PFNGLBINDBUFFERBASEPROC glBindBufferBase;
   62.16  
   62.17  //GL_ARB_debug_output
   62.18  extern PFNGLDEBUGMESSAGECONTROLARBPROC glDebugMessageControlARB;
    63.1 --- a/indra/llrender/llglslshader.cpp	Fri Sep 27 17:22:31 2013 -0400
    63.2 +++ b/indra/llrender/llglslshader.cpp	Fri Oct 04 15:36:52 2013 -0400
    63.3 @@ -355,8 +355,8 @@
    63.4  	stop_glerror();
    63.5  }
    63.6  
    63.7 -BOOL LLGLSLShader::createShader(vector<string> * attributes,
    63.8 -								vector<string> * uniforms,
    63.9 +BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
   63.10 +								std::vector<LLStaticHashedString> * uniforms,
   63.11  								U32 varying_count,
   63.12  								const char** varyings)
   63.13  {
   63.14 @@ -374,7 +374,7 @@
   63.15  
   63.16  	// Create program
   63.17  	mProgramObject = glCreateProgramObjectARB();
   63.18 -
   63.19 +	
   63.20  #if LL_DARWIN
   63.21      // work-around missing mix(vec3,vec3,bvec3)
   63.22      mDefines["OLD_SELECT"] = "1";
   63.23 @@ -443,7 +443,8 @@
   63.24  
   63.25  		for (S32 i = 0; i < channel_count; i++)
   63.26  		{
   63.27 -			uniform1i(llformat("tex%d", i), i);
   63.28 +			LLStaticHashedString uniName(llformat("tex%d", i));
   63.29 +			uniform1i(uniName, i);
   63.30  		}
   63.31  
   63.32  		S32 cur_tex = channel_count; //adjust any texture channels that might have been overwritten
   63.33 @@ -500,7 +501,7 @@
   63.34  	}
   63.35  }
   63.36  
   63.37 -BOOL LLGLSLShader::mapAttributes(const vector<string> * attributes)
   63.38 +BOOL LLGLSLShader::mapAttributes(const std::vector<LLStaticHashedString> * attributes)
   63.39  {
   63.40  	//before linking, make sure reserved attributes always have consistent locations
   63.41  	for (U32 i = 0; i < LLShaderMgr::instance()->mReservedAttribs.size(); i++)
   63.42 @@ -537,7 +538,7 @@
   63.43  		{
   63.44  			for (U32 i = 0; i < numAttributes; i++)
   63.45  			{
   63.46 -				const char* name = (*attributes)[i].c_str();
   63.47 +				const char* name = (*attributes)[i].String().c_str();
   63.48  				S32 index = glGetAttribLocationARB(mProgramObject, name);
   63.49  				if (index != -1)
   63.50  				{
   63.51 @@ -553,7 +554,7 @@
   63.52  	return FALSE;
   63.53  }
   63.54  
   63.55 -void LLGLSLShader::mapUniform(GLint index, const vector<string> * uniforms)
   63.56 +void LLGLSLShader::mapUniform(GLint index, const vector<LLStaticHashedString> * uniforms)
   63.57  {
   63.58  	if (index == -1)
   63.59  	{
   63.60 @@ -623,8 +624,10 @@
   63.61  			is_array[0] = 0;
   63.62  		}
   63.63  
   63.64 -		mUniformMap[name] = location;
   63.65 +		LLStaticHashedString hashedName(name);
   63.66  		mUniformNameMap[location] = name;
   63.67 +		mUniformMap[hashedName] = location;
   63.68 +
   63.69  		LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL;
   63.70  	
   63.71  		//find the index of this uniform
   63.72 @@ -645,7 +648,7 @@
   63.73  			for (U32 i = 0; i < uniforms->size(); i++)
   63.74  			{
   63.75  				if ( (mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] == -1)
   63.76 -					&& ((*uniforms)[i] == name))
   63.77 +					&& ((*uniforms)[i].String() == name))
   63.78  				{
   63.79  					//found it
   63.80  					mUniform[i+LLShaderMgr::instance()->mReservedUniforms.size()] = location;
   63.81 @@ -679,7 +682,7 @@
   63.82  	return -1;
   63.83  }
   63.84  
   63.85 -BOOL LLGLSLShader::mapUniforms(const vector<string> * uniforms)
   63.86 +BOOL LLGLSLShader::mapUniforms(const vector<LLStaticHashedString> * uniforms)
   63.87  {
   63.88  	BOOL res = TRUE;
   63.89  	
   63.90 @@ -1141,18 +1144,18 @@
   63.91  	}
   63.92  }
   63.93  
   63.94 -GLint LLGLSLShader::getUniformLocation(const string& uniform)
   63.95 +GLint LLGLSLShader::getUniformLocation(const LLStaticHashedString& uniform)
   63.96  {
   63.97  	GLint ret = -1;
   63.98  	if (mProgramObject > 0)
   63.99  	{
  63.100 -		std::map<string, GLint>::iterator iter = mUniformMap.find(uniform);
  63.101 +		LLStaticStringTable<GLint>::iterator iter = mUniformMap.find(uniform);
  63.102  		if (iter != mUniformMap.end())
  63.103  		{
  63.104  			if (gDebugGL)
  63.105  			{
  63.106  				stop_glerror();
  63.107 -				if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.c_str()))
  63.108 +				if (iter->second != glGetUniformLocationARB(mProgramObject, uniform.String().c_str()))
  63.109  				{
  63.110  					llerrs << "Uniform does not match." << llendl;
  63.111  				}
  63.112 @@ -1189,7 +1192,7 @@
  63.113  	}
  63.114  }
  63.115  
  63.116 -void LLGLSLShader::uniform1i(const string& uniform, GLint v)
  63.117 +void LLGLSLShader::uniform1i(const LLStaticHashedString& uniform, GLint v)
  63.118  {
  63.119  	GLint location = getUniformLocation(uniform);
  63.120  				
  63.121 @@ -1205,7 +1208,7 @@
  63.122  	}
  63.123  }
  63.124  
  63.125 -void LLGLSLShader::uniform2i(const string& uniform, GLint i, GLint j)
  63.126 +void LLGLSLShader::uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j)
  63.127  {
  63.128  	GLint location = getUniformLocation(uniform);
  63.129  				
  63.130 @@ -1222,7 +1225,7 @@
  63.131  }
  63.132  
  63.133  
  63.134 -void LLGLSLShader::uniform1f(const string& uniform, GLfloat v)
  63.135 +void LLGLSLShader::uniform1f(const LLStaticHashedString& uniform, GLfloat v)
  63.136  {
  63.137  	GLint location = getUniformLocation(uniform);
  63.138  				
  63.139 @@ -1238,7 +1241,7 @@
  63.140  	}
  63.141  }
  63.142  
  63.143 -void LLGLSLShader::uniform2f(const string& uniform, GLfloat x, GLfloat y)
  63.144 +void LLGLSLShader::uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y)
  63.145  {
  63.146  	GLint location = getUniformLocation(uniform);
  63.147  				
  63.148 @@ -1255,7 +1258,7 @@
  63.149  
  63.150  }
  63.151  
  63.152 -void LLGLSLShader::uniform3f(const string& uniform, GLfloat x, GLfloat y, GLfloat z)
  63.153 +void LLGLSLShader::uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z)
  63.154  {
  63.155  	GLint location = getUniformLocation(uniform);
  63.156  				
  63.157 @@ -1271,23 +1274,7 @@
  63.158  	}
  63.159  }
  63.160  
  63.161 -void LLGLSLShader::uniform4f(const string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  63.162 -{
  63.163 -	GLint location = getUniformLocation(uniform);
  63.164 -
  63.165 -	if (location >= 0)
  63.166 -	{
  63.167 -		std::map<GLint, LLVector4>::iterator iter = mValue.find(location);
  63.168 -		LLVector4 vec(x,y,z,w);
  63.169 -		if (iter == mValue.end() || shouldChange(iter->second,vec))
  63.170 -		{
  63.171 -			glUniform4fARB(location, x,y,z,w);
  63.172 -			mValue[location] = vec;
  63.173 -		}
  63.174 -	}
  63.175 -}
  63.176 -
  63.177 -void LLGLSLShader::uniform1fv(const string& uniform, U32 count, const GLfloat* v)
  63.178 +void LLGLSLShader::uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
  63.179  {
  63.180  	GLint location = getUniformLocation(uniform);
  63.181  
  63.182 @@ -1303,7 +1290,7 @@
  63.183  	}
  63.184  }
  63.185  
  63.186 -void LLGLSLShader::uniform2fv(const string& uniform, U32 count, const GLfloat* v)
  63.187 +void LLGLSLShader::uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
  63.188  {
  63.189  	GLint location = getUniformLocation(uniform);
  63.190  				
  63.191 @@ -1319,7 +1306,7 @@
  63.192  	}
  63.193  }
  63.194  
  63.195 -void LLGLSLShader::uniform3fv(const string& uniform, U32 count, const GLfloat* v)
  63.196 +void LLGLSLShader::uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
  63.197  {
  63.198  	GLint location = getUniformLocation(uniform);
  63.199  				
  63.200 @@ -1335,7 +1322,7 @@
  63.201  	}
  63.202  }
  63.203  
  63.204 -void LLGLSLShader::uniform4fv(const string& uniform, U32 count, const GLfloat* v)
  63.205 +void LLGLSLShader::uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v)
  63.206  {
  63.207  	GLint location = getUniformLocation(uniform);
  63.208  
  63.209 @@ -1353,27 +1340,7 @@
  63.210  	}
  63.211  }
  63.212  
  63.213 -void LLGLSLShader::uniformMatrix2fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
  63.214 -{
  63.215 -	GLint location = getUniformLocation(uniform);
  63.216 -				
  63.217 -	if (location >= 0)
  63.218 -	{
  63.219 -		glUniformMatrix2fvARB(location, count, transpose, v);
  63.220 -	}
  63.221 -}
  63.222 -
  63.223 -void LLGLSLShader::uniformMatrix3fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
  63.224 -{
  63.225 -	GLint location = getUniformLocation(uniform);
  63.226 -				
  63.227 -	if (location >= 0)
  63.228 -	{
  63.229 -		glUniformMatrix3fvARB(location, count, transpose, v);
  63.230 -	}
  63.231 -}
  63.232 -
  63.233 -void LLGLSLShader::uniformMatrix4fv(const string& uniform, U32 count, GLboolean transpose, const GLfloat* v)
  63.234 +void LLGLSLShader::uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat* v)
  63.235  {
  63.236  	GLint location = getUniformLocation(uniform);
  63.237  				
    64.1 --- a/indra/llrender/llglslshader.h	Fri Sep 27 17:22:31 2013 -0400
    64.2 +++ b/indra/llrender/llglslshader.h	Fri Oct 04 15:36:52 2013 -0400
    64.3 @@ -29,6 +29,7 @@
    64.4  
    64.5  #include "llgl.h"
    64.6  #include "llrender.h"
    64.7 +#include "llstaticstringtable.h"
    64.8  
    64.9  class LLShaderFeatures
   64.10  {
   64.11 @@ -90,16 +91,16 @@
   64.12  	void placeProfileQuery();
   64.13  	void readProfileQuery(U32 count, U32 mode);
   64.14  
   64.15 -	BOOL createShader(std::vector<std::string> * attributes,
   64.16 -						std::vector<std::string> * uniforms,
   64.17 +	BOOL createShader(std::vector<LLStaticHashedString> * attributes,
   64.18 +						std::vector<LLStaticHashedString> * uniforms,
   64.19  						U32 varying_count = 0,
   64.20  						const char** varyings = NULL);
   64.21  	BOOL attachObject(std::string object);
   64.22  	void attachObject(GLhandleARB object);
   64.23  	void attachObjects(GLhandleARB* objects = NULL, S32 count = 0);
   64.24 -	BOOL mapAttributes(const std::vector<std::string> * attributes);
   64.25 -	BOOL mapUniforms(const std::vector<std::string> * uniforms);
   64.26 -	void mapUniform(GLint index, const std::vector<std::string> * uniforms);
   64.27 +	BOOL mapAttributes(const std::vector<LLStaticHashedString> * attributes);
   64.28 +	BOOL mapUniforms(const std::vector<LLStaticHashedString> *);
   64.29 +	void mapUniform(GLint index, const std::vector<LLStaticHashedString> *);
   64.30  	void uniform1i(U32 index, GLint i);
   64.31  	void uniform1f(U32 index, GLfloat v);
   64.32  	void uniform2f(U32 index, GLfloat x, GLfloat y);
   64.33 @@ -110,30 +111,27 @@
   64.34  	void uniform2fv(U32 index, U32 count, const GLfloat* v);
   64.35  	void uniform3fv(U32 index, U32 count, const GLfloat* v);
   64.36  	void uniform4fv(U32 index, U32 count, const GLfloat* v);
   64.37 -	void uniform1i(const std::string& uniform, GLint i);
   64.38 -	void uniform2i(const std::string& uniform, GLint i, GLint j);
   64.39 -	void uniform1f(const std::string& uniform, GLfloat v);
   64.40 -	void uniform2f(const std::string& uniform, GLfloat x, GLfloat y);
   64.41 -	void uniform3f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z);
   64.42 -	void uniform4f(const std::string& uniform, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
   64.43 -	void uniform1iv(const std::string& uniform, U32 count, const GLint* i);
   64.44 -	void uniform1fv(const std::string& uniform, U32 count, const GLfloat* v);
   64.45 -	void uniform2fv(const std::string& uniform, U32 count, const GLfloat* v);
   64.46 -	void uniform3fv(const std::string& uniform, U32 count, const GLfloat* v);
   64.47 -	void uniform4fv(const std::string& uniform, U32 count, const GLfloat* v);
   64.48 +	void uniform2i(const LLStaticHashedString& uniform, GLint i, GLint j);
   64.49  	void uniformMatrix2fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
   64.50  	void uniformMatrix3fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
   64.51  	void uniformMatrix4fv(U32 index, U32 count, GLboolean transpose, const GLfloat *v);
   64.52 -	void uniformMatrix2fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
   64.53 -	void uniformMatrix3fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
   64.54 -	void uniformMatrix4fv(const std::string& uniform, U32 count, GLboolean transpose, const GLfloat *v);
   64.55 +	void uniform1i(const LLStaticHashedString& uniform, GLint i);
   64.56 +	void uniform1f(const LLStaticHashedString& uniform, GLfloat v);
   64.57 +	void uniform2f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y);
   64.58 +	void uniform3f(const LLStaticHashedString& uniform, GLfloat x, GLfloat y, GLfloat z);
   64.59 +	void uniform1fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
   64.60 +	void uniform2fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
   64.61 +	void uniform3fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
   64.62 +	void uniform4fv(const LLStaticHashedString& uniform, U32 count, const GLfloat* v);
   64.63 +	void uniformMatrix4fv(const LLStaticHashedString& uniform, U32 count, GLboolean transpose, const GLfloat *v);
   64.64  
   64.65  	void setMinimumAlpha(F32 minimum);
   64.66  
   64.67  	void vertexAttrib4f(U32 index, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
   64.68  	void vertexAttrib4fv(U32 index, GLfloat* v);
   64.69  	
   64.70 -	GLint getUniformLocation(const std::string& uniform);
   64.71 +	//GLint getUniformLocation(const std::string& uniform);
   64.72 +	GLint getUniformLocation(const LLStaticHashedString& uniform);	
   64.73  	GLint getUniformLocation(U32 index);
   64.74  
   64.75  	GLint getAttribLocation(U32 attrib);
   64.76 @@ -170,7 +168,7 @@
   64.77  	std::vector<GLint> mAttribute; //lookup table of attribute enum to attribute channel
   64.78  	U32 mAttributeMask;  //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask())
   64.79  	std::vector<GLint> mUniform;   //lookup table of uniform enum to uniform location
   64.80 -	std::map<std::string, GLint> mUniformMap;  //lookup map of uniform name to uniform location
   64.81 +	LLStaticStringTable<GLint> mUniformMap; //lookup map of uniform name to uniform location
   64.82  	std::map<GLint, std::string> mUniformNameMap; //lookup map of uniform location to uniform name
   64.83  	std::map<GLint, LLVector4> mValue; //lookup map of uniform location to last known value
   64.84  	std::vector<GLint> mTexture;
    65.1 --- a/indra/llrender/llimagegl.cpp	Fri Sep 27 17:22:31 2013 -0400
    65.2 +++ b/indra/llrender/llimagegl.cpp	Fri Oct 04 15:36:52 2013 -0400
    65.3 @@ -715,9 +715,9 @@
    65.4  
    65.5  					mMipLevels = wpo2(llmax(w, h));
    65.6  
    65.7 -					//use legacy mipmap generation mode
    65.8 +					//use legacy mipmap generation mode (note: making this condional can cause rendering issues)
    65.9  					glTexParameteri(mTarget, GL_GENERATE_MIPMAP, GL_TRUE);
   65.10 -					
   65.11 +
   65.12  					LLImageGL::setManualImage(mTarget, 0, mFormatInternal,
   65.13  								 w, h, 
   65.14  								 mFormatPrimary, mFormatType,
   65.15 @@ -1089,6 +1089,16 @@
   65.16  	LLFastTimer t(FTM_GENERATE_TEXTURES);
   65.17  	bool empty = true;
   65.18  
   65.19 +	if (LLRender::sGLCoreProfile)
   65.20 +	{
   65.21 +		switch (format)
   65.22 +		{
   65.23 +			case GL_LUMINANCE8: format = GL_RGB8; break;
   65.24 +			case GL_LUMINANCE8_ALPHA8:
   65.25 +			case GL_ALPHA8: format = GL_RGBA8; break;
   65.26 +		}
   65.27 +	}
   65.28 +
   65.29  	dead_texturelist_t::iterator iter = sDeadTextureList[type].find(format);
   65.30  	
   65.31  	if (iter != sDeadTextureList[type].end())
    66.1 --- a/indra/llrender/llpostprocess.cpp	Fri Sep 27 17:22:31 2013 -0400
    66.2 +++ b/indra/llrender/llpostprocess.cpp	Fri Oct 04 15:36:52 2013 -0400
    66.3 @@ -31,6 +31,21 @@
    66.4  #include "llsdserialize.h"
    66.5  #include "llrender.h"
    66.6  
    66.7 +static LLStaticHashedString sRenderTexture("RenderTexture");
    66.8 +static LLStaticHashedString sBrightness("brightness");
    66.9 +static LLStaticHashedString sContrast("contrast");
   66.10 +static LLStaticHashedString sContrastBase("contrastBase");
   66.11 +static LLStaticHashedString sSaturation("saturation");
   66.12 +static LLStaticHashedString sLumWeights("lumWeights");
   66.13 +static LLStaticHashedString sNoiseTexture("NoiseTexture");
   66.14 +static LLStaticHashedString sBrightMult("brightMult");
   66.15 +static LLStaticHashedString sNoiseStrength("noiseStrength");
   66.16 +static LLStaticHashedString sExtractLow("extractLow");
   66.17 +static LLStaticHashedString sExtractHigh("extractHigh");
   66.18 +static LLStaticHashedString sBloomStrength("bloomStrength");
   66.19 +static LLStaticHashedString sTexelSize("texelSize");
   66.20 +static LLStaticHashedString sBlurDirection("blurDirection");
   66.21 +static LLStaticHashedString sBlurWidth("blurWidth");
   66.22  
   66.23  LLPostProcess * gPostProcess = NULL;
   66.24  
   66.25 @@ -258,12 +273,12 @@
   66.26  void LLPostProcess::createColorFilterShader(void)
   66.27  {
   66.28  	/// Define uniform names
   66.29 -	colorFilterUniforms["RenderTexture"] = 0;
   66.30 -	colorFilterUniforms["brightness"] = 0;
   66.31 -	colorFilterUniforms["contrast"] = 0;
   66.32 -	colorFilterUniforms["contrastBase"] = 0;
   66.33 -	colorFilterUniforms["saturation"] = 0;
   66.34 -	colorFilterUniforms["lumWeights"] = 0;
   66.35 +	colorFilterUniforms[sRenderTexture] = 0;
   66.36 +	colorFilterUniforms[sBrightness] = 0;
   66.37 +	colorFilterUniforms[sContrast] = 0;
   66.38 +	colorFilterUniforms[sContrastBase] = 0;
   66.39 +	colorFilterUniforms[sSaturation] = 0;
   66.40 +	colorFilterUniforms[sLumWeights] = 0;
   66.41  }
   66.42  
   66.43  void LLPostProcess::applyNightVisionShader(void)
   66.44 @@ -307,11 +322,11 @@
   66.45  void LLPostProcess::createNightVisionShader(void)
   66.46  {
   66.47  	/// Define uniform names
   66.48 -	nightVisionUniforms["RenderTexture"] = 0;
   66.49 -	nightVisionUniforms["NoiseTexture"] = 0;
   66.50 -	nightVisionUniforms["brightMult"] = 0;	
   66.51 -	nightVisionUniforms["noiseStrength"] = 0;
   66.52 -	nightVisionUniforms["lumWeights"] = 0;	
   66.53 +	nightVisionUniforms[sRenderTexture] = 0;
   66.54 +	nightVisionUniforms[sNoiseTexture] = 0;
   66.55 +	nightVisionUniforms[sBrightMult] = 0;	
   66.56 +	nightVisionUniforms[sNoiseStrength] = 0;
   66.57 +	nightVisionUniforms[sLumWeights] = 0;	
   66.58  
   66.59  	createNoiseTexture(mNoiseTexture);
   66.60  }
   66.61 @@ -326,25 +341,25 @@
   66.62  	createTexture(mTempBloomTexture, unsigned(screenW * 0.5), unsigned(screenH * 0.5));
   66.63  
   66.64  	/// Create Bloom Extract Shader
   66.65 -	bloomExtractUniforms["RenderTexture"] = 0;
   66.66 -	bloomExtractUniforms["extractLow"] = 0;
   66.67 -	bloomExtractUniforms["extractHigh"] = 0;	
   66.68 -	bloomExtractUniforms["lumWeights"] = 0;	
   66.69 +	bloomExtractUniforms[sRenderTexture] = 0;
   66.70 +	bloomExtractUniforms[sExtractLow] = 0;
   66.71 +	bloomExtractUniforms[sExtractHigh] = 0;	
   66.72 +	bloomExtractUniforms[sLumWeights] = 0;	
   66.73  	
   66.74  	/// Create Bloom Blur Shader
   66.75 -	bloomBlurUniforms["RenderTexture"] = 0;
   66.76 -	bloomBlurUniforms["bloomStrength"] = 0;	
   66.77 -	bloomBlurUniforms["texelSize"] = 0;
   66.78 -	bloomBlurUniforms["blurDirection"] = 0;
   66.79 -	bloomBlurUniforms["blurWidth"] = 0;
   66.80 +	bloomBlurUniforms[sRenderTexture] = 0;
   66.81 +	bloomBlurUniforms[sBloomStrength] = 0;	
   66.82 +	bloomBlurUniforms[sTexelSize] = 0;
   66.83 +	bloomBlurUniforms[sBlurDirection] = 0;
   66.84 +	bloomBlurUniforms[sBlurWidth] = 0;
   66.85  }
   66.86  
   66.87  void LLPostProcess::getShaderUniforms(glslUniforms & uniforms, GLhandleARB & prog)
   66.88  {
   66.89  	/// Find uniform locations and insert into map	
   66.90 -	std::map<const char *, GLuint>::iterator i;
   66.91 +	glslUniforms::iterator i;
   66.92  	for (i  = uniforms.begin(); i != uniforms.end(); ++i){
   66.93 -		i->second = glGetUniformLocationARB(prog, i->first);
   66.94 +		i->second = glGetUniformLocationARB(prog, i->first.String().c_str());
   66.95  	}
   66.96  }
   66.97  
    67.1 --- a/indra/llrender/llpostprocess.h	Fri Sep 27 17:22:31 2013 -0400
    67.2 +++ b/indra/llrender/llpostprocess.h	Fri Oct 04 15:36:52 2013 -0400
    67.3 @@ -31,6 +31,7 @@
    67.4  #include <fstream>
    67.5  #include "llgl.h"
    67.6  #include "llglheaders.h"
    67.7 +#include "llstaticstringtable.h"
    67.8  
    67.9  class LLPostProcess 
   67.10  {
   67.11 @@ -44,7 +45,7 @@
   67.12  	} QuadType;
   67.13  
   67.14  	/// GLSL Shader Encapsulation Struct
   67.15 -	typedef std::map<const char *, GLuint> glslUniforms;
   67.16 +	typedef LLStaticStringTable<GLuint> glslUniforms;
   67.17  
   67.18  	struct PostProcessTweaks : public LLSD {
   67.19  		inline PostProcessTweaks() : LLSD(LLSD::emptyMap())
    68.1 --- a/indra/llrender/llrender.cpp	Fri Sep 27 17:22:31 2013 -0400
    68.2 +++ b/indra/llrender/llrender.cpp	Fri Oct 04 15:36:52 2013 -0400
    68.3 @@ -225,26 +225,15 @@
    68.4  bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind)
    68.5  {
    68.6  	stop_glerror();
    68.7 -	if (mIndex < 0) return false;
    68.8 -
    68.9 +	if (mIndex >= 0)
   68.10 +	{
   68.11  	gGL.flush();
   68.12  
   68.13  	LLImageGL* gl_tex = NULL ;
   68.14 -	if (texture == NULL || !(gl_tex = texture->getGLTexture()))
   68.15 +		if (texture != NULL && (gl_tex = texture->getGLTexture()))
   68.16  	{
   68.17 -		llwarns << "NULL LLTexUnit::bind texture" << llendl;
   68.18 -		return false;
   68.19 -	}
   68.20 -
   68.21 -	if (!gl_tex->getTexName()) //if texture does not exist
   68.22 +			if (gl_tex->getTexName()) //if texture exists
   68.23  	{
   68.24 -		//if deleted, will re-generate it immediately
   68.25 -		texture->forceImmediateUpdate() ;
   68.26 -
   68.27 -		gl_tex->forceUpdateBindStats() ;
   68.28 -		return texture->bindDefaultImage(mIndex);
   68.29 -	}
   68.30 -
   68.31  	//in audit, replace the selected texture by the default one.
   68.32  	if ((mCurrTexture != gl_tex->getTexName()) || forceBind)
   68.33  	{
   68.34 @@ -265,6 +254,27 @@
   68.35  			setTextureFilteringOption(gl_tex->mFilterOption);
   68.36  		}
   68.37  	}
   68.38 +			}
   68.39 +			else
   68.40 +			{
   68.41 +				//if deleted, will re-generate it immediately
   68.42 +				texture->forceImmediateUpdate() ;
   68.43 +
   68.44 +				gl_tex->forceUpdateBindStats() ;
   68.45 +				return texture->bindDefaultImage(mIndex);
   68.46 +			}
   68.47 +		}
   68.48 +		else
   68.49 +		{
   68.50 +			llwarns << "NULL LLTexUnit::bind texture" << llendl;
   68.51 +			return false;
   68.52 +		}
   68.53 +	}
   68.54 +	else
   68.55 +	{ // mIndex < 0
   68.56 +		return false;
   68.57 +	}
   68.58 +
   68.59  	return true;
   68.60  }
   68.61  
   68.62 @@ -1058,6 +1068,16 @@
   68.63  
   68.64  void LLRender::init()
   68.65  {
   68.66 +	if (sGLCoreProfile && !LLVertexBuffer::sUseVAO)
   68.67 +	{ //bind a dummy vertex array object so we're core profile compliant
   68.68 +#ifdef GL_ARB_vertex_array_object
   68.69 +		U32 ret;
   68.70 +		glGenVertexArrays(1, &ret);
   68.71 +		glBindVertexArray(ret);
   68.72 +#endif
   68.73 +	}
   68.74 +
   68.75 +
   68.76  	llassert_always(mBuffer.isNull()) ;
   68.77  	stop_glerror();
   68.78  	mBuffer = new LLVertexBuffer(immediate_mask, 0);
   68.79 @@ -1852,33 +1872,33 @@
   68.80  		//store mCount in a local variable to avoid re-entrance (drawArrays may call flush)
   68.81  		U32 count = mCount;
   68.82  
   68.83 -		if (mMode == LLRender::QUADS && !sGLCoreProfile)
   68.84 -		{
   68.85 -			if (mCount%4 != 0)
   68.86 +			if (mMode == LLRender::QUADS && !sGLCoreProfile)
   68.87  			{
   68.88 +				if (mCount%4 != 0)
   68.89 +				{
   68.90  				count -= (mCount % 4);
   68.91  				llwarns << "Incomplete quad requested." << llendl;
   68.92 +				}
   68.93  			}
   68.94 -		}
   68.95 -
   68.96 -		if (mMode == LLRender::TRIANGLES)
   68.97 -		{
   68.98 -			if (mCount%3 != 0)
   68.99 +			
  68.100 +			if (mMode == LLRender::TRIANGLES)
  68.101  			{
  68.102 +				if (mCount%3 != 0)
  68.103 +				{
  68.104  				count -= (mCount % 3);
  68.105  				llwarns << "Incomplete triangle requested." << llendl;
  68.106 +				}
  68.107  			}
  68.108 -		}
  68.109 -
  68.110 -		if (mMode == LLRender::LINES)
  68.111 -		{
  68.112 -			if (mCount%2 != 0)
  68.113 +			
  68.114 +			if (mMode == LLRender::LINES)
  68.115  			{
  68.116 +				if (mCount%2 != 0)
  68.117 +				{
  68.118  				count -= (mCount % 2);
  68.119  				llwarns << "Incomplete line requested." << llendl;
  68.120  			}
  68.121  		}
  68.122 -		
  68.123 +
  68.124  		mCount = 0;
  68.125  
  68.126  		if (mBuffer->useVBOs() && !mBuffer->isLocked())
  68.127 @@ -2281,6 +2301,22 @@
  68.128  	}
  68.129  }
  68.130  
  68.131 +void LLRender::diffuseColor4ub(U8 r, U8 g, U8 b, U8 a)
  68.132 +{
  68.133 +	LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr;
  68.134 +	llassert(!LLGLSLShader::sNoFixedFunction || shader != NULL);
  68.135 +
  68.136 +	if (shader)
  68.137 +	{
  68.138 +		shader->uniform4f(LLShaderMgr::DIFFUSE_COLOR, r/255.f, g/255.f, b/255.f, a/255.f);
  68.139 +	}
  68.140 +	else
  68.141 +	{
  68.142 +		glColor4ub(r,g,b,a);
  68.143 +	}
  68.144 +}
  68.145 +
  68.146 +
  68.147  void LLRender::debugTexUnits(void)
  68.148  {
  68.149  	LL_INFOS("TextureUnit") << "Active TexUnit: " << mCurrTextureUnitIndex << LL_ENDL;
    69.1 --- a/indra/llrender/llrender.h	Fri Sep 27 17:22:31 2013 -0400
    69.2 +++ b/indra/llrender/llrender.h	Fri Oct 04 15:36:52 2013 -0400
    69.3 @@ -396,6 +396,7 @@
    69.4  	void diffuseColor4f(F32 r, F32 g, F32 b, F32 a);
    69.5  	void diffuseColor4fv(const F32* c);
    69.6  	void diffuseColor4ubv(const U8* c);
    69.7 +	void diffuseColor4ub(U8 r, U8 g, U8 b, U8 a);
    69.8  
    69.9  	void vertexBatchPreTransformed(LLVector3* verts, S32 vert_count);
   69.10  	void vertexBatchPreTransformed(LLVector3* verts, LLVector2* uvs, S32 vert_count);
    70.1 --- a/indra/llrender/llrendertarget.cpp	Fri Sep 27 17:22:31 2013 -0400
    70.2 +++ b/indra/llrender/llrendertarget.cpp	Fri Oct 04 15:36:52 2013 -0400
    70.3 @@ -262,7 +262,7 @@
    70.4  	}
    70.5  #endif
    70.6      
    70.7 -
    70.8 +    
    70.9  	return true;
   70.10  }
   70.11  
   70.12 @@ -364,56 +364,36 @@
   70.13  
   70.14  		sBytesAllocated -= mResX*mResY*4;
   70.15  	}
   70.16 -	else if (mFBO)
   70.17 -	{
   70.18 +	else if (mUseDepth && mFBO)
   70.19 +	{ //detach shared depth buffer
   70.20  		glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
   70.21 -
   70.22 -		if (mUseDepth)
   70.23 -		{ //detach shared depth buffer
   70.24 -			if (mStencil)
   70.25 -			{ //attached as a renderbuffer
   70.26 -				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
   70.27 -				glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
   70.28 -				mStencil = false;
   70.29 -			}
   70.30 -			else
   70.31 -			{ //attached as a texture
   70.32 -				glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
   70.33 -			}
   70.34 -			mUseDepth = false;
   70.35 +		if (mStencil)
   70.36 +		{ //attached as a renderbuffer
   70.37 +			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
   70.38 +			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
   70.39 +			mStencil = false;
   70.40  		}
   70.41 -	}
   70.42 -
   70.43 -	// Detach any extra color buffers (e.g. SRGB spec buffers)
   70.44 -	//
   70.45 -	if (mFBO && (mTex.size() > 1))
   70.46 -	{		
   70.47 -		S32 z;
   70.48 -		for (z = mTex.size() - 1; z >= 1; z--)
   70.49 -		{
   70.50 -			sBytesAllocated -= mResX*mResY*4;
   70.51 -			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+z, LLTexUnit::getInternalType(mUsage), 0, 0);
   70.52 -			stop_glerror();
   70.53 -			LLImageGL::deleteTextures(mUsage, mInternalFormat[z], 0, 1, &mTex[z], true);
   70.54 +		else
   70.55 +		{ //attached as a texture
   70.56 +			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, LLTexUnit::getInternalType(mUsage), 0, 0);
   70.57  		}
   70.58 +		mUseDepth = false;
   70.59  	}
   70.60  
   70.61  	if (mFBO)
   70.62  	{
   70.63  		glDeleteFramebuffers(1, (GLuint *) &mFBO);
   70.64 -		stop_glerror();
   70.65  		mFBO = 0;
   70.66  	}
   70.67  
   70.68  	if (mTex.size() > 0)
   70.69  	{
   70.70 -		sBytesAllocated -= mResX*mResY*4;
   70.71 -		LLImageGL::deleteTextures(mUsage, mInternalFormat[0], 0, 1, &mTex[0], true);
   70.72 +		sBytesAllocated -= mResX*mResY*4*mTex.size();
   70.73 +		LLImageGL::deleteTextures(mUsage, mInternalFormat[0], 0, mTex.size(), &mTex[0], true);
   70.74 +		mTex.clear();
   70.75 +		mInternalFormat.clear();
   70.76  	}
   70.77 -
   70.78 -	mTex.clear();
   70.79 -	mInternalFormat.clear();
   70.80 -
   70.81 +	
   70.82  	mResX = mResY = 0;
   70.83  
   70.84  	sBoundTarget = NULL;
   70.85 @@ -495,6 +475,12 @@
   70.86  	return mTex[attachment];
   70.87  }
   70.88  
   70.89 +U32 LLRenderTarget::getNumTextures() const
   70.90 +{
   70.91 +	return mTex.size();
   70.92 +}
   70.93 +
   70.94 +
   70.95  void LLRenderTarget::bindTexture(U32 index, S32 channel)
   70.96  {
   70.97  	gGL.getTexUnit(channel)->bindManual(mUsage, getTexture(index));
    71.1 --- a/indra/llrender/llrendertarget.h	Fri Sep 27 17:22:31 2013 -0400
    71.2 +++ b/indra/llrender/llrendertarget.h	Fri Oct 04 15:36:52 2013 -0400
    71.3 @@ -115,6 +115,7 @@
    71.4  	LLTexUnit::eTextureType getUsage(void) const { return mUsage; }
    71.5  
    71.6  	U32 getTexture(U32 attachment = 0) const;
    71.7 +	U32 getNumTextures() const;
    71.8  
    71.9  	U32 getDepth(void) const { return mDepth; }
   71.10  	bool hasStencil() const { return mStencil; }
    72.1 --- a/indra/llrender/llshadermgr.cpp	Fri Sep 27 17:22:31 2013 -0400
    72.2 +++ b/indra/llrender/llshadermgr.cpp	Fri Oct 04 15:36:52 2013 -0400
    72.3 @@ -993,7 +993,9 @@
    72.4  	mReservedUniforms.push_back("texture_matrix1");
    72.5  	mReservedUniforms.push_back("texture_matrix2");
    72.6  	mReservedUniforms.push_back("texture_matrix3");
    72.7 -	llassert(mReservedUniforms.size() == LLShaderMgr::TEXTURE_MATRIX3+1);
    72.8 +	mReservedUniforms.push_back("object_plane_s");
    72.9 +	mReservedUniforms.push_back("object_plane_t");
   72.10 +	llassert(mReservedUniforms.size() == LLShaderMgr::OBJECT_PLANE_T+1);
   72.11  
   72.12  	mReservedUniforms.push_back("viewport");
   72.13  
   72.14 @@ -1135,15 +1137,54 @@
   72.15  	mReservedUniforms.push_back("lightMap");
   72.16  	mReservedUniforms.push_back("bloomMap");
   72.17  	mReservedUniforms.push_back("projectionMap");
   72.18 +	mReservedUniforms.push_back("norm_mat");
   72.19 +
   72.20 +	mReservedUniforms.push_back("global_gamma");
   72.21 +	mReservedUniforms.push_back("texture_gamma");
   72.22  	
   72.23 -	mReservedUniforms.push_back("global_gamma");
   72.24 -	mReservedUniforms.push_back("texture_gamma");	
   72.25 -
   72.26  	mReservedUniforms.push_back("specular_color");
   72.27  	mReservedUniforms.push_back("env_intensity");
   72.28  
   72.29 +	mReservedUniforms.push_back("matrixPalette");
   72.30 +	
   72.31 +	mReservedUniforms.push_back("screenTex");
   72.32 +	mReservedUniforms.push_back("screenDepth");
   72.33 +	mReservedUniforms.push_back("refTex");
   72.34 +	mReservedUniforms.push_back("eyeVec");
   72.35 +	mReservedUniforms.push_back("time");
   72.36 +	mReservedUniforms.push_back("d1");
   72.37 +	mReservedUniforms.push_back("d2");
   72.38 +	mReservedUniforms.push_back("lightDir");
   72.39 +	mReservedUniforms.push_back("specular");
   72.40 +	mReservedUniforms.push_back("lightExp");
   72.41 +	mReservedUniforms.push_back("waterFogColor");
   72.42 +	mReservedUniforms.push_back("waterFogDensity");
   72.43 +	mReservedUniforms.push_back("waterFogKS");
   72.44 +	mReservedUniforms.push_back("refScale");
   72.45 +	mReservedUniforms.push_back("waterHeight");
   72.46 +	mReservedUniforms.push_back("waterPlane");
   72.47 +	mReservedUniforms.push_back("normScale");
   72.48 +	mReservedUniforms.push_back("fresnelScale");
   72.49 +	mReservedUniforms.push_back("fresnelOffset");
   72.50 +	mReservedUniforms.push_back("blurMultiplier");
   72.51 +	mReservedUniforms.push_back("sunAngle");
   72.52 +	mReservedUniforms.push_back("scaledAngle");
   72.53 +	mReservedUniforms.push_back("sunAngle2");
   72.54 +	
   72.55 +	mReservedUniforms.push_back("camPosLocal");
   72.56 +
   72.57 +	mReservedUniforms.push_back("gWindDir");
   72.58 +	mReservedUniforms.push_back("gSinWaveParams");
   72.59 +	mReservedUniforms.push_back("gGravity");
   72.60 +
   72.61 +	mReservedUniforms.push_back("detail_0");
   72.62 +	mReservedUniforms.push_back("detail_1");
   72.63 +	mReservedUniforms.push_back("detail_2");
   72.64 +	mReservedUniforms.push_back("detail_3");
   72.65 +	mReservedUniforms.push_back("alpha_ramp");
   72.66 +
   72.67 +	mReservedUniforms.push_back("origin");
   72.68  	mReservedUniforms.push_back("display_gamma");
   72.69 -
   72.70  	llassert(mReservedUniforms.size() == END_RESERVED_UNIFORMS);
   72.71  
   72.72  	std::set<std::string> dupe_check;
    73.1 --- a/indra/llrender/llshadermgr.h	Fri Sep 27 17:22:31 2013 -0400
    73.2 +++ b/indra/llrender/llshadermgr.h	Fri Oct 04 15:36:52 2013 -0400
    73.3 @@ -47,6 +47,8 @@
    73.4  		TEXTURE_MATRIX1,
    73.5  		TEXTURE_MATRIX2,
    73.6  		TEXTURE_MATRIX3,
    73.7 +		OBJECT_PLANE_S,
    73.8 +		OBJECT_PLANE_T,
    73.9  		VIEWPORT,
   73.10  		LIGHT_POSITION,
   73.11  		LIGHT_DIRECTION,
   73.12 @@ -165,15 +167,54 @@
   73.13  		DEFERRED_LIGHT,
   73.14  		DEFERRED_BLOOM,
   73.15  		DEFERRED_PROJECTION,
   73.16 +		DEFERRED_NORM_MATRIX,
   73.17 +
   73.18 +		GLOBAL_GAMMA,
   73.19 +		TEXTURE_GAMMA,
   73.20  		
   73.21 -		GLOBAL_GAMMA,
   73.22 -		TEXTURE_GAMMA,		
   73.23 -
   73.24  		SPECULAR_COLOR,
   73.25  		ENVIRONMENT_INTENSITY,
   73.26  		
   73.27 -		DISPLAY_GAMMA,
   73.28 +		AVATAR_MATRIX,
   73.29  
   73.30 +		WATER_SCREENTEX,
   73.31 +		WATER_SCREENDEPTH,
   73.32 +		WATER_REFTEX,
   73.33 +		WATER_EYEVEC,
   73.34 +		WATER_TIME,
   73.35 +		WATER_WAVE_DIR1,
   73.36 +		WATER_WAVE_DIR2,
   73.37 +		WATER_LIGHT_DIR,
   73.38 +		WATER_SPECULAR,
   73.39 +		WATER_SPECULAR_EXP,
   73.40 +		WATER_FOGCOLOR,
   73.41 +		WATER_FOGDENSITY,
   73.42 +		WATER_FOGKS,
   73.43 +		WATER_REFSCALE,
   73.44 +		WATER_WATERHEIGHT,
   73.45 +		WATER_WATERPLANE,
   73.46 +		WATER_NORM_SCALE,
   73.47 +		WATER_FRESNEL_SCALE,
   73.48 +		WATER_FRESNEL_OFFSET,
   73.49 +		WATER_BLUR_MULTIPLIER,
   73.50 +		WATER_SUN_ANGLE,
   73.51 +		WATER_SCALED_ANGLE,
   73.52 +		WATER_SUN_ANGLE2,
   73.53 +		
   73.54 +		WL_CAMPOSLOCAL,
   73.55 +
   73.56 +		AVATAR_WIND,
   73.57 +		AVATAR_SINWAVE,
   73.58 +		AVATAR_GRAVITY,
   73.59 +
   73.60 +		TERRAIN_DETAIL0,
   73.61 +		TERRAIN_DETAIL1,
   73.62 +		TERRAIN_DETAIL2,
   73.63 +		TERRAIN_DETAIL3,
   73.64 +		TERRAIN_ALPHARAMP,
   73.65 +		
   73.66 +		SHINY_ORIGIN,
   73.67 +DISPLAY_GAMMA,
   73.68  		END_RESERVED_UNIFORMS
   73.69  	} eGLSLReservedUniforms;
   73.70  
    74.1 --- a/indra/llrender/llvertexbuffer.cpp	Fri Sep 27 17:22:31 2013 -0400
    74.2 +++ b/indra/llrender/llvertexbuffer.cpp	Fri Oct 04 15:36:52 2013 -0400
    74.3 @@ -85,6 +85,7 @@
    74.4  //static
    74.5  LLVBOPool LLVertexBuffer::sStreamVBOPool(GL_STREAM_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
    74.6  LLVBOPool LLVertexBuffer::sDynamicVBOPool(GL_DYNAMIC_DRAW_ARB, GL_ARRAY_BUFFER_ARB);
    74.7 +LLVBOPool LLVertexBuffer::sDynamicCopyVBOPool(GL_DYNAMIC_COPY_ARB, GL_ARRAY_BUFFER_ARB);
    74.8  LLVBOPool LLVertexBuffer::sStreamIBOPool(GL_STREAM_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
    74.9  LLVBOPool LLVertexBuffer::sDynamicIBOPool(GL_DYNAMIC_DRAW_ARB, GL_ELEMENT_ARRAY_BUFFER_ARB);
   74.10  
   74.11 @@ -199,7 +200,10 @@
   74.12  		if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
   74.13  		{
   74.14  			glBufferDataARB(mType, size, 0, mUsage);
   74.15 -			ret = (U8*) ll_aligned_malloc_16(size);
   74.16 +			if (mUsage != GL_DYNAMIC_COPY_ARB)
   74.17 +			{ //data will be provided by application
   74.18 +				ret = (U8*) ll_aligned_malloc(size, 64);
   74.19 +			}
   74.20  		}
   74.21  		else
   74.22  		{ //always use a true hint of static draw when allocating non-client-backed buffers
   74.23 @@ -252,7 +256,7 @@
   74.24  	llassert(vbo_block_size(size) == size);
   74.25  
   74.26  	deleteBuffer(name);
   74.27 -	ll_aligned_free_16((U8*) buffer);
   74.28 +	ll_aligned_free((U8*) buffer);
   74.29  
   74.30  	if (mType == GL_ARRAY_BUFFER_ARB)
   74.31  	{
   74.32 @@ -306,7 +310,7 @@
   74.33  			
   74.34  			if (r.mClientData)
   74.35  			{
   74.36 -				ll_aligned_free_16((void*) r.mClientData);
   74.37 +				ll_aligned_free((void*) r.mClientData);
   74.38  			}
   74.39  
   74.40  			l.pop_front();
   74.41 @@ -412,6 +416,7 @@
   74.42  {
   74.43  	sStreamVBOPool.seedPool();
   74.44  	sDynamicVBOPool.seedPool();
   74.45 +	sDynamicCopyVBOPool.seedPool();
   74.46  	sStreamIBOPool.seedPool();
   74.47  	sDynamicIBOPool.seedPool();
   74.48  }
   74.49 @@ -753,10 +758,10 @@
   74.50  	U16* idx = ((U16*) getIndicesPointer())+indices_offset;
   74.51  
   74.52  	stop_glerror();
   74.53 -		LLGLSLShader::startProfile();
   74.54 -		glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, 
   74.55 +	LLGLSLShader::startProfile();
   74.56 +	glDrawRangeElements(sGLMode[mode], start, end, count, GL_UNSIGNED_SHORT, 
   74.57  		idx);
   74.58 -		LLGLSLShader::stopProfile(count, mode);
   74.59 +	LLGLSLShader::stopProfile(count, mode);
   74.60  	stop_glerror();
   74.61  
   74.62  	
   74.63 @@ -910,6 +915,7 @@
   74.64  	sDynamicIBOPool.cleanup();
   74.65  	sStreamVBOPool.cleanup();
   74.66  	sDynamicVBOPool.cleanup();
   74.67 +	sDynamicCopyVBOPool.cleanup();
   74.68  
   74.69  	if(sPrivatePoolp)
   74.70  	{
   74.71 @@ -946,6 +952,8 @@
   74.72  	
   74.73  	if (ret_usage && ret_usage != GL_STREAM_DRAW_ARB)
   74.74  	{ //only stream_draw and dynamic_draw are supported when using VBOs, dynamic draw is the default
   74.75 +		if (ret_usage != GL_DYNAMIC_COPY_ARB)
   74.76 +		{
   74.77  		if (sDisableVBOMapping)
   74.78  		{ //always use stream draw if VBO mapping is disabled
   74.79  			ret_usage = GL_STREAM_DRAW_ARB;
   74.80 @@ -955,6 +963,7 @@
   74.81  			ret_usage = GL_DYNAMIC_DRAW_ARB;
   74.82  		}
   74.83  	}
   74.84 +	}
   74.85  	
   74.86  	return ret_usage;
   74.87  }
   74.88 @@ -1102,10 +1111,15 @@
   74.89  	{
   74.90  		mMappedData = sStreamVBOPool.allocate(mGLBuffer, mSize);
   74.91  	}
   74.92 -	else
   74.93 +	else if (mUsage == GL_DYNAMIC_DRAW_ARB)
   74.94  	{
   74.95  		mMappedData = sDynamicVBOPool.allocate(mGLBuffer, mSize);
   74.96  	}
   74.97 +	else
   74.98 +	{
   74.99 +		mMappedData = sDynamicCopyVBOPool.allocate(mGLBuffer, mSize);
  74.100 +	}
  74.101 +	
  74.102  	
  74.103  	sGLCount++;
  74.104  }
  74.105 @@ -2144,21 +2158,14 @@
  74.106  
  74.107  	if (useVBOs() && (force_bind || (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive))))
  74.108  	{
  74.109 -		LLFastTimer t(FTM_BIND_GL_BUFFER);
  74.110 -		/*if (sMapped)
  74.111 -		{
  74.112 -			llerrs << "VBO bound while another VBO mapped!" << llendl;
  74.113 -		}*/
  74.114 +		//LLFastTimer t(FTM_BIND_GL_BUFFER); <-- this timer is showing up as a hotspot (irony)
  74.115 +		
  74.116  		glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer);
  74.117  		sGLRenderBuffer = mGLBuffer;
  74.118  		sBindCount++;
  74.119  		sVBOActive = true;
  74.120  
  74.121 -		if (mGLArray)
  74.122 -		{
  74.123 -			llassert(sGLRenderArray == mGLArray);
  74.124 -			//mCachedRenderBuffer = mGLBuffer;
  74.125 -		}
  74.126 +		llassert(!mGLArray || sGLRenderArray == mGLArray);
  74.127  
  74.128  		ret = true;
  74.129  	}
  74.130 @@ -2236,7 +2243,7 @@
  74.131  					required_mask |= required;
  74.132  				}
  74.133  			}
  74.134 -        
  74.135 +
  74.136  			if ((data_mask & required_mask) != required_mask)
  74.137  			{
  74.138  				
  74.139 @@ -2440,7 +2447,8 @@
  74.140  		if (data_mask & MAP_COLOR)
  74.141  		{
  74.142  			S32 loc = TYPE_COLOR;
  74.143 -			void* ptr = (void*)(base + mOffsets[TYPE_COLOR]);
  74.144 +			//bind emissive instead of color pointer if emissive is present
  74.145 +			void* ptr = (data_mask & MAP_EMISSIVE) ? (void*)(base + mOffsets[TYPE_EMISSIVE]) : (void*)(base + mOffsets[TYPE_COLOR]);
  74.146  			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_COLOR], ptr);
  74.147  		}
  74.148  		if (data_mask & MAP_EMISSIVE)
  74.149 @@ -2448,6 +2456,12 @@
  74.150  			S32 loc = TYPE_EMISSIVE;
  74.151  			void* ptr = (void*)(base + mOffsets[TYPE_EMISSIVE]);
  74.152  			glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
  74.153 +
  74.154 +			if (!(data_mask & MAP_COLOR))
  74.155 +			{ //map emissive to color channel when color is not also being bound to avoid unnecessary shader swaps
  74.156 +				loc = TYPE_COLOR;
  74.157 +				glVertexAttribPointerARB(loc, 4, GL_UNSIGNED_BYTE, GL_TRUE, LLVertexBuffer::sTypeSize[TYPE_EMISSIVE], ptr);
  74.158 +			}
  74.159  		}
  74.160  		if (data_mask & MAP_WEIGHT)
  74.161  		{
  74.162 @@ -2533,8 +2547,7 @@
  74.163  LLVertexBuffer::MappedRegion::MappedRegion(S32 type, S32 index, S32 count)
  74.164  : mType(type), mIndex(index), mCount(count)
  74.165  { 
  74.166 -	llassert(mType == LLVertexBuffer::TYPE_INDEX || 
  74.167 -			mType < LLVertexBuffer::TYPE_TEXTURE_INDEX);
  74.168 +	mEnd = mIndex+mCount;	
  74.169  }	
  74.170  
  74.171  
    75.1 --- a/indra/llrender/llvertexbuffer.h	Fri Sep 27 17:22:31 2013 -0400
    75.2 +++ b/indra/llrender/llvertexbuffer.h	Fri Oct 04 15:36:52 2013 -0400
    75.3 @@ -107,6 +107,7 @@
    75.4  		S32 mType;
    75.5  		S32 mIndex;
    75.6  		S32 mCount;
    75.7 +		S32 mEnd;
    75.8  		
    75.9  		MappedRegion(S32 type, S32 index, S32 count);
   75.10  	};
   75.11 @@ -125,9 +126,10 @@
   75.12  
   75.13  	static LLVBOPool sStreamVBOPool;
   75.14  	static LLVBOPool sDynamicVBOPool;
   75.15 +	static LLVBOPool sDynamicCopyVBOPool;
   75.16  	static LLVBOPool sStreamIBOPool;
   75.17  	static LLVBOPool sDynamicIBOPool;
   75.18 -
   75.19 +	
   75.20  	static std::list<U32> sAvailableVAOName;
   75.21  	static U32 sCurVAOName;
   75.22  
    76.1 --- a/indra/llui/llconsole.cpp	Fri Sep 27 17:22:31 2013 -0400
    76.2 +++ b/indra/llui/llconsole.cpp	Fri Oct 04 15:36:52 2013 -0400
    76.3 @@ -243,7 +243,6 @@
    76.4  void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color) 
    76.5  {
    76.6  	LLSD paragraph_color_segments;
    76.7 -	
    76.8  	paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText);
    76.9  	LLSD color_sd = color.getValue();
   76.10  	paragraph_color_segments[0]["color"]=color_sd;
    77.1 --- a/indra/llui/llconsole.h	Fri Sep 27 17:22:31 2013 -0400
    77.2 +++ b/indra/llui/llconsole.h	Fri Oct 04 15:36:52 2013 -0400
    77.3 @@ -37,6 +37,7 @@
    77.4  class LLConsole : public LLFixedBuffer, public LLUICtrl, public LLInstanceTracker<LLConsole>
    77.5  {
    77.6  public:
    77.7 +
    77.8  	typedef enum e_font_size
    77.9  	{
   77.10  		MONOSPACE = -1,
    78.1 --- a/indra/llui/llfloater.h	Fri Sep 27 17:22:31 2013 -0400
    78.2 +++ b/indra/llui/llfloater.h	Fri Oct 04 15:36:52 2013 -0400
    78.3 @@ -112,6 +112,8 @@
    78.4  	bool operator!=(const LLCoordFloater& other) const { return !(*this == other); }
    78.5  
    78.6  	void setFloater(LLFloater& floater);
    78.7 +
    78.8 +	
    78.9  };
   78.10  
   78.11  class LLFloater : public LLPanel, public LLInstanceTracker<LLFloater>
   78.12 @@ -121,6 +123,7 @@
   78.13  	friend class LLMultiFloater;
   78.14  
   78.15  public:
   78.16 +
   78.17  	struct KeyCompare
   78.18  	{
   78.19  //		static bool compare(const LLSD& a, const LLSD& b);
    79.1 --- a/indra/llui/llkeywords.cpp	Fri Sep 27 17:22:31 2013 -0400
    79.2 +++ b/indra/llui/llkeywords.cpp	Fri Oct 04 15:36:52 2013 -0400
    79.3 @@ -367,7 +367,6 @@
    79.4  
    79.5  	const llwchar* base = wtext.c_str();
    79.6  	const llwchar* cur = base;
    79.7 -
    79.8  	while( *cur )
    79.9  	{
   79.10  		if( *cur == '\n' || cur == base )
    80.1 --- a/indra/llui/lllayoutstack.h	Fri Sep 27 17:22:31 2013 -0400
    80.2 +++ b/indra/llui/lllayoutstack.h	Fri Oct 04 15:36:52 2013 -0400
    80.3 @@ -38,6 +38,7 @@
    80.4  class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack>
    80.5  {
    80.6  public:
    80.7 +
    80.8  	typedef enum e_layout_orientation
    80.9  	{
   80.10  		HORIZONTAL,
    81.1 --- a/indra/llui/llmodaldialog.h	Fri Sep 27 17:22:31 2013 -0400
    81.2 +++ b/indra/llui/llmodaldialog.h	Fri Oct 04 15:36:52 2013 -0400
    81.3 @@ -40,7 +40,7 @@
    81.4  {
    81.5  public:
    81.6  	LLModalDialog( const LLSD& key, BOOL modal = true );
    81.7 -	/*virtual*/ ~LLModalDialog();
    81.8 +	virtual		~LLModalDialog();
    81.9  	
   81.10  	/*virtual*/ BOOL 	postBuild();
   81.11  	
    82.1 --- a/indra/llui/llnotifications.cpp	Fri Sep 27 17:22:31 2013 -0400
    82.2 +++ b/indra/llui/llnotifications.cpp	Fri Oct 04 15:36:52 2013 -0400
    82.3 @@ -1125,7 +1125,7 @@
    82.4  	mName(p.name.isProvided() ? p.name : LLUUID::generateNewID().asString())
    82.5  {
    82.6  	BOOST_FOREACH(const std::string& source, p.sources)
    82.7 -{
    82.8 +    {
    82.9  		connectToChannel(source);
   82.10  	}
   82.11  }
   82.12 @@ -1209,6 +1209,10 @@
   82.13  	LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
   82.14  }
   82.15  
   82.16 +void LLNotifications::clear()
   82.17 +{
   82.18 +   mDefaultChannels.clear();
   82.19 +}
   82.20  
   82.21  // The expiration channel gets all notifications that are cancelled
   82.22  bool LLNotifications::expirationFilter(LLNotificationPtr pNotification)
    83.1 --- a/indra/llui/llnotifications.h	Fri Sep 27 17:22:31 2013 -0400
    83.2 +++ b/indra/llui/llnotifications.h	Fri Oct 04 15:36:52 2013 -0400
    83.3 @@ -138,6 +138,7 @@
    83.4  class LLNotificationContext : public LLInstanceTracker<LLNotificationContext, LLUUID>
    83.5  {
    83.6  public:
    83.7 +
    83.8  	LLNotificationContext() : LLInstanceTracker<LLNotificationContext, LLUUID>(LLUUID::generateNewID())
    83.9  	{
   83.10  	}
   83.11 @@ -873,6 +874,13 @@
   83.12  
   83.13  	friend class LLSingleton<LLNotifications>;
   83.14  public:
   83.15 +
   83.16 +    // Needed to clear up RefCounted things prior to actual destruction
   83.17 +    // as the singleton nature of the class makes them do "bad things"
   83.18 +    // on at least Mac, if not all 3 platforms
   83.19 +    //
   83.20 +    void clear();
   83.21 +
   83.22  	// load all notification descriptions from file
   83.23  	// calling more than once will overwrite existing templates
   83.24  	// but never delete a template
    84.1 --- a/indra/llui/lltextbase.cpp	Fri Sep 27 17:22:31 2013 -0400
    84.2 +++ b/indra/llui/lltextbase.cpp	Fri Oct 04 15:36:52 2013 -0400
    84.3 @@ -2379,7 +2379,6 @@
    84.4  {
    84.5  	// Figure out which line we're nearest to.
    84.6  	LLRect doc_rect = mDocumentView->getRect();
    84.7 -
    84.8  	S32 doc_y = local_y - doc_rect.mBottom;
    84.9  	
   84.10  	// binary search for line that starts before local_y
    85.1 --- a/indra/llwindow/lldragdropwin32.h	Fri Sep 27 17:22:31 2013 -0400
    85.2 +++ b/indra/llwindow/lldragdropwin32.h	Fri Oct 04 15:36:52 2013 -0400
    85.3 @@ -57,7 +57,7 @@
    85.4  #include <windows.h>
    85.5  #include <ole2.h>
    85.6  
    85.7 -// imposter class that does nothing 
    85.8 +// impostor class that does nothing 
    85.9  class LLDragDropWin32
   85.10  {
   85.11  	public:
    86.1 --- a/indra/llwindow/llopenglview-objc.h	Fri Sep 27 17:22:31 2013 -0400
    86.2 +++ b/indra/llwindow/llopenglview-objc.h	Fri Oct 04 15:36:52 2013 -0400
    86.3 @@ -65,6 +65,7 @@
    86.4  - (unsigned long) getVramSize;
    86.5  
    86.6  - (void) allowMarkedTextInput:(bool)allowed;
    86.7 +- (void) viewDidEndLiveResize;
    86.8  
    86.9  @end
   86.10  
    87.1 --- a/indra/llwindow/llopenglview-objc.mm	Fri Sep 27 17:22:31 2013 -0400
    87.2 +++ b/indra/llwindow/llopenglview-objc.mm	Fri Oct 04 15:36:52 2013 -0400
    87.3 @@ -91,6 +91,13 @@
    87.4  
    87.5  @implementation LLOpenGLView
    87.6  
    87.7 +// Force a high quality update after live resizing
    87.8 +- (void) viewDidEndLiveResize
    87.9 +{
   87.10 +    NSSize size = [self frame].size;
   87.11 +    callResize(size.width, size.height);
   87.12 +}
   87.13 +
   87.14  - (unsigned long)getVramSize
   87.15  {
   87.16      CGLRendererInfoObj info = 0;
   87.17 @@ -119,9 +126,8 @@
   87.18  
   87.19  - (void)windowResized:(NSNotification *)notification;
   87.20  {
   87.21 -	NSSize size = [self frame].size;
   87.22 -	
   87.23 -	callResize(size.width, size.height);
   87.24 +	//NSSize size = [self frame].size;
   87.25 +	//callResize(size.width, size.height);
   87.26  }
   87.27  
   87.28  - (void)dealloc
    88.1 --- a/indra/llwindow/llwindow.h	Fri Sep 27 17:22:31 2013 -0400
    88.2 +++ b/indra/llwindow/llwindow.h	Fri Oct 04 15:36:52 2013 -0400
    88.3 @@ -42,6 +42,7 @@
    88.4  class LLWindow : public LLInstanceTracker<LLWindow>
    88.5  {
    88.6  public:
    88.7 +
    88.8  	struct LLWindowResolution
    88.9  	{
   88.10  		S32 mWidth;
    89.1 --- a/indra/llwindow/llwindowmacosx-objc.h	Fri Sep 27 17:22:31 2013 -0400
    89.2 +++ b/indra/llwindow/llwindowmacosx-objc.h	Fri Oct 04 15:36:52 2013 -0400
    89.3 @@ -49,6 +49,7 @@
    89.4  bool runMainLoop();
    89.5  void initMainLoop();
    89.6  void cleanupViewer();
    89.7 +void handleUrl(const char* url);
    89.8  
    89.9  /* Defined in llwindowmacosx-objc.mm: */
   89.10  int createNSApp(int argc, const char **argv);
    90.1 --- a/indra/llwindow/llwindowmacosx-objc.mm	Fri Sep 27 17:22:31 2013 -0400
    90.2 +++ b/indra/llwindow/llwindowmacosx-objc.mm	Fri Oct 04 15:36:52 2013 -0400
    90.3 @@ -57,7 +57,7 @@
    90.4  		[[NSUserDefaults standardUserDefaults] setObject:@"NO" forKey:@"NSTreatUnknownArgumentsAsOpen"];
    90.5  		
    90.6  		[pool release];
    90.7 -		
    90.8 +
    90.9  		inited = true;
   90.10  	}
   90.11  }
    91.1 --- a/indra/lscript/lscript_compile/indra.l	Fri Sep 27 17:22:31 2013 -0400
    91.2 +++ b/indra/lscript/lscript_compile/indra.l	Fri Oct 04 15:36:52 2013 -0400
    91.3 @@ -79,8 +79,8 @@
    91.4  #define yyfree indra_free
    91.5  
    91.6  
    91.7 +int yyparse( void );
    91.8  int yylex( void );
    91.9 -int yyparse( void );
   91.10  int yyerror(const char *fmt, ...);
   91.11  
   91.12  %}
   91.13 @@ -161,6 +161,7 @@
   91.14  "STATUS_DIE_AT_EDGE"	{ count(); yylval.ival = 0x80; return(INTEGER_CONSTANT); }
   91.15  "STATUS_RETURN_AT_EDGE"	{ count(); yylval.ival = 0x100; return(INTEGER_CONSTANT); }
   91.16  "STATUS_CAST_SHADOWS"	{ count(); yylval.ival = 0x200; return(INTEGER_CONSTANT); }
   91.17 +"STATUS_BLOCK_GRAB_OBJECT"	{ count(); yylval.ival = 0x400; return(INTEGER_CONSTANT); }
   91.18  
   91.19  "AGENT_FLYING"			{ count(); yylval.ival = AGENT_FLYING; return(INTEGER_CONSTANT); }
   91.20  "AGENT_ATTACHMENTS"		{ count(); yylval.ival = AGENT_ATTACHMENTS; return(INTEGER_CONSTANT); }
   91.21 @@ -235,6 +236,8 @@
   91.22  "PERMISSION_TRACK_CAMERA"		{ count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TRACK_CAMERA]; return(INTEGER_CONSTANT); }
   91.23  "PERMISSION_CONTROL_CAMERA"		{ count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_CONTROL_CAMERA]; return(INTEGER_CONSTANT); }
   91.24  "PERMISSION_TELEPORT"			{ count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_TELEPORT]; return(INTEGER_CONSTANT); }
   91.25 +"PERMISSION_SILENT_ESTATE_MANAGEMENT"   { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_SILENT_ESTATE_MANAGEMENT]; return(INTEGER_CONSTANT); }
   91.26 +"PERMISSION_OVERRIDE_ANIMATIONS"    { count(); yylval.ival = LSCRIPTRunTimePermissionBits[SCRIPT_PERMISSION_OVERRIDE_ANIMATIONS]; return(INTEGER_CONSTANT); }
   91.27  
   91.28  "INVENTORY_TEXTURE"					{ count(); yylval.ival = LLAssetType::AT_TEXTURE; return(INTEGER_CONSTANT); }
   91.29  "INVENTORY_SOUND"					{ count(); yylval.ival = LLAssetType::AT_SOUND; return(INTEGER_CONSTANT); }
   91.30 @@ -271,6 +274,22 @@
   91.31  "OBJECT_OWNER"			{ count(); yylval.ival = OBJECT_OWNER; return(INTEGER_CONSTANT); }
   91.32  "OBJECT_GROUP"			{ count(); yylval.ival = OBJECT_GROUP; return(INTEGER_CONSTANT); }
   91.33  "OBJECT_CREATOR"		{ count(); yylval.ival = OBJECT_CREATOR; return(INTEGER_CONSTANT); }
   91.34 +"OBJECT_RUNNING_SCRIPT_COUNT"	{ count(); yylval.ival = OBJECT_RUNNING_SCRIPT_COUNT; return(INTEGER_CONSTANT); }
   91.35 +"OBJECT_TOTAL_SCRIPT_COUNT"		{ count(); yylval.ival = OBJECT_TOTAL_SCRIPT_COUNT; return(INTEGER_CONSTANT); }
   91.36 +"OBJECT_SCRIPT_MEMORY"			{ count(); yylval.ival = OBJECT_SCRIPT_MEMORY; return(INTEGER_CONSTANT); }
   91.37 +"OBJECT_SCRIPT_TIME"			{ count(); yylval.ival = OBJECT_SCRIPT_TIME; return(INTEGER_CONSTANT); }
   91.38 +"OBJECT_PRIM_EQUIVALENCE"		{ count(); yylval.ival = OBJECT_PRIM_EQUIVALENCE; return(INTEGER_CONSTANT); }
   91.39 +"OBJECT_SERVER_COST"			{ count(); yylval.ival = OBJECT_SERVER_COST; return(INTEGER_CONSTANT); }
   91.40 +"OBJECT_STREAMING_COST"			{ count(); yylval.ival = OBJECT_STREAMING_COST; return(INTEGER_CONSTANT); }
   91.41 +"OBJECT_PHYSICS_COST"			{ count(); yylval.ival = OBJECT_PHYSICS_COST; return(INTEGER_CONSTANT); }
   91.42 +"OBJECT_CHARACTER_TIME"			{ count(); yylval.ival = OBJECT_CHARACTER_TIME; return(INTEGER_CONSTANT); }
   91.43 +"OBJECT_ROOT"					{ count(); yylval.ival = OBJECT_ROOT; return(INTEGER_CONSTANT); }
   91.44 +"OBJECT_ATTACHED_POINT"			{ count(); yylval.ival = OBJECT_ATTACHED_POINT; return(INTEGER_CONSTANT); }
   91.45 +"OBJECT_PATHFINDING_TYPE"		{ count(); yylval.ival = OBJECT_PATHFINDING_TYPE; return(INTEGER_CONSTANT); }
   91.46 +"OBJECT_PHYSICS"				{ count(); yylval.ival = OBJECT_PHYSICS; return(INTEGER_CONSTANT); }
   91.47 +"OBJECT_PHANTOM"				{ count(); yylval.ival = OBJECT_PHANTOM; return(INTEGER_CONSTANT); }
   91.48 +"OBJECT_TEMP_ON_REZ"			{ count(); yylval.ival = OBJECT_TEMP_ON_REZ; return(INTEGER_CONSTANT); }
   91.49 +"OBJECT_RENDER_WEIGHT"			{ count(); yylval.ival = OBJECT_RENDER_WEIGHT; return(INTEGER_CONSTANT); }
   91.50  
   91.51  "TYPE_INTEGER"			{ count(); yylval.ival = LST_INTEGER; return(INTEGER_CONSTANT); }	
   91.52  "TYPE_FLOAT"			{ count(); yylval.ival = LST_FLOATINGPOINT; return(INTEGER_CONSTANT); }	
   91.53 @@ -376,6 +395,10 @@
   91.54  "PSYS_PART_END_SCALE"	{ count(); yylval.ival = LLPS_PART_END_SCALE; return (INTEGER_CONSTANT); }
   91.55  "PSYS_PART_MAX_AGE"		{ count(); yylval.ival = LLPS_PART_MAX_AGE; return (INTEGER_CONSTANT); }
   91.56  
   91.57 +"PSYS_PART_BLEND_FUNC_SOURCE"	{ count(); yylval.ival = LLPS_PART_BLEND_FUNC_SOURCE; return (INTEGER_CONSTANT); }
   91.58 +"PSYS_PART_BLEND_FUNC_DEST"		{ count(); yylval.ival = LLPS_PART_BLEND_FUNC_DEST; return (INTEGER_CONSTANT); }
   91.59 +"PSYS_PART_START_GLOW"	{ count(); yylval.ival = LLPS_PART_START_GLOW; return (INTEGER_CONSTANT); }
   91.60 +"PSYS_PART_END_GLOW"	{ count(); yylval.ival = LLPS_PART_END_GLOW; return (INTEGER_CONSTANT); }
   91.61  
   91.62  "PSYS_PART_WIND_MASK"				{ count(); yylval.ival = LLPartData::LL_PART_WIND_MASK; return(INTEGER_CONSTANT); }
   91.63  "PSYS_PART_INTERP_COLOR_MASK"		{ count(); yylval.ival = LLPartData::LL_PART_INTERP_COLOR_MASK; return(INTEGER_CONSTANT); }
   91.64 @@ -386,6 +409,16 @@
   91.65  "PSYS_PART_TARGET_POS_MASK"			{ count(); yylval.ival = LLPartData::LL_PART_TARGET_POS_MASK; return(INTEGER_CONSTANT); }
   91.66  "PSYS_PART_EMISSIVE_MASK"			{ count(); yylval.ival = LLPartData::LL_PART_EMISSIVE_MASK; return(INTEGER_CONSTANT); }
   91.67  "PSYS_PART_TARGET_LINEAR_MASK"		{ count(); yylval.ival = LLPartData::LL_PART_TARGET_LINEAR_MASK; return(INTEGER_CONSTANT); }
   91.68 +"PSYS_PART_RIBBON_MASK"				{ count(); yylval.ival = LLPartData::LL_PART_RIBBON_MASK; return(INTEGER_CONSTANT); }
   91.69 +
   91.70 +"PSYS_PART_BF_ONE"						{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE; return(INTEGER_CONSTANT); }
   91.71 +"PSYS_PART_BF_ZERO"						{ count(); yylval.ival = LLPartData::LL_PART_BF_ZERO; return(INTEGER_CONSTANT); }
   91.72 +"PSYS_PART_BF_DEST_COLOR"				{ count(); yylval.ival = LLPartData::LL_PART_BF_DEST_COLOR; return(INTEGER_CONSTANT); }
   91.73 +"PSYS_PART_BF_SOURCE_COLOR"				{ count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_COLOR; return(INTEGER_CONSTANT); }
   91.74 +"PSYS_PART_BF_ONE_MINUS_DEST_COLOR"		{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_DEST_COLOR; return(INTEGER_CONSTANT); }
   91.75 +"PSYS_PART_BF_ONE_MINUS_SOURCE_COLOR"	{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_COLOR; return(INTEGER_CONSTANT); }
   91.76 +"PSYS_PART_BF_SOURCE_ALPHA"				{ count(); yylval.ival = LLPartData::LL_PART_BF_SOURCE_ALPHA; return(INTEGER_CONSTANT); }
   91.77 +"PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA"	{ count(); yylval.ival = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA; return(INTEGER_CONSTANT); }
   91.78  
   91.79  
   91.80  "PSYS_SRC_MAX_AGE"					{ count(); yylval.ival = LLPS_SRC_MAX_AGE; return(INTEGER_CONSTANT); }
   91.81 @@ -481,7 +514,17 @@
   91.82  "PRIM_BUMP_SHINY"		{ count(); yylval.ival = LSL_PRIM_BUMP_SHINY; return(INTEGER_CONSTANT); }
   91.83  "PRIM_FULLBRIGHT"		{ count(); yylval.ival = LSL_PRIM_FULLBRIGHT; return(INTEGER_CONSTANT); }
   91.84  "PRIM_TEXGEN"			{ count(); yylval.ival = LSL_PRIM_TEXGEN; return(INTEGER_CONSTANT); }
   91.85 -"PRIM_GLOW"	     		{ count(); yylval.ival = LSL_PRIM_GLOW; return(INTEGER_CONSTANT); }
   91.86 +"PRIM_GLOW"				{ count(); yylval.ival = LSL_PRIM_GLOW; return(INTEGER_CONSTANT); }
   91.87 +"PRIM_TEXT"				{ count(); yylval.ival = LSL_PRIM_TEXT; return(INTEGER_CONSTANT); }
   91.88 +"PRIM_NAME"				{ count(); yylval.ival = LSL_PRIM_NAME; return(INTEGER_CONSTANT); }
   91.89 +"PRIM_DESC"				{ count(); yylval.ival = LSL_PRIM_DESC; return(INTEGER_CONSTANT); }
   91.90 +"PRIM_OMEGA"			{ count(); yylval.ival = LSL_PRIM_OMEGA; return(INTEGER_CONSTANT); }
   91.91 +"PRIM_LINK_TARGET"		{ count(); yylval.ival = LSL_PRIM_LINK_TARGET; return(INTEGER_CONSTANT); }
   91.92 +"PRIM_SLICE"			{ count(); yylval.ival = LSL_PRIM_SLICE; return(INTEGER_CONSTANT); }
   91.93 +
   91.94 +"PRIM_PHYSICS_SHAPE_PRIM"	{ count(); yylval.ival = LSL_PRIM_PHYSICS_SHAPE_PRIM; return(INTEGER_CONSTANT); }
   91.95 +"PRIM_PHYSICS_SHAPE_NONE"	{ count(); yylval.ival = LSL_PRIM_PHYSICS_SHAPE_NONE; return(INTEGER_CONSTANT); }
   91.96 +"PRIM_PHYSICS_SHAPE_CONVEX"	{ count(); yylval.ival = LSL_PRIM_PHYSICS_SHAPE_CONVEX; return(INTEGER_CONSTANT); }
   91.97  
   91.98  "PRIM_TYPE_BOX"			{ count(); yylval.ival = LSL_PRIM_TYPE_BOX; return(INTEGER_CONSTANT); }
   91.99  "PRIM_TYPE_CYLINDER"	{ count(); yylval.ival = LSL_PRIM_TYPE_CYLINDER; return(INTEGER_CONSTANT); }
    92.1 --- a/indra/lscript/lscript_execute/lscript_readlso.cpp	Fri Sep 27 17:22:31 2013 -0400
    92.2 +++ b/indra/lscript/lscript_execute/lscript_readlso.cpp	Fri Oct 04 15:36:52 2013 -0400
    92.3 @@ -145,7 +145,6 @@
    92.4  		// get offset to skip past name
    92.5  		varoffset = global_v_offset;
    92.6  		bytestream2integer(mRawData, global_v_offset);
    92.7 -		
    92.8  		// get typeexport
    92.9  		type = *(mRawData + global_v_offset++);
   92.10  
   92.11 @@ -347,6 +346,7 @@
   92.12  				S32 temp_end;
   92.13  
   92.14  				opcode_end = worst_case_opcode_end;
   92.15 +				(void)opcode_end;