Commits

Scott Lawrence committed b597373 Merge

merge up to latest viewer-development

Comments (0)

Files changed (224)

 09984bfa6cae17e0f72d02b75c1b7393c65eecfc 2.7.5-beta1
 e1ed60913230dd64269a7f7fc52cbc6004f6d52c 2.8.0-start
 502f6a5deca9365ddae57db4f1e30172668e171e 2.8.1-start
+c04e68e1b0034fd0a20815ae24c77e5f8428e822 DRTVWR-188
 888768f162d2c0a8de1dcc5fb9a08bd8bd120a6b DRTVWR-175
 2a3965b3ad202df7ea25d2be689291bb14a1280e DRTVWR-155
 6866d9df6efbd441c66451debd376d21211de39c DRTVWR-68_2.7.5-release
 a8057e1b9a1246b434a27405be35e030f7d28b0c 3.3.4-beta3
 4281aa899fb2cedb7a9ca7ce91c5c29d4aa69594 DRTVWR-180
 9cd174d3a54d93d409a7c346a15b8bfb40fc58f4 DRTVWR-184
+47f0d08ba7ade0a3905074009067c6d3df7e16ae DRTVWR-190
 5c08e1d8edd871807153603b690e3ee9dbb548aa DRTVWR-183
 6c75f220b103db1420919c8b635fe53e2177f318 3.3.4-beta4
 ab2ffc547c8a8950ff187c4f6c95e5334fab597b 3.3.4-beta5
 28e100d0379a2b0710c57647a28fc5239d3d7b99 3.3.4-release
 a8b3eca451a9eaab59987efb0ab1c4217e3f2dcc DRTVWR-182
 1f27cdfdc54246484f8afbbe42ce48e954175cbd 3.4.0-beta1
+81f6b745ef27f5915fd07f988fdec9944f2bb73e DRTVWR-186
+78ca0bbf43a92e8914d4cfa87d69a6717ef7d4cf DRTVWR-194
+cc953f00956be52cc64c30637bbeec310eea603f DRTVWR-181
+9ee9387789701d597130f879d9011a4958753862 DRTVWR-189
+e9732c739c8a72a590216951505ea9c76a526a84 DRTVWR-193
+33a2fc7a910ae29ff8b4850316ed7fbff9f64d33 DRTVWR-195
+421126293dcbde918e0da027ca0ab9deb5b4fbf2 DRTVWR-192
+4b2c52aecb7a75de31dbb12d9f5b9a251d8707be DRTVWR-191
+7602f61c804a512764e349c034c02ddabeefebc4 DRTVWR-196
File contents unchanged.
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>d91e1f483209cd3eba04135c6a59e829</string>
+              <string>a5b2dff0d97b643227a58473e5c57906</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-kdu-private/rev/221672/arch/Darwin/installer/kdu-6.4.1-darwin-20110218.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-kdu-private/rev/256978/arch/Darwin/installer/kdu-7.0.0-darwin-20120515.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>6cd9f36465ef73a3df34bf2b3bba2ced</string>
+              <string>6d80d35524e1c0c32d3385014d02d48c</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-kdu-private/rev/221672/arch/CYGWIN/installer/kdu-6.4.1-windows-20110218.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/3p-kdu-private/rev/256978/arch/CYGWIN/installer/kdu-7.0.0-windows-20120515.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>de22a97b276913a6dd05838b7fe297af</string>
+              <string>0578fa67ef9906c6aaa326f51db2669f</string>
               <key>hash_algorithm</key>
               <string>md5</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source/rev/262536/arch/Darwin/installer/llphysicsextensions_source-0.3-darwin-20120725.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source/rev/263415/arch/Darwin/installer/llphysicsextensions_source-0.3-darwin-20120814.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>d2dfbbc11aac34ebd551df86524c8c9c</string>
+              <string>b706fdeed4ce2182d434043dc33d9d1d</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source/rev/262536/arch/Linux/installer/llphysicsextensions_source-0.3-linux-20120725.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source/rev/263415/arch/Linux/installer/llphysicsextensions_source-0.3-linux-20120814.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>99abccc5d117ab82cadb8cff0d85b867</string>
+              <string>0cebd359ea732a7db363d88f9886a1ef</string>
               <key>url</key>
-              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source/rev/262536/arch/CYGWIN/installer/llphysicsextensions_source-0.3-windows-20120725.tar.bz2</string>
+              <string>http://s3-proxy.lindenlab.com/private-builds-secondlife-com/hg/repo/llphysicsextensions-source/rev/263415/arch/CYGWIN/installer/llphysicsextensions_source-0.3-windows-20120814.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>3528620230fbd288fcc9dbbd8d8a6b59</string>
+              <string>3ae798d4dfb54a1d806ee5f8b31f7626</string>
               <key>hash_algorithm</key>
               <string>md5</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub/rev/262536/arch/Darwin/installer/llphysicsextensions_stub-0.3-darwin-20120725.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub/rev/263415/arch/Darwin/installer/llphysicsextensions_stub-0.3-darwin-20120814.tar.bz2</string>
             </map>
             <key>name</key>
             <string>darwin</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>69d188f72f9494b0e74c94ca0496f618</string>
+              <string>aa8a2f25e8629cf5e6a96cc0eb93de8e</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub/rev/262536/arch/Linux/installer/llphysicsextensions_stub-0.3-linux-20120725.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub/rev/263415/arch/Linux/installer/llphysicsextensions_stub-0.3-linux-20120814.tar.bz2</string>
             </map>
             <key>name</key>
             <string>linux</string>
             <key>archive</key>
             <map>
               <key>hash</key>
-              <string>61fc2b84ad53cf8d98d1784c31f9928e</string>
+              <string>3ea4cee6a8dd4c89fbfd3ad6abd703c2</string>
               <key>url</key>
-              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub/rev/262536/arch/CYGWIN/installer/llphysicsextensions_stub-0.3-windows-20120725.tar.bz2</string>
+              <string>http://automated-builds-secondlife-com.s3.amazonaws.com/hg/repo/llphysicsextensions-stub/rev/263415/arch/CYGWIN/installer/llphysicsextensions_stub-0.3-windows-20120814.tar.bz2</string>
             </map>
             <key>name</key>
             <string>windows</string>

indra/llcommon/CMakeLists.txt

     llfoldertype.h
     llformat.h
     llframetimer.h
+    llhandle.h
     llhash.h
     llheartbeat.h
     llhttpstatuscodes.h

indra/llcommon/indra_constants.h

 	STAT_FILTER_BY_PARCEL	= 0x00000001,
 	STAT_FILTER_BY_OWNER	= 0x00000002,
 	STAT_FILTER_BY_OBJECT	= 0x00000004,
+	STAT_FILTER_BY_PARCEL_NAME	= 0x00000008,
 	STAT_REQUEST_LAST_ENTRY	= 0x80000000,
 };
 

indra/llcommon/llhandle.h

+/** 
+* @file llhandle.h
+* @brief "Handle" to an object (usually a floater) whose lifetime you don't
+* control.
+*
+* $LicenseInfo:firstyear=2001&license=viewerlgpl$
+* Second Life Viewer Source Code
+* Copyright (C) 2010, Linden Research, Inc.
+* 
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation;
+* version 2.1 of the License only.
+* 
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+* Lesser General Public License for more details.
+* 
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+* 
+* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+* $/LicenseInfo$
+*/
+#ifndef LLHANDLE_H
+#define LLHANDLE_H
+
+#include "llpointer.h"
+#include <boost/type_traits/is_convertible.hpp>
+#include <boost/utility/enable_if.hpp>
+
+/**
+ * Helper object for LLHandle. Don't instantiate these directly, used
+ * exclusively by LLHandle.
+ */
+class LLTombStone : public LLRefCount
+{
+public:
+	LLTombStone(void* target = NULL) : mTarget(target) {}
+
+	void setTarget(void* target) { mTarget = target; }
+	void* getTarget() const { return mTarget; }
+private:
+	mutable void* mTarget;
+};
+
+/**
+ *	LLHandles are used to refer to objects whose lifetime you do not control or influence.  
+ *	Calling get() on a handle will return a pointer to the referenced object or NULL, 
+ *	if the object no longer exists.  Note that during the lifetime of the returned pointer, 
+ *	you are assuming that the object will not be deleted by any action you perform, 
+ *	or any other thread, as normal when using pointers, so avoid using that pointer outside of
+ *	the local code block.
+ * 
+ *  https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669
+ *
+ * The implementation is like some "weak pointer" implementations. When we
+ * can't control the lifespan of the referenced object of interest, we can
+ * still instantiate a proxy object whose lifespan we DO control, and store in
+ * the proxy object a dumb pointer to the actual target. Then we just have to
+ * ensure that on destruction of the target object, the proxy's dumb pointer
+ * is set NULL.
+ *
+ * LLTombStone is our proxy object. LLHandle contains an LLPointer to the
+ * LLTombStone, so every copy of an LLHandle increments the LLTombStone's ref
+ * count as usual.
+ *
+ * One copy of the LLHandle, specifically the LLRootHandle, must be stored in
+ * the referenced object. Destroying the LLRootHandle is what NULLs the
+ * proxy's target pointer.
+ *
+ * Minor optimization: we want LLHandle's mTombStone to always be a valid
+ * LLPointer, saving some conditionals in dereferencing. That's the
+ * getDefaultTombStone() mechanism. The default LLTombStone object's target
+ * pointer is always NULL, so it's semantically identical to allowing
+ * mTombStone to be invalid.
+ */
+template <typename T>
+class LLHandle
+{
+	template <typename U> friend class LLHandle;
+	template <typename U> friend class LLHandleProvider;
+public:
+	LLHandle() : mTombStone(getDefaultTombStone()) {}
+
+	template<typename U>
+	LLHandle(const LLHandle<U>& other, typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0)
+	: mTombStone(other.mTombStone)
+	{}
+
+	bool isDead() const 
+	{ 
+		return mTombStone->getTarget() == NULL; 
+	}
+
+	void markDead() 
+	{ 
+		mTombStone = getDefaultTombStone();
+	}
+
+	T* get() const
+	{
+		return reinterpret_cast<T*>(mTombStone->getTarget());
+	}
+
+	friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+	{
+		return lhs.mTombStone == rhs.mTombStone;
+	}
+	friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+	{
+		return !(lhs == rhs);
+	}
+	friend bool	operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+	{
+		return lhs.mTombStone < rhs.mTombStone;
+	}
+	friend bool	operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
+	{
+		return lhs.mTombStone > rhs.mTombStone;
+	}
+
+protected:
+	LLPointer<LLTombStone> mTombStone;
+
+private:
+	typedef T* pointer_t;
+	static LLPointer<LLTombStone>& getDefaultTombStone()
+	{
+		static LLPointer<LLTombStone> sDefaultTombStone = new LLTombStone;
+		return sDefaultTombStone;
+	}
+};
+
+/**
+ * LLRootHandle isa LLHandle which must be stored in the referenced object.
+ * You can either store it directly and explicitly bind(this), or derive from
+ * LLHandleProvider (q.v.) which automates that for you. The essential point
+ * is that destroying the LLRootHandle (as a consequence of destroying the
+ * referenced object) calls unbind(), setting the LLTombStone's target pointer
+ * NULL.
+ */
+template <typename T>
+class LLRootHandle : public LLHandle<T>
+{
+public:
+	typedef LLRootHandle<T> self_t;
+	typedef LLHandle<T> base_t;
+
+	LLRootHandle(T* object) { bind(object); }
+	LLRootHandle() {};
+	~LLRootHandle() { unbind(); }
+
+	// this is redundant, since an LLRootHandle *is* an LLHandle
+	//LLHandle<T> getHandle() { return LLHandle<T>(*this); }
+
+	void bind(T* object) 
+	{ 
+		// unbind existing tombstone
+		if (LLHandle<T>::mTombStone.notNull())
+		{
+			if (LLHandle<T>::mTombStone->getTarget() == (void*)object) return;
+			LLHandle<T>::mTombStone->setTarget(NULL);
+		}
+		// tombstone reference counted, so no paired delete
+		LLHandle<T>::mTombStone = new LLTombStone((void*)object);
+	}
+
+	void unbind() 
+	{
+		LLHandle<T>::mTombStone->setTarget(NULL);
+	}
+
+	//don't allow copying of root handles, since there should only be one
+private:
+	LLRootHandle(const LLRootHandle& other) {};
+};
+
+/**
+ * Use this as a mixin for simple classes that need handles and when you don't
+ * want handles at multiple points of the inheritance hierarchy
+ */
+template <typename T>
+class LLHandleProvider
+{
+public:
+	LLHandle<T> getHandle() const
+	{ 
+		// perform lazy binding to avoid small tombstone allocations for handle
+		// providers whose handles are never referenced
+		mHandle.bind(static_cast<T*>(const_cast<LLHandleProvider<T>* >(this))); 
+		return mHandle; 
+	}
+
+protected:
+	typedef LLHandle<T> handle_type_t;
+	LLHandleProvider() 
+	{
+		// provided here to enforce T deriving from LLHandleProvider<T>
+	} 
+
+	template <typename U>
+	LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
+	{
+		LLHandle<U> downcast_handle;
+		downcast_handle.mTombStone = getHandle().mTombStone;
+		return downcast_handle;
+	}
+
+
+private:
+	mutable LLRootHandle<T> mHandle;
+};
+
+#endif

indra/llcommon/llinitparam.h

 #include <boost/shared_ptr.hpp>
 
 #include "llerror.h"
-#include "lltypeinfolookup.h"
+#include "llstl.h"
 
 namespace LLInitParam
 {
 
 	public:
 		
-		struct CompareTypeID
-		{
-			bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
-			{
-				return lhs->before(*rhs);
-			}
-		};
-
 		typedef std::vector<std::pair<std::string, bool> >					name_stack_t;
 		typedef std::pair<name_stack_t::iterator, name_stack_t::iterator>	name_stack_range_t;
 		typedef std::vector<std::string>									possible_values_t;
 		typedef bool (*parser_write_func_t)(Parser& parser, const void*, name_stack_t&);
 		typedef boost::function<void (name_stack_t&, S32, S32, const possible_values_t*)>	parser_inspect_func_t;
 
-		typedef LLTypeInfoLookup<parser_read_func_t>		parser_read_func_map_t;
-		typedef LLTypeInfoLookup<parser_write_func_t>		parser_write_func_map_t;
-		typedef LLTypeInfoLookup<parser_inspect_func_t>		parser_inspect_func_map_t;
+		typedef std::map<const std::type_info*, parser_read_func_t>		parser_read_func_map_t;
+		typedef std::map<const std::type_info*, parser_write_func_t>	parser_write_func_map_t;
+		typedef std::map<const std::type_info*, parser_inspect_func_t>	parser_inspect_func_map_t;
 
 		Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
 		:	mParseSilently(false),

indra/llcommon/llregistry.h

 
 #include <boost/type_traits.hpp>
 #include "llsingleton.h"
-#include "lltypeinfolookup.h"
+#include "llstl.h"
 
 template <typename T>
-class LLRegistryDefaultComparator
+struct LLRegistryDefaultComparator
 {
-	bool operator()(const T& lhs, const T& rhs) { return lhs < rhs; }
-};
-
-template <typename KEY, typename VALUE>
-struct LLRegistryMapSelector
-{
-    typedef std::map<KEY, VALUE> type;
-};
-
-template <typename VALUE>
-struct LLRegistryMapSelector<std::type_info*, VALUE>
-{
-    typedef LLTypeInfoLookup<VALUE> type;
-};
-
-template <typename VALUE>
-struct LLRegistryMapSelector<const std::type_info*, VALUE>
-{
-    typedef LLTypeInfoLookup<VALUE> type;
+	bool operator()(const T& lhs, const T& rhs) const
+	{
+		using std::less;
+		return less<T>()(lhs, rhs);
+	}
 };
 
 template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultComparator<KEY> >
 	{
 		friend class LLRegistry<KEY, VALUE, COMPARATOR>;
 	public:
-		typedef typename LLRegistryMapSelector<KEY, VALUE>::type registry_map_t;
+		typedef std::map<KEY, VALUE, COMPARATOR> registry_map_t;
 
 		bool add(ref_const_key_t key, ref_const_value_t value)
 		{

indra/llcommon/llstl.h

 #include <vector>
 #include <set>
 #include <deque>
+#include <typeinfo>
 
 // Use to compare the first element only of a pair
 // e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t; 
   return llbinder2nd<_Operation>(__oper, _Arg2_type(__x));
 }
 
+/**
+ * Compare std::type_info* pointers a la std::less. We break this out as a
+ * separate function for use in two different std::less specializations.
+ */
+inline
+bool before(const std::type_info* lhs, const std::type_info* rhs)
+{
+#if LL_LINUX && defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
+    // If we're building on Linux with gcc, and it's either gcc 3.x or
+    // 4.{0,1,2,3}, then we have to use a workaround. Note that we use gcc on
+    // Mac too, and some people build with gcc on Windows (cygwin or mingw).
+    // On Linux, different load modules may produce different type_info*
+    // pointers for the same type. Have to compare name strings to get good
+    // results.
+    return strcmp(lhs->name(), rhs->name()) < 0;
+#else  // not Linux, or gcc 4.4+
+    // Just use before(), as we normally would
+    return lhs->before(*rhs);
+#endif
+}
+
+/**
+ * Specialize std::less<std::type_info*> to use std::type_info::before().
+ * See MAINT-1175. It is NEVER a good idea to directly compare std::type_info*
+ * because, on Linux, you might get different std::type_info* pointers for the
+ * same type (from different load modules)!
+ */
+namespace std
+{
+	template <>
+	struct less<const std::type_info*>:
+		public std::binary_function<const std::type_info*, const std::type_info*, bool>
+	{
+		bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
+		{
+			return before(lhs, rhs);
+		}
+	};
+
+	template <>
+	struct less<std::type_info*>:
+		public std::binary_function<std::type_info*, std::type_info*, bool>
+	{
+		bool operator()(std::type_info* lhs, std::type_info* rhs) const
+		{
+			return before(lhs, rhs);
+		}
+	};
+} // std
+
 #endif // LL_LLSTL_H

indra/llcommon/lltypeinfolookup.h

 #if ! defined(LL_LLTYPEINFOLOOKUP_H)
 #define LL_LLTYPEINFOLOOKUP_H
 
-#include "llsortedvector.h"
+#include <boost/unordered_map.hpp>
+#include <boost/functional/hash.hpp>
+#include <boost/optional.hpp>
+#include <functional>               // std::binary_function
 #include <typeinfo>
 
 /**
+ * The following helper classes are based on the Boost.Unordered documentation:
+ * http://www.boost.org/doc/libs/1_45_0/doc/html/unordered/hash_equality.html
+ */
+
+/**
+ * Compute hash for a string passed as const char*
+ */
+struct const_char_star_hash: public std::unary_function<const char*, std::size_t>
+{
+    std::size_t operator()(const char* str) const
+    {
+        std::size_t seed = 0;
+        for ( ; *str; ++str)
+        {
+            boost::hash_combine(seed, *str);
+        }
+        return seed;
+    }
+};
+
+/**
+ * Compute equality for strings passed as const char*
+ *
+ * I (nat) suspect that this is where the default behavior breaks for the
+ * const char* values returned from std::type_info::name(). If you compare the
+ * two const char* pointer values, as a naive, unspecialized implementation
+ * will surely do, they'll compare unequal.
+ */
+struct const_char_star_equal: public std::binary_function<const char*, const char*, bool>
+{
+    bool operator()(const char* lhs, const char* rhs) const
+    {
+        return strcmp(lhs, rhs) == 0;
+    }
+};
+
+/**
  * LLTypeInfoLookup is specifically designed for use cases for which you might
  * consider std::map<std::type_info*, VALUE>. We have several such data
  * structures in the viewer. The trouble with them is that at least on Linux,
  * different load modules will produce different std::type_info*.
  * LLTypeInfoLookup contains a workaround to address this issue.
  *
- * Specifically, when we don't find the passed std::type_info*,
- * LLTypeInfoLookup performs a linear search over registered entries to
- * compare name() strings. Presuming that this succeeds, we cache the new
- * (previously unrecognized) std::type_info* to speed future lookups.
- *
- * This worst-case fallback search (linear search with string comparison)
- * should only happen the first time we look up a given type from a particular
- * load module other than the one from which we initially registered types.
- * (However, a lookup which wouldn't succeed anyway will always have
- * worst-case performance.) This class is probably best used with less than a
- * few dozen different types.
+ * The API deliberately diverges from std::map in several respects:
+ * * It avoids iterators, not only begin()/end() but also as return values
+ *   from insert() and find(). This bypasses transform_iterator overhead.
+ * * Since we literally use compile-time types as keys, the essential insert()
+ *   and find() methods accept the key type as a @em template parameter,
+ *   accepting and returning value_type as a normal runtime value. This is to
+ *   permit future optimization (e.g. compile-time type hashing) without
+ *   changing the API.
  */
 template <typename VALUE>
 class LLTypeInfoLookup
 {
+    // Use this for our underlying implementation: lookup by
+    // std::type_info::name() string. This is one of the rare cases in which I
+    // dare use const char* directly, rather than std::string, because I'm
+    // sure that every value returned by std::type_info::name() is static.
+    // HOWEVER, specify our own hash + equality functors: naively comparing
+    // distinct const char* values won't work.
+    typedef boost::unordered_map<const char*, VALUE,
+                                 const_char_star_hash, const_char_star_equal> impl_map_type;
+
 public:
-    typedef LLTypeInfoLookup<VALUE> self;
-    typedef LLSortedVector<const std::type_info*, VALUE> vector_type;
-    typedef typename vector_type::key_type key_type;
-    typedef typename vector_type::mapped_type mapped_type;
-    typedef typename vector_type::value_type value_type;
-    typedef typename vector_type::iterator iterator;
-    typedef typename vector_type::const_iterator const_iterator;
+    typedef VALUE value_type;
 
     LLTypeInfoLookup() {}
 
-    iterator begin() { return mVector.begin(); }
-    iterator end()   { return mVector.end(); }
-    const_iterator begin() const { return mVector.begin(); }
-    const_iterator end()   const { return mVector.end(); }
-    bool empty() const { return mVector.empty(); }
-    std::size_t size() const { return mVector.size(); }
+    bool empty() const { return mMap.empty(); }
+    std::size_t size() const { return mMap.size(); }
 
-    std::pair<iterator, bool> insert(const std::type_info* key, const VALUE& value)
+    template <typename KEY>
+    bool insert(const value_type& value)
     {
-        return insert(value_type(key, value));
+        // Obtain and store the std::type_info::name() string as the key.
+        // Return just the bool from std::map::insert()'s return pair.
+        return mMap.insert(typename impl_map_type::value_type(typeid(KEY).name(), value)).second;
     }
 
-    std::pair<iterator, bool> insert(const value_type& pair)
+    template <typename KEY>
+    boost::optional<value_type> find() const
     {
-        return mVector.insert(pair);
-    }
-
-    // const find() forwards to non-const find(): this can alter mVector!
-    const_iterator find(const std::type_info* key) const
-    {
-        return const_cast<self*>(this)->find(key);
-    }
-
-    // non-const find() caches previously-unknown type_info* to speed future
-    // lookups.
-    iterator find(const std::type_info* key)
-    {
-        iterator found = mVector.find(key);
-        if (found != mVector.end())
-        {
-            // If LLSortedVector::find() found, great, we're done.
-            return found;
-        }
-        // Here we didn't find the passed type_info*. On Linux, though, even
-        // for the same type, typeid(sametype) produces a different type_info*
-        // when used in different load modules. So the fact that we didn't
-        // find the type_info* we seek doesn't mean this type isn't
-        // registered. Scan for matching name() string.
-        for (typename vector_type::iterator ti(mVector.begin()), tend(mVector.end());
-             ti != tend; ++ti)
-        {
-            if (std::string(ti->first->name()) == key->name())
-            {
-                // This unrecognized 'key' is for the same type as ti->first.
-                // To speed future lookups, insert a new entry that lets us
-                // look up ti->second using this same 'key'.
-                return insert(key, ti->second).first;
-            }
-        }
-        // We simply have never seen a type with this type_info* from any load
-        // module.
-        return mVector.end();
+        // Use the std::type_info::name() string as the key.
+        typename impl_map_type::const_iterator found = mMap.find(typeid(KEY).name());
+        if (found == mMap.end())
+            return boost::optional<value_type>();
+        return found->second;
     }
 
 private:
-    vector_type mVector;
+    impl_map_type mMap;
 };
 
 #endif /* ! defined(LL_LLTYPEINFOLOOKUP_H) */

indra/llimage/llimage.cpp

 	++sRawImageCount;
 }
 
-LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components)
+LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy)
 	: LLImageBase()
 {
 	mMemType = LLMemType::MTYPE_IMAGERAW;
-	if(allocateDataSize(width, height, components))
+
+	if(no_copy)
+	{
+		setDataAndSize(data, width, height, components);
+	}
+	else if(allocateDataSize(width, height, components))
 	{
 		memcpy(getData(), data, width*height*components);
 	}

indra/llimage/llimage.h

 public:
 	LLImageRaw();
 	LLImageRaw(U16 width, U16 height, S8 components);
-	LLImageRaw(U8 *data, U16 width, U16 height, S8 components);
+	LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy = false);
 	// Construct using createFromFile (used by tools)
 	//LLImageRaw(const std::string& filename, bool j2c_lowest_mip_only = false);
 

indra/llimage/llimagej2c.cpp

File contents unchanged.

indra/llkdu/llimagej2ckdu.cpp

 			llassert(mDims == comp_dims); // Safety check; the caller has ensured this
 		}
 		bool use_shorts = (mComps[c].get_bit_depth(true) <= 16);
-		mLines[c].pre_create(&mAllocator,mDims.size.x,mReversible[c],use_shorts);
+		mLines[c].pre_create(&mAllocator,mDims.size.x,mReversible[c],use_shorts,0,0);
 		if (res.which() == 0) // No DWT levels used
 		{
 			mEngines[c] = kdu_decoder(res.access_subband(LL_BAND),&mAllocator,use_shorts);
 	{
 		for (c = 0; c < mNumComponents; c++)
 		{
-			mEngines[c].pull(mLines[c],true);
+			mEngines[c].pull(mLines[c]);
 		}
 		if ((mNumComponents >= 3) && mUseYCC)
 		{

indra/llkdu/llimagej2ckdu.h

 //
 // KDU core header files
 //
+#define KDU_NO_THREADS
 #include "kdu_elementary.h"
 #include "kdu_messaging.h"
 #include "kdu_params.h"

indra/llkdu/llkdumem.h

 #define LL_LLKDUMEM_H
 
 // Support classes for reading and writing from memory buffers in KDU
+#define KDU_NO_THREADS
 #include "kdu_image.h"
 #include "kdu_elementary.h"
 #include "kdu_messaging.h"

indra/llkdu/tests/llimagej2ckdu_test.cpp

 void kdu_resolution::get_dims(kdu_dims& ) { }
 int kdu_resolution::which() { return 0; }
 int kdu_resolution::get_valid_band_indices(int &) { return 1; }
-kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*) { }
 kdu_synthesis::kdu_synthesis(kdu_resolution, kdu_sample_allocator*, bool, float, kdu_thread_env*, kdu_thread_queue*) { }
 kdu_params::kdu_params(const char*, bool, bool, bool, bool, bool) { }
 kdu_params::~kdu_params() { }
 void kdu_codestream::collect_timing_stats(int ) { }
 void kdu_codestream::set_max_bytes(kdu_long, bool, bool ) { }
 void kdu_codestream::get_valid_tiles(kdu_dims& ) { }
-void kdu_codestream::create(siz_params*, kdu_compressed_target*, kdu_dims*, int, kdu_long ) { }
 void kdu_codestream::create(kdu_compressed_source*, kdu_thread_env*) { }
 void kdu_codestream::apply_input_restrictions( int, int, int, int, kdu_dims*, kdu_component_access_mode ) { }
 void kdu_codestream::get_subsampling(int , kdu_coords&, bool ) { }
 bool kdu_codestream_comment::put_text(const char*) { return false; }
 void kdu_customize_warnings(kdu_message*) { }
 void kdu_customize_errors(kdu_message*) { }
-void kdu_convert_ycc_to_rgb(kdu_line_buf&, kdu_line_buf&, kdu_line_buf&, int) { }
+
 kdu_long kdu_multi_analysis::create(kdu_codestream, kdu_tile, bool, kdu_roi_image*, bool, int, kdu_thread_env*, kdu_thread_queue*, bool ) { kdu_long a = 0; return a; }
 siz_params::siz_params() : kdu_params(NULL, false, false, false, false, false) { }
 void siz_params::finalize(bool ) { }
 bool siz_params::check_marker_segment(kdu_uint16, int, kdu_byte a[], int&) { return false; }
 bool siz_params::read_marker_segment(kdu_uint16, int, kdu_byte a[], int) { return false; }
 
+#ifdef LL_LINUX
+// Linux use the old pre KDU v7.0.0
+// *TODO: Supress this legacy stubbs once Linux migrates to v7.0.0
+kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*) { }
+void kdu_codestream::create(siz_params*, kdu_compressed_target*, kdu_dims*, int, kdu_long ) { }
+void kdu_convert_ycc_to_rgb(kdu_line_buf&, kdu_line_buf&, kdu_line_buf&, int) { }
+#else
+kdu_decoder::kdu_decoder(kdu_subband , kdu_sample_allocator*, bool , float, int, kdu_thread_env*, kdu_thread_queue*, int) { }
+void kdu_codestream::create(siz_params*, kdu_compressed_target*, kdu_dims*, int, kdu_long, kdu_thread_env* ) { }
+void (*kdu_convert_ycc_to_rgb_rev16)(kdu_int16*,kdu_int16*,kdu_int16*,int);
+void (*kdu_convert_ycc_to_rgb_irrev16)(kdu_int16*,kdu_int16*,kdu_int16*,int);
+void (*kdu_convert_ycc_to_rgb_rev32)(kdu_int32*,kdu_int32*,kdu_int32*,int);
+void (*kdu_convert_ycc_to_rgb_irrev32)(float*,float*,float*,int);
+#endif
+
 // -------------------------------------------------------------------------------------------
 // TUT
 // -------------------------------------------------------------------------------------------

indra/llmessage/llavatarnamecache.cpp

     /// Time when unrefreshed cached names were checked last
     static F64 sLastExpireCheck;
 
+	/// Time-to-live for a temp cache entry.
+	const F64 TEMP_CACHE_ENTRY_LIFETIME = 60.0;
+
 	//-----------------------------------------------------------------------
 	// Internal methods
 	//-----------------------------------------------------------------------
     {
         // there is no existing cache entry, so make a temporary name from legacy
         LL_WARNS("AvNameCache") << "LLAvatarNameCache get legacy for agent "
-                                << agent_id << LL_ENDL;
+								<< agent_id << LL_ENDL;
         gCacheName->get(agent_id, false,  // legacy compatibility
                         boost::bind(&LLAvatarNameCache::legacyNameCallback,
                                     _1, _2, _3));
         // Clear this agent from the pending list
         LLAvatarNameCache::sPendingQueue.erase(agent_id);
 
-        const LLAvatarName& av_name = existing->second;
+        LLAvatarName& av_name = existing->second;
         LL_DEBUGS("AvNameCache") << "LLAvatarNameCache use cache for agent "
                                  << agent_id 
                                  << "user '" << av_name.mUsername << "' "
                                  << "display '" << av_name.mDisplayName << "' "
                                  << "expires in " << av_name.mExpires - LLFrameTimer::getTotalSeconds() << " seconds"
                                  << LL_ENDL;
+		av_name.mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME; // reset expiry time so we don't constantly rerequest.
     }
 }
 
 							 << LL_ENDL;
 	buildLegacyName(full_name, &av_name);
 
-	// Don't add to cache, the data already exists in the legacy name system
-	// cache and we don't want or need duplicate storage, because keeping the
-	// two copies in sync is complex.
-	processName(agent_id, av_name, false);
+	// Add to cache, because if we don't we'll keep rerequesting the
+	// same record forever.  buildLegacyName should always guarantee
+	// that these records expire reasonably soon
+	// (in TEMP_CACHE_ENTRY_LIFETIME seconds), so if the failure was due
+	// to something temporary we will eventually request and get the right data.
+	processName(agent_id, av_name, true);
 }
 
 void LLAvatarNameCache::requestNamesViaLegacy()
 	av_name->mDisplayName = full_name;
 	av_name->mIsDisplayNameDefault = true;
 	av_name->mIsTemporaryName = true;
-	av_name->mExpires = F64_MAX; // not used because these are not cached
+	av_name->mExpires = LLFrameTimer::getTotalSeconds() + TEMP_CACHE_ENTRY_LIFETIME;
 	LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::buildLegacyName "
 							 << full_name
 							 << LL_ENDL;

indra/llmessage/llcurl.cpp

 
 		if(!completed)
 		{
-		setPriority(LLQueuedThread::PRIORITY_LOW) ;
-	}
+			setPriority(LLQueuedThread::PRIORITY_LOW) ;
+		}
 	}
 
 	return completed ;
 {
 	if(mMulti->isDead())
 	{
-	mCurlThread->deleteMulti(mMulti) ;
+		mCurlThread->deleteMulti(mMulti) ;
 	}
 	else
 	{
 		return ;
 	}
 
+
 	multi->markDead() ;
 }
 
 {
 	getByteRange(url, headers_t(), 0, -1, responder);
 }
-	
+
+// Note: (length==0) is interpreted as "the rest of the file", i.e. the whole file if (offset==0) or
+// the remainder of the file if not.
 bool LLCurlRequest::getByteRange(const std::string& url,
 								 const headers_t& headers,
 								 S32 offset, S32 length,
 		std::string range = llformat("Range: bytes=%d-%d", offset,offset+length-1);
 		easy->slist_append(range.c_str());
 	}
+	else if (offset > 0)
+	{
+		std::string range = llformat("Range: bytes=%d-", offset);
+		easy->slist_append(range.c_str());
+	}
 	easy->setHeaders();
 	bool res = addEasy(easy);
 	return res;
 	return queued;
 }
 
+LLCurlTextureRequest::LLCurlTextureRequest(S32 concurrency) : 
+	LLCurlRequest(), 
+	mConcurrency(concurrency),
+	mInQueue(0),
+	mMutex(NULL),
+	mHandleCounter(1),
+	mTotalIssuedRequests(0),
+	mTotalReceivedBits(0)
+{
+	mGlobalTimer.reset();
+}
+
+LLCurlTextureRequest::~LLCurlTextureRequest()
+{
+	mRequestMap.clear();
+
+	for(req_queue_t::iterator iter = mCachedRequests.begin(); iter != mCachedRequests.end(); ++iter)
+	{
+		delete *iter;
+	}
+	mCachedRequests.clear();
+}
+
+//return 0: success
+// > 0: cached handle
+U32 LLCurlTextureRequest::getByteRange(const std::string& url,
+								 const headers_t& headers,
+								 S32 offset, S32 length, U32 pri,
+								 LLCurl::ResponderPtr responder, F32 delay_time)
+{
+	U32 ret_val = 0;
+	bool success = false;	
+
+	if(mInQueue < mConcurrency && delay_time < 0.f)
+	{
+		success = LLCurlRequest::getByteRange(url, headers, offset, length, responder);		
+	}
+
+	LLMutexLock lock(&mMutex);
+
+	if(success)
+	{
+		mInQueue++;
+		mTotalIssuedRequests++;
+	}
+	else
+	{
+		request_t* request = new request_t(mHandleCounter, url, headers, offset, length, pri, responder);
+		if(delay_time > 0.f)
+		{
+			request->mStartTime = mGlobalTimer.getElapsedTimeF32() + delay_time;
+		}
+
+		mCachedRequests.insert(request);
+		mRequestMap[mHandleCounter] = request;
+		ret_val = mHandleCounter;
+		mHandleCounter++;
+
+		if(!mHandleCounter)
+		{
+			mHandleCounter = 1;
+		}
+	}
+
+	return ret_val;
+}
+
+void LLCurlTextureRequest::completeRequest(S32 received_bytes)
+{
+	LLMutexLock lock(&mMutex);
+
+	llassert_always(mInQueue > 0);
+
+	mInQueue--;
+	mTotalReceivedBits += received_bytes * 8;
+}
+
+void LLCurlTextureRequest::nextRequests()
+{
+	if(mCachedRequests.empty() || mInQueue >= mConcurrency)
+	{
+		return;
+	}
+
+	F32 cur_time = mGlobalTimer.getElapsedTimeF32();
+
+	req_queue_t::iterator iter;	
+	{
+		LLMutexLock lock(&mMutex);
+		iter = mCachedRequests.begin();
+	}
+	while(1)
+	{
+		request_t* request = *iter;
+		if(request->mStartTime < cur_time)
+		{
+			if(!LLCurlRequest::getByteRange(request->mUrl, request->mHeaders, request->mOffset, request->mLength, request->mResponder))
+			{
+				break;
+			}
+
+			LLMutexLock lock(&mMutex);
+			++iter;
+			mInQueue++;
+			mTotalIssuedRequests++;
+			mCachedRequests.erase(request);
+			mRequestMap.erase(request->mHandle);
+			delete request;
+
+			if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
+			{
+				break;
+			}
+		}
+		else
+		{
+			LLMutexLock lock(&mMutex);
+			++iter;
+			if(iter == mCachedRequests.end() || mInQueue >= mConcurrency)
+			{
+				break;
+			}
+		}
+	}
+
+	return;
+}
+
+void LLCurlTextureRequest::updatePriority(U32 handle, U32 pri)
+{
+	if(!handle)
+	{
+		return;
+	}
+
+	LLMutexLock lock(&mMutex);
+
+	std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
+	if(iter != mRequestMap.end())
+	{
+		request_t* req = iter->second;
+		
+		if(req->mPriority != pri)
+		{
+			mCachedRequests.erase(req);
+			req->mPriority = pri;
+			mCachedRequests.insert(req);
+		}
+	}
+}
+
+void LLCurlTextureRequest::removeRequest(U32 handle)
+{
+	if(!handle)
+	{
+		return;
+	}
+
+	LLMutexLock lock(&mMutex);
+
+	std::map<S32, request_t*>::iterator iter = mRequestMap.find(handle);
+	if(iter != mRequestMap.end())
+	{
+		request_t* req = iter->second;
+		mRequestMap.erase(iter);
+		mCachedRequests.erase(req);
+		delete req;
+	}
+}
+
+bool LLCurlTextureRequest::isWaiting(U32 handle)
+{
+	if(!handle)
+	{
+		return false;
+	}
+
+	LLMutexLock lock(&mMutex);
+	return mRequestMap.find(handle) != mRequestMap.end();
+}
+
+U32 LLCurlTextureRequest::getTotalReceivedBits()
+{
+	LLMutexLock lock(&mMutex);
+
+	U32 bits = mTotalReceivedBits;
+	mTotalReceivedBits = 0;
+	return bits;
+}
+
+U32 LLCurlTextureRequest::getTotalIssuedRequests()
+{
+	LLMutexLock lock(&mMutex);
+	return mTotalIssuedRequests;
+}
+
+S32 LLCurlTextureRequest::getNumRequests()
+{
+	LLMutexLock lock(&mMutex);
+	return mInQueue;
+}
+
 ////////////////////////////////////////////////////////////////////////////
 // For generating one easy request
 // associated with a single multi request

indra/llmessage/llcurl.h

 	BOOL mProcessing;
 };
 
+//for texture fetch only
+class LLCurlTextureRequest : public LLCurlRequest
+{
+public:
+	LLCurlTextureRequest(S32 concurrency);
+	~LLCurlTextureRequest();
+
+	U32 getByteRange(const std::string& url, const headers_t& headers, S32 offset, S32 length, U32 pri, LLCurl::ResponderPtr responder, F32 delay_time = -1.f);
+	void nextRequests();
+	void completeRequest(S32 received_bytes);
+
+	void updatePriority(U32 handle, U32 pri);
+	void removeRequest(U32 handle);
+
+	U32 getTotalReceivedBits();
+	U32 getTotalIssuedRequests();
+	S32 getNumRequests();
+	bool isWaiting(U32 handle);
+	
+private:
+	LLMutex mMutex;
+	S32 mConcurrency;
+	S32 mInQueue; //request currently in queue.
+	U32 mHandleCounter;
+	U32 mTotalIssuedRequests;
+	U32 mTotalReceivedBits;
+
+	typedef struct _request_t
+	{
+		_request_t(U32 handle, const std::string& url, const headers_t& headers, S32 offset, S32 length, U32 pri, LLCurl::ResponderPtr responder) :
+				mHandle(handle), mUrl(url), mHeaders(headers), mOffset(offset), mLength(length), mPriority(pri), mResponder(responder), mStartTime(0.f)
+				{}
+
+		U32  mHandle;
+		std::string mUrl;
+		LLCurlRequest::headers_t mHeaders;
+		S32 mOffset;
+		S32 mLength;
+		LLCurl::ResponderPtr mResponder;
+		U32 mPriority;
+		F32 mStartTime; //start time to issue this request
+	} request_t;
+
+	struct request_compare
+	{
+		bool operator()(const request_t* lhs, const request_t* rhs) const
+		{
+			if(lhs->mPriority != rhs->mPriority)
+			{
+				return lhs->mPriority > rhs->mPriority; // higher priority in front of queue (set)
+			}
+			else
+			{
+				return (U32)lhs < (U32)rhs;
+			}
+		}
+	};
+
+	typedef std::set<request_t*, request_compare> req_queue_t;
+	req_queue_t mCachedRequests;
+	std::map<S32, request_t*> mRequestMap;
+
+	LLFrameTimer mGlobalTimer;
+};
+
 class LLCurlEasyRequest
 {
 public:

indra/llprimitive/llprimitive.cpp

 LLPrimitive::LLPrimitive()
 :	mTextureList(),
 	mNumTEs(0),
-	mMiscFlags(0)
+	mMiscFlags(0),
+	mNumBumpmapTEs(0)
 {
 	mPrimitiveCode = 0;
 
 //===============================================================
 void LLPrimitive::setTE(const U8 index, const LLTextureEntry& te)
 {
-	mTextureList.copyTexture(index, te);
+	if(mTextureList.copyTexture(index, te) != TEM_CHANGE_NONE && te.getBumpmap() > 0)
+	{
+		mNumBumpmapTEs++;
+	}
 }
 
 S32  LLPrimitive::setTETexture(const U8 index, const LLUUID &id)
 //===============================================================
 S32  LLPrimitive::setTEBumpShinyFullbright(const U8 index, const U8 bump)
 {
+	updateNumBumpmap(index, bump);
 	return mTextureList.setBumpShinyFullbright(index, bump);
 }
 
 
 S32  LLPrimitive::setTEBumpmap(const U8 index, const U8 bump)
 {
+	updateNumBumpmap(index, bump);
 	return mTextureList.setBumpMap(index, bump);
 }
 
 S32  LLPrimitive::setTEBumpShiny(const U8 index, const U8 bump_shiny)
 {
+	updateNumBumpmap(index, bump_shiny);
 	return mTextureList.setBumpShiny(index, bump_shiny);
 }
 
 	mTextureList.take(other_list);
 }
 
+void LLPrimitive::updateNumBumpmap(const U8 index, const U8 bump)
+{
+	LLTextureEntry* te = getTE(index);
+	if(!te)
+	{
+		return;
+	}
+
+	U8 old_bump = te->getBumpmap();	
+	if(old_bump > 0)
+	{
+		mNumBumpmapTEs--;
+	}
+	if((bump & TEM_BUMP_MASK) > 0)
+	{
+		mNumBumpmapTEs++;
+	}
+
+	return;
+}
 //============================================================================
 
 // Moved from llselectmgr.cpp

indra/llprimitive/llprimitive.h

 	inline BOOL	isAvatar() const;
 	inline BOOL	isSittingAvatar() const;
 	inline BOOL	isSittingAvatarOnGround() const;
-
+	inline bool hasBumpmap() const  { return mNumBumpmapTEs > 0;}
+	
 	void setFlags(U32 flags) { mMiscFlags = flags; }
 	void addFlags(U32 flags) { mMiscFlags |= flags; }
 	void removeFlags(U32 flags) { mMiscFlags &= ~flags; }
 	inline static BOOL isPrimitive(const LLPCode pcode);
 	inline static BOOL isApp(const LLPCode pcode);
 
+private:
+	void updateNumBumpmap(const U8 index, const U8 bump);
+
 protected:
 	LLPCode				mPrimitiveCode;		// Primitive code
 	LLVector3			mVelocity;			// how fast are we moving?
 	LLPrimTextureList	mTextureList;		// list of texture GUIDs, scales, offsets
 	U8					mMaterial;			// Material code
 	U8					mNumTEs;			// # of faces on the primitve	
+	U8                  mNumBumpmapTEs;     // number of bumpmap TEs.
 	U32 				mMiscFlags;			// home for misc bools
 
 public:

indra/llrender/llglstates.h

 	LLGLEnable mColorMaterial;
 	LLGLDisable mAlphaTest, mBlend, mCullFace, mDither, mFog, 
 		mLineSmooth, mLineStipple, mNormalize, mPolygonSmooth,
-		mTextureGenQ, mTextureGenR, mTextureGenS, mTextureGenT,
 		mGLMultisample;
 public:
 	LLGLSDefault()
 		mLineStipple(GL_LINE_STIPPLE),
 		mNormalize(GL_NORMALIZE),
 		mPolygonSmooth(GL_POLYGON_SMOOTH),
-		mTextureGenQ(GL_TEXTURE_GEN_Q), 
-		mTextureGenR(GL_TEXTURE_GEN_R),
-		mTextureGenS(GL_TEXTURE_GEN_S), 
-		mTextureGenT(GL_TEXTURE_GEN_T),
 		mGLMultisample(GL_MULTISAMPLE_ARB)
 	{ }
 };

indra/llrender/llimagegl.cpp

 	return check_power_of_two(width) && check_power_of_two(height);
 }
 
-void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents)
+void LLImageGL::setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level)
 {
 	if (width != mWidth || height != mHeight || ncomponents != mComponents)
 	{
 				width >>= 1;
 				height >>= 1;
 			}
+
+			if(discard_level > 0)
+			{
+				mMaxDiscardLevel = llmax(mMaxDiscardLevel, (S8)discard_level);
+			}
 		}
 		else
 		{
 		llassert(mCurrentDiscardLevel >= 0);
 		discard_level = mCurrentDiscardLevel;
 	}
-	discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
-
+	
 	// Actual image width/height = raw image width/height * 2^discard_level
 	S32 w = raw_image->getWidth() << discard_level;
 	S32 h = raw_image->getHeight() << discard_level;
 
 	// setSize may call destroyGLTexture if the size does not match
-	setSize(w, h, raw_image->getComponents());
+	setSize(w, h, raw_image->getComponents(), discard_level);
 
 	if( !mHasExplicitFormat )
 	{
 		llassert(mCurrentDiscardLevel >= 0);
 		discard_level = mCurrentDiscardLevel;
 	}
-	discard_level = llclamp(discard_level, 0, (S32)mMaxDiscardLevel);
-
+	
 	// Actual image width/height = raw image width/height * 2^discard_level
 	S32 raw_w = imageraw->getWidth() ;
 	S32 raw_h = imageraw->getHeight() ;
 	S32 h = raw_h << discard_level;
 
 	// setSize may call destroyGLTexture if the size does not match
-	setSize(w, h, imageraw->getComponents());
+	setSize(w, h, imageraw->getComponents(), discard_level);
 
 	if( !mHasExplicitFormat )
 	{

indra/llrender/llimagegl.h

 public:
 	virtual void dump();	// debugging info to llinfos
 	
-	void setSize(S32 width, S32 height, S32 ncomponents);
+	void setSize(S32 width, S32 height, S32 ncomponents, S32 discard_level = -1);
 	void setComponents(S32 ncomponents) { mComponents = (S8)ncomponents ;}
 	void setAllowCompression(bool allow) { mAllowCompression = allow; }
 

indra/llrender/llrender.cpp

 		gGL.flush();
 		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);
 	}
-
+	
 	// We want an early out, because this function does a LOT of stuff.
 	if ( ( (isAlpha && (mCurrAlphaOp == op) && (mCurrAlphaSrc1 == src1) && (mCurrAlphaSrc2 == src2))
 			|| (!isAlpha && (mCurrColorOp == op) && (mCurrColorSrc1 == src1) && (mCurrColorSrc2 == src2)) ) && !gGL.mDirty)
 	mMatrixMode = mode;
 }
 
+U32 LLRender::getMatrixMode()
+{
+	if (mMatrixMode >= MM_TEXTURE0 && mMatrixMode <= MM_TEXTURE3)
+	{ //always return MM_TEXTURE if current matrix mode points at any texture matrix
+		return MM_TEXTURE;
+	}
+
+	return mMatrixMode;
+}
+
+
 void LLRender::loadIdentity()
 {
 	flush();

indra/llrender/llrender.h

 	void loadIdentity();
 	void multMatrix(const GLfloat* m);
 	void matrixMode(U32 mode);	
+	U32 getMatrixMode();
 
 	const glh::matrix4f& getModelviewMatrix();
 	const glh::matrix4f& getProjectionMatrix();

indra/llrender/llshadermgr.cpp

 		text[count++] = strdup("#define textureCube texture\n");
 		text[count++] = strdup("#define texture2DLod textureLod\n");
 		text[count++] = strdup("#define	shadow2D(a,b) vec2(texture(a,b))\n");
-
+		
 		if (major_version > 1 || minor_version >= 40)
 		{ //GLSL 1.40 replaces texture2DRect et al with texture
 			text[count++] = strdup("#define texture2DRect texture\n");

indra/llrender/llvertexbuffer.cpp

 
 
 
+
 void LLVBOPool::cleanup()
 {
 	U32 size = LL_VBO_BLOCK_SIZE;

indra/llui/CMakeLists.txt

     llflyoutbutton.h 
     llfocusmgr.h
     llfunctorregistry.h
-    llhandle.h
     llhelp.h
     lliconctrl.h
     llkeywords.h

indra/llui/llfloater.cpp

File contents unchanged.

indra/llui/llhandle.h

-/** 
-* @file llhandle.h
-* @brief "Handle" to an object (usually a floater) whose lifetime you don't
-* control.
-*
-* $LicenseInfo:firstyear=2001&license=viewerlgpl$
-* Second Life Viewer Source Code
-* Copyright (C) 2010, Linden Research, Inc.
-* 
-* This library is free software; you can redistribute it and/or
-* modify it under the terms of the GNU Lesser General Public
-* License as published by the Free Software Foundation;
-* version 2.1 of the License only.
-* 
-* This library is distributed in the hope that it will be useful,
-* but WITHOUT ANY WARRANTY; without even the implied warranty of
-* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-* Lesser General Public License for more details.
-* 
-* You should have received a copy of the GNU Lesser General Public
-* License along with this library; if not, write to the Free Software
-* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-* 
-* Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
-* $/LicenseInfo$
-*/
-#ifndef LLHANDLE_H
-#define LLHANDLE_H
-
-#include "llpointer.h"
-#include <boost/type_traits/is_convertible.hpp>
-#include <boost/utility/enable_if.hpp>
-
-class LLTombStone : public LLRefCount
-{
-public:
-	LLTombStone(void* target = NULL) : mTarget(target) {}
-
-	void setTarget(void* target) { mTarget = target; }
-	void* getTarget() const { return mTarget; }
-private:
-	mutable void* mTarget;
-};
-
-//	LLHandles are used to refer to objects whose lifetime you do not control or influence.  
-//	Calling get() on a handle will return a pointer to the referenced object or NULL, 
-//	if the object no longer exists.  Note that during the lifetime of the returned pointer, 
-//	you are assuming that the object will not be deleted by any action you perform, 
-//	or any other thread, as normal when using pointers, so avoid using that pointer outside of
-//	the local code block.
-// 
-//  https://wiki.lindenlab.com/mediawiki/index.php?title=LLHandle&oldid=79669
-
-template <typename T>
-class LLHandle
-{
-	template <typename U> friend class LLHandle;
-	template <typename U> friend class LLHandleProvider;
-public:
-	LLHandle() : mTombStone(getDefaultTombStone()) {}
-
-	template<typename U>
-	LLHandle(const LLHandle<U>& other, typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0)
-	: mTombStone(other.mTombStone)
-	{}
-
-	bool isDead() const 
-	{ 
-		return mTombStone->getTarget() == NULL; 
-	}
-
-	void markDead() 
-	{ 
-		mTombStone = getDefaultTombStone();
-	}
-
-	T* get() const
-	{
-		return reinterpret_cast<T*>(mTombStone->getTarget());
-	}
-
-	friend bool operator== (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
-	{
-		return lhs.mTombStone == rhs.mTombStone;
-	}
-	friend bool operator!= (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
-	{
-		return !(lhs == rhs);
-	}
-	friend bool	operator< (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
-	{
-		return lhs.mTombStone < rhs.mTombStone;
-	}
-	friend bool	operator> (const LLHandle<T>& lhs, const LLHandle<T>& rhs)
-	{
-		return lhs.mTombStone > rhs.mTombStone;
-	}
-
-protected:
-	LLPointer<LLTombStone> mTombStone;
-
-private:
-	typedef T* pointer_t;
-	static LLPointer<LLTombStone>& getDefaultTombStone()
-	{
-		static LLPointer<LLTombStone> sDefaultTombStone = new LLTombStone;
-		return sDefaultTombStone;
-	}
-};
-
-template <typename T>
-class LLRootHandle : public LLHandle<T>
-{
-public:
-	typedef LLRootHandle<T> self_t;
-	typedef LLHandle<T> base_t;
-
-	LLRootHandle(T* object) { bind(object); }
-	LLRootHandle() {};
-	~LLRootHandle() { unbind(); }
-
-	// this is redundant, since an LLRootHandle *is* an LLHandle
-	//LLHandle<T> getHandle() { return LLHandle<T>(*this); }
-
-	void bind(T* object) 
-	{ 
-		// unbind existing tombstone
-		if (LLHandle<T>::mTombStone.notNull())
-		{
-			if (LLHandle<T>::mTombStone->getTarget() == (void*)object) return;
-			LLHandle<T>::mTombStone->setTarget(NULL);
-		}
-		// tombstone reference counted, so no paired delete
-		LLHandle<T>::mTombStone = new LLTombStone((void*)object);
-	}
-
-	void unbind() 
-	{
-		LLHandle<T>::mTombStone->setTarget(NULL);
-	}
-
-	//don't allow copying of root handles, since there should only be one
-private:
-	LLRootHandle(const LLRootHandle& other) {};
-};
-
-// Use this as a mixin for simple classes that need handles and when you don't
-// want handles at multiple points of the inheritance hierarchy
-template <typename T>
-class LLHandleProvider
-{
-public:
-	LLHandle<T> getHandle() const
-	{ 
-		// perform lazy binding to avoid small tombstone allocations for handle
-		// providers whose handles are never referenced
-		mHandle.bind(static_cast<T*>(const_cast<LLHandleProvider<T>* >(this))); 
-		return mHandle; 
-	}
-
-protected:
-	typedef LLHandle<T> handle_type_t;
-	LLHandleProvider() 
-	{
-		// provided here to enforce T deriving from LLHandleProvider<T>
-	} 
-
-	template <typename U>
-	LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
-	{
-		LLHandle<U> downcast_handle;
-		downcast_handle.mTombStone = getHandle().mTombStone;
-		return downcast_handle;
-	}
-
-
-private:
-	mutable LLRootHandle<T> mHandle;
-};
-
-#endif

indra/llui/llradiogroup.cpp

File contents unchanged.

indra/llui/llrngwriter.cpp

File contents unchanged.

indra/llui/llscrolllistcolumn.cpp

File contents unchanged.

indra/llui/llscrolllistctrl.cpp

 	return !mSortColumns.empty();
 }
 
+void LLScrollListCtrl::clearSortOrder()
+{
+	mSortColumns.clear();
+}
+
 void LLScrollListCtrl::clearColumns()
 {
 	column_map_t::iterator itor;

indra/llui/llscrolllistctrl.h

 	std::string     getSortColumnName();
 	BOOL			getSortAscending() { return mSortColumns.empty() ? TRUE : mSortColumns.back().second; }
 	BOOL			hasSortOrder() const;
+	void			clearSortOrder();
 
 	S32		selectMultiple( uuid_vec_t ids );
 	// conceptually const, but mutates mItemList

indra/llui/lltextbase.cpp

File contents unchanged.

indra/llui/lltooltip.cpp

File contents unchanged.

indra/llui/lluictrlfactory.cpp

File contents unchanged.

indra/llui/lluictrlfactory.h

 #include "llinitparam.h"
 #include "llregistry.h"
 #include "llxuiparser.h"
+#include "llstl.h"
 
 class LLView;
 
-// sort functor for typeid maps
-struct LLCompareTypeID
-{
-	bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
-	{
-		return lhs->before(*rhs);
-	}
-};
-
 // lookup widget constructor funcs by widget name
 template <typename DERIVED_TYPE>
 class LLChildRegistry : public LLRegistrySingleton<std::string, LLWidgetCreatorFunc, DERIVED_TYPE>
 
 // lookup widget name by type
 class LLWidgetNameRegistry 
-:	public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry , LLCompareTypeID>
+:	public LLRegistrySingleton<const std::type_info*, std::string, LLWidgetNameRegistry>
 {};
 
 // lookup function for generating empty param block by widget type
 // this is used for schema generation
 //typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();
 //class LLDefaultParamBlockRegistry
-//:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID>
+//:	public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry>
 //{};
 
 extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP;

indra/llui/llxuiparser.cpp

File contents unchanged.

indra/llui/llxuiparser.h

File contents unchanged.

indra/newview/CMakeLists.txt

File contents unchanged.