diff --git a/doc/contributions.txt b/doc/contributions.txt
index ff5f76ca3ee3f64fb4254f378ea5f0a592982178..8ae828e7385e18ca31bd4f3e4f0ca6081ef7f8fc 100755
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -265,6 +265,7 @@ Benjamin Bigdipper
 Beq Janus
 	BUG-227094
 	SL-10288
+    SL-11300
 	SL-13583
 	SL-14766
 Beth Walcher
@@ -1356,6 +1357,12 @@ Sovereign Engineer
     SL-11079
     OPEN-343
 	SL-11625
+	SL-14705
+	SL-14706
+	SL-14707
+	SL-14731
+	SL-14732
+	SL-15096
 SpacedOut Frye
 	VWR-34
 	VWR-45
diff --git a/indra/edit-me-to-trigger-new-build.txt b/indra/edit-me-to-trigger-new-build.txt
index 48082f72f087ce7e6fa75b9c41d7387daecd447b..5366987cff8af097af8af87892cfa26ba97f3ddf 100644
--- a/indra/edit-me-to-trigger-new-build.txt
+++ b/indra/edit-me-to-trigger-new-build.txt
@@ -1 +1,3 @@
-12
+euclid 5/29/2020
+euclid 7/23/2020
+euclid 4/29/2021
\ No newline at end of file
diff --git a/indra/llappearance/llavatarjoint.cpp b/indra/llappearance/llavatarjoint.cpp
index 80b3e42b52904b7a32d2b63097d24b441a3cc7d8..a1d4fe6423e222e59f62dcab8b86964179579e56 100644
--- a/indra/llappearance/llavatarjoint.cpp
+++ b/indra/llappearance/llavatarjoint.cpp
@@ -103,7 +103,7 @@ void LLAvatarJoint::setValid( BOOL valid, BOOL recursive )
 		for (joints_t::iterator iter = mChildren.begin();
 			 iter != mChildren.end(); ++iter)
 		{
-			LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
+			LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
 			joint->setValid(valid, TRUE);
 		}
 	}
@@ -136,7 +136,7 @@ void LLAvatarJoint::setVisible(BOOL visible, BOOL recursive)
 		for (joints_t::iterator iter = mChildren.begin();
 			 iter != mChildren.end(); ++iter)
 		{
-			LLAvatarJoint* joint = (LLAvatarJoint*)(*iter);
+			LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
 			joint->setVisible(visible, recursive);
 		}
 	}
@@ -167,7 +167,7 @@ void LLAvatarJoint::updateJointGeometry()
 	for (joints_t::iterator iter = mChildren.begin();
 		 iter != mChildren.end(); ++iter)
 	{
-		LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(*iter);
+		LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(*iter);
 		joint->updateJointGeometry();
 	}
 }
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 255b50c8d04516d3e3da19c77c2dd4766346639a..565d7cfb6372246b569aa6b1013e55c8940813f7 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -29,7 +29,7 @@
 #ifndef LL_LLAPR_H
 #define LL_LLAPR_H
 
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX
 #include <sys/param.h>  // Need PATH_MAX in APR headers...
 #endif
 
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index 08ea668964eec0e1fb18e1e8f22405dd37c7f429..5b6a7b82f803bf35b455d4b37ffcb83b7b326b41 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -43,7 +43,7 @@
 
 #if LL_WINDOWS
 #include "lltimer.h"
-#elif LL_LINUX || LL_SOLARIS
+#elif LL_LINUX
 #include <sys/time.h>
 #include <sched.h>
 #include "lltimer.h"
@@ -64,7 +64,7 @@ bool        BlockTimer::sLog		     = false;
 std::string BlockTimer::sLogName         = "";
 bool        BlockTimer::sMetricLog       = false;
 
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX
 U64         BlockTimer::sClockResolution = 1000000000; // Nanosecond resolution
 #else
 U64         BlockTimer::sClockResolution = 1000000; // Microsecond resolution
@@ -151,12 +151,12 @@ void BlockTimer::setLogLock(LLMutex* lock)
 
 
 //static
-#if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
+#if (LL_DARWIN || LL_LINUX) && !(defined(__i386__) || defined(__amd64__))
 U64 BlockTimer::countsPerSecond()
 {
 	return sClockResolution;
 }
-#else // windows or x86-mac or x86-linux or x86-solaris
+#else // windows or x86-mac or x86-linux
 U64 BlockTimer::countsPerSecond()
 {
 #if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 5628a05b00d1d94f407192a39644d5d61aee6c98..dfc63d08a2979203866b0cf6ff7647e66867853e 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -125,9 +125,9 @@ class BlockTimer
 #endif
 
 
-#if (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
+#if (LL_LINUX) && !(defined(__i386__) || defined(__amd64__))
 	//
-	// Linux and Solaris implementation of CPU clock - non-x86.
+	// Linux implementation of CPU clock - non-x86.
 	// This is accurate but SLOW!  Only use out of desperation.
 	//
 	// Try to use the MONOTONIC clock if available, this is a constant time counter
@@ -153,12 +153,12 @@ class BlockTimer
 		return (U32)(getCPUClockCount64() >> 8);
 	}
 
-#endif // (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
+#endif // (LL_LINUX) && !(defined(__i386__) || defined(__amd64__))
 
 
-#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
+#if (LL_LINUX || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
 	//
-	// Mac+Linux+Solaris FAST x86 implementation of CPU clock
+	// Mac+Linux FAST x86 implementation of CPU clock
 	static U32 getCPUClockCount32()
 	{
 		U32 low(0),high(0);
diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp
index 1884d6f04fbdab37acae68de43c5eccc9f873860..ea84e4c1ea1baf971233db28fed511180828ca80 100644
--- a/indra/llcommon/llmemory.cpp
+++ b/indra/llcommon/llmemory.cpp
@@ -35,7 +35,7 @@
 # include <sys/types.h>
 # include <mach/task.h>
 # include <mach/mach_init.h>
-#elif LL_LINUX || LL_SOLARIS
+#elif LL_LINUX
 # include <unistd.h>
 #endif
 
@@ -55,7 +55,6 @@ static LLTrace::SampleStatHandle<F64Megabytes> sVirtualMem("virtual_mem", "virtu
 U32Kilobytes LLMemory::sAllocatedMemInKB(0);
 U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
 U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
-BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
 
 void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
 {
@@ -75,10 +74,9 @@ void ll_assert_aligned_func(uintptr_t ptr,U32 alignment)
 }
 
 //static 
-void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure)
+void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size)
 {
 	sMaxHeapSizeInKB = U32Kilobytes::convert(max_heap_size);
-	sEnableMemoryFailurePrevention = prevent_heap_failure ;
 }
 
 //static 
@@ -158,56 +156,6 @@ void LLMemory::logMemoryInfo(BOOL update)
 	LL_INFOS() << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << LL_ENDL ;
 }
 
-//return 0: everything is normal;
-//return 1: the memory pool is low, but not in danger;
-//return -1: the memory pool is in danger, is about to crash.
-//static 
-bool LLMemory::isMemoryPoolLow()
-{
-	static const U32Megabytes LOW_MEMORY_POOL_THRESHOLD(64);
-	const static U32Megabytes MAX_SIZE_CHECKED_MEMORY_BLOCK(64);
-	static void* last_reserved_address = NULL ;
-
-	if(!sEnableMemoryFailurePrevention)
-	{
-		return false ; //no memory failure prevention.
-	}
-
-	if(sAvailPhysicalMemInKB < (LOW_MEMORY_POOL_THRESHOLD / 4)) //out of physical memory
-	{
-		return true ;
-	}
-
-	if(sAllocatedPageSizeInKB + (LOW_MEMORY_POOL_THRESHOLD / 4) > sMaxHeapSizeInKB) //out of virtual address space.
-	{
-		return true ;
-	}
-
-	bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD 
-						|| sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ;
-
-	//check the virtual address space fragmentation
-	if(!is_low)
-	{
-		if(!last_reserved_address)
-		{
-			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
-		}
-		else
-		{
-			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
-			if(!last_reserved_address) //failed, try once more
-			{
-				last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
-			}
-		}
-
-		is_low = !last_reserved_address ; //allocation failed
-	}
-
-	return is_low ;
-}
-
 //static 
 U32Kilobytes LLMemory::getAvailableMemKB() 
 {
@@ -309,35 +257,6 @@ U64 LLMemory::getCurrentRSS()
 	return rss;
 }
 
-#elif LL_SOLARIS
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#define _STRUCTURED_PROC 1
-#include <sys/procfs.h>
-
-U64 LLMemory::getCurrentRSS()
-{
-	char path [LL_MAX_PATH];	/* Flawfinder: ignore */ 
-
-	sprintf(path, "/proc/%d/psinfo", (int)getpid());
-	int proc_fd = -1;
-	if((proc_fd = open(path, O_RDONLY)) == -1){
-		LL_WARNS() << "LLmemory::getCurrentRSS() unable to open " << path << ". Returning 0 RSS!" << LL_ENDL;
-		return 0;
-	}
-	psinfo_t proc_psinfo;
-	if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
-		LL_WARNS() << "LLmemory::getCurrentRSS() Unable to read from " << path << ". Returning 0 RSS!" << LL_ENDL;
-		close(proc_fd);
-		return 0;
-	}
-
-	close(proc_fd);
-
-	return((U64)proc_psinfo.pr_rssize * 1024);
-}
-
 #else
 
 U64 LLMemory::getCurrentRSS()
diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h
index f04ae5f5cbe8b7419a789e090b7cdaed49cc5e5b..24f86cc11ee3a7b5c9d0b567e2907539b8fee015 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -344,10 +344,9 @@ class LL_COMMON_API LLMemory
 	// Return value is zero if not known.
 	static U64 getCurrentRSS();
 	static void* tryToAlloc(void* address, U32 size);
-	static void initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure);
+	static void initMaxHeapSizeGB(F32Gigabytes max_heap_size);
 	static void updateMemoryInfo() ;
 	static void logMemoryInfo(BOOL update = FALSE);
-	static bool isMemoryPoolLow();
 
 	static U32Kilobytes getAvailableMemKB() ;
 	static U32Kilobytes getMaxMemKB() ;
@@ -359,7 +358,6 @@ class LL_COMMON_API LLMemory
 	static U32Kilobytes sAllocatedPageSizeInKB ;
 
 	static U32Kilobytes sMaxHeapSizeInKB;
-	static BOOL sEnableMemoryFailurePrevention;
 };
 
 // LLRefCount moved to llrefcount.h
diff --git a/indra/llcommon/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index bae402110aa3f8326ccdc5674681aff97650fadc..b17a8e761a1f5b6dd50fa9c803185c3ed15abf21 100644
--- a/indra/llcommon/llpreprocessor.h
+++ b/indra/llcommon/llpreprocessor.h
@@ -34,16 +34,7 @@
 #include <endian.h>
 #endif	//	LL_LINUX
 
-#if LL_SOLARIS
-#   ifdef  __sparc     // Since we're talking Solaris 10 and up, only 64 bit is supported.
-#      define LL_BIG_ENDIAN 1
-#      define LL_SOLARIS_ALIGNED_CPU 1     //  used to designate issues where SPARC alignment is addressed
-#      define LL_SOLARIS_NON_MESA_GL 1      //  The SPARC GL does not provide a MESA-based GL API
-#   endif
-#   include <sys/isa_defs.h> // ensure we know which end is up
-#endif // LL_SOLARIS
-
-#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)) || (defined(LL_SOLARIS) && defined(__i386)))
+#if (defined(LL_WINDOWS) || (defined(LL_LINUX) && (__BYTE_ORDER == __LITTLE_ENDIAN)) || (defined(LL_DARWIN) && defined(__LITTLE_ENDIAN__)))
 #define LL_LITTLE_ENDIAN 1
 #else
 #define LL_BIG_ENDIAN 1
diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp
index 3f3edb661fdc1183d91f3e7e21cfefca93d6e300..eb3a96b1333d6d6902ea277b5c46ed60905f5829 100644
--- a/indra/llcommon/llsdutil.cpp
+++ b/indra/llcommon/llsdutil.cpp
@@ -33,7 +33,7 @@
 #if LL_WINDOWS
 #	define WIN32_LEAN_AND_MEAN
 #	include <winsock2.h>	// for htonl
-#elif LL_LINUX || LL_SOLARIS
+#elif LL_LINUX
 #	include <netinet/in.h>
 #elif LL_DARWIN
 #	include <arpa/inet.h>
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 6b1a1e0a03288f86e06fdea14b395f4c75589aad..4263122f366f8668f5d76b460cab418292c54a4a 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -37,7 +37,7 @@
 #include <map>
 #include "llformat.h"
 
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX
 #include <wctype.h>
 #include <wchar.h>
 #endif
@@ -45,16 +45,10 @@
 #include <string.h>
 #include <boost/scoped_ptr.hpp>
 
-#if LL_SOLARIS
-// stricmp and strnicmp do not exist on Solaris:
-#define stricmp strcasecmp
-#define strnicmp strncasecmp
-#endif
-
 const char LL_UNKNOWN_CHAR = '?';
 class LLSD;
 
-#if LL_DARWIN || LL_LINUX || LL_SOLARIS
+#if LL_DARWIN || LL_LINUX
 // Template specialization of char_traits for U16s. Only necessary on Mac and Linux (exists on Windows already)
 #include <cstring>
 
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index eff4dd91ea3ab3feae954559f64bcfdf4154e852..4e61fb8a5805bce07f583e958675da0b33756a64 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -88,17 +88,6 @@ using namespace llsd;
 #   include <stdexcept>
 const char MEMINFO_FILE[] = "/proc/meminfo";
 #   include <gnu/libc-version.h>
-#elif LL_SOLARIS
-#	include <stdio.h>
-#	include <unistd.h>
-#	include <sys/utsname.h>
-#	define _STRUCTURED_PROC 1
-#	include <sys/procfs.h>
-#	include <sys/types.h>
-#	include <sys/stat.h>
-#	include <fcntl.h>
-#	include <errno.h>
-extern int errno;
 #endif
 
 LLCPUInfo gSysCPU;
@@ -544,8 +533,6 @@ const std::string& LLOSInfo::getOSVersionString() const
 U32 LLOSInfo::getProcessVirtualSizeKB()
 {
 	U32 virtual_size = 0;
-#if LL_WINDOWS
-#endif
 #if LL_LINUX
 #   define STATUS_SIZE 2048	
 	LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
@@ -565,24 +552,6 @@ U32 LLOSInfo::getProcessVirtualSizeKB()
 		}
 		fclose(status_filep);
 	}
-#elif LL_SOLARIS
-	char proc_ps[LL_MAX_PATH];
-	sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
-	int proc_fd = -1;
-	if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
-		LL_WARNS() << "unable to open " << proc_ps << LL_ENDL;
-		return 0;
-	}
-	psinfo_t proc_psinfo;
-	if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
-		LL_WARNS() << "Unable to read " << proc_ps << LL_ENDL;
-		close(proc_fd);
-		return 0;
-	}
-
-	close(proc_fd);
-
-	virtual_size = proc_psinfo.pr_size;
 #endif
 	return virtual_size;
 }
@@ -591,8 +560,6 @@ U32 LLOSInfo::getProcessVirtualSizeKB()
 U32 LLOSInfo::getProcessResidentSizeKB()
 {
 	U32 resident_size = 0;
-#if LL_WINDOWS
-#endif
 #if LL_LINUX
 	LLFILE* status_filep = LLFile::fopen("/proc/self/status", "rb");
 	if (status_filep != NULL)
@@ -611,24 +578,6 @@ U32 LLOSInfo::getProcessResidentSizeKB()
 		}
 		fclose(status_filep);
 	}
-#elif LL_SOLARIS
-	char proc_ps[LL_MAX_PATH];
-	sprintf(proc_ps, "/proc/%d/psinfo", (int)getpid());
-	int proc_fd = -1;
-	if((proc_fd = open(proc_ps, O_RDONLY)) == -1){
-		LL_WARNS() << "unable to open " << proc_ps << LL_ENDL;
-		return 0;
-	}
-	psinfo_t proc_psinfo;
-	if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
-		LL_WARNS() << "Unable to read " << proc_ps << LL_ENDL;
-		close(proc_fd);
-		return 0;
-	}
-
-	close(proc_fd);
-
-	resident_size = proc_psinfo.pr_rssize;
 #endif
 	return resident_size;
 }
@@ -773,11 +722,6 @@ U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
 	phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
 	return U64Bytes(phys);
 
-#elif LL_SOLARIS
-	U64 phys = 0;
-	phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
-	return U64Bytes(phys);
-
 #else
 	return 0;
 
@@ -1066,13 +1010,6 @@ LLSD LLMemoryInfo::loadStatsMap()
 			}
 	}
 
-#elif LL_SOLARIS
-	U64 phys = 0;
-
-	phys = (U64)(sysconf(_SC_PHYS_PAGES)) * (U64)(sysconf(_SC_PAGESIZE)/1024);
-
-	stats.add("Total Physical KB", phys);
-
 #elif LL_LINUX
 	std::ifstream meminfo(MEMINFO_FILE);
 	if (meminfo.is_open())
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 0b9dec969ce0f738684346dc7312018677670360..98905f3b7193dfbc5ba9b97cfee2a25ef59d7541 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -36,7 +36,7 @@
 #include "lltracethreadrecorder.h"
 #include "llexception.h"
 
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX
 #include <sched.h>
 #endif
 
diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp
index 76e892212a75721639951178f96d971c5fc888f8..aaa6df325cb741060c7b66c0ee2c0c5a0462760b 100644
--- a/indra/llcommon/lltimer.cpp
+++ b/indra/llcommon/lltimer.cpp
@@ -32,7 +32,7 @@
 
 #if LL_WINDOWS
 #	include "llwin32headerslean.h"
-#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
+#elif LL_LINUX || LL_DARWIN
 #   include <errno.h>
 #	include <sys/time.h>
 #else 
@@ -74,7 +74,7 @@ U32 micro_sleep(U64 us, U32 max_yields)
 	ms_sleep((U32)(us / 1000));
     return 0;
 }
-#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
+#elif LL_LINUX || LL_DARWIN
 static void _sleep_loop(struct timespec& thiswait)
 {
 	struct timespec nextwait;
@@ -187,7 +187,7 @@ F64 calc_clock_frequency()
 #endif // LL_WINDOWS
 
 
-#if LL_LINUX || LL_DARWIN || LL_SOLARIS
+#if LL_LINUX || LL_DARWIN
 // Both Linux and Mac use gettimeofday for accurate time
 F64 calc_clock_frequency()
 {
diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h
index ec70213447cfd3079f599abe3b69befc0837e091..010f290b24780db7f3fabe7ef5af00b644698fe1 100644
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -27,7 +27,7 @@
 #ifndef LL_TIMER_H					
 #define LL_TIMER_H
 
-#if LL_LINUX || LL_DARWIN || LL_SOLARIS
+#if LL_LINUX || LL_DARWIN
 #include <sys/time.h>
 #endif
 #include <limits.h>
diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp
index b05630c6b59fbc17a248077f529ac33c6c35d7df..e3b293e465c050031e9d30f272d44017ac4be065 100644
--- a/indra/llcommon/lluuid.cpp
+++ b/indra/llcommon/lluuid.cpp
@@ -601,9 +601,7 @@ S32 LLUUID::getNodeID(unsigned char *node_id)
 #define HAVE_NETINET_IN_H
 #ifdef HAVE_NETINET_IN_H
 #include <netinet/in.h>
-#if LL_SOLARIS
-#include <sys/sockio.h>
-#elif !LL_DARWIN
+#if !LL_DARWIN
 #include <linux/sockios.h>
 #endif
 #endif
diff --git a/indra/llcommon/stdtypes.h b/indra/llcommon/stdtypes.h
index 6c9871e76c9fd5ed45a9435b1faaf52f89bb877a..887f6ab7332413fcd2a8bc043636935c516729e1 100644
--- a/indra/llcommon/stdtypes.h
+++ b/indra/llcommon/stdtypes.h
@@ -57,7 +57,7 @@ typedef unsigned __int64		U64;
 #else
 typedef long long int			S64;
 typedef long long unsigned int		U64;
-#if LL_DARWIN || LL_LINUX || LL_SOLARIS
+#if LL_DARWIN || LL_LINUX
 #define S64L(a)				(a##LL)
 #define U64L(a)				(a##ULL)
 #endif
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index 8f01ad6c1cad3f02a79c14b928327ba62bd43a61..e4ccd81faf444a0d7e2532a83f12640a50676768 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -47,9 +47,6 @@
 #elif (LL_LINUX && __GNUC__ <= 2)
 #define llisnan(val)	isnan(val)
 #define llfinite(val)	isfinite(val)
-#elif LL_SOLARIS
-#define llisnan(val)    isnan(val)
-#define llfinite(val)   (val <= std::numeric_limits<double>::max())
 #else
 #define llisnan(val)	std::isnan(val)
 #define llfinite(val)	std::isfinite(val)
diff --git a/indra/llmath/llsdutil_math.cpp b/indra/llmath/llsdutil_math.cpp
index 591f7fde360896bfe5846e71f771afff4975863e..51e5e3764f4192375bb47f22f2048679a817f3c6 100644
--- a/indra/llmath/llsdutil_math.cpp
+++ b/indra/llmath/llsdutil_math.cpp
@@ -40,7 +40,7 @@
 #if LL_WINDOWS
 #	define WIN32_LEAN_AND_MEAN
 #	include <winsock2.h>	// for htonl
-#elif LL_LINUX || LL_SOLARIS
+#elif LL_LINUX
 #	include <netinet/in.h>
 #elif LL_DARWIN
 #	include <arpa/inet.h>
diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h
index 52dbf871dbc963be38a38b4bbf597946b4a3b7ef..e25a9ea7efdeb4cf1f9a0cbef0777638b02641d8 100644
--- a/indra/llmessage/message.h
+++ b/indra/llmessage/message.h
@@ -35,10 +35,6 @@
 #include <netinet/in.h>
 #endif
 
-#if LL_SOLARIS
-#include <netinet/in.h>
-#endif
-
 #if LL_WINDOWS
 #include "winsock2.h" // htons etc.
 #endif
diff --git a/indra/llprimitive/llmaterial.cpp b/indra/llprimitive/llmaterial.cpp
index a1bfc4edd90979aee600125f7b3c3e8c0b885fff..a219ac14501a9fee140e004bbbfb132ba6aca9d5 100644
--- a/indra/llprimitive/llmaterial.cpp
+++ b/indra/llprimitive/llmaterial.cpp
@@ -28,8 +28,6 @@
 
 #include "llmaterial.h"
 
-#include "../llrender/llglheaders.h"
-
 /**
  * Materials cap parameters
  */
@@ -107,8 +105,6 @@ LLMaterial::LLMaterial()
     , mSpecularLightExponent(LLMaterial::DEFAULT_SPECULAR_LIGHT_EXPONENT)
     , mEnvironmentIntensity(LLMaterial::DEFAULT_ENV_INTENSITY)
     , mDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
-    , mDiffuseFormatPrimary(GL_RGBA)
-    , mDiffuseBaked(false)
     , mAlphaMaskCutoff(0)
 {
 }
@@ -315,20 +311,6 @@ void LLMaterial::setEnvironmentIntensity(U8 intensity)
     mEnvironmentIntensity = intensity;
 }
 
-U8 LLMaterial::getDiffuseAlphaModeRender() const
-{
-    if (mDiffuseBaked
-        || mDiffuseFormatPrimary == GL_RGBA
-        || mDiffuseFormatPrimary == GL_ALPHA)
-    {
-        return mDiffuseAlphaMode;
-    }
-    else
-    {
-        return DIFFUSE_ALPHA_MODE_NONE;
-    }
-}
-
 U8 LLMaterial::getDiffuseAlphaMode() const
 {
     return mDiffuseAlphaMode;
@@ -339,26 +321,6 @@ void LLMaterial::setDiffuseAlphaMode(U8 alpha_mode)
     mDiffuseAlphaMode = alpha_mode;
 }
 
-U32 LLMaterial::getDiffuseFormatPrimary() const
-{
-    return mDiffuseFormatPrimary;
-}
-
-void LLMaterial::setDiffuseFormatPrimary(U32 format_primary)
-{
-    mDiffuseFormatPrimary = format_primary;
-}
-
-bool LLMaterial::getIsDiffuseBaked() const
-{
-    return mDiffuseBaked;
-}
-
-void LLMaterial::setDiffuseBaked(bool baked)
-{
-    mDiffuseBaked = baked;
-}
-
 U8 LLMaterial::getAlphaMaskCutoff() const
 {
     return mAlphaMaskCutoff;
@@ -475,7 +437,7 @@ U32 LLMaterial::getShaderMask(U32 alpha_mode)
     }
     else
     {
-        ret = getDiffuseAlphaModeRender();
+        ret = getDiffuseAlphaMode();
     }
 
     llassert(ret < SHADER_COUNT);
diff --git a/indra/llprimitive/llmaterial.h b/indra/llprimitive/llmaterial.h
index 1207917568e27347db9f9dc7522257824c7b0231..d58b7ee8127ae7d86488827702723bdbd2f6ab3b 100644
--- a/indra/llprimitive/llmaterial.h
+++ b/indra/llprimitive/llmaterial.h
@@ -115,17 +115,8 @@ class LLMaterial : public LLRefCount
     void        setSpecularLightExponent(U8 exponent);
     U8          getEnvironmentIntensity() const;
     void        setEnvironmentIntensity(U8 intensity);
-
-    // getDiffuseAlphaModeRender takes into account if image supports alpha
-    // and returns value apropriate for render
-    // getDiffuseAlphaMode() returns value as is
-    U8          getDiffuseAlphaModeRender() const;
     U8          getDiffuseAlphaMode() const;
     void        setDiffuseAlphaMode(U8 alpha_mode);
-    U32         getDiffuseFormatPrimary() const;
-    void        setDiffuseFormatPrimary(U32 format_primary);
-    bool        getIsDiffuseBaked() const;
-    void        setDiffuseBaked(bool baked);
     U8          getAlphaMaskCutoff() const;
     void        setAlphaMaskCutoff(U8 cutoff);
 
@@ -156,8 +147,6 @@ class LLMaterial : public LLRefCount
     U8          mSpecularLightExponent;
     U8          mEnvironmentIntensity;
     U8          mDiffuseAlphaMode;
-    U32         mDiffuseFormatPrimary; // value from texture, LLGLenum, is not included in fromLLSD/asLLSD
-    bool        mDiffuseBaked; // is not included in fromLLSD/asLLSD
     U8          mAlphaMaskCutoff;
 };
 
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index ee02a90b54cedb67d18120d7c83f367675dfa0bb..43fedeca64053ddc78a3d202c0170baec33b35c8 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -151,7 +151,7 @@ LLMatrix4 gGLObliqueProjectionInverse;
 
 std::list<LLGLUpdate*> LLGLUpdate::sGLQ;
 
-#if (LL_WINDOWS || LL_LINUX || LL_SOLARIS)  && !LL_MESA_HEADLESS
+#if (LL_WINDOWS || LL_LINUX)  && !LL_MESA_HEADLESS
 // ATI prototypes
 
 #if LL_WINDOWS
@@ -328,7 +328,7 @@ PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
 #endif
 
 // vertex shader prototypes
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX
 PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB = NULL;
 PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB = NULL;
 PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB = NULL;
@@ -347,7 +347,7 @@ PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB = NULL;
 PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB = NULL;
 PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB = NULL;
 PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB = NULL;
-#endif // LL_LINUX || LL_SOLARIS
+#endif // LL_LINUX
 PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB = NULL;
 PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB = NULL;
 PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB = NULL;
@@ -355,7 +355,7 @@ PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB = NULL;
 PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB = NULL;
 PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB = NULL;
 PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB = NULL;
-#if LL_LINUX  || LL_SOLARIS
+#if LL_LINUX
 PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB = NULL;
 PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB = NULL;
 PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB = NULL;
@@ -393,7 +393,7 @@ PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB = NULL;
 PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB = NULL;
 PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB = NULL;
 PFNGLISPROGRAMARBPROC glIsProgramARB = NULL;
-#endif // LL_LINUX || LL_SOLARIS
+#endif // LL_LINUX
 PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB = NULL;
 PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB = NULL;
 PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB = NULL;
@@ -471,8 +471,6 @@ LLGLManager::LLGLManager() :
 
 	mHasSeparateSpecularColor(FALSE),
 
-	mDebugGPU(FALSE),
-
 	mDriverVersionMajor(1),
 	mDriverVersionMinor(0),
 	mDriverVersionRelease(0),
@@ -854,10 +852,6 @@ bool LLGLManager::initGL()
 
 	stop_glerror();
 	
-	setToDebugGPU();
-
-	stop_glerror();
-
 	initGLStates();
 
 	stop_glerror();
@@ -865,17 +859,6 @@ bool LLGLManager::initGL()
 	return true;
 }
 
-void LLGLManager::setToDebugGPU()
-{
-	//"MOBILE INTEL(R) 965 EXPRESS CHIP", 
-	if (mGLRenderer.find("INTEL") != std::string::npos && mGLRenderer.find("965") != std::string::npos)
-	{
-		mDebugGPU = TRUE ;
-	}
-
-	return ;
-}
-
 void LLGLManager::getGLInfo(LLSD& info)
 {
 	if (gHeadlessClient)
@@ -1032,7 +1015,6 @@ void LLGLManager::asLLSD(LLSD& info)
 	// Other fields
 	info["has_requirements"] = mHasRequirements;
 	info["has_separate_specular_color"] = mHasSeparateSpecularColor;
-	info["debug_gpu"] = mDebugGPU;
 	info["max_vertex_range"] = mGLMaxVertexRange;
 	info["max_index_range"] = mGLMaxIndexRange;
 	info["max_texture_size"] = mGLMaxTextureSize;
@@ -1167,7 +1149,7 @@ void LLGLManager::initExtensions()
 	mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts));
 #endif
 
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX
 	LL_INFOS() << "initExtensions() checking shell variables to adjust features..." << LL_ENDL;
 	// Our extension support for the Linux Client is very young with some
 	// potential driver gotchas, so offer a semi-secret way to turn it off.
@@ -1237,7 +1219,7 @@ void LLGLManager::initExtensions()
 		if (strchr(blacklist,'u')) mHasDepthClamp = FALSE;
 		
 	}
-#endif // LL_LINUX || LL_SOLARIS
+#endif // LL_LINUX
 	
 	if (!mHasMultitexture)
 	{
@@ -1315,7 +1297,7 @@ void LLGLManager::initExtensions()
 	glGetIntegerv(GL_MAX_ELEMENTS_INDICES, (GLint*) &mGLMaxIndexRange);
 	glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*) &mGLMaxTextureSize);
 
-#if (LL_WINDOWS || LL_LINUX || LL_SOLARIS) && !LL_MESA_HEADLESS
+#if (LL_WINDOWS || LL_LINUX) && !LL_MESA_HEADLESS
 	LL_DEBUGS("RenderInit") << "GL Probe: Getting symbols" << LL_ENDL;
 	if (mHasVertexBufferObject)
 	{
@@ -1414,7 +1396,7 @@ void LLGLManager::initExtensions()
 		glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) GLH_EXT_GET_PROC_ADDRESS("glDebugMessageCallbackARB");
 		glGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC) GLH_EXT_GET_PROC_ADDRESS("glGetDebugMessageLogARB");
 	}
-#if (!LL_LINUX && !LL_SOLARIS) || LL_LINUX_NV_GL_HEADERS
+#if (!LL_LINUX) || LL_LINUX_NV_GL_HEADERS
 	// This is expected to be a static symbol on Linux GL implementations, except if we use the nvidia headers - bah
 	glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC)GLH_EXT_GET_PROC_ADDRESS("glDrawRangeElements");
 	if (!glDrawRangeElements)
@@ -2775,8 +2757,9 @@ LLGLSPipelineBlendSkyBox::LLGLSPipelineBlendSkyBox(bool depth_test, bool depth_w
 
 #if LL_WINDOWS
 // Expose desired use of high-performance graphics processor to Optimus driver and to AMD driver
+// https://docs.nvidia.com/gameworks/content/technologies/desktop/optimus.htm
 extern "C" 
-{
+{ 
     __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
     __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
 }
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 966c4b3c77139de1ef4591cc83b12006d80df733..a07e2d9bb02871a8a724fa00c0d46ebd00fb1335 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -142,9 +142,6 @@ class LLGLManager
 	// Misc extensions
 	BOOL mHasSeparateSpecularColor;
 
-	//whether this GPU is in the debug list.
-	BOOL mDebugGPU;
-	
 	S32 mDriverVersionMajor;
 	S32 mDriverVersionMinor;
 	S32 mDriverVersionRelease;
@@ -178,7 +175,6 @@ class LLGLManager
 	void initExtensions();
 	void initGLStates();
 	void initGLImages();
-	void setToDebugGPU();
 };
 
 extern LLGLManager gGLManager;
diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h
index 36fbb381bb13425096a5713b1e692298f96d6879..6bca3623e09c101b01656bd505355062a6acbff2 100644
--- a/indra/llrender/llglheaders.h
+++ b/indra/llrender/llglheaders.h
@@ -27,242 +27,7 @@
 #ifndef LL_LLGLHEADERS_H
 #define LL_LLGLHEADERS_H
 
-#if LL_SOLARIS
-#   if defined(__sparc)
-#      define I_NEED_OS2_H 	//  avoiding BOOL conflicts
-#   endif
-#   include "GL/gl.h"
-#   if defined(__sparc)
-#      undef I_NEED_OS2_H
-#      ifdef BOOL
-#         undef BOOL		// now get rid of Xmd.h crap
-#      endif
-#   endif
-#   include "GL/glx.h"
-#   define  GL_GLEXT_PROTOTYPES 1
-#   include "GL/glext.h"
-#   include "GL/glu.h"
-#   include "GL/glx.h"
-#   define  GLX_GLXEXT_PROTOTYPES 1
-#   include "GL/glxext.h"
-//#   define  GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddressARB((const GLubyte*)(p))
-#   define  GLH_EXT_GET_PROC_ADDRESS(p) glXGetProcAddress((const GLubyte*)(p))
-
-// The __APPLE__ kludge is to make glh_extensions.h not symbol-clash horribly
-// This header is distributed with SL.  You'll find it in linden/libraries/include/GL/
-# define __APPLE__
-# include "GL/glh_extensions.h"
-# undef __APPLE__
-
-
-// GL_ARB_vertex_buffer_object
-extern PFNGLBINDBUFFERARBPROC		glBindBufferARB;
-extern PFNGLDELETEBUFFERSARBPROC	glDeleteBuffersARB;
-extern PFNGLGENBUFFERSARBPROC		glGenBuffersARB;
-extern PFNGLISBUFFERARBPROC			glIsBufferARB;
-extern PFNGLBUFFERDATAARBPROC		glBufferDataARB;
-extern PFNGLBUFFERSUBDATAARBPROC	glBufferSubDataARB;
-extern PFNGLGETBUFFERSUBDATAARBPROC glGetBufferSubDataARB;
-extern PFNGLMAPBUFFERARBPROC		glMapBufferARB;
-extern PFNGLUNMAPBUFFERARBPROC		glUnmapBufferARB;
-extern PFNGLGETBUFFERPARAMETERIVARBPROC	glGetBufferParameterivARB;
-extern PFNGLGETBUFFERPOINTERVARBPROC	glGetBufferPointervARB;
-
-// GL_ARB_vertex_array_object
-extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray;
-extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays;
-extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
-extern PFNGLISVERTEXARRAYPROC glIsVertexArray;
-
-// GL_ARB_sync
-extern PFNGLFENCESYNCPROC				glFenceSync;
-extern PFNGLISSYNCPROC					glIsSync;
-extern PFNGLDELETESYNCPROC				glDeleteSync;
-extern PFNGLCLIENTWAITSYNCPROC			glClientWaitSync;
-extern PFNGLWAITSYNCPROC				glWaitSync;
-extern PFNGLGETINTEGER64VPROC			glGetInteger64v;
-extern PFNGLGETSYNCIVPROC				glGetSynciv;
-
-// GL_APPLE_flush_buffer_range
-extern PFNGLBUFFERPARAMETERIAPPLEPROC	glBufferParameteriAPPLE;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEAPPLEPROC glFlushMappedBufferRangeAPPLE;
-
-// GL_ARB_map_buffer_range
-extern PFNGLMAPBUFFERRANGEPROC			glMapBufferRange;
-extern PFNGLFLUSHMAPPEDBUFFERRANGEPROC	glFlushMappedBufferRange;
-
-// GL_ATI_vertex_array_object
-extern PFNGLNEWOBJECTBUFFERATIPROC			glNewObjectBufferATI;
-extern PFNGLISOBJECTBUFFERATIPROC			glIsObjectBufferATI;
-extern PFNGLUPDATEOBJECTBUFFERATIPROC		glUpdateObjectBufferATI;
-extern PFNGLGETOBJECTBUFFERFVATIPROC		glGetObjectBufferfvATI;
-extern PFNGLGETOBJECTBUFFERIVATIPROC		glGetObjectBufferivATI;
-extern PFNGLFREEOBJECTBUFFERATIPROC		    glFreeObjectBufferATI;
-extern PFNGLARRAYOBJECTATIPROC				glArrayObjectATI;
-extern PFNGLVERTEXATTRIBARRAYOBJECTATIPROC	glVertexAttribArrayObjectATI;
-extern PFNGLGETARRAYOBJECTFVATIPROC			glGetArrayObjectfvATI;
-extern PFNGLGETARRAYOBJECTIVATIPROC			glGetArrayObjectivATI;
-extern PFNGLVARIANTARRAYOBJECTATIPROC		glVariantObjectArrayATI;
-extern PFNGLGETVARIANTARRAYOBJECTFVATIPROC	glGetVariantArrayObjectfvATI;
-extern PFNGLGETVARIANTARRAYOBJECTIVATIPROC	glGetVariantArrayObjectivATI;
-
-// GL_ARB_occlusion_query
-extern PFNGLGENQUERIESARBPROC glGenQueriesARB;
-extern PFNGLDELETEQUERIESARBPROC glDeleteQueriesARB;
-extern PFNGLISQUERYARBPROC glIsQueryARB;
-extern PFNGLBEGINQUERYARBPROC glBeginQueryARB;
-extern PFNGLENDQUERYARBPROC glEndQueryARB;
-extern PFNGLGETQUERYIVARBPROC glGetQueryivARB;
-extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB;
-extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB;
-
-// GL_ARB_timer_query
-extern PFNGLQUERYCOUNTERPROC glQueryCounter;
-extern PFNGLGETQUERYOBJECTI64VPROC glGetQueryObjecti64v;
-extern PFNGLGETQUERYOBJECTUI64VPROC glGetQueryObjectui64v;
-
-// GL_ARB_point_parameters
-extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB;
-extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB;
-
-// GL_ARB_shader_objects
-extern PFNGLDELETEOBJECTARBPROC glDeleteObjectARB;
-extern PFNGLGETHANDLEARBPROC glGetHandleARB;
-extern PFNGLDETACHOBJECTARBPROC glDetachObjectARB;
-extern PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB;
-extern PFNGLSHADERSOURCEARBPROC glShaderSourceARB;
-extern PFNGLCOMPILESHADERARBPROC glCompileShaderARB;
-extern PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB;
-extern PFNGLATTACHOBJECTARBPROC glAttachObjectARB;
-extern PFNGLLINKPROGRAMARBPROC glLinkProgramARB;
-extern PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB;
-extern PFNGLVALIDATEPROGRAMARBPROC glValidateProgramARB;
-extern PFNGLUNIFORM1FARBPROC glUniform1fARB;
-extern PFNGLUNIFORM2FARBPROC glUniform2fARB;
-extern PFNGLUNIFORM3FARBPROC glUniform3fARB;
-extern PFNGLUNIFORM4FARBPROC glUniform4fARB;
-extern PFNGLUNIFORM1IARBPROC glUniform1iARB;
-extern PFNGLUNIFORM2IARBPROC glUniform2iARB;
-extern PFNGLUNIFORM3IARBPROC glUniform3iARB;
-extern PFNGLUNIFORM4IARBPROC glUniform4iARB;
-extern PFNGLUNIFORM1FVARBPROC glUniform1fvARB;
-extern PFNGLUNIFORM2FVARBPROC glUniform2fvARB;
-extern PFNGLUNIFORM3FVARBPROC glUniform3fvARB;
-extern PFNGLUNIFORM4FVARBPROC glUniform4fvARB;
-extern PFNGLUNIFORM1IVARBPROC glUniform1ivARB;
-extern PFNGLUNIFORM2IVARBPROC glUniform2ivARB;
-extern PFNGLUNIFORM3IVARBPROC glUniform3ivARB;
-extern PFNGLUNIFORM4IVARBPROC glUniform4ivARB;
-extern PFNGLUNIFORMMATRIX2FVARBPROC glUniformMatrix2fvARB;
-extern PFNGLUNIFORMMATRIX3FVARBPROC glUniformMatrix3fvARB;
-extern PFNGLUNIFORMMATRIX3X4FVPROC glUniformMatrix3x4fv;
-extern PFNGLUNIFORMMATRIX4FVARBPROC glUniformMatrix4fvARB;
-extern PFNGLGETOBJECTPARAMETERFVARBPROC glGetObjectParameterfvARB;
-extern PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB;
-extern PFNGLGETINFOLOGARBPROC glGetInfoLogARB;
-extern PFNGLGETATTACHEDOBJECTSARBPROC glGetAttachedObjectsARB;
-extern PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB;
-extern PFNGLGETACTIVEUNIFORMARBPROC glGetActiveUniformARB;
-extern PFNGLGETUNIFORMFVARBPROC glGetUniformfvARB;
-extern PFNGLGETUNIFORMIVARBPROC glGetUniformivARB;
-extern PFNGLGETSHADERSOURCEARBPROC glGetShaderSourceARB;
-
-// GL_ARB_vertex_shader
-extern PFNGLVERTEXATTRIB1DARBPROC glVertexAttrib1dARB;
-extern PFNGLVERTEXATTRIB1DVARBPROC glVertexAttrib1dvARB;
-extern PFNGLVERTEXATTRIB1FARBPROC glVertexAttrib1fARB;
-extern PFNGLVERTEXATTRIB1FVARBPROC glVertexAttrib1fvARB;
-extern PFNGLVERTEXATTRIB1SARBPROC glVertexAttrib1sARB;
-extern PFNGLVERTEXATTRIB1SVARBPROC glVertexAttrib1svARB;
-extern PFNGLVERTEXATTRIB2DARBPROC glVertexAttrib2dARB;
-extern PFNGLVERTEXATTRIB2DVARBPROC glVertexAttrib2dvARB;
-extern PFNGLVERTEXATTRIB2FARBPROC glVertexAttrib2fARB;
-extern PFNGLVERTEXATTRIB2FVARBPROC glVertexAttrib2fvARB;
-extern PFNGLVERTEXATTRIB2SARBPROC glVertexAttrib2sARB;
-extern PFNGLVERTEXATTRIB2SVARBPROC glVertexAttrib2svARB;
-extern PFNGLVERTEXATTRIB3DARBPROC glVertexAttrib3dARB;
-extern PFNGLVERTEXATTRIB3DVARBPROC glVertexAttrib3dvARB;
-extern PFNGLVERTEXATTRIB3FARBPROC glVertexAttrib3fARB;
-extern PFNGLVERTEXATTRIB3FVARBPROC glVertexAttrib3fvARB;
-extern PFNGLVERTEXATTRIB3SARBPROC glVertexAttrib3sARB;
-extern PFNGLVERTEXATTRIB3SVARBPROC glVertexAttrib3svARB;
-extern PFNGLVERTEXATTRIB4NBVARBPROC glVertexAttrib4nbvARB;
-extern PFNGLVERTEXATTRIB4NIVARBPROC glVertexAttrib4nivARB;
-extern PFNGLVERTEXATTRIB4NSVARBPROC glVertexAttrib4nsvARB;
-extern PFNGLVERTEXATTRIB4NUBARBPROC glVertexAttrib4nubARB;
-extern PFNGLVERTEXATTRIB4NUBVARBPROC glVertexAttrib4nubvARB;
-extern PFNGLVERTEXATTRIB4NUIVARBPROC glVertexAttrib4nuivARB;
-extern PFNGLVERTEXATTRIB4NUSVARBPROC glVertexAttrib4nusvARB;
-extern PFNGLVERTEXATTRIB4BVARBPROC glVertexAttrib4bvARB;
-extern PFNGLVERTEXATTRIB4DARBPROC glVertexAttrib4dARB;
-extern PFNGLVERTEXATTRIB4DVARBPROC glVertexAttrib4dvARB;
-extern PFNGLVERTEXATTRIB4FARBPROC glVertexAttrib4fARB;
-extern PFNGLVERTEXATTRIB4FVARBPROC glVertexAttrib4fvARB;
-extern PFNGLVERTEXATTRIB4IVARBPROC glVertexAttrib4ivARB;
-extern PFNGLVERTEXATTRIB4SARBPROC glVertexAttrib4sARB;
-extern PFNGLVERTEXATTRIB4SVARBPROC glVertexAttrib4svARB;
-extern PFNGLVERTEXATTRIB4UBVARBPROC glVertexAttrib4ubvARB;
-extern PFNGLVERTEXATTRIB4UIVARBPROC glVertexAttrib4uivARB;
-extern PFNGLVERTEXATTRIB4USVARBPROC glVertexAttrib4usvARB;
-extern PFNGLVERTEXATTRIBPOINTERARBPROC glVertexAttribPointerARB;
-extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer;
-extern PFNGLENABLEVERTEXATTRIBARRAYARBPROC glEnableVertexAttribArrayARB;
-extern PFNGLDISABLEVERTEXATTRIBARRAYARBPROC glDisableVertexAttribArrayARB;
-extern PFNGLPROGRAMSTRINGARBPROC glProgramStringARB;
-extern PFNGLBINDPROGRAMARBPROC glBindProgramARB;
-extern PFNGLDELETEPROGRAMSARBPROC glDeleteProgramsARB;
-extern PFNGLGENPROGRAMSARBPROC glGenProgramsARB;
-extern PFNGLPROGRAMENVPARAMETER4DARBPROC glProgramEnvParameter4dARB;
-extern PFNGLPROGRAMENVPARAMETER4DVARBPROC glProgramEnvParameter4dvARB;
-extern PFNGLPROGRAMENVPARAMETER4FARBPROC glProgramEnvParameter4fARB;
-extern PFNGLPROGRAMENVPARAMETER4FVARBPROC glProgramEnvParameter4fvARB;
-extern PFNGLPROGRAMLOCALPARAMETER4DARBPROC glProgramLocalParameter4dARB;
-extern PFNGLPROGRAMLOCALPARAMETER4DVARBPROC glProgramLocalParameter4dvARB;
-extern PFNGLPROGRAMLOCALPARAMETER4FARBPROC glProgramLocalParameter4fARB;
-extern PFNGLPROGRAMLOCALPARAMETER4FVARBPROC glProgramLocalParameter4fvARB;
-extern PFNGLGETPROGRAMENVPARAMETERDVARBPROC glGetProgramEnvParameterdvARB;
-extern PFNGLGETPROGRAMENVPARAMETERFVARBPROC glGetProgramEnvParameterfvARB;
-extern PFNGLGETPROGRAMLOCALPARAMETERDVARBPROC glGetProgramLocalParameterdvARB;
-extern PFNGLGETPROGRAMLOCALPARAMETERFVARBPROC glGetProgramLocalParameterfvARB;
-extern PFNGLGETPROGRAMIVARBPROC glGetProgramivARB;
-extern PFNGLGETPROGRAMSTRINGARBPROC glGetProgramStringARB;
-extern PFNGLGETVERTEXATTRIBDVARBPROC glGetVertexAttribdvARB;
-extern PFNGLGETVERTEXATTRIBFVARBPROC glGetVertexAttribfvARB;
-extern PFNGLGETVERTEXATTRIBIVARBPROC glGetVertexAttribivARB;
-extern PFNGLGETVERTEXATTRIBPOINTERVARBPROC glGetVertexAttribPointervARB;
-extern PFNGLISPROGRAMARBPROC glIsProgramARB;
-extern PFNGLBINDATTRIBLOCATIONARBPROC glBindAttribLocationARB;
-extern PFNGLGETACTIVEATTRIBARBPROC glGetActiveAttribARB;
-extern PFNGLGETATTRIBLOCATIONARBPROC glGetAttribLocationARB;
-
-extern PFNGLCOMPRESSEDTEXIMAGE2DARBPROC glCompressedTexImage2DARB;
-extern PFNGLGETCOMPRESSEDTEXIMAGEARBPROC glGetCompressedTexImageARB;
-
-extern PFNGLCOLORTABLEEXTPROC glColorTableEXT;
-
-//GL_EXT_blend_func_separate
-extern PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT;
-
-//GL_EXT_framebuffer_object
-extern PFNGLISRENDERBUFFEREXTPROC glIsRenderbufferEXT;
-extern PFNGLBINDRENDERBUFFEREXTPROC glBindRenderbufferEXT;
-extern PFNGLDELETERENDERBUFFERSEXTPROC glDeleteRenderbuffersEXT;
-extern PFNGLGENRENDERBUFFERSEXTPROC glGenRenderbuffersEXT;
-extern PFNGLRENDERBUFFERSTORAGEEXTPROC glRenderbufferStorageEXT;
-extern PFNGLGETRENDERBUFFERPARAMETERIVEXTPROC glGetRenderbufferParameterivEXT;
-extern PFNGLISFRAMEBUFFEREXTPROC glIsFramebufferEXT;
-extern PFNGLBINDFRAMEBUFFEREXTPROC glBindFramebufferEXT;
-extern PFNGLDELETEFRAMEBUFFERSEXTPROC glDeleteFramebuffersEXT;
-extern PFNGLGENFRAMEBUFFERSEXTPROC glGenFramebuffersEXT;
-extern PFNGLCHECKFRAMEBUFFERSTATUSEXTPROC glCheckFramebufferStatusEXT;
-extern PFNGLFRAMEBUFFERTEXTURE1DEXTPROC glFramebufferTexture1DEXT;
-extern PFNGLFRAMEBUFFERTEXTURE2DEXTPROC glFramebufferTexture2DEXT;
-extern PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT;
-extern PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT;
-extern PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT;
-extern PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT;
-
-#elif LL_MESA
+#if LL_MESA
 //----------------------------------------------------------------------------
 // MESA headers
 // quotes so we get libraries/.../GL/ version
diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp
index 384e5bf99fe3e87c45134d3e7771871ef4884dcf..4351f6e2c86cdde783f128c835c95f4f6f4e4604 100644
--- a/indra/llrender/llglslshader.cpp
+++ b/indra/llrender/llglslshader.cpp
@@ -37,6 +37,10 @@
 #include "OpenGL/OpenGL.h"
 #endif
 
+// Print-print list of shader included source files that are linked together via glAttachObjectARB()
+// i.e. On macOS / OSX the AMD GLSL linker will display an error if a varying is left in an undefined state.
+#define DEBUG_SHADER_INCLUDES 0
+
 // Lots of STL stuff in here, using namespace std to keep things more readable
 using std::vector;
 using std::pair;
@@ -392,16 +396,28 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
     mLightHash = 0xFFFFFFFF;
 
     llassert_always(!mShaderFiles.empty());
-    BOOL success = TRUE;
 
     // Create program
     mProgramObject = glCreateProgramObjectARB();
+    if (mProgramObject == 0)
+    {
+        // Shouldn't happen if shader related extensions, like ARB_vertex_shader, exist.
+        LL_SHADER_LOADING_WARNS() << "Failed to create handle for shader: " << mName << LL_ENDL;
+        unloadInternal();
+        return FALSE;
+    }
+
+    BOOL success = TRUE;
     
 #if LL_DARWIN
     // work-around missing mix(vec3,vec3,bvec3)
     mDefines["OLD_SELECT"] = "1";
 #endif
     
+#if DEBUG_SHADER_INCLUDES
+    fprintf(stderr, "--- %s ---\n", mName.c_str());
+#endif // DEBUG_SHADER_INCLUDES
+
     //compile new source
     vector< pair<string,GLenum> >::iterator fileIter = mShaderFiles.begin();
     for ( ; fileIter != mShaderFiles.end(); fileIter++ )
@@ -485,11 +501,36 @@ BOOL LLGLSLShader::createShader(std::vector<LLStaticHashedString> * attributes,
     return success;
 }
 
-BOOL LLGLSLShader::attachVertexObject(std::string object_path) {
+#if DEBUG_SHADER_INCLUDES
+void dumpAttachObject( const char *func_name, GLhandleARB program_object, const std::string &object_path )
+{
+    GLcharARB* info_log;
+    GLint      info_len_expect = 0;
+    GLint      info_len_actual = 0;
+
+    glGetObjectParameterivARB(program_object, GL_OBJECT_INFO_LOG_LENGTH_ARB, &info_len_expect);
+    fprintf(stderr, " * %-20s(), log size: %d, %s\n", func_name, info_len_expect, object_path.c_str());
+
+    if (info_len_expect > 0)
+    {
+        fprintf(stderr, " ========== %s() ========== \n", func_name);
+        info_log = new GLcharARB [ info_len_expect ];
+        glGetInfoLogARB(program_object, info_len_expect, &info_len_actual, info_log);
+        fprintf(stderr, "%s\n",  info_log);
+        delete [] info_log;
+    }
+}
+#endif // DEBUG_SHADER_INCLUDES
+
+BOOL LLGLSLShader::attachVertexObject(std::string object_path)
+{
     if (LLShaderMgr::instance()->mVertexShaderObjects.count(object_path) > 0)
     {
         stop_glerror();
         glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mVertexShaderObjects[object_path]);
+#if DEBUG_SHADER_INCLUDES
+        dumpAttachObject("attachVertexObject", mProgramObject, object_path);
+#endif // DEBUG_SHADER_INCLUDES
         stop_glerror();
         return TRUE;
     }
@@ -506,6 +547,9 @@ BOOL LLGLSLShader::attachFragmentObject(std::string object_path)
     {
         stop_glerror();
         glAttachObjectARB(mProgramObject, LLShaderMgr::instance()->mFragmentShaderObjects[object_path]);
+#if DEBUG_SHADER_INCLUDES
+        dumpAttachObject("attachFragmentObject", mProgramObject, object_path);
+#endif // DEBUG_SHADER_INCLUDES
         stop_glerror();
         return TRUE;
     }
@@ -522,6 +566,10 @@ void LLGLSLShader::attachObject(GLhandleARB object)
     {
         stop_glerror();
         glAttachObjectARB(mProgramObject, object);
+#if DEBUG_SHADER_INCLUDES
+        std::string object_path("???");
+        dumpAttachObject("attachObject", mProgramObject, object_path);
+#endif // DEBUG_SHADER_INCLUDES
         stop_glerror();
     }
     else
diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp
index 11d9ef3f57fdd42633124929011b1b8b1bdd31fe..d515fc707aa6a6aa9b22b717bf60e923aa4ccaac 100644
--- a/indra/llrender/llrender.cpp
+++ b/indra/llrender/llrender.cpp
@@ -871,10 +871,10 @@ void LLTexUnit::setTextureColorSpace(eTextureColorSpace space)
         }
     }
     else
-#endif
     {
         glTexParameteri(sGLTextureType[mCurrTexType], GL_TEXTURE_SRGB_DECODE_EXT, GL_SKIP_DECODE_EXT);
     }
+#endif
 }
 
 LLLightState::LLLightState(S32 index)
diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp
index 236ebbd78fa013ccf0e8c0b0e799885bed5fb186..e8c62959303e9be71b878021cb70fe5662ea8c8c 100644
--- a/indra/llrender/llshadermgr.cpp
+++ b/indra/llrender/llshadermgr.cpp
@@ -611,13 +611,11 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 #endif
 
 	GLenum error = GL_NO_ERROR;
-	if (gDebugGL)
+
+	error = glGetError();
+	if (error != GL_NO_ERROR)
 	{
-		error = glGetError();
-		if (error != GL_NO_ERROR)
-		{
-			LL_SHADER_LOADING_WARNS() << "GL ERROR entering loadShaderFile(): " << error << LL_ENDL;
-		}
+		LL_SHADER_LOADING_WARNS() << "GL ERROR entering loadShaderFile(): " << error << " for file: " << filename << LL_ENDL;
 	}
 	
 	if (filename.empty()) 
@@ -966,55 +964,45 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade
 
 	//create shader object
 	GLhandleARB ret = glCreateShaderObjectARB(type);
-	if (gDebugGL)
+
+	error = glGetError();
+	if (error != GL_NO_ERROR)
 	{
-		error = glGetError();
-		if (error != GL_NO_ERROR)
-		{
-			LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << LL_ENDL;
-		}
+		LL_WARNS("ShaderLoading") << "GL ERROR in glCreateShaderObjectARB: " << error << " for file: " << open_file_name << LL_ENDL;
 	}
-	
+
 	//load source
 	glShaderSourceARB(ret, shader_code_count, (const GLcharARB**) shader_code_text, NULL);
 
-	if (gDebugGL)
+	error = glGetError();
+	if (error != GL_NO_ERROR)
 	{
-		error = glGetError();
-		if (error != GL_NO_ERROR)
-		{
-			LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << LL_ENDL;
-		}
+		LL_WARNS("ShaderLoading") << "GL ERROR in glShaderSourceARB: " << error << " for file: " << open_file_name << LL_ENDL;
 	}
 
 	//compile source
 	glCompileShaderARB(ret);
 
-	if (gDebugGL)
+	error = glGetError();
+	if (error != GL_NO_ERROR)
 	{
-		error = glGetError();
-		if (error != GL_NO_ERROR)
-		{
-			LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << LL_ENDL;
-		}
+		LL_WARNS("ShaderLoading") << "GL ERROR in glCompileShaderARB: " << error << " for file: " << open_file_name << LL_ENDL;
 	}
-		
+
 	if (error == GL_NO_ERROR)
 	{
 		//check for errors
 		GLint success = GL_TRUE;
 		glGetObjectParameterivARB(ret, GL_OBJECT_COMPILE_STATUS_ARB, &success);
-		if (gDebugGL || success == GL_FALSE)
+
+		error = glGetError();
+		if (error != GL_NO_ERROR || success == GL_FALSE) 
 		{
-			error = glGetError();
-			if (error != GL_NO_ERROR || success == GL_FALSE) 
-			{
-				//an error occured, print log
-				LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL;
-				dumpObjectLog(ret, TRUE, open_file_name);
-                dumpShaderSource(shader_code_count, shader_code_text);
-				ret = 0;
-			}
+			//an error occured, print log
+			LL_WARNS("ShaderLoading") << "GLSL Compilation Error:" << LL_ENDL;
+			dumpObjectLog(ret, TRUE, open_file_name);
+			dumpShaderSource(shader_code_count, shader_code_text);
+			ret = 0;
 		}
 	}
 	else
diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h
index 127b5ce5b6875785a1de467a27fbf2bbc3724b90..3908efd4ec723e492f92ebd63fe94dfd7bea62c2 100644
--- a/indra/llrender/llshadermgr.h
+++ b/indra/llrender/llshadermgr.h
@@ -36,221 +36,223 @@ class LLShaderMgr
 	LLShaderMgr();
 	virtual ~LLShaderMgr();
 
-	typedef enum
-	{
-		MODELVIEW_MATRIX = 0,
-		PROJECTION_MATRIX,
-		INVERSE_PROJECTION_MATRIX,
-		MODELVIEW_PROJECTION_MATRIX,
-        INVERSE_MODELVIEW_MATRIX,
-		NORMAL_MATRIX,
-		TEXTURE_MATRIX0,
-		TEXTURE_MATRIX1,
-		TEXTURE_MATRIX2,
-		TEXTURE_MATRIX3,
-		OBJECT_PLANE_S,
-		OBJECT_PLANE_T,
-		VIEWPORT,
-		LIGHT_POSITION,
-		LIGHT_DIRECTION,
-		LIGHT_ATTENUATION,
-		LIGHT_DIFFUSE,
-		LIGHT_AMBIENT,
-		MULTI_LIGHT_COUNT,
-		MULTI_LIGHT,
-		MULTI_LIGHT_COL,
-		MULTI_LIGHT_FAR_Z,
-		PROJECTOR_MATRIX,
-		PROJECTOR_NEAR,
-		PROJECTOR_P,
-		PROJECTOR_N,
-		PROJECTOR_ORIGIN,
-		PROJECTOR_RANGE,
-		PROJECTOR_AMBIANCE,
-		PROJECTOR_SHADOW_INDEX,
-		PROJECTOR_SHADOW_FADE,
-		PROJECTOR_FOCUS,
-		PROJECTOR_LOD,
-		PROJECTOR_AMBIENT_LOD,
-		DIFFUSE_COLOR,
-		DIFFUSE_MAP,
-        ALTERNATE_DIFFUSE_MAP,
-		SPECULAR_MAP,
-		BUMP_MAP,
-        BUMP_MAP2,
-		ENVIRONMENT_MAP,
-		CLOUD_NOISE_MAP,
-        CLOUD_NOISE_MAP_NEXT,
-		FULLBRIGHT,
-		LIGHTNORM,
-		SUNLIGHT_COLOR,
-		AMBIENT,
-		BLUE_HORIZON,
-		BLUE_DENSITY,
-		HAZE_HORIZON,
-		HAZE_DENSITY,
-		CLOUD_SHADOW,
-		DENSITY_MULTIPLIER,
-		DISTANCE_MULTIPLIER,
-		MAX_Y,
-		GLOW,
-		CLOUD_COLOR,
-		CLOUD_POS_DENSITY1,
-		CLOUD_POS_DENSITY2,
-		CLOUD_SCALE,
-		GAMMA,
-		SCENE_LIGHT_STRENGTH,
-		LIGHT_CENTER,
-		LIGHT_SIZE,
-		LIGHT_FALLOFF,
-		BOX_CENTER,
-		BOX_SIZE,
-
-		GLOW_MIN_LUMINANCE,
-		GLOW_MAX_EXTRACT_ALPHA,
-		GLOW_LUM_WEIGHTS,
-		GLOW_WARMTH_WEIGHTS,
-		GLOW_WARMTH_AMOUNT,
-		GLOW_STRENGTH,
-		GLOW_DELTA,
-
-		MINIMUM_ALPHA,
-		EMISSIVE_BRIGHTNESS,
-
-		DEFERRED_SHADOW_MATRIX,
-		DEFERRED_ENV_MAT,
-		DEFERRED_SHADOW_CLIP,
-		DEFERRED_SUN_WASH,
-		DEFERRED_SHADOW_NOISE,
-		DEFERRED_BLUR_SIZE,
-		DEFERRED_SSAO_RADIUS,
-		DEFERRED_SSAO_MAX_RADIUS,
-		DEFERRED_SSAO_FACTOR,
-		DEFERRED_SSAO_FACTOR_INV,
-		DEFERRED_SSAO_EFFECT_MAT,
-		DEFERRED_SCREEN_RES,
-		DEFERRED_NEAR_CLIP,
-		DEFERRED_SHADOW_OFFSET,
-		DEFERRED_SHADOW_BIAS,
-		DEFERRED_SPOT_SHADOW_BIAS,
-		DEFERRED_SPOT_SHADOW_OFFSET,
-		DEFERRED_SUN_DIR,
-        DEFERRED_MOON_DIR,
-		DEFERRED_SHADOW_RES,
-		DEFERRED_PROJ_SHADOW_RES,
-		DEFERRED_DEPTH_CUTOFF,
-		DEFERRED_NORM_CUTOFF,
-		DEFERRED_SHADOW_TARGET_WIDTH,
-
-		FXAA_TC_SCALE,
-		FXAA_RCP_SCREEN_RES,
-		FXAA_RCP_FRAME_OPT,
-		FXAA_RCP_FRAME_OPT2,
-
-		DOF_FOCAL_DISTANCE,
-		DOF_BLUR_CONSTANT,
-		DOF_TAN_PIXEL_ANGLE,
-		DOF_MAGNIFICATION,
-		DOF_MAX_COF,
-		DOF_RES_SCALE,
-		DOF_WIDTH,
-		DOF_HEIGHT,
-
-		DEFERRED_DEPTH,
-		DEFERRED_SHADOW0,
-		DEFERRED_SHADOW1,
-		DEFERRED_SHADOW2,
-		DEFERRED_SHADOW3,
-		DEFERRED_SHADOW4,
-		DEFERRED_SHADOW5,
-		DEFERRED_NORMAL,
-		DEFERRED_POSITION,
-		DEFERRED_DIFFUSE,
-		DEFERRED_SPECULAR,
-		DEFERRED_NOISE,
-		DEFERRED_LIGHTFUNC,
-		DEFERRED_LIGHT,
-		DEFERRED_BLOOM,
-		DEFERRED_PROJECTION,
-		DEFERRED_NORM_MATRIX,
-		TEXTURE_GAMMA,		
-		SPECULAR_COLOR,
-		ENVIRONMENT_INTENSITY,
-		
-		AVATAR_MATRIX,
-		AVATAR_TRANSLATION,
-
-		WATER_SCREENTEX,
-		WATER_SCREENDEPTH,
-		WATER_REFTEX,
-		WATER_EYEVEC,
-		WATER_TIME,
-		WATER_WAVE_DIR1,
-		WATER_WAVE_DIR2,
-		WATER_LIGHT_DIR,
-		WATER_SPECULAR,
-		WATER_SPECULAR_EXP,
-		WATER_FOGCOLOR,
-		WATER_FOGDENSITY,
-		WATER_FOGKS,
-		WATER_REFSCALE,
-		WATER_WATERHEIGHT,
-		WATER_WATERPLANE,
-		WATER_NORM_SCALE,
-		WATER_FRESNEL_SCALE,
-		WATER_FRESNEL_OFFSET,
-		WATER_BLUR_MULTIPLIER,
-		WATER_SUN_ANGLE,
-		WATER_SCALED_ANGLE,
-		WATER_SUN_ANGLE2,
-		
-		WL_CAMPOSLOCAL,
-
-		AVATAR_WIND,
-		AVATAR_SINWAVE,
-		AVATAR_GRAVITY,
-
-		TERRAIN_DETAIL0,
-		TERRAIN_DETAIL1,
-		TERRAIN_DETAIL2,
-		TERRAIN_DETAIL3,
-		TERRAIN_ALPHARAMP,
-		
-		SHINY_ORIGIN,
-        DISPLAY_GAMMA,
-
-        INSCATTER_RT,
-        SUN_SIZE,
-        FOG_COLOR,
+    // clang-format off
+    typedef enum
+    {                                       // Shader uniform name, set in LLShaderMgr::initAttribsAndUniforms()
+        MODELVIEW_MATRIX = 0,               //  "modelview_matrix"
+        PROJECTION_MATRIX,                  //  "projection_matrix"
+        INVERSE_PROJECTION_MATRIX,          //  "inv_proj"
+        MODELVIEW_PROJECTION_MATRIX,        //  "modelview_projection_matrix"
+        INVERSE_MODELVIEW_MATRIX,           //  "inv_modelview"
+        NORMAL_MATRIX,                      //  "normal_matrix"
+        TEXTURE_MATRIX0,                    //  "texture_matrix0"
+        TEXTURE_MATRIX1,                    //  "texture_matrix1"
+        TEXTURE_MATRIX2,                    //  "texture_matrix2"
+        TEXTURE_MATRIX3,                    //  "texture_matrix3"
+        OBJECT_PLANE_S,                     //  "object_plane_s"
+        OBJECT_PLANE_T,                     //  "object_plane_t"
+        VIEWPORT,                           //  "viewport"
+        LIGHT_POSITION,                     //  "light_position"
+        LIGHT_DIRECTION,                    //  "light_direction"
+        LIGHT_ATTENUATION,                  //  "light_attenuation"
+        LIGHT_DIFFUSE,                      //  "light_diffuse"
+        LIGHT_AMBIENT,                      //  "light_ambient"
+        MULTI_LIGHT_COUNT,                  //  "light_count"
+        MULTI_LIGHT,                        //  "light"
+        MULTI_LIGHT_COL,                    //  "light_col"
+        MULTI_LIGHT_FAR_Z,                  //  "far_z"
+        PROJECTOR_MATRIX,                   //  "proj_mat"
+        PROJECTOR_NEAR,                     //  "proj_near"
+        PROJECTOR_P,                        //  "proj_p"
+        PROJECTOR_N,                        //  "proj_n"
+        PROJECTOR_ORIGIN,                   //  "proj_origin"
+        PROJECTOR_RANGE,                    //  "proj_range"
+        PROJECTOR_AMBIANCE,                 //  "proj_ambiance"
+        PROJECTOR_SHADOW_INDEX,             //  "proj_shadow_idx"
+        PROJECTOR_SHADOW_FADE,              //  "shadow_fade"
+        PROJECTOR_FOCUS,                    //  "proj_focus"
+        PROJECTOR_LOD,                      //  "proj_lod"
+        PROJECTOR_AMBIENT_LOD,              //  "proj_ambient_lod"
+        DIFFUSE_COLOR,                      //  "color"
+        DIFFUSE_MAP,                        //  "diffuseMap"
+        ALTERNATE_DIFFUSE_MAP,              //  "altDiffuseMap"
+        SPECULAR_MAP,                       //  "specularMap"
+        BUMP_MAP,                           //  "bumpMap"
+        BUMP_MAP2,                          //  "bumpMap2"
+        ENVIRONMENT_MAP,                    //  "environmentMap"
+        CLOUD_NOISE_MAP,                    //  "cloud_noise_texture"
+        CLOUD_NOISE_MAP_NEXT,               //  "cloud_noise_texture_next"
+        FULLBRIGHT,                         //  "fullbright"
+        LIGHTNORM,                          //  "lightnorm"
+        SUNLIGHT_COLOR,                     //  "sunlight_color"
+        AMBIENT,                            //  "ambient_color"
+        BLUE_HORIZON,                       //  "blue_horizon"
+        BLUE_DENSITY,                       //  "blue_density"
+        HAZE_HORIZON,                       //  "haze_horizon"
+        HAZE_DENSITY,                       //  "haze_density"
+        CLOUD_SHADOW,                       //  "cloud_shadow"
+        DENSITY_MULTIPLIER,                 //  "density_multiplier"
+        DISTANCE_MULTIPLIER,                //  "distance_multiplier"
+        MAX_Y,                              //  "max_y"
+        GLOW,                               //  "glow"
+        CLOUD_COLOR,                        //  "cloud_color"
+        CLOUD_POS_DENSITY1,                 //  "cloud_pos_density1"
+        CLOUD_POS_DENSITY2,                 //  "cloud_pos_density2"
+        CLOUD_SCALE,                        //  "cloud_scale"
+        GAMMA,                              //  "gamma"
+        SCENE_LIGHT_STRENGTH,               //  "scene_light_strength"
+        LIGHT_CENTER,                       //  "center"
+        LIGHT_SIZE,                         //  "size"
+        LIGHT_FALLOFF,                      //  "falloff"
+        BOX_CENTER,                         //  "box_center"
+        BOX_SIZE,                           //  "box_size"
+
+        GLOW_MIN_LUMINANCE,                 //  "minLuminance"
+        GLOW_MAX_EXTRACT_ALPHA,             //  "maxExtractAlpha"
+        GLOW_LUM_WEIGHTS,                   //  "lumWeights"
+        GLOW_WARMTH_WEIGHTS,                //  "warmthWeights"
+        GLOW_WARMTH_AMOUNT,                 //  "warmthAmount"
+        GLOW_STRENGTH,                      //  "glowStrength"
+        GLOW_DELTA,                         //  "glowDelta"
+
+        MINIMUM_ALPHA,                      //  "minimum_alpha"
+        EMISSIVE_BRIGHTNESS,                //  "emissive_brightness"
+
+        DEFERRED_SHADOW_MATRIX,             //  "shadow_matrix"
+        DEFERRED_ENV_MAT,                   //  "env_mat"
+        DEFERRED_SHADOW_CLIP,               //  "shadow_clip"
+        DEFERRED_SUN_WASH,                  //  "sun_wash"
+        DEFERRED_SHADOW_NOISE,              //  "shadow_noise"
+        DEFERRED_BLUR_SIZE,                 //  "blur_size"
+        DEFERRED_SSAO_RADIUS,               //  "ssao_radius"
+        DEFERRED_SSAO_MAX_RADIUS,           //  "ssao_max_radius"
+        DEFERRED_SSAO_FACTOR,               //  "ssao_factor"
+        DEFERRED_SSAO_FACTOR_INV,           //  "ssao_factor_inv"
+        DEFERRED_SSAO_EFFECT_MAT,           //  "ssao_effect_mat"
+        DEFERRED_SCREEN_RES,                //  "screen_res"
+        DEFERRED_NEAR_CLIP,                 //  "near_clip"
+        DEFERRED_SHADOW_OFFSET,             //  "shadow_offset"
+        DEFERRED_SHADOW_BIAS,               //  "shadow_bias"
+        DEFERRED_SPOT_SHADOW_BIAS,          //  "spot_shadow_bias"
+        DEFERRED_SPOT_SHADOW_OFFSET,        //  "spot_shadow_offset"
+        DEFERRED_SUN_DIR,                   //  "sun_dir"
+        DEFERRED_MOON_DIR,                  //  "moon_dir"
+        DEFERRED_SHADOW_RES,                //  "shadow_res"
+        DEFERRED_PROJ_SHADOW_RES,           //  "proj_shadow_res"
+        DEFERRED_DEPTH_CUTOFF,              //  "depth_cutoff"
+        DEFERRED_NORM_CUTOFF,               //  "norm_cutoff"
+        DEFERRED_SHADOW_TARGET_WIDTH,       //  "shadow_target_width"
+
+        FXAA_TC_SCALE,                      //  "tc_scale"
+        FXAA_RCP_SCREEN_RES,                //  "rcp_screen_res"
+        FXAA_RCP_FRAME_OPT,                 //  "rcp_frame_opt"
+        FXAA_RCP_FRAME_OPT2,                //  "rcp_frame_opt2"
+
+        DOF_FOCAL_DISTANCE,                 //  "focal_distance"
+        DOF_BLUR_CONSTANT,                  //  "blur_constant"
+        DOF_TAN_PIXEL_ANGLE,                //  "tan_pixel_angle"
+        DOF_MAGNIFICATION,                  //  "magnification"
+        DOF_MAX_COF,                        //  "max_cof"
+        DOF_RES_SCALE,                      //  "res_scale"
+        DOF_WIDTH,                          //  "dof_width"
+        DOF_HEIGHT,                         //  "dof_height"
+
+        DEFERRED_DEPTH,                     //  "depthMap"
+        DEFERRED_SHADOW0,                   //  "shadowMap0"
+        DEFERRED_SHADOW1,                   //  "shadowMap1"
+        DEFERRED_SHADOW2,                   //  "shadowMap2"
+        DEFERRED_SHADOW3,                   //  "shadowMap3"
+        DEFERRED_SHADOW4,                   //  "shadowMap4"
+        DEFERRED_SHADOW5,                   //  "shadowMap5"
+        DEFERRED_NORMAL,                    //  "normalMap"
+        DEFERRED_POSITION,                  //  "positionMap"
+        DEFERRED_DIFFUSE,                   //  "diffuseRect"
+        DEFERRED_SPECULAR,                  //  "specularRect"
+        DEFERRED_NOISE,                     //  "noiseMap"
+        DEFERRED_LIGHTFUNC,                 //  "lightFunc"
+        DEFERRED_LIGHT,                     //  "lightMap"
+        DEFERRED_BLOOM,                     //  "bloomMap"
+        DEFERRED_PROJECTION,                //  "projectionMap"
+        DEFERRED_NORM_MATRIX,               //  "norm_mat"
+        TEXTURE_GAMMA,                      //  "texture_gamma"
+        SPECULAR_COLOR,                     //  "specular_color"
+        ENVIRONMENT_INTENSITY,              //  "env_intensity"
+
+        AVATAR_MATRIX,                      //  "matrixPalette"
+        AVATAR_TRANSLATION,                 //  "translationPalette"
+
+        WATER_SCREENTEX,                    //  "screenTex"
+        WATER_SCREENDEPTH,                  //  "screenDepth"
+        WATER_REFTEX,                       //  "refTex"
+        WATER_EYEVEC,                       //  "eyeVec"
+        WATER_TIME,                         //  "time"
+        WATER_WAVE_DIR1,                    //  "waveDir1"
+        WATER_WAVE_DIR2,                    //  "waveDir2"
+        WATER_LIGHT_DIR,                    //  "lightDir"
+        WATER_SPECULAR,                     //  "specular"
+        WATER_SPECULAR_EXP,                 //  "lightExp"
+        WATER_FOGCOLOR,                     //  "waterFogColor"
+        WATER_FOGDENSITY,                   //  "waterFogDensity"
+        WATER_FOGKS,                        //  "waterFogKS"
+        WATER_REFSCALE,                     //  "refScale"
+        WATER_WATERHEIGHT,                  //  "waterHeight"
+        WATER_WATERPLANE,                   //  "waterPlane"
+        WATER_NORM_SCALE,                   //  "normScale"
+        WATER_FRESNEL_SCALE,                //  "fresnelScale"
+        WATER_FRESNEL_OFFSET,               //  "fresnelOffset"
+        WATER_BLUR_MULTIPLIER,              //  "blurMultiplier"
+        WATER_SUN_ANGLE,                    //  "sunAngle"
+        WATER_SCALED_ANGLE,                 //  "scaledAngle"
+        WATER_SUN_ANGLE2,                   //  "sunAngle2"
+
+        WL_CAMPOSLOCAL,                     //  "camPosLocal"
+
+        AVATAR_WIND,                        //  "gWindDir"
+        AVATAR_SINWAVE,                     //  "gSinWaveParams"
+        AVATAR_GRAVITY,                     //  "gGravity"
+
+        TERRAIN_DETAIL0,                    //  "detail_0"
+        TERRAIN_DETAIL1,                    //  "detail_1"
+        TERRAIN_DETAIL2,                    //  "detail_2"
+        TERRAIN_DETAIL3,                    //  "detail_3"
+        TERRAIN_ALPHARAMP,                  //  "alpha_ramp"
+
+        SHINY_ORIGIN,                       //  "origin"
+        DISPLAY_GAMMA,                      //  "display_gamma"
+
+        INSCATTER_RT,                       //  "inscatter"
+        SUN_SIZE,                           //  "sun_size"
+        FOG_COLOR,                          //  "fog_color"
 
         // precomputed textures
-        TRANSMITTANCE_TEX,
-        SCATTER_TEX,
-        SINGLE_MIE_SCATTER_TEX,
-        ILLUMINANCE_TEX,
-        BLEND_FACTOR,
-
-        NO_ATMO,
-        MOISTURE_LEVEL,
-        DROPLET_RADIUS,
-        ICE_LEVEL,
-        RAINBOW_MAP,
-        HALO_MAP,
-
-        MOON_BRIGHTNESS,
-
-        CLOUD_VARIANCE,
-
-        SH_INPUT_L1R,
-        SH_INPUT_L1G,
-        SH_INPUT_L1B,
-
-        SUN_MOON_GLOW_FACTOR,
-        WATER_EDGE_FACTOR,
-        SUN_UP_FACTOR,
-        MOONLIGHT_COLOR,
-		END_RESERVED_UNIFORMS
-	} eGLSLReservedUniforms;
+        TRANSMITTANCE_TEX,                  //  "transmittance_texture"
+        SCATTER_TEX,                        //  "scattering_texture"
+        SINGLE_MIE_SCATTER_TEX,             //  "single_mie_scattering_texture"
+        ILLUMINANCE_TEX,                    //  "irradiance_texture"
+        BLEND_FACTOR,                       //  "blend_factor"
+
+        NO_ATMO,                            //  "no_atmo"
+        MOISTURE_LEVEL,                     //  "moisture_level"
+        DROPLET_RADIUS,                     //  "droplet_radius"
+        ICE_LEVEL,                          //  "ice_level"
+        RAINBOW_MAP,                        //  "rainbow_map"
+        HALO_MAP,                           //  "halo_map"
+
+        MOON_BRIGHTNESS,                    //  "moon_brightness"
+
+        CLOUD_VARIANCE,                     //  "cloud_variance"
+
+        SH_INPUT_L1R,                       //  "sh_input_r"
+        SH_INPUT_L1G,                       //  "sh_input_g"
+        SH_INPUT_L1B,                       //  "sh_input_b"
+
+        SUN_MOON_GLOW_FACTOR,               //  "sun_moon_glow_factor"
+        WATER_EDGE_FACTOR,                  //  "water_edge"
+        SUN_UP_FACTOR,                      //  "sun_up_factor"
+        MOONLIGHT_COLOR,                    //  "moonlight_color"
+        END_RESERVED_UNIFORMS
+    } eGLSLReservedUniforms;
+    // clang-format on
 
 	// singleton pattern implementation
 	static LLShaderMgr * instance();
diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h
index 9867bd16d6394d6982271afdefc2527108cfa83d..dbe1a3687f12c06056d901ba01c1ca455f5252ec 100644
--- a/indra/llrender/llvertexbuffer.h
+++ b/indra/llrender/llvertexbuffer.h
@@ -155,9 +155,8 @@ class LLVertexBuffer : public LLRefCount, public LLTrace::MemTrackable<LLVertexB
 	//get the size of a buffer with the given typemask and vertex count
 	//fill offsets with the offset of each vertex component array into the buffer
 	// indexed by the following enum
-	static S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices);		
+	static S32 calcOffsets(const U32& typemask, S32* offsets, S32 num_vertices);
 
-	
 	//WARNING -- when updating these enums you MUST 
 	// 1 - update LLVertexBuffer::sTypeSize
 	// 2 - add a strider accessor
@@ -165,24 +164,28 @@ class LLVertexBuffer : public LLRefCount, public LLTrace::MemTrackable<LLVertexB
 	// 4 - modify LLVertexBuffer::setupClientArray
 	// 5 - modify LLViewerShaderMgr::mReservedAttribs
 	// 6 - update LLVertexBuffer::setupVertexArray
-	enum {
-		TYPE_VERTEX = 0,
-		TYPE_NORMAL,
-		TYPE_TEXCOORD0,
-		TYPE_TEXCOORD1,
-		TYPE_TEXCOORD2,
-		TYPE_TEXCOORD3,
-		TYPE_COLOR,
-		TYPE_EMISSIVE,
-		TYPE_TANGENT,
-		TYPE_WEIGHT,
-		TYPE_WEIGHT4,
-		TYPE_CLOTHWEIGHT,
-		TYPE_TEXTURE_INDEX,
-		TYPE_MAX,   // TYPE_MAX is the size/boundary marker for attributes that go in the vertex buffer
-		TYPE_INDEX,	// TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer	
-	};
-	enum {
+
+    // clang-format off
+    enum {                      // Shader attribute name, set in LLShaderMgr::initAttribsAndUniforms()
+        TYPE_VERTEX = 0,        //  "position"
+        TYPE_NORMAL,            //  "normal"
+        TYPE_TEXCOORD0,         //  "texcoord0"
+        TYPE_TEXCOORD1,         //  "texcoord1"
+        TYPE_TEXCOORD2,         //  "texcoord2"
+        TYPE_TEXCOORD3,         //  "texcoord3"
+        TYPE_COLOR,             //  "diffuse_color"
+        TYPE_EMISSIVE,          //  "emissive"
+        TYPE_TANGENT,           //  "tangent"
+        TYPE_WEIGHT,            //  "weight"
+        TYPE_WEIGHT4,           //  "weight4"
+        TYPE_CLOTHWEIGHT,       //  "clothing"
+        TYPE_TEXTURE_INDEX,     //  "texture_index"
+        TYPE_MAX,   // TYPE_MAX is the size/boundary marker for attributes that go in the vertex buffer
+        TYPE_INDEX,	// TYPE_INDEX is beyond _MAX because it lives in a separate (index) buffer	
+    };
+    // clang-format on
+
+    enum {
 		MAP_VERTEX = (1<<TYPE_VERTEX),
 		MAP_NORMAL = (1<<TYPE_NORMAL),
 		MAP_TEXCOORD0 = (1<<TYPE_TEXCOORD0),
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index 6e924c1f19f91125ba382bc06cf54d6dfd0dbc0f..d65c220974222928d444e967c863cea9d27b6357 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -295,9 +295,6 @@ const std::string LLLocale::SYSTEM_LOCALE("English_United States.1252");
 #elif LL_DARWIN
 const std::string LLLocale::USER_LOCALE("en_US.iso8859-1");// = LLStringUtil::null;
 const std::string LLLocale::SYSTEM_LOCALE("en_US.iso8859-1");
-#elif LL_SOLARIS
-const std::string LLLocale::USER_LOCALE("en_US.ISO8859-1");
-const std::string LLLocale::SYSTEM_LOCALE("C");
 #else // LL_LINUX likes this
 const std::string LLLocale::USER_LOCALE("en_US.utf8");
 const std::string LLLocale::SYSTEM_LOCALE("C");
diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp
index 10fbc06c61cbe96fecfd5ca486e543db6eb2da9d..9e9abbadff8f31b4c94102cce7e4affd030a481a 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -61,9 +61,6 @@ LLDir_Win32 gDirUtil;
 #elif LL_DARWIN
 #include "lldir_mac.h"
 LLDir_Mac gDirUtil;
-#elif LL_SOLARIS
-#include "lldir_solaris.h"
-LLDir_Solaris gDirUtil;
 #else
 #include "lldir_linux.h"
 LLDir_Linux gDirUtil;
diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h
index 38e204ef04729a9657a74f45a8540ae4a3083ce0..4988b9c6e39d1b817c9cc91d3b14e11b0c491c05 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -27,11 +27,6 @@
 #ifndef LL_LLDIR_H
 #define LL_LLDIR_H
 
-#if LL_SOLARIS
-#include <sys/param.h>
-#define MAX_PATH MAXPATHLEN
-#endif
-
 // these numbers are read from settings_files.xml, so we need to be explicit
 typedef enum ELLPath
 {
diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp
deleted file mode 100644
index f18560ff20256f6c9dcd1b4d2c24cf6811beff83..0000000000000000000000000000000000000000
--- a/indra/llvfs/lldir_solaris.cpp
+++ /dev/null
@@ -1,266 +0,0 @@
-/** 
- * @file fmodwrapper.cpp
- * @brief dummy source file for building a shared library to wrap libfmod.a
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#include "linden_common.h"
-
-#include "lldir_solaris.h"
-#include "llerror.h"
-#include "llrand.h"
-#include "llstring.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <glob.h>
-#include <pwd.h>
-#include <sys/utsname.h>
-#define _STRUCTURED_PROC 1
-#include <sys/procfs.h>
-#include <fcntl.h>
-
-static std::string getCurrentUserHome(char* fallback)
-{
-	// fwiw this exactly duplicates getCurrentUserHome() in lldir_linux.cpp...
-	// we should either derive both from LLDir_Posix or just axe Solaris.
-	const uid_t uid = getuid();
-	struct passwd *pw;
-
-	pw = getpwuid(uid);
-	if ((pw != NULL) && (pw->pw_dir != NULL))
-	{
-		return pw->pw_dir;
-	}
-
-	LL_INFOS() << "Couldn't detect home directory from passwd - trying $HOME" << LL_ENDL;
-	auto home_env = LLStringUtil::getoptenv("HOME");
-	if (home_env)
-	{
-		return *home_env;
-	}
-	else
-	{
-		LL_WARNS() << "Couldn't detect home directory!  Falling back to " << fallback << LL_ENDL;
-		return fallback;
-	}
-}
-
-
-LLDir_Solaris::LLDir_Solaris()
-{
-	mDirDelimiter = "/";
-	mCurrentDirIndex = -1;
-	mCurrentDirCount = -1;
-	mDirp = NULL;
-
-	char tmp_str[LL_MAX_PATH];	/* Flawfinder: ignore */ 
-	if (getcwd(tmp_str, LL_MAX_PATH) == NULL)
-	{
-		strcpy(tmp_str, "/tmp");
-		LL_WARNS() << "Could not get current directory; changing to "
-				<< tmp_str << LL_ENDL;
-		if (chdir(tmp_str) == -1)
-		{
-			LL_ERRS() << "Could not change directory to " << tmp_str << LL_ENDL;
-		}
-	}
-
-	mExecutableFilename = "";
-	mExecutablePathAndName = "";
-	mExecutableDir = strdup(tmp_str);
-	mWorkingDir = strdup(tmp_str);
-	mAppRODataDir = strdup(tmp_str);
-	mOSUserDir = getCurrentUserHome(tmp_str);
-	mOSUserAppDir = "";
-	mLindenUserDir = "";
-
-	char path [LL_MAX_PATH];	/* Flawfinder: ignore */ 
-
-	sprintf(path, "/proc/%d/psinfo", (int)getpid());
-	int proc_fd = -1;
-	if((proc_fd = open(path, O_RDONLY)) == -1){
-		LL_WARNS() << "unable to open " << path << LL_ENDL;
-		return;
-	}
-	psinfo_t proc_psinfo;
-	if(read(proc_fd, &proc_psinfo, sizeof(psinfo_t)) != sizeof(psinfo_t)){
-		LL_WARNS() << "Unable to read " << path << LL_ENDL;
-		close(proc_fd);
-		return;
-	}
-
-	close(proc_fd);
-
-	mExecutableFilename = strdup(proc_psinfo.pr_fname);
-	LL_INFOS() << "mExecutableFilename = [" << mExecutableFilename << "]" << LL_ENDL;
-
-	sprintf(path, "/proc/%d/path/a.out", (int)getpid());
-
-	char execpath[LL_MAX_PATH];
-	if(readlink(path, execpath, LL_MAX_PATH) == -1){
-		LL_WARNS() << "Unable to read link from " << path << LL_ENDL;
-		return;
-	}
-
-	char *p = execpath;			// nuke trash in link, if any exists
-	int i = 0;
-	while(*p != NULL && ++i < LL_MAX_PATH && isprint((int)(*p++)));
-	*p = NULL;
-
-	mExecutablePathAndName = strdup(execpath);
-	LL_INFOS() << "mExecutablePathAndName = [" << mExecutablePathAndName << "]" << LL_ENDL;
-
-	//NOTE: Why force people to cd into the package directory?
-	//      Look for SECONDLIFE env variable and use it, if set.
-
-	auto SECONDLIFE(LLDirUtil::getoptenv("SECONDLIFE"));
-	if(SECONDLIFE){
-		mExecutableDir = add(*SECONDLIFE, "bin"); //NOTE:  make sure we point at the bin
-	}else{
-		mExecutableDir = getDirName(execpath);
-		LL_INFOS() << "mExecutableDir = [" << mExecutableDir << "]" << LL_ENDL;
-	}
-
-	mLLPluginDir = add(mExecutableDir, "llplugin");
-
-	// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
-	mTempDir = "/tmp";
-}
-
-LLDir_Solaris::~LLDir_Solaris()
-{
-}
-
-// Implementation
-
-
-void LLDir_Solaris::initAppDirs(const std::string &app_name,
-								const std::string& app_read_only_data_dir)
-{
-	// Allow override so test apps can read newview directory
-	if (!app_read_only_data_dir.empty())
-	{
-		mAppRODataDir = app_read_only_data_dir;
-		mSkinBaseDir = add(mAppRODataDir, "skins");
-	}
-	mAppName = app_name;
-
-	std::string upper_app_name(app_name);
-	LLStringUtil::toUpper(upper_app_name);
-
-	auto app_home_env(LLStringUtil::getoptenv(upper_app_name + "_USER_DIR"));
-	if (app_home_env)
-	{
-		// user has specified own userappdir i.e. $SECONDLIFE_USER_DIR
-		mOSUserAppDir = *app_home_env;
-	}
-	else
-	{
-		// traditionally on unixoids, MyApp gets ~/.myapp dir for data
-		mOSUserAppDir = mOSUserDir;
-		mOSUserAppDir += "/";
-		mOSUserAppDir += ".";
-		std::string lower_app_name(app_name);
-		LLStringUtil::toLower(lower_app_name);
-		mOSUserAppDir += lower_app_name;
-	}
-
-	// create any directories we expect to write to.
-
-	int res = LLFile::mkdir(mOSUserAppDir);
-	if (res == -1)
-	{
-		LL_WARNS() << "Couldn't create app user dir " << mOSUserAppDir << LL_ENDL;
-		LL_WARNS() << "Default to base dir" << mOSUserDir << LL_ENDL;
-		mOSUserAppDir = mOSUserDir;
-	}
-
-	res = LLFile::mkdir(getExpandedFilename(LL_PATH_LOGS,""));
-	if (res == -1)
-	{
-		LL_WARNS() << "Couldn't create LL_PATH_LOGS dir " << getExpandedFilename(LL_PATH_LOGS,"") << LL_ENDL;
-	}
-	
-	res = LLFile::mkdir(getExpandedFilename(LL_PATH_USER_SETTINGS,""));
-	if (res == -1)
-	{
-		LL_WARNS() << "Couldn't create LL_PATH_USER_SETTINGS dir " << getExpandedFilename(LL_PATH_USER_SETTINGS,"") << LL_ENDL;
-	}
-
-	res = LLFile::mkdir(getExpandedFilename(LL_PATH_CACHE,""));
-	if (res == -1)
-	{
-		LL_WARNS() << "Couldn't create LL_PATH_CACHE dir " << getExpandedFilename(LL_PATH_CACHE,"") << LL_ENDL;
-	}
-
-	mCAFile = getExpandedFilename(LL_PATH_EXECUTABLE, "ca-bundle.crt");
-}
-
-U32 LLDir_Solaris::countFilesInDir(const std::string &dirname, const std::string &mask)
-{
-	U32 file_count = 0;
-	glob_t g;
-
-	std::string tmp_str;
-	tmp_str = dirname;
-	tmp_str += mask;
-	
-	if(glob(tmp_str.c_str(), GLOB_NOSORT, NULL, &g) == 0)
-	{
-		file_count = g.gl_pathc;
-
-		globfree(&g);
-	}
-
-	return (file_count);
-}
-
-std::string LLDir_Solaris::getCurPath()
-{
-	char tmp_str[LL_MAX_PATH];	/* Flawfinder: ignore */ 
-	if (getcwd(tmp_str, LL_MAX_PATH) == NULL)
-	{
-		LL_WARNS() << "Could not get current directory" << LL_ENDL;
-		tmp_str[0] = '\0';
-	}
-	return tmp_str;
-}
-
-
-bool LLDir_Solaris::fileExists(const std::string &filename) const
-{
-	struct stat stat_data;
-	// Check the age of the file
-	// Now, we see if the files we've gathered are recent...
-	int res = stat(filename.c_str(), &stat_data);
-	if (!res)
-	{
-		return TRUE;
-	}
-	else
-	{
-		return FALSE;
-	}
-}
-
diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h
deleted file mode 100644
index c6dac57e1445795c6da708360e65f3ef46181da8..0000000000000000000000000000000000000000
--- a/indra/llvfs/lldir_solaris.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/** 
- * @file fmodwrapper.cpp
- * @brief dummy source file for building a shared library to wrap libfmod.a
- *
- * $LicenseInfo:firstyear=2005&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2010, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-#if !LL_SOLARIS
-#error This header must not be included when compiling for any target other than Solaris. Consider including lldir.h instead.
-#endif // !LL_SOLARIS
-
-#ifndef LL_LLDIR_SOLARIS_H
-#define LL_LLDIR_SOLARIS_H
-
-#include "lldir.h"
-
-#include <dirent.h>
-#include <errno.h>
-
-class LLDir_Solaris : public LLDir
-{
-public:
-	LLDir_Solaris();
-	virtual ~LLDir_Solaris();
-
-	/*virtual*/ void initAppDirs(const std::string &app_name,
-		const std::string& app_read_only_data_dir);
-
-	virtual std::string getCurPath();
-	virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask);
-	/*virtual*/ bool fileExists(const std::string &filename) const;
-
-private:
-	DIR *mDirp;
-	int mCurrentDirIndex;
-	int mCurrentDirCount;
-	std::string mCurrentDir;
-};
-
-#endif // LL_LLDIR_SOLARIS_H
-
-
diff --git a/indra/llvfs/llvfs.cpp b/indra/llvfs/llvfs.cpp
index 617056d94d224eeea3d89b26b45063fe469811e4..2c64bf563eff395e27f7e344a424b1c0d93dff4e 100644
--- a/indra/llvfs/llvfs.cpp
+++ b/indra/llvfs/llvfs.cpp
@@ -33,10 +33,6 @@
 #include <map>
 #if LL_WINDOWS
 #include <share.h>
-#elif LL_SOLARIS
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
 #else
 #include <sys/file.h>
 #endif
@@ -2146,12 +2142,6 @@ LLFILE *LLVFS::openAndLock(const std::string& filename, const char* mode, BOOL r
 	int fd;
 	
 	// first test the lock in a non-destructive way
-#if LL_SOLARIS
-        struct flock fl;
-        fl.l_whence = SEEK_SET;
-        fl.l_start = 0;
-        fl.l_len = 1;
-#else // !LL_SOLARIS
 	if (strchr(mode, 'w') != NULL)
 	{
 		fp = LLFile::fopen(filename, "rb");	/* Flawfinder: ignore */
@@ -2167,19 +2157,13 @@ LLFILE *LLVFS::openAndLock(const std::string& filename, const char* mode, BOOL r
 			fclose(fp);
 		}
 	}
-#endif // !LL_SOLARIS
 
 	// now actually open the file for use
 	fp = LLFile::fopen(filename, mode);	/* Flawfinder: ignore */
 	if (fp)
 	{
 		fd = fileno(fp);
-#if LL_SOLARIS
-                fl.l_type = read_lock ? F_RDLCK : F_WRLCK;
-                if (fcntl(fd, F_SETLK, &fl) == -1)
-#else
 		if (flock(fd, (read_lock ? LOCK_SH : LOCK_EX) | LOCK_NB) == -1)
-#endif
 		{
 			fclose(fp);
 			fp = NULL;
@@ -2207,14 +2191,6 @@ void LLVFS::unlockAndClose(LLFILE *fp)
 	  flock(fd, LOCK_UN);
 	  #endif
     */
-#if LL_SOLARIS
-	        struct flock fl;
-		fl.l_whence = SEEK_SET;
-		fl.l_start = 0;
-		fl.l_len = 1;
-		fl.l_type = F_UNLCK;
-		fcntl(fileno(fp), F_SETLK, &fl);
-#endif
 		fclose(fp);
 	}
 }
diff --git a/indra/llwindow/llwindowsdl.cpp b/indra/llwindow/llwindowsdl.cpp
index c20e639fc74917d1204fe6044cec39eb7e5f690d..85eb9d6d1b17e47eda95d9e7c6e0225a5ef54538 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -51,13 +51,13 @@ extern "C" {
 # include "fontconfig/fontconfig.h"
 }
 
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX
 // not necessarily available on random SDL platforms, so #if LL_LINUX
 // for execv(), waitpid(), fork()
 # include <unistd.h>
 # include <sys/types.h>
 # include <sys/wait.h>
-#endif // LL_LINUX || LL_SOLARIS
+#endif // LL_LINUX
 
 extern BOOL gDebugWindowProc;
 
@@ -323,12 +323,6 @@ static int x11_detect_VRAM_kb_fp(FILE *fp, const char *prefix_str)
 
 static int x11_detect_VRAM_kb()
 {
-#if LL_SOLARIS && defined(__sparc)
-      //  NOTE: there's no Xorg server on SPARC so just return 0
-      //        and allow SDL to attempt to get the amount of VRAM
-      return(0);
-#else
-
 	std::string x_log_location("/var/log/");
 	std::string fname;
 	int rtn = 0; // 'could not detect'
@@ -409,7 +403,6 @@ static int x11_detect_VRAM_kb()
 		}
 	}
 	return rtn;
-#endif // LL_SOLARIS
 }
 #endif // LL_X11
 
@@ -484,27 +477,10 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
 	SDL_GL_SetAttribute(SDL_GL_RED_SIZE,  8);
 	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE,8);
 	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
-#if !LL_SOLARIS
-        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, (bits <= 16) ? 16 : 24);
+    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, (bits <= 16) ? 16 : 24);
 	// We need stencil support for a few (minor) things.
 	if (!getenv("LL_GL_NO_STENCIL"))
 		SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
-#else
-	// NOTE- use smaller Z-buffer to enable more graphics cards
-        //     - This should not affect better GPUs and has been proven
-        //	 to provide 24-bit z-buffers when available.
-	//
-        // As the API states: 
-	//
-        // GLX_DEPTH_SIZE    Must be followed by a nonnegative
-        //                   minimum size specification.  If this
-        //                   value is zero, visuals with no depth
-        //                   buffer are preferred.  Otherwise, the
-        //                   largest available depth buffer of at
-        //                   least the minimum size is preferred.
-
-        SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16);
-#endif
         SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, (bits <= 16) ? 1 : 8);
 
         // *FIX: try to toggle vsync here?
@@ -682,25 +658,13 @@ BOOL LLWindowSDL::createContext(int x, int y, int width, int height, int bits, B
 	// fixme: actually, it's REALLY important for picking that we get at
 	// least 8 bits each of red,green,blue.  Alpha we can be a bit more
 	// relaxed about if we have to.
-#if LL_SOLARIS && defined(__sparc)
-//  again the __sparc required because Xsun support, 32bit are very pricey on SPARC
-	if(colorBits < 24)		//HACK:  on SPARC allow 24-bit color
-#else
 	if (colorBits < 32)
-#endif
 	{
 		close();
 		setupFailure(
-#if LL_SOLARIS && defined(__sparc)
-			"Second Life requires at least 24-bit color on SPARC to run in a window.\n"
-			"Please use fbconfig to set your default color depth to 24 bits.\n"
-			"You may also need to adjust the X11 setting in SMF.  To do so use\n"
-			"  'svccfg -s svc:/application/x11/x11-server setprop options/default_depth=24'\n"
-#else
 			"Second Life requires True Color (32-bit) to run in a window.\n"
 			"Please go to Control Panels -> Display -> Settings and\n"
 			"set the screen to 32-bit color.\n"
-#endif
 			"Alternately, if you choose to run fullscreen, Second Life\n"
 			"will automatically adjust the screen each time it runs.",
 			"Error",
@@ -2503,7 +2467,7 @@ BOOL LLWindowSDL::dialogColorPicker( F32 *r, F32 *g, F32 *b)
 }
 #endif // LL_GTK
 
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX
 // extracted from spawnWebBrowser for clarity and to eliminate
 //  compiler confusion regarding close(int fd) vs. LLWindow::close()
 void exec_cmd(const std::string& cmd, const std::string& arg)
@@ -2559,7 +2523,7 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
 
 	LL_INFOS() << "spawn_web_browser: " << escaped_url << LL_ENDL;
 	
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX
 # if LL_X11
 	if (mSDL_Display)
 	{
@@ -2578,7 +2542,7 @@ void LLWindowSDL::spawnWebBrowser(const std::string& escaped_url, bool async)
 	cmd += "launch_url.sh";
 	arg = escaped_url;
 	exec_cmd(cmd, arg);
-#endif // LL_LINUX || LL_SOLARIS
+#endif // LL_LINUX
 
 	LL_INFOS() << "spawn_web_browser returning." << LL_ENDL;
 }
diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp
index f774cd0d31227b18a3881873a761ca627f91fc7a..b2b123f0da0764e297b46ac67d82bcac22ba9044 100644
--- a/indra/llwindow/llwindowwin32.cpp
+++ b/indra/llwindow/llwindowwin32.cpp
@@ -483,7 +483,7 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
 	memset(mPrevGammaRamp, 0, sizeof(mPrevGammaRamp));
 	mCustomGammaSet = FALSE;
 	mWindowHandle = NULL;
-
+	
 	if (!SystemParametersInfo(SPI_GETMOUSEVANISH, 0, &mMouseVanish, 0))
 	{
 		mMouseVanish = TRUE;
@@ -746,6 +746,37 @@ LLWindowWin32::LLWindowWin32(LLWindowCallbacks* callbacks,
 	//		TrackMouseEvent( &track_mouse_event ); 
 	//	}
 
+    // SL-12971 dual GPU display
+    DISPLAY_DEVICEA display_device;
+    int             display_index = -1;
+    DWORD           display_flags = 0; // EDD_GET_DEVICE_INTERFACE_NAME ?
+    const size_t    display_bytes = sizeof(display_device);
+
+    do
+    {
+        if (display_index >= 0)
+        {
+            // CHAR DeviceName  [ 32] Adapter name
+            // CHAR DeviceString[128]
+            CHAR text[256];
+
+            size_t name_len = strlen(display_device.DeviceName  );
+            size_t desc_len = strlen(display_device.DeviceString);
+
+            CHAR *name = name_len ? display_device.DeviceName   : "???";
+            CHAR *desc = desc_len ? display_device.DeviceString : "???";
+
+            sprintf(text, "Display Device %d: %s, %s", display_index, name, desc);
+            LL_INFOS("Window") << text << LL_ENDL;
+        }
+
+        ::ZeroMemory(&display_device,display_bytes);
+        display_device.cb = display_bytes;
+
+        display_index++;
+    }  while( EnumDisplayDevicesA(NULL, display_index, &display_device, display_flags ));
+
+    LL_INFOS("Window") << "Total Display Devices: " << display_index << LL_ENDL;
 
 	//-----------------------------------------------------------------------
 	// Create GL drawing context
@@ -1271,22 +1302,22 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
     {
         // Looks like ChoosePixelFormat can crash in case of faulty driver
         if (!(pixel_format = SafeChoosePixelFormat(mhDC, &pfd)))
-        {
+	{
             LL_WARNS("Window") << "ChoosePixelFormat failed, code: " << GetLastError() << LL_ENDL;
             OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
                 mCallbacks->translateString("MBError"), OSMB_OK);
-            close();
+		close();
             return FALSE;
         }
     }
     catch (...)
     {
         LOG_UNHANDLED_EXCEPTION("ChoosePixelFormat");
-        OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
-            mCallbacks->translateString("MBError"), OSMB_OK);
+		OSMessageBox(mCallbacks->translateString("MBPixelFmtErr"),
+			mCallbacks->translateString("MBError"), OSMB_OK);
         close();
-        return FALSE;
-    }
+		return FALSE;
+	}
 
 	LL_INFOS("Window") << "Pixel format chosen." << LL_ENDL ;
 
@@ -1513,21 +1544,27 @@ BOOL LLWindowWin32::switchContext(BOOL fullscreen, const LLCoordScreen &size, BO
 		LL_INFOS("Window") << "pixel formats done." << LL_ENDL ;
 
 		S32 swap_method = 0;
-		S32 cur_format = num_formats-1;
+		S32   cur_format  = 0;
+const	S32   max_format  = (S32)num_formats - 1;
 		GLint swap_query = WGL_SWAP_METHOD_ARB;
 
-		BOOL found_format = FALSE;
-
-		while (!found_format && wglGetPixelFormatAttribivARB(mhDC, pixel_format, 0, 1, &swap_query, &swap_method))
+		// SL-14705 Fix name tags showing in front of objects with AMD GPUs.
+		// On AMD hardware we need to iterate from the first pixel format to the end.
+		// Spec:
+		//     https://www.khronos.org/registry/OpenGL/extensions/ARB/WGL_ARB_pixel_format.txt
+		while (wglGetPixelFormatAttribivARB(mhDC, pixel_formats[cur_format], 0, 1, &swap_query, &swap_method))
 		{
-			if (swap_method == WGL_SWAP_UNDEFINED_ARB || cur_format <= 0)
+			if (swap_method == WGL_SWAP_UNDEFINED_ARB)
 			{
-				found_format = TRUE;
+				break;
 			}
-			else
+			else if (cur_format >= max_format)
 			{
-				--cur_format;
+				cur_format = 0;
+				break;
 			}
+
+			++cur_format;
 		}
 		
 		pixel_format = pixel_formats[cur_format];
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index e8e5b839571854967416451a1ca8613264e15ba8..424fd17707b1403ed5c011d0276daac1ea33cf75 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -589,6 +589,7 @@ set(viewer_SOURCE_FILES
     llsyntaxid.cpp
     llsyswellitem.cpp
     llsyswellwindow.cpp
+    lltelemetry.cpp
     llteleporthistory.cpp
     llteleporthistorystorage.cpp
     lltextureatlas.cpp
diff --git a/indra/newview/VIEWER_VERSION.txt b/indra/newview/VIEWER_VERSION.txt
index 427dc381adc46644c4314d8086894f91f7ce7e16..e786022da5d4f75c8734f90965b20f1e132ce6cd 100644
--- a/indra/newview/VIEWER_VERSION.txt
+++ b/indra/newview/VIEWER_VERSION.txt
@@ -1 +1 @@
-6.4.19
+6.4.20
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index fa47596bfa73675705271e564dc6d05c186085e6..1df3ed53463565832a1a9f0c7f64d00918da77cf 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -6597,7 +6597,7 @@
     <key>Value</key>
     <integer>1</integer>
   </map>
-  <key>MemoryFailurePreventionEnabled</key>
+  <key>MemoryFailurePreventionEnabled</key> <!-- deprecated, only used for obsolete-in-2020 Intel 965 Express GPU -->
   <map>
     <key>Comment</key>
     <string>If set, the viewer will quit to avoid crash when memory failure happens</string>
@@ -9124,7 +9124,7 @@
     <key>Type</key>
     <string>F32</string>
     <key>Value</key>
-    <real>0.03</real>
+    <real>0.1</real>
   </map>
   <key>RenderDebugPipeline</key>
     <map>
diff --git a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
index b7036e02cfcc8f169dcdad32f858f334c79159c5..8e0a0014038514208f6772cccd09b38b8925172c 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/cloudsV.glsl
@@ -1,24 +1,24 @@
-/**
+/** 
  * @file WLCloudsV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2005, 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$
  */
@@ -33,26 +33,26 @@ ATTRIBUTE vec2 texcoord0;
 ///////////////////////////////////////////////////////////////////////////////
 
 // Output parameters
-VARYING vec4  vary_CloudColorSun;
-VARYING vec4  vary_CloudColorAmbient;
+VARYING vec4 vary_CloudColorSun;
+VARYING vec4 vary_CloudColorAmbient;
 VARYING float vary_CloudDensity;
 
-VARYING vec2  vary_texcoord0;
-VARYING vec2  vary_texcoord1;
-VARYING vec2  vary_texcoord2;
-VARYING vec2  vary_texcoord3;
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
 VARYING float altitude_blend_factor;
 
 // Inputs
 uniform vec3 camPosLocal;
 
-uniform vec4  lightnorm;
-uniform vec4  sunlight_color;
-uniform vec4  moonlight_color;
-uniform int   sun_up_factor;
-uniform vec4  ambient_color;
-uniform vec4  blue_horizon;
-uniform vec4  blue_density;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 moonlight_color;
+uniform int sun_up_factor;
+uniform vec4 ambient_color;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
 uniform float haze_horizon;
 uniform float haze_density;
 
@@ -60,7 +60,7 @@ uniform float cloud_shadow;
 uniform float density_multiplier;
 uniform float max_y;
 
-uniform vec4  glow;
+uniform vec4 glow;
 uniform float sun_moon_glow_factor;
 
 uniform vec4 cloud_color;
@@ -75,53 +75,53 @@ uniform float cloud_scale;
 //       indra\newview\llsettingsvo.cpp
 void main()
 {
-    // World / view / projection
-    gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+	// World / view / projection
+	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
 
-    // Texture coords
+	// Texture coords
     // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll
     vary_texcoord0 = vec2(-texcoord0.x, texcoord0.y);  // See: LLSettingsVOSky::applySpecial
 
-    vary_texcoord0.xy -= 0.5;
-    vary_texcoord0.xy /= cloud_scale;
-    vary_texcoord0.xy += 0.5;
+	vary_texcoord0.xy -= 0.5;
+	vary_texcoord0.xy /= cloud_scale;
+	vary_texcoord0.xy += 0.5;
 
-    vary_texcoord1 = vary_texcoord0;
-    vary_texcoord1.x += lightnorm.x * 0.0125;
-    vary_texcoord1.y += lightnorm.z * 0.0125;
+	vary_texcoord1 = vary_texcoord0;
+	vary_texcoord1.x += lightnorm.x * 0.0125;
+	vary_texcoord1.y += lightnorm.z * 0.0125;
 
-    vary_texcoord2 = vary_texcoord0 * 16.;
-    vary_texcoord3 = vary_texcoord1 * 16.;
+	vary_texcoord2 = vary_texcoord0 * 16.;
+	vary_texcoord3 = vary_texcoord1 * 16.;
 
-    // Get relative position
+	// Get relative position
     vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
 
     altitude_blend_factor = clamp((rel_pos.y + 512.0) / max_y, 0.0, 1.0);
 
-    // Set altitude
+	// Set altitude
     if (rel_pos.y > 0)
-    {
+	{
         rel_pos *= (max_y / rel_pos.y);
-    }
+	}
     if (rel_pos.y < 0)
-    {
-        altitude_blend_factor = 0;  // SL-11589 Fix clouds drooping below horizon
+	{
+		altitude_blend_factor = 0; // SL-11589 Fix clouds drooping below horizon
         rel_pos *= (-32000. / rel_pos.y);
-    }
+	}
 
-    // Can normalize then
+	// Can normalize then
     vec3  rel_pos_norm = normalize(rel_pos);
     float rel_pos_len  = length(rel_pos);
 
-    // Initialize temp variables
-    vec4 sunlight = sunlight_color;
-    vec4 light_atten;
+	// Initialize temp variables
+	vec4 sunlight = sunlight_color;
+	vec4 light_atten;
 
-    // Sunlight attenuation effect (hue and brightness) due to atmosphere
-    // this is used later for sunlight modulation at various altitudes
+	// Sunlight attenuation effect (hue and brightness) due to atmosphere
+	// this is used later for sunlight modulation at various altitudes
     light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
 
-    // Calculate relative weights
+	// Calculate relative weights
     vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
     vec4 blue_weight   = blue_density / combined_haze;
     vec4 haze_weight   = haze_density / combined_haze;
@@ -130,63 +130,64 @@ void main()
     float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
     sunlight *= exp(-light_atten * off_axis);
 
-    // Distance
+	// Distance
     float density_dist = rel_pos_len * density_multiplier;
 
     // Transparency (-> combined_haze)
     // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
-    // compiler gets confused.
+	// compiler gets confused.
     combined_haze = exp(-combined_haze * density_dist);
 
-    // Compute haze glow
+	// Compute haze glow
     float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
     // haze_glow is 0 at the sun and increases away from sun
     haze_glow = max(haze_glow, .001);
-    // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
     haze_glow *= glow.x;
-    // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
     haze_glow = pow(haze_glow, glow.z);
-    // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
 
     haze_glow *= sun_moon_glow_factor;
 
-    // Add "minimum anti-solar illumination"
+	// Add "minimum anti-solar illumination"
     // For sun, add to glow.  For moon, remove glow entirely. SL-13768
     haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
 
-    // Increase ambient when there are more clouds
-    vec4 tmpAmbient = ambient_color;
-    tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
+	// Increase ambient when there are more clouds
+	vec4 tmpAmbient = ambient_color;
+	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; 
 
-    // Dim sunlight by cloud shadow percentage
-    sunlight *= (1. - cloud_shadow);
+	// Dim sunlight by cloud shadow percentage
+	sunlight *= (1. - cloud_shadow);
 
-    // Haze color below cloud
+	// Haze color below cloud
     vec4 additiveColorBelowCloud =
         (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
 
-    // CLOUDS
+	// CLOUDS
+    sunlight = sunlight_color;  // SL-14707 reset color -- Clouds are unusually dim in EEP
     off_axis = 1.0 / max(1e-6, lightnorm.y * 2.);
     sunlight *= exp(-light_atten * off_axis);
 
-    // Cloud color out
+	// Cloud color out
     vary_CloudColorSun     = (sunlight * haze_glow) * cloud_color;
-    vary_CloudColorAmbient = tmpAmbient * cloud_color;
-
-    // Attenuate cloud color by atmosphere
+	vary_CloudColorAmbient = tmpAmbient * cloud_color;
+	
+	// Attenuate cloud color by atmosphere
     combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds
     vary_CloudColorSun *= combined_haze;
     vary_CloudColorAmbient *= combined_haze;
     vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
 
-    // Make a nice cloud density based on the cloud_shadow value that was passed in.
-    vary_CloudDensity = 2. * (cloud_shadow - 0.25);
+	// Make a nice cloud density based on the cloud_shadow value that was passed in.
+	vary_CloudDensity = 2. * (cloud_shadow - 0.25);
 
-    // Combine these to minimize register use
-    vary_CloudColorAmbient += oHazeColorBelowCloud;
+	// Combine these to minimize register use
+	vary_CloudColorAmbient += oHazeColorBelowCloud;
 
-    // needs this to compile on mac
-    // vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+	// needs this to compile on mac
+	//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
 
-    // END CLOUDS
+	// END CLOUDS
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
index 6b36d00f97e504b57a33e0b9f7c31b3bccfbab89..9fcee04c3254d1dca6152348cda08107112f5118 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/fullbrightShinyF.glsl
@@ -64,28 +64,27 @@ void main()
 #else
 	vec4 color = texture2D(diffuseMap, vary_texcoord0.xy);
 #endif
-
+	
 	color.rgb *= vertex_color.rgb;
 
 	// SL-9632 HUDs are affected by Atmosphere
 	if (no_atmo == 0)
 	{
-		vec3 sunlit;
-		vec3 amblit;
-		vec3 additive;
-		vec3 atten;
+	vec3 sunlit;
+	vec3 amblit;
+	vec3 additive;
+	vec3 atten;
 		vec3 pos = vary_position.xyz/vary_position.w;
 
-		calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
-
-		vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
-		float env_intensity = vertex_color.a;
+	calcAtmosphericVars(pos.xyz, vec3(0), 1.0, sunlit, amblit, additive, atten, false);
+	
+	vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;	
+	float env_intensity = vertex_color.a;
 
 	//color.rgb = srgb_to_linear(color.rgb);
 		color.rgb = mix(color.rgb, envColor.rgb, env_intensity);
-
-		color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten);
-		color.rgb = fullbrightScaleSoftClip(color.rgb);
+	color.rgb = fullbrightAtmosTransportFrag(color.rgb, additive, atten);
+	color.rgb = fullbrightScaleSoftClip(color.rgb);
 	}
 
 /*
diff --git a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
index d29e8a9423ab73f3b058c0a323251cfe3499bd04..eb6e56e718cf3da79584bcc5792b972e25f2e2e8 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/impostorF.glsl
@@ -40,6 +40,8 @@ uniform sampler2D specularMap;
 
 VARYING vec2 vary_texcoord0;
 
+vec3 linear_to_srgb(vec3 c);
+
 void main() 
 {
 	vec4 col = texture2D(diffuseMap, vary_texcoord0.xy);
@@ -52,6 +54,7 @@ void main()
 	vec4 norm = texture2D(normalMap,   vary_texcoord0.xy);
 	vec4 spec = texture2D(specularMap, vary_texcoord0.xy);
 
+	col.rgb = linear_to_srgb(col.rgb);
 	frag_data[0] = vec4(col.rgb, 0.0);
 	frag_data[1] = spec;
 	frag_data[2] = vec4(norm.xy,0,0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
index 80d19102b6ce957d0e8defa72d93bbcd77617322..e1f7031af6ad587650665da70158588d8cf16da0 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/materialF.glsl
@@ -406,6 +406,8 @@ void main()
 
     vec3 light = vec3(0, 0, 0);
     
+    final_specular.rgb = srgb_to_linear(final_specular.rgb); // SL-14035
+
 #define LIGHT_LOOP(i) light.rgb += calcPointLightOrSpotLight(light_diffuse[i].rgb, npos, diffuse.rgb, final_specular, pos.xyz, norm.xyz, light_position[i], light_direction[i].xyz, light_attenuation[i].x, light_attenuation[i].y, light_attenuation[i].z, glare, light_attenuation[i].w );
 
     LIGHT_LOOP(1)
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
index 8c402fcb5466f54b229074e4498326d370085c67..09c47165ddcd7dd4e2e89ddc1e6051e609d37f14 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiPointLightF.glsl
@@ -73,9 +73,7 @@ void main()
     vec3 norm = getNorm(frag.xy);
 
     vec4 spec = texture2DRect(specularRect, frag.xy);
-    spec.rgb  = srgb_to_linear(spec.rgb);
     vec3 diff = texture2DRect(diffuseRect, frag.xy).rgb;
-    diff.rgb  = srgb_to_linear(diff.rgb);
 
     float noise = texture2D(noiseMap, frag.xy / 128.0).b;
     vec3  npos  = normalize(-pos);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
index 9bba45bc4ea1f7163724d264430efcd1d3f19c20..ec3fb9c54316dc16e398142484eb338bb58d1246 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/multiSpotLightF.glsl
@@ -182,10 +182,6 @@ void main()
 		
 		
 	vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
-    // SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space.
-    //          We can't switch to linear here unless we do it everywhere*
-	// *gbuffer is sRGB, convert to linear whenever sampling from it
-    diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
 
 	vec3 dlit = vec3(0, 0, 0);
 	
diff --git a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
index d805c9ea48a97436011da003cfcf343a34883595..18616a9bb36c8bc6e6019304f164bf66f6d3f0dd 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/pointLightF.glsl
@@ -90,7 +90,6 @@ void main()
     float noise = texture2D(noiseMap, frag.xy/128.0).b;
     
     vec3 col = texture2DRect(diffuseRect, frag.xy).rgb;
-    col.rgb = srgb_to_linear(col.rgb);
 
     float fa = falloff+1.0;
     float dist_atten = clamp(1.0-(dist-1.0*(1.0-fa))/fa, 0.0, 1.0);
@@ -127,7 +126,7 @@ void main()
     {
         discard;
     }
-//col.rgb = vec3(0);        
+
     frag_color.rgb = col;   
     frag_color.a = 0.0;
 }
diff --git a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
index f80f1a985a31a9ea796e2d47d3fef08939831e03..7f2c603f87a7f867cfebc2377bdd61a2a409fc95 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightF.glsl
@@ -90,7 +90,7 @@ void main()
     vec4 diffuse = texture2DRect(diffuseRect, tc);
 
     //convert to gamma space
-    //diffuse.rgb = linear_to_srgb(diffuse.rgb);
+    diffuse.rgb = linear_to_srgb(diffuse.rgb); // SL-14035
 
     vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
     vec3 color = vec3(0);
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
index 454af2a9bcee478fbe107402a564d52a32a5328c..b2fa5d8a2567edd65462194e2fbc94d637cd8496 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunDiscF.glsl
@@ -49,10 +49,6 @@ void main()
     vec4 sunDiscB = texture2D(altDiffuseMap, vary_texcoord0.xy);
     vec4 c     = mix(sunDiscA, sunDiscB, blend_factor);
 
-    c.rgb = srgb_to_linear(c.rgb);
-    c.rgb = clamp(c.rgb, vec3(0), vec3(1));
-    c.rgb = pow(c.rgb, vec3(0.7f));
-
     //c.rgb = fullbrightAtmosTransport(c.rgb);
     c.rgb = fullbrightScaleSoftClip(c.rgb);
 
diff --git a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
index 6f7e777d23f6e16abc6324afe0cbbc0b1ec35054..5e966293c6fed83e1332dcaa5647ec8d99c4d8fe 100644
--- a/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
+++ b/indra/newview/app_settings/shaders/class1/lighting/lightFullbrightShinyF.glsl
@@ -48,15 +48,15 @@ void fullbright_shiny_lighting()
 {
 	vec4 color = diffuseLookup(vary_texcoord0.xy);
 	color.rgb *= vertex_color.rgb;
-
+	
 	// SL-9632 HUDs are affected by Atmosphere
 	if (no_atmo == 0)
 	{
-		vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;
-		color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a*0.75); // MAGIC NUMBER SL-12574; ALM: Off, Quality > Low
+	vec3 envColor = textureCube(environmentMap, vary_texcoord1.xyz).rgb;	
+	color.rgb = mix(color.rgb, envColor.rgb, vertex_color.a*0.75); // MAGIC NUMBER SL-12574; ALM: Off, Quality > Low
 
-		color.rgb = fullbrightShinyAtmosTransport(color.rgb);
-		color.rgb = fullbrightScaleSoftClip(color.rgb);
+	color.rgb = fullbrightShinyAtmosTransport(color.rgb);
+	color.rgb = fullbrightScaleSoftClip(color.rgb);
 	}
 /*
 	// NOTE: HUD objects will be full bright. Uncomment if you want "some" environment lighting effecting these HUD objects.
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
index a0699affbf078c73ad0d3c7b26817cc9b379bddf..3b4d358cfab8fad00916f07ce815a8f8fcde884d 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsF.glsl
@@ -1,30 +1,37 @@
-/** 
+/**
  * @file class1\windlight\atmosphericVarsF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2007, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
 
-vec3 getPositionEye()
-{
-	return vec3(0,0,0);
-}
+VARYING vec3 vary_AdditiveColor;
+VARYING vec3 vary_AtmosAttenuation;
+
+vec3 getAmblitColor() { return vec3(0, 0, 0); }
+
+vec3 getAdditiveColor() { return vary_AdditiveColor; }
+
+vec3 getAtmosAttenuation() { return vec3(vary_AtmosAttenuation); }
+
+vec3 getSunlitColor() { return vec3(0, 0, 0); }
+
+vec3 getPositionEye() { return vec3(0, 0, 0); }
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
index bd1d150fc81956fdcb110ede0ccafa552be0f8e9..1fea2c362898f6b74b22461ca5f736e8b2fa58a7 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsV.glsl
@@ -1,36 +1,56 @@
-/** 
+/**
  * @file class1\windlight\atmosphericVarsV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2007, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
 
+VARYING vec3 vary_AdditiveColor;
+VARYING vec3 vary_AtmosAttenuation;
 
-vec3 getPositionEye()
+vec3 additive_color;
+vec3 atmos_attenuation;
+vec3 sunlit_color;
+vec3 amblit_color;
+vec3 position_eye;
+
+vec3 getSunlitColor() { return sunlit_color; }
+void setSunlitColor(vec3 v) { sunlit_color = v; }
+
+vec3 getAdditiveColor() { return additive_color; }
+void setAdditiveColor(vec3 v)
 {
-	return vec3(0,0,0);
+    additive_color     = v;
+    vary_AdditiveColor = v;
 }
 
-void setPositionEye(vec3 v)
+vec3 getAmblitColor() { return amblit_color; }
+void setAmblitColor(vec3 v) { amblit_color = v; }
+
+vec3 getAtmosAttenuation() { return atmos_attenuation; }
+void setAtmosAttenuation(vec3 v)
 {
-	
+    atmos_attenuation     = v;
+    vary_AtmosAttenuation = v;
 }
+
+vec3 getPositionEye() { return position_eye; }
+void setPositionEye(vec3 v) { position_eye = v; }
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterF.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterF.glsl
index 5dc086ab1e05d38241db5d7bebe8711a603e05cb..f83434b7ec907a6d69b6b28bad2c5066846eae55 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterF.glsl
@@ -1,33 +1,38 @@
-/** 
+/**
  * @file class1\windlight\atmosphericVarsWaterF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2007, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
 
 VARYING vec3 vary_PositionEye;
+VARYING vec3 vary_AdditiveColor;
+VARYING vec3 vary_AtmosAttenuation;
+
+vec3 getSunlitColor() { return vec3(0, 0, 0); }
+
+vec3 getAmblitColor() { return vec3(0, 0, 0); }
+
+vec3 getAdditiveColor() { return vary_AdditiveColor; }
 
-vec3 getPositionEye()
-{
-	return vary_PositionEye;
-}
+vec3 getAtmosAttenuation() { return vary_AtmosAttenuation; }
 
+vec3 getPositionEye() { return vary_PositionEye; }
diff --git a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterV.glsl b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterV.glsl
index e59eca265a80d85810e27f2c4e5e6475e77d1607..65d117677787019eec5c6cae8392b3c7230be47a 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterV.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/atmosphericsVarsWaterV.glsl
@@ -1,37 +1,51 @@
-/** 
+/**
  * @file class1\windlight\atmosphericVarsWaterV.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2007, Linden Research, Inc.
- * 
+ *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation;
  * version 2.1 of the License only.
- * 
+ *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * Lesser General Public License for more details.
- * 
+ *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this library; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
+ *
  * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  * $/LicenseInfo$
  */
- 
- 
+
 VARYING vec3 vary_PositionEye;
+VARYING vec3 vary_AdditiveColor;
+VARYING vec3 vary_AtmosAttenuation;
 
-vec3 getPositionEye()
-{
-	return vary_PositionEye;
-}
+vec3 atmos_attenuation;
+vec3 sunlit_color;
+vec3 amblit_color;
+
+vec3 getSunlitColor() { return sunlit_color; }
+void setSunlitColor(vec3 v) { sunlit_color = v; }
+
+vec3 getAmblitColor() { return amblit_color; }
+void setAmblitColor(vec3 v) { amblit_color = v; }
 
-void setPositionEye(vec3 v)
+vec3 getAdditiveColor() { return vary_AdditiveColor; }
+void setAdditiveColor(vec3 v) { vary_AdditiveColor = v; }
+
+vec3 getAtmosAttenuation() { return atmos_attenuation; }
+void setAtmosAttenuation(vec3 v)
 {
-	vary_PositionEye = v;
+    atmos_attenuation     = v;
+    vary_AtmosAttenuation = v;
 }
+
+vec3 getPositionEye() { return vary_PositionEye; }
+void setPositionEye(vec3 v) { vary_PositionEye = v; }
diff --git a/indra/newview/app_settings/shaders/class1/windlight/sunDiscF.glsl b/indra/newview/app_settings/shaders/class1/windlight/sunDiscF.glsl
index b9ae7a02262b01cc62aa485f142168418cc10aa9..5a41dc644a55fa321bcfc964fcf70d48280c7160 100644
--- a/indra/newview/app_settings/shaders/class1/windlight/sunDiscF.glsl
+++ b/indra/newview/app_settings/shaders/class1/windlight/sunDiscF.glsl
@@ -51,7 +51,6 @@ void main()
 // SL-9806 stars poke through
 //    c.a *= sun_fade;
 
-    c.rgb = pow(c.rgb, vec3(0.7f));
     c.rgb = fullbrightAtmosTransport(c.rgb);
     c.rgb = fullbrightScaleSoftClip(c.rgb);
     frag_color = c;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index 5d7a28c359284de7a8836e313c7c987123e85f4c..1b7a1cc6ecc70a0874acded92d8c7b1ba0446840 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -191,10 +191,6 @@ void main()
     float da = dot(norm, lv);
         
     vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
-    // SL-12005 Projector light pops as we get closer, more objectionable than being in wrong color space.
-    //          We can't switch to linear here unless we do it everywhere*
-    // *gbuffer IS sRGB, convert to linear since this shader outputs linear
-    diff_tex.rgb = srgb_to_linear(diff_tex.rgb);
  
     vec4 spec = texture2DRect(specularRect, frag.xy);
 
diff --git a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
index 1485c515a4d27863e5a4f64a26accd235de57933..6841a8194f6c27ebe4f84c48e82f9608d6e9e84d 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/skyF.glsl
@@ -73,7 +73,21 @@ uniform float ice_level;
 
 vec3 rainbow(float d)
 {
-    d         = clamp(d, -1.0, 0.0);
+    // d is the dot product of view and sun directions, so ranging -1.0..1.0
+    // 'interesting' values of d are the range -0.75..-0.825, when view is nearly opposite of sun vec
+    // Rainbox texture mode is GL_REPEAT, so tc of -.75 is equiv to 0.25, -0.825 equiv to 0.175.
+
+    // SL-13629 Rainbow texture has colors within the correct .175...250 range, but order is inverted.
+    // Rather than replace the texture, we mirror and translate the y tc to keep the colors within the
+    // interesting range, but in reversed order:  i.e. d = (1 - d) - 1.575
+    d = clamp(-0.575 - d, 0.0, 1.0);
+
+    // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible.
+    // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate
+    // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857
+    float interior_coord = max(0.0, d - 0.25) * 4.2857;
+    d = clamp(d, 0.0, 0.25) + interior_coord;
+
     float rad = (droplet_radius - 5.0f) / 1024.0f;
     return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
 }
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
index f4db53e0b7816815fff8323758940e17283a2322..7700d16007a4a68d5cf37665c5bd3e9a5a479d9c 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
@@ -87,8 +87,9 @@ void main()
     float light_gamma = 1.0 / 1.3;
     da                = pow(da, light_gamma);
 
-    vec4 diffuse = texture2DRect(diffuseRect, tc);
-    vec4 spec    = texture2DRect(specularRect, vary_fragcoord.xy);
+    vec4 diffuse     = texture2DRect(diffuseRect, tc);
+         diffuse.rgb = linear_to_srgb(diffuse.rgb); // SL-14025
+    vec4 spec        = texture2DRect(specularRect, vary_fragcoord.xy);
 
     vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
     scol_ambocc      = pow(scol_ambocc, vec2(light_gamma));
diff --git a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
index 5ab0b5c5b4d9ff0ccca3c74d77eab178f4dd52b5..774f537821c8ee6692cbc10eae5f6beb2a5daad4 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/spotLightF.glsl
@@ -189,7 +189,7 @@ void main()
 	lv = normalize(lv);
 	float da = dot(norm, lv);
 		
-	vec3 diff_tex = srgb_to_linear(texture2DRect(diffuseRect, frag.xy).rgb);
+	vec3 diff_tex = texture2DRect(diffuseRect, frag.xy).rgb;
 	vec4 spec = texture2DRect(specularRect, frag.xy);
 	vec3 dlit = vec3(0, 0, 0);
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
index d758f85d713eafb34643c126c6212f17ef6fa136..07733bda18b43fdbd162db6d8be2df87962bfe14 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/atmosphericsVarsF.glsl
@@ -1,5 +1,5 @@
 /** 
- * @file class2\wl\atmosphericVars.glsl
+ * @file class2\wl\atmosphericVarsF.glsl
  *
  * $LicenseInfo:firstyear=2007&license=viewerlgpl$
  * Second Life Viewer Source Code
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
index 75bf8730df46e3efcdff262cc488f1518a564a2e..fa928d993ef4fea39635cdecb2551200a155147a 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsF.glsl
@@ -26,9 +26,9 @@
 /*[EXTRA_CODE_HERE]*/ 
 
 #ifdef DEFINE_GL_FRAGCOLOR
-out vec4 frag_data[3];
+out vec4 frag_color;
 #else
-#define frag_data gl_FragData
+#define frag_color gl_FragColor
 #endif
 
 /////////////////////////////////////////////////////////////////////////
@@ -126,8 +126,6 @@ void main()
     color.rgb = scaleSoftClip(color.rgb);
 
     /// Gamma correct for WL (soft clip effect).
-    frag_data[0] = vec4(color.rgb, alpha1);
-    frag_data[1] = vec4(0.0,0.0,0.0,0.0);
-    frag_data[2] = vec4(0,0,0,1);
+    frag_color = vec4(color.rgb, alpha1);
 }
 
diff --git a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
index 1f881eb44b5fcb4f94b1e72ddd4136dac7d9bfc1..97ffa9feef9418f77dc4843a95a82471f0a6bee1 100644
--- a/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
+++ b/indra/newview/app_settings/shaders/class2/windlight/cloudsV.glsl
@@ -1,24 +1,24 @@
-/**
+/** 
  * @file class2\wl\cloudsV.glsl
  *
  * $LicenseInfo:firstyear=2005&license=viewerlgpl$
  * Second Life Viewer Source Code
  * Copyright (C) 2005, 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$
  */
@@ -33,26 +33,26 @@ ATTRIBUTE vec2 texcoord0;
 ///////////////////////////////////////////////////////////////////////////////
 
 // Output parameters
-VARYING vec4  vary_CloudColorSun;
-VARYING vec4  vary_CloudColorAmbient;
+VARYING vec4 vary_CloudColorSun;
+VARYING vec4 vary_CloudColorAmbient;
 VARYING float vary_CloudDensity;
 
-VARYING vec2  vary_texcoord0;
-VARYING vec2  vary_texcoord1;
-VARYING vec2  vary_texcoord2;
-VARYING vec2  vary_texcoord3;
+VARYING vec2 vary_texcoord0;
+VARYING vec2 vary_texcoord1;
+VARYING vec2 vary_texcoord2;
+VARYING vec2 vary_texcoord3;
 VARYING float altitude_blend_factor;
 
 // Inputs
 uniform vec3 camPosLocal;
 
-uniform vec4  lightnorm;
-uniform vec4  sunlight_color;
-uniform vec4  moonlight_color;
-uniform int   sun_up_factor;
-uniform vec4  ambient_color;
-uniform vec4  blue_horizon;
-uniform vec4  blue_density;
+uniform vec4 lightnorm;
+uniform vec4 sunlight_color;
+uniform vec4 moonlight_color;
+uniform int sun_up_factor;
+uniform vec4 ambient_color;
+uniform vec4 blue_horizon;
+uniform vec4 blue_density;
 uniform float haze_horizon;
 uniform float haze_density;
 
@@ -60,7 +60,7 @@ uniform float cloud_shadow;
 uniform float density_multiplier;
 uniform float max_y;
 
-uniform vec4  glow;
+uniform vec4 glow;
 uniform float sun_moon_glow_factor;
 
 uniform vec4 cloud_color;
@@ -75,8 +75,8 @@ uniform float cloud_scale;
 //       indra\newview\llsettingsvo.cpp
 void main()
 {
-    // World / view / projection
-    gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
+	// World / view / projection
+	gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0);
 
     // Texture coords
     // SL-13084 EEP added support for custom cloud textures -- flip them horizontally to match the preview of Clouds > Cloud Scroll
@@ -93,7 +93,7 @@ void main()
     vary_texcoord2 = vary_texcoord0 * 16.;
     vary_texcoord3 = vary_texcoord1 * 16.;
 
-    // Get relative position
+	// Get relative position
     vec3 rel_pos = position.xyz - camPosLocal.xyz + vec3(0, 50, 0);
 
     // fade clouds beyond a certain point so the bottom of the sky dome doesn't look silly at high altitude
@@ -101,27 +101,27 @@ void main()
 
     // Adj position vector to clamp altitude
     if (rel_pos.y > 0.)
-    {
+	{
         rel_pos *= (max_y / rel_pos.y);
-    }
+	}
     if (rel_pos.y < 0.)
-    {
+	{
         rel_pos *= (-32000. / rel_pos.y);
-    }
+	}
 
-    // Can normalize then
+	// Can normalize then
     vec3  rel_pos_norm = normalize(rel_pos);
     float rel_pos_len  = length(rel_pos);
 
-    // Initialize temp variables
-    vec4 sunlight = sunlight_color;
-    vec4 light_atten;
+	// Initialize temp variables
+	vec4 sunlight = sunlight_color;
+	vec4 light_atten;
 
-    // Sunlight attenuation effect (hue and brightness) due to atmosphere
-    // this is used later for sunlight modulation at various altitudes
+	// Sunlight attenuation effect (hue and brightness) due to atmosphere
+	// this is used later for sunlight modulation at various altitudes
     light_atten = (blue_density + vec4(haze_density * 0.25)) * (density_multiplier * max_y);
 
-    // Calculate relative weights
+	// Calculate relative weights
     vec4 combined_haze = abs(blue_density) + vec4(abs(haze_density));
     vec4 blue_weight   = blue_density / combined_haze;
     vec4 haze_weight   = haze_density / combined_haze;
@@ -130,63 +130,64 @@ void main()
     float off_axis = 1.0 / max(1e-6, max(0., rel_pos_norm.y) + lightnorm.y);
     sunlight *= exp(-light_atten * off_axis);
 
-    // Distance
+	// Distance
     float density_dist = rel_pos_len * density_multiplier;
 
     // Transparency (-> combined_haze)
     // ATI Bugfix -- can't store combined_haze*density_dist in a variable because the ati
-    // compiler gets confused.
+	// compiler gets confused.
     combined_haze = exp(-combined_haze * density_dist);
 
-    // Compute haze glow
+	// Compute haze glow
     float haze_glow = 1.0 - dot(rel_pos_norm, lightnorm.xyz);
     // haze_glow is 0 at the sun and increases away from sun
     haze_glow = max(haze_glow, .001);
-    // Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
+		// Set a minimum "angle" (smaller glow.y allows tighter, brighter hotspot)
     haze_glow *= glow.x;
-    // Higher glow.x gives dimmer glow (because next step is 1 / "angle")
+		// Higher glow.x gives dimmer glow (because next step is 1 / "angle")
     haze_glow = pow(haze_glow, glow.z);
-    // glow.z should be negative, so we're doing a sort of (1 / "angle") function
+		// glow.z should be negative, so we're doing a sort of (1 / "angle") function
 
     haze_glow *= sun_moon_glow_factor;
 
-    // Add "minimum anti-solar illumination"
+	// Add "minimum anti-solar illumination"
     // For sun, add to glow.  For moon, remove glow entirely. SL-13768
     haze_glow = (sun_moon_glow_factor < 1.0) ? 0.0 : (haze_glow + 0.25);
 
-    // Increase ambient when there are more clouds
-    vec4 tmpAmbient = ambient_color;
-    tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5;
+	// Increase ambient when there are more clouds
+	vec4 tmpAmbient = ambient_color;
+	tmpAmbient += (1. - tmpAmbient) * cloud_shadow * 0.5; 
 
-    // Dim sunlight by cloud shadow percentage
-    sunlight *= (1. - cloud_shadow);
+	// Dim sunlight by cloud shadow percentage
+	sunlight *= (1. - cloud_shadow);
 
-    // Haze color below cloud
+	// Haze color below cloud
     vec4 additiveColorBelowCloud =
         (blue_horizon * blue_weight * (sunlight + tmpAmbient) + (haze_horizon * haze_weight) * (sunlight * haze_glow + tmpAmbient));
 
-    // CLOUDS
+	// CLOUDS
+    sunlight = sunlight_color;  // SL-14707 reset color -- Clouds are unusually dim in EEP
     off_axis = 1.0 / max(1e-6, lightnorm.y * 2.);
     sunlight *= exp(-light_atten * off_axis);
 
-    // Cloud color out
+	// Cloud color out
     vary_CloudColorSun     = (sunlight * haze_glow) * cloud_color;
-    vary_CloudColorAmbient = tmpAmbient * cloud_color;
-
-    // Attenuate cloud color by atmosphere
+	vary_CloudColorAmbient = tmpAmbient * cloud_color;
+	
+	// Attenuate cloud color by atmosphere
     combined_haze = sqrt(combined_haze);  // less atmos opacity (more transparency) below clouds
     vary_CloudColorSun *= combined_haze;
     vary_CloudColorAmbient *= combined_haze;
     vec4 oHazeColorBelowCloud = additiveColorBelowCloud * (1. - combined_haze);
 
-    // Make a nice cloud density based on the cloud_shadow value that was passed in.
-    vary_CloudDensity = 2. * (cloud_shadow - 0.25);
+	// Make a nice cloud density based on the cloud_shadow value that was passed in.
+	vary_CloudDensity = 2. * (cloud_shadow - 0.25);
 
-    // Combine these to minimize register use
-    vary_CloudColorAmbient += oHazeColorBelowCloud;
+	// Combine these to minimize register use
+	vary_CloudColorAmbient += oHazeColorBelowCloud;
 
-    // needs this to compile on mac
-    // vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
+	// needs this to compile on mac
+	//vary_AtmosAttenuation = vec3(0.0,0.0,0.0);
 
-    // END CLOUDS
+	// END CLOUDS
 }
diff --git a/indra/newview/app_settings/shaders/class3/deferred/lightUtil.glsl b/indra/newview/app_settings/shaders/class3/deferred/lightUtil.glsl
deleted file mode 100644
index 8bb3f07fc6450457928e4123bf57525fb70a9d9d..0000000000000000000000000000000000000000
--- a/indra/newview/app_settings/shaders/class3/deferred/lightUtil.glsl
+++ /dev/null
@@ -1,117 +0,0 @@
-/** 
- * @file lightInfo.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * Second Life Viewer Source Code
- * Copyright (C) 2007, Linden Research, Inc.
- * 
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation;
- * version 2.1 of the License only.
- * 
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- * 
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
- * 
- * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
- * $/LicenseInfo$
- */
-
-struct DirectionalLightInfo
-{
-    vec4 pos;
-    float depth;
-    vec4 normal;
-    vec3 normalizedLightDirection;
-    vec3 normalizedToLight;
-    float lightIntensity;
-    vec3 lightDiffuseColor;
-    float specExponent;
-    float shadow;
-};
-
-struct SpotLightInfo
-{
-    vec4 pos;
-    float depth;
-    vec4 normal;
-    vec3 normalizedLightDirection;
-    vec3 normalizedToLight;
-    float lightIntensity;
-    float attenuation;
-    float distanceToLight;
-    vec3 lightDiffuseColor;
-    float innerHalfAngleCos;
-    float outerHalfAngleCos;
-    float spotExponent;
-    float specExponent;
-    float shadow;
-};
-
-struct PointLightInfo
-{
-    vec4 pos;
-    float depth;
-    vec4 normal;
-    vec3 normalizedToLight;
-    float lightIntensity;
-    float attenuation;
-    float distanceToLight;
-    vec3 lightDiffuseColor;
-    float lightRadius;
-    float specExponent;
-    vec3 worldspaceLightDirection;
-    float shadow;
-};
-
-float attenuate(float attenuationSelection, float distanceToLight)
-{
-// LLRENDER_REVIEW
-// sh/could eventually consume attenuation func defined in texture
-    return (attenuationSelection == 0.0f) ? 1.0f : // none
-           (attenuationSelection <  1.0f) ? (1.0f / distanceToLight) : // linear atten 
-           (attenuationSelection <  2.0f) ? (1.0f / (distanceToLight*distanceToLight)) // quadratic atten
-										  : (1.0f / (distanceToLight*distanceToLight*distanceToLight));	// cubic atten    
-}
-
-
-vec3 lightDirectional(struct DirectionalLightInfo dli)
-{
-    float lightIntensity = dli.lightIntensity;
-	lightIntensity *= dot(dli.normal.xyz, dli.normalizedLightDirection);
-    //lightIntensity *= directionalShadowSample(vec4(dli.pos.xyz, 1.0f), dli.depth, dli.directionalShadowMap, dli.directionalShadowMatrix);
-	return lightIntensity * dli.lightDiffuseColor;
-}
-
-
-vec3 lightSpot(struct SpotLightInfo sli)    
-{
-	float penumbraRange = (sli.outerHalfAngleCos - sli.innerHalfAngleCos);
-    float coneAngleCos = max(dot(sli.normalizedLightDirection, sli.normalizedToLight), 0.0);
-	float coneAttenFactor = (coneAngleCos <= sli.outerHalfAngleCos) ? 1.0f : pow(smoothstep(1,0, sli.outerHalfAngleCos / penumbraRange), sli.spotExponent);
-    float distanceAttenuation = attenuate(sli.attenuation, sli.distanceToLight);
-    float lightIntensity = sli.lightIntensity;
-    lightIntensity *= distanceAttenuation;
-	lightIntensity *= max(dot(sli.normal.xyz, sli.normalizedLightDirection), 0.0);
-	lightIntensity *= coneAttenFactor;
-    lightIntensity *= sli.shadow;
-	return lightIntensity * sli.lightDiffuseColor;
-}
-
-vec3 lightPoint(struct PointLightInfo pli)
-{
-    float padRadius = pli.lightRadius * 0.1; // distance for which to perform smoothed dropoff past light radius
-	float distanceAttenuation =	attenuate(pli.attenuation, pli.distanceToLight);
-    float lightIntensity = pli.lightIntensity;
-    lightIntensity*= distanceAttenuation;    
-	lightIntensity *= clamp((padRadius - pli.distanceToLight + pli.lightRadius) / padRadius, 0.0, 1.0);
-    lightIntensity *= pli.shadow;
-    lightIntensity *= max(dot(pli.normal.xyz, pli.normalizedToLight), 0.0);
-	return lightIntensity * pli.lightDiffuseColor;
-}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl b/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
index 6de01cb667c3e6bc9f55a1d96493a5d84ea51420..a0b082ed7ccb7f5e44931f7fbd9410392e903ad2 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/skyF.glsl
@@ -56,8 +56,23 @@ vec3 GetSkyLuminanceToPoint(vec3 camPos, vec3 pos, float shadow_length, vec3 dir
 vec3 ColorFromRadiance(vec3 radiance);
 vec3 rainbow(float d)
 {
-   float rad = (droplet_radius - 5.0f) / 1024.0f;
-   return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
+    // d is the dot product of view and sun directions, so ranging -1.0..1.0
+    // 'interesting' values of d are the range -0.75..-0.825, when view is nearly opposite of sun vec
+    // Rainbox texture mode is GL_REPEAT, so tc of -.75 is equiv to 0.25, -0.825 equiv to 0.175.
+
+    // SL-13629 Rainbow texture has colors within the correct .175...250 range, but order is inverted.
+    // Rather than replace the texture, we mirror and translate the y tc to keep the colors within the
+    // interesting range, but in reversed order:  i.e. d = (1 - d) - 1.575
+    d = clamp(-0.575 - d, 0.0, 1.0);
+
+    // With the colors in the lower 1/4 of the texture, inverting the coords leaves most of it inaccessible.
+    // So, we can stretch the texcoord above the colors (ie > 0.25) to fill the entire remaining coordinate
+    // space. This improves gradation, reduces banding within the rainbow interior. (1-0.25) / (0.425/0.25) = 4.2857
+    float interior_coord = max(0.0, d - 0.25) * 4.2857;
+    d = clamp(d, 0.0, 0.25) + interior_coord;
+
+    float rad = (droplet_radius - 5.0f) / 1024.0f;
+    return pow(texture2D(rainbow_map, vec2(rad, d)).rgb, vec3(1.8)) * moisture_level;
 }
 
 vec3 halo22(float d)
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 9d03edc0606b141eb0a3cb57ad64e91524509a9d..c0971ba943144ee0448e8bced7d0e58db9fe5975 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -91,6 +91,7 @@
 #include "llsdutil_math.h"
 #include "lllocationhistory.h"
 #include "llfasttimerview.h"
+#include "lltelemetry.h"
 #include "llvector4a.h"
 #include "llviewermenufile.h"
 #include "llvoicechannel.h"
@@ -257,9 +258,9 @@
 // define a self-registering event API object
 #include "llappviewerlistener.h"
 
-#if (LL_LINUX || LL_SOLARIS) && LL_GTK
+#if LL_LINUX && LL_GTK
 #include "glib.h"
-#endif // (LL_LINUX || LL_SOLARIS) && LL_GTK
+#endif // (LL_LINUX) && LL_GTK
 
 #if LL_MSVC
 // disable boost::lexical_cast warning
@@ -1100,6 +1101,46 @@ bool LLAppViewer::init()
 		}
 	}
 
+#if LL_WINDOWS && ADDRESS_SIZE == 64
+    if (gGLManager.mIsIntel)
+    {
+        // Check intel driver's version
+        // Ex: "3.1.0 - Build 8.15.10.2559";
+        std::string version = ll_safe_string((const char *)glGetString(GL_VERSION));
+
+        const boost::regex is_intel_string("[0-9].[0-9].[0-9] - Build [0-9]{1,2}.[0-9]{2}.[0-9]{2}.[0-9]{4}");
+
+        if (boost::regex_search(version, is_intel_string))
+        {
+            // Valid string, extract driver version
+            std::size_t found = version.find("Build ");
+            std::string driver = version.substr(found + 6);
+            S32 v1, v2, v3, v4;
+            S32 count = sscanf(driver.c_str(), "%d.%d.%d.%d", &v1, &v2, &v3, &v4);
+            if (count > 0 && v1 <= 10)
+            {
+                LL_INFOS("AppInit") << "Detected obsolete intel driver: " << driver << LL_ENDL;
+                LLUIString details = LLNotifications::instance().getGlobalString("UnsupportedIntelDriver");
+                std::string gpu_name = ll_safe_string((const char *)glGetString(GL_RENDERER));
+                details.setArg("[VERSION]", driver);
+                details.setArg("[GPUNAME]", gpu_name);
+                S32 button = OSMessageBox(details.getString(),
+                                          LLStringUtil::null,
+                                          OSMB_YESNO);
+                if (OSBTN_YES == button && gViewerWindow)
+                {
+                    std::string url = LLWeb::escapeURL(LLTrans::getString("IntelDriverPage"));
+                    if (gViewerWindow->getWindow())
+                    {
+                        gViewerWindow->getWindow()->spawnWebBrowser(url, false);
+                    }
+                }
+            }
+        }
+    }
+#endif
+
+    // Obsolete? mExpectedGLVersion is always zero
 #if LL_WINDOWS
 	if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion())
 	{
@@ -1324,39 +1365,8 @@ void LLAppViewer::initMaxHeapSize()
 
 	//F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ;
 	F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ;
-	BOOL enable_mem_failure_prevention = (BOOL)gSavedSettings.getBOOL("MemoryFailurePreventionEnabled") ;
 
-	LLMemory::initMaxHeapSizeGB(max_heap_size_gb, enable_mem_failure_prevention) ;
-}
-
-void LLAppViewer::checkMemory()
-{
-	const static F32 MEMORY_CHECK_INTERVAL = 1.0f ; //second
-	//const static F32 MAX_QUIT_WAIT_TIME = 30.0f ; //seconds
-	//static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;
-
-	if(!gGLManager.mDebugGPU)
-	{
-		return ;
-	}
-
-	if(MEMORY_CHECK_INTERVAL > mMemCheckTimer.getElapsedTimeF32())
-	{
-		return ;
-	}
-	mMemCheckTimer.reset() ;
-
-		//update the availability of memory
-		LLMemory::updateMemoryInfo() ;
-
-	bool is_low = LLMemory::isMemoryPoolLow() ;
-
-	LLPipeline::throttleNewMemoryAllocation(is_low) ;
-
-	if(is_low)
-	{
-		LLMemory::logMemoryInfo() ;
-	}
+	LLMemory::initMaxHeapSizeGB(max_heap_size_gb);
 }
 
 static LLTrace::BlockTimerStatHandle FTM_MESSAGES("System Messages");
@@ -1435,9 +1445,6 @@ bool LLAppViewer::doFrame()
 	//clear call stack records
 	LL_CLEAR_CALLSTACKS();
 
-	//check memory availability information
-	checkMemory() ;
-
 	{
 		pingMainloopTimeout("Main:MiscNativeWindowEvents");
 
@@ -1672,6 +1679,8 @@ bool LLAppViewer::doFrame()
 		LL_INFOS() << "Exiting main_loop" << LL_ENDL;
 	}
 
+    LLPROFILE_UPDATE();
+
 	return ! LLApp::isRunning();
 }
 
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index d24cdcedc7b01c7800cebac43adc3b35c4f794bd..5ceb54078430cf286c2b3428273b85e1a4e5c6b4 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -235,7 +235,6 @@ class LLAppViewer : public LLApp
 	bool initConfiguration(); // Initialize settings from the command line/config file.
 	void initStrings();       // Initialize LLTrans machinery
 	bool initCache(); // Initialize local client cache.
-	void checkMemory() ;
 
 	// We have switched locations of both Mac and Windows cache, make sure
 	// files migrate and old cache is cleared out.
@@ -314,8 +313,6 @@ class LLAppViewer : public LLApp
 
     LLAllocator mAlloc;
 
-	LLFrameTimer mMemCheckTimer;
-
 	// llcorehttp library init/shutdown helper
 	LLAppCoreHttp mAppCoreHttp;
 
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index 6f32aab851ebb2c451490f037ce80637faf0185b..dc487967fc695a3a7993a744a6e8690d93570fc1 100644
--- a/indra/newview/llappviewerlinux.cpp
+++ b/indra/newview/llappviewerlinux.cpp
@@ -73,10 +73,6 @@ static void exceptionTerminateHandler()
 
 int main( int argc, char **argv ) 
 {
-#if LL_SOLARIS && defined(__sparc)
-	asm ("ta\t6");		 // NOTE:  Make sure memory alignment is enforced on SPARC
-#endif
-
 	gArgC = argc;
 	gArgV = argv;
 
@@ -336,8 +332,6 @@ void LLAppViewerLinux::initCrashReporting(bool reportFreeze)
 	cmd += gDirUtilp->getDirDelimiter();
 #if LL_LINUX
 	cmd += "linux-crash-logger.bin";
-#elif LL_SOLARIS
-	cmd += "solaris-crash-logger";
 #else
 # error Unknown platform
 #endif
@@ -394,9 +388,6 @@ bool LLAppViewerLinux::beingDebugged()
 {
 	static enum {unknown, no, yes} debugged = unknown;
 
-#if LL_SOLARIS
-	return debugged == no;	// BUG: fix this for Solaris
-#else
 	if (debugged == unknown)
 	{
 		pid_t ppid = getppid();
@@ -431,7 +422,6 @@ bool LLAppViewerLinux::beingDebugged()
 	}
 
 	return debugged == yes;
-#endif
 }
 
 void LLAppViewerLinux::initLoggingAndGetLastDuration()
diff --git a/indra/newview/llconversationmodel.cpp b/indra/newview/llconversationmodel.cpp
index 4cfde21e328fa91c45d0992097019046f562b003..a6856394275bdaef46472beea7374ba6cc8b9b45 100644
--- a/indra/newview/llconversationmodel.cpp
+++ b/indra/newview/llconversationmodel.cpp
@@ -380,7 +380,7 @@ LLConversationItemParticipant* LLConversationItemSession::findParticipant(const
 	for (iter = mChildren.begin(); iter != mChildren.end(); iter++)
 	{
 		participant = dynamic_cast<LLConversationItemParticipant*>(*iter);
-		if (participant->hasSameValue(participant_id))
+		if (participant && participant->hasSameValue(participant_id))
 		{
 			break;
 		}
@@ -491,7 +491,7 @@ const bool LLConversationItemSession::getTime(F64& time) const
 	{
 		participant = dynamic_cast<LLConversationItemParticipant*>(*iter);
 		F64 participant_time;
-		if (participant->getTime(participant_time))
+		if (participant && participant->getTime(participant_time))
 		{
 			has_time = true;
 			most_recent_time = llmax(most_recent_time,participant_time);
diff --git a/indra/newview/llconversationview.cpp b/indra/newview/llconversationview.cpp
index df16868132c1792ec0122651ba8693f1cfaab736..65cec68884da0a1a7a2ce35c2bdd37ad89ca35b0 100644
--- a/indra/newview/llconversationview.cpp
+++ b/indra/newview/llconversationview.cpp
@@ -696,10 +696,13 @@ void LLConversationViewParticipant::refresh()
 {
 	// Refresh the participant view from its model data
 	LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(getViewModelItem());
-	participant_model->resetRefresh();
-	
-	// *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat
-	mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted());
+    if (participant_model)
+    {
+        participant_model->resetRefresh();
+
+        // *TODO: We should also do something with vmi->isModerator() to echo that state in the UI somewhat
+        mSpeakingIndicator->setIsModeratorMuted(participant_model->isModeratorMuted());
+    }
 
 	// Do the regular upstream refresh
 	LLFolderViewItem::refresh();
diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp
index b8e6e81ee6695c92f5239d0d1d3f1c118226e652..01790ad19e480d31c3a9a9f8bf75e34974e1c90f 100644
--- a/indra/newview/lldirpicker.cpp
+++ b/indra/newview/lldirpicker.cpp
@@ -37,7 +37,7 @@
 #include "llviewercontrol.h"
 #include "llwin32headerslean.h"
 
-#if LL_LINUX || LL_SOLARIS || LL_DARWIN
+#if LL_LINUX || LL_DARWIN
 # include "llfilepicker.h"
 #endif
 
@@ -187,7 +187,7 @@ std::string LLDirPicker::getDirName()
 	return mFilePicker->getFirstFile();
 }
 
-#elif LL_LINUX || LL_SOLARIS
+#elif LL_LINUX
 
 LLDirPicker::LLDirPicker() :
 	mFileName(NULL),
diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h
index c7dba12130b9e26c8d8490823ff21a9a71701207..52febe45235920d2d76974671d5b42bb6fe7fe5a 100644
--- a/indra/newview/lldirpicker.h
+++ b/indra/newview/lldirpicker.h
@@ -78,7 +78,7 @@ class LLDirPicker
 	void buildDirname( void );
 	bool check_local_file_access_enabled();
 
-#if LL_LINUX || LL_SOLARIS || LL_DARWIN
+#if LL_LINUX || LL_DARWIN
 	// On Linux we just implement LLDirPicker on top of LLFilePicker
 	LLFilePicker *mFilePicker;
 #endif
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 5034bd1c5e5e64007accea7f99663e8417bc9495..507af56cb0d2b8be0a0068a03c1276191a1cf7da 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -912,22 +912,18 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
             if (volume->getAvatar())
             {
                 const LLVector3* av_box = volume->getAvatar()->getLastAnimExtents();
-                LLVector3d cam_pos = gAgent.getPosGlobalFromAgent(LLViewerCamera::getInstance()->getOrigin());
-                LLVector3 cam_region_pos = LLVector3(cam_pos - volume->getRegion()->getOriginGlobal());
-                
-                LLVector3 cam_to_box_offset = point_to_box_offset(cam_region_pos, av_box);
+                LLVector3 cam_pos_from_agent = LLViewerCamera::getInstance()->getOrigin();
+                LLVector3 cam_to_box_offset = point_to_box_offset(cam_pos_from_agent, av_box);
                 mDistanceWRTCamera = llmax(0.01f, ll_round(cam_to_box_offset.magVec(), 0.01f));
                 LL_DEBUGS("DynamicBox") << volume->getAvatar()->getFullname() 
                                         << " pos (ignored) " << pos
-                                        << " cam pos " << cam_pos
-                                        << " cam region pos " << cam_region_pos
+                                        << " cam pos " << cam_pos_from_agent
                                         << " box " << av_box[0] << "," << av_box[1] 
                                         << " -> dist " << mDistanceWRTCamera
                                         << LL_ENDL;
                 mVObjp->updateLOD();
                 return;
             }
-            
 		}
 		else
 		{
diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp
index 55b3864b6db7f47c86be5d783a29c4ac68567303..687b13d2c8366d46496f27495ebbdb6709bac068 100644
--- a/indra/newview/lldrawpoolavatar.cpp
+++ b/indra/newview/lldrawpoolavatar.cpp
@@ -2129,7 +2129,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 
             if (mat)
             {                
-                switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaModeRender()))
+                switch (LLMaterial::eDiffuseAlphaMode(mat->getDiffuseAlphaMode()))
                 {
                     case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
                     {
@@ -2267,7 +2267,7 @@ void LLDrawPoolAvatar::renderRigged(LLVOAvatar* avatar, U32 type, bool glow)
 				sVertexProgram->uniform4f(LLShaderMgr::SPECULAR_COLOR, col.mV[0], col.mV[1], col.mV[2], spec);
 				sVertexProgram->uniform1f(LLShaderMgr::ENVIRONMENT_INTENSITY, env);
 
-				if (mat->getDiffuseAlphaModeRender() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
+				if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
 				{
                     F32 cutoff = mat->getAlphaMaskCutoff()/255.f;
 					sVertexProgram->setMinimumAlpha(cutoff);
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index d4e7f1600e7637b025c41ab05fe94f0ddbfd2934..0c3d8f3098fa334bd0ef8a4c1325a3766c0b93b8 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -226,7 +226,7 @@ void LLDrawPoolWLSky::renderSkyHaze(const LLVector3& camPosLocal, F32 camHeightL
     }
 }
 
-void LLDrawPoolWLSky::renderStars(void) const
+void LLDrawPoolWLSky::renderStars(const LLVector3& camPosLocal) const
 {
     LLGLSPipelineBlendSkyBox gls_skybox(true, false);
 	
@@ -266,6 +266,7 @@ void LLDrawPoolWLSky::renderStars(void) const
     }
 
 	gGL.pushMatrix();
+	gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], camPosLocal.mV[2]);
 	gGL.rotatef(gFrameTimeSeconds*0.01f, 0.f, 0.f, 1.f);
 	if (LLGLSLShader::sNoFixedFunction)
 	{
@@ -296,7 +297,7 @@ void LLDrawPoolWLSky::renderStars(void) const
 	}
 }
 
-void LLDrawPoolWLSky::renderStarsDeferred(void) const
+void LLDrawPoolWLSky::renderStarsDeferred(const LLVector3& camPosLocal) const
 {
 	LLGLSPipelineBlendSkyBox gls_sky(true, false);
 
@@ -337,6 +338,8 @@ void LLDrawPoolWLSky::renderStarsDeferred(void) const
         gGL.getTexUnit(1)->bind(tex_b);
     }
 
+	gGL.pushMatrix();
+	gGL.translatef(camPosLocal.mV[0], camPosLocal.mV[1], camPosLocal.mV[2]);
     gDeferredStarProgram.uniform1f(LLShaderMgr::BLEND_FACTOR, blend_factor);
 
     if (LLPipeline::sReflectionRender)
@@ -355,6 +358,8 @@ void LLDrawPoolWLSky::renderStarsDeferred(void) const
     gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE);
 
     gDeferredStarProgram.unbind();
+
+	gGL.popMatrix();
 }
 
 void LLDrawPoolWLSky::renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const
@@ -601,7 +606,7 @@ void LLDrawPoolWLSky::renderDeferred(S32 pass)
     if (gPipeline.canUseWindLightShaders())
     {
         renderSkyHazeDeferred(origin, camHeightLocal);
-        renderStarsDeferred();
+        renderStarsDeferred(origin);
         renderHeavenlyBodies();
         renderSkyCloudsDeferred(origin, camHeightLocal, cloud_shader);
     }
@@ -620,7 +625,7 @@ void LLDrawPoolWLSky::render(S32 pass)
     LLVector3 const & origin = LLViewerCamera::getInstance()->getOrigin();
     
 	renderSkyHaze(origin, camHeightLocal);    
-    renderStars();
+    renderStars(origin);
     renderHeavenlyBodies();	
 	renderSkyClouds(origin, camHeightLocal, cloud_shader);
 
diff --git a/indra/newview/lldrawpoolwlsky.h b/indra/newview/lldrawpoolwlsky.h
index a4f176d6db7f3247e3bbeef48c355096c5683111..324886ed42f3db5854036094b72f2bf71ef6c731 100644
--- a/indra/newview/lldrawpoolwlsky.h
+++ b/indra/newview/lldrawpoolwlsky.h
@@ -78,8 +78,8 @@ class LLDrawPoolWLSky : public LLDrawPool {
 	void renderSkyHazeDeferred(const LLVector3& camPosLocal, F32 camHeightLocal) const;
     void renderSkyCloudsDeferred(const LLVector3& camPosLocal, F32 camHeightLocal, LLGLSLShader* cloudshader) const;
 
-    void renderStarsDeferred(void) const;
-	void renderStars(void) const;
+    void renderStarsDeferred(const LLVector3& camPosLocal) const;
+	void renderStars(const LLVector3& camPosLocal) const;
 	void renderHeavenlyBodies();    
 };
 
diff --git a/indra/newview/lldynamictexture.cpp b/indra/newview/lldynamictexture.cpp
index 89c20904c1143beef560abccfc0c4f49900a2990..8b8273d18304d4b259cfa477228d0680dc341389 100644
--- a/indra/newview/lldynamictexture.cpp
+++ b/indra/newview/lldynamictexture.cpp
@@ -56,13 +56,6 @@ LLViewerDynamicTexture::LLViewerDynamicTexture(S32 width, S32 height, S32 compon
 {
 	llassert((1 <= components) && (components <= 4));
 
-	if(gGLManager.mDebugGPU)
-	{
-		if(components == 3)
-		{
-			mComponents = 4 ; //convert to 32bits.
-		}
-	}
 	generateGLTexture();
 
 	llassert( 0 <= order && order < ORDER_COUNT );
@@ -211,7 +204,7 @@ void LLViewerDynamicTexture::postRender(BOOL success)
 BOOL LLViewerDynamicTexture::updateAllInstances()
 {
 	sNumRenders = 0;
-	if (gGLManager.mIsDisabled || LLPipeline::sMemAllocationThrottled)
+	if (gGLManager.mIsDisabled)
 	{
 		return TRUE;
 	}
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 01d8b6775bf9109c5854dc8e50e9dd81bfaa7913..4a802ad9aa774462f5faa92d06c1f9dd7cc6567d 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1165,7 +1165,7 @@ bool LLFace::canRenderAsMask()
 	}
 	
 	LLMaterial* mat = te->getMaterialParams();
-	if (mat && mat->getDiffuseAlphaModeRender() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
+	if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND)
 	{
 		return false;
 	}
@@ -1412,7 +1412,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
 			}
 			else
 			{
-				if (!mat || mat->getDiffuseAlphaModeRender() != LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
+				if (!mat || mat->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
 				{
 					shiny_in_alpha = true;
 				}
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index dc9816c9f797c4115b7718bd8abeb7f02b01cf5f..e6bbe234b3e56f93aca526375adecaa83c3f78d1 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -755,12 +755,7 @@ void LLFeatureManager::applyBaseMasks()
 		maskFeatures("RAM256MB");
 	}
 	
-#if LL_SOLARIS && defined(__sparc) 	//  even low MHz SPARCs are fast
-#error The 800 is hinky. Would something like a LL_MIN_MHZ make more sense here?
-	if (gSysCPU.getMHz() < 800)
-#else
 	if (gSysCPU.getMHz() < 1100)
-#endif
 	{
 		maskFeatures("CPUSlow");
 	}
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index b6fd70452e7dfee28f5b4a843c13ce3e6aea91fd..3669fb1eeb000e103e5a2187ac829b901d39a810 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -40,7 +40,7 @@
 #include "llwindowsdl.h" // for some X/GTK utils to help with filepickers
 #endif // LL_SDL
 
-#if LL_LINUX || LL_SOLARIS
+#if LL_LINUX
 #include "llhttpconstants.h"    // file picker uses some of thes constants on Linux
 #endif
 
@@ -939,7 +939,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const std::string& filename,
 }
 //END LL_DARWIN
 
-#elif LL_LINUX || LL_SOLARIS
+#elif LL_LINUX
 
 # if LL_GTK
 
@@ -1504,4 +1504,4 @@ BOOL LLFilePicker::getMultipleOpenFiles( ELoadFilter filter, bool blocking)
 	return FALSE;
 }
 
-#endif // LL_LINUX || LL_SOLARIS
+#endif // LL_LINUX
diff --git a/indra/newview/llfloaterimcontainer.cpp b/indra/newview/llfloaterimcontainer.cpp
index 8d38a5743bb53615f2d3c4ccfd3ccc4d6af5c48d..9c84fa199122bbe84f7139ef0f26e50f72938778 100644
--- a/indra/newview/llfloaterimcontainer.cpp
+++ b/indra/newview/llfloaterimcontainer.cpp
@@ -59,7 +59,9 @@
 #include "boost/foreach.hpp"
 
 
-const S32 EVENTS_PER_IDLE_LOOP = 100;
+const S32 EVENTS_PER_IDLE_LOOP_CURRENT_SESSION = 80;
+const S32 EVENTS_PER_IDLE_LOOP_BACKGROUND = 40;
+const F32 EVENTS_PER_IDLE_LOOP_MIN_PERCENTAGE = 0.01f; // process a minimum of 1% of total events per frame
 
 //
 // LLFloaterIMContainer
@@ -426,8 +428,11 @@ void LLFloaterIMContainer::processParticipantsStyleUpdate()
 		while (current_participant_model != end_participant_model)
 		{
 			LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
-			// Get the avatar name for this participant id from the cache and update the model
-			participant_model->updateName();
+            if (participant_model)
+            {
+                // Get the avatar name for this participant id from the cache and update the model
+                participant_model->updateName();
+            }
 			// Next participant
 			current_participant_model++;
 		}
@@ -474,8 +479,11 @@ void LLFloaterIMContainer::idleUpdate()
                 while (current_participant_model != end_participant_model)
                 {
                     LLConversationItemParticipant* participant_model = dynamic_cast<LLConversationItemParticipant*>(*current_participant_model);
-                    participant_model->setModeratorOptionsVisible(is_moderator);
-                    participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID);
+                    if (participant_model)
+                    {
+                        participant_model->setModeratorOptionsVisible(is_moderator);
+                        participant_model->setGroupBanVisible(can_ban && participant_model->getUUID() != gAgentID);
+                    }
 
                     current_participant_model++;
                 }
@@ -508,20 +516,49 @@ void LLFloaterIMContainer::idleUpdate()
 
 void LLFloaterIMContainer::idleProcessEvents()
 {
-	if (!mConversationEventQueue.empty())
-	{
-		S32 events_to_handle = llmin((S32)mConversationEventQueue.size(), EVENTS_PER_IDLE_LOOP);
-		for (S32 i = 0; i < events_to_handle; i++)
-		{
-			handleConversationModelEvent(mConversationEventQueue.back());
-			mConversationEventQueue.pop_back();
-		}
-	}
+    LLUUID current_session_id = getSelectedSession();
+    conversations_items_deque::iterator iter = mConversationEventQueue.begin();
+    conversations_items_deque::iterator end = mConversationEventQueue.end();
+    while (iter != end)
+    {
+        std::deque<LLSD> &events = iter->second;
+        if (!events.empty())
+        {
+            S32 events_to_handle;
+            S32 query_size = (S32)events.size();
+            if (current_session_id == iter->first)
+            {
+                events_to_handle = EVENTS_PER_IDLE_LOOP_CURRENT_SESSION;
+            }
+            else
+            {
+                events_to_handle = EVENTS_PER_IDLE_LOOP_BACKGROUND;
+            }
+
+            if (events_to_handle <= query_size)
+            {
+                // Some groups can be very large and can generate huge amount of updates, scale processing up to keep up
+                events_to_handle = llmax(events_to_handle, (S32)(query_size * EVENTS_PER_IDLE_LOOP_MIN_PERCENTAGE));
+            }
+            else
+            {
+                events_to_handle = query_size;
+            }
+
+            for (S32 i = 0; i < events_to_handle; i++)
+            {
+                handleConversationModelEvent(events.back());
+                events.pop_back();
+            }
+        }
+        iter++;
+    }
 }
 
 bool LLFloaterIMContainer::onConversationModelEvent(const LLSD& event)
 {
-	mConversationEventQueue.push_front(event);
+	LLUUID id = event.get("session_uuid").asUUID();
+	mConversationEventQueue[id].push_front(event);
 	return true;
 }
 
@@ -1834,6 +1871,8 @@ bool LLFloaterIMContainer::removeConversationListItem(const LLUUID& uuid, bool c
 	// Suppress the conversation items and widgets from their respective maps
 	mConversationsItems.erase(uuid);
 	mConversationsWidgets.erase(uuid);
+	// Clear event query (otherwise reopening session in some way can bombard session with stale data)
+	mConversationEventQueue.erase(uuid);
 	
 	// Don't let the focus fall IW, select and refocus on the first conversation in the list
 	if (change_focus)
diff --git a/indra/newview/llfloaterimcontainer.h b/indra/newview/llfloaterimcontainer.h
index 468b47f1f1b457037b013c1f3a9da46975ff5f8f..b4a9d377ab9b61cf794c52ed1e26f201b8eb0eea 100644
--- a/indra/newview/llfloaterimcontainer.h
+++ b/indra/newview/llfloaterimcontainer.h
@@ -229,9 +229,10 @@ class LLFloaterIMContainer
 	conversations_widgets_map mConversationsWidgets;
 	LLConversationViewModel mConversationViewModel;
 	LLFolderView* mConversationsRoot;
-	LLEventStream mConversationsEventStream; 
+	LLEventStream mConversationsEventStream;
 
-	std::deque<LLSD> mConversationEventQueue;
+	typedef std::map<LLUUID, std::deque<LLSD> > conversations_items_deque;
+	conversations_items_deque mConversationEventQueue;
 
 	LLTimer mParticipantRefreshTimer;
 };
diff --git a/indra/newview/llfloaterimsessiontab.cpp b/indra/newview/llfloaterimsessiontab.cpp
index e7f428c06a7e9ee0477108dd2fd6ee126dacc014..7541bb5efefa1662962652e610f85a58907600fa 100644
--- a/indra/newview/llfloaterimsessiontab.cpp
+++ b/indra/newview/llfloaterimsessiontab.cpp
@@ -497,7 +497,10 @@ void LLFloaterIMSessionTab::buildConversationViewParticipant()
 	while (current_participant_model != end_participant_model)
 	{
 		LLConversationItem* participant_model = dynamic_cast<LLConversationItem*>(*current_participant_model);
-		addConversationViewParticipant(participant_model);
+        if (participant_model)
+        {
+            addConversationViewParticipant(participant_model);
+        }
 		current_participant_model++;
 	}
 }
diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp
index 999e4a9582fa02c4d2cb2e0330a13a816a993a03..d9edd4dc30b16b6a7f3f03431c70e92c7b267edf 100644
--- a/indra/newview/llfloatermodelpreview.cpp
+++ b/indra/newview/llfloatermodelpreview.cpp
@@ -911,7 +911,7 @@ BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks)
     {
         LLFloaterModelUploadBase::handleScrollWheel(x, y, clicks);
     }
-    return TRUE;
+	return TRUE;
 }
 
 /*virtual*/
@@ -1292,47 +1292,47 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl
 void LLFloaterModelPreview::addStringToLog(const std::string& message, const LLSD& args, bool flash, S32 lod)
 {
     if (sInstance && sInstance->hasString(message))
-    {
+	{
         std::string str;
         switch (lod)
-        {
+{
         case LLModel::LOD_IMPOSTOR: str = "LOD0 "; break;
         case LLModel::LOD_LOW:      str = "LOD1 "; break;
         case LLModel::LOD_MEDIUM:   str = "LOD2 "; break;
         case LLModel::LOD_PHYSICS:  str = "PHYS "; break;
         case LLModel::LOD_HIGH:     str = "LOD3 ";   break;
         default: break;
-        }
-        
+}
+
         LLStringUtil::format_map_t args_msg;
         LLSD::map_const_iterator iter = args.beginMap();
         LLSD::map_const_iterator end = args.endMap();
         for (; iter != end; ++iter)
-        {
+{
             args_msg[iter->first] = iter->second.asString();
-        }
+		}		
         str += sInstance->getString(message, args_msg);
         sInstance->addStringToLogTab(str, flash);
-    }
-}
+	}
+	}
 
 // static
 void LLFloaterModelPreview::addStringToLog(const std::string& str, bool flash)
-{
+	{
     if (sInstance)
-    {
+		{
         sInstance->addStringToLogTab(str, flash);
-    }
-}
+				}
+			}
 
 // static
 void LLFloaterModelPreview::addStringToLog(const std::ostringstream& strm, bool flash)
-{
+			{
     if (sInstance)
-    {
+            {
         sInstance->addStringToLogTab(strm.str(), flash);
-    }
-}
+            }
+		}
 
 void LLFloaterModelPreview::clearAvatarTab()
 {
@@ -1343,9 +1343,9 @@ void LLFloaterModelPreview::clearAvatarTab()
     joints_pos->deleteAllItems();    mSelectedJointName.clear();
 
     for (U32 i = 0; i < LLModel::NUM_LODS; ++i)
-    {
+{
         mJointOverrides[i].clear();
-    }
+	}
 
     LLTextBox *joint_total_descr = panel->getChild<LLTextBox>("conflicts_description");
     joint_total_descr->setTextArg("[CONFLICTS]", llformat("%d", 0));
@@ -1354,34 +1354,34 @@ void LLFloaterModelPreview::clearAvatarTab()
 
     LLTextBox *joint_pos_descr = panel->getChild<LLTextBox>("pos_overrides_descr");
     joint_pos_descr->setTextArg("[JOINT]", std::string("mPelvis")); // Might be better to hide it
-}
+			}
 
 void LLFloaterModelPreview::updateAvatarTab(bool highlight_overrides)
-{
+			{
     S32 display_lod = mModelPreview->mPreviewLOD;
     if (mModelPreview->mModel[display_lod].empty())
-    {
+				{
         mSelectedJointName.clear();
         return;
-    }
+					}
 
     // Joints will be listed as long as they are listed in mAlternateBindMatrix
     // even if they are for some reason identical to defaults.
     // Todo: Are overrides always identical for all lods? They normally are, but there might be situations where they aren't.
     if (mJointOverrides[display_lod].empty())
-    {
+					{
         // populate map
         for (LLModelLoader::scene::iterator iter = mModelPreview->mScene[display_lod].begin(); iter != mModelPreview->mScene[display_lod].end(); ++iter)
-        {
+					{
             for (LLModelLoader::model_instance_list::iterator model_iter = iter->second.begin(); model_iter != iter->second.end(); ++model_iter)
-            {
+					{
                 LLModelInstance& instance = *model_iter;
                 LLModel* model = instance.mModel;
                 const LLMeshSkinInfo *skin = &model->mSkinInfo;
                 U32 joint_count = LLSkinningUtil::getMeshJointCount(skin);
                 U32 bind_count = highlight_overrides ? skin->mAlternateBindMatrix.size() : 0; // simply do not include overrides if data is not needed
                 if (bind_count > 0 && bind_count != joint_count)
-                {
+						{
                     std::ostringstream out;
                     out << "Invalid joint overrides for model " << model->getName();
                     out << ". Amount of joints " << joint_count;
@@ -1390,68 +1390,68 @@ void LLFloaterModelPreview::updateAvatarTab(bool highlight_overrides)
                     addStringToLog(out.str(), true);
                     // Disable overrides for this model
                     bind_count = 0;
-                }
+						}
                 if (bind_count > 0)
-                {
+						{
                     for (U32 j = 0; j < joint_count; ++j)
-                    {
+							{
                         const LLVector3& joint_pos = skin->mAlternateBindMatrix[j].getTranslation();
                         LLJointOverrideData &data = mJointOverrides[display_lod][skin->mJointNames[j]];
 
                         LLJoint* pJoint = LLModelPreview::lookupJointByName(skin->mJointNames[j], mModelPreview);
                         if (pJoint)
-                        {
+							{
                             // see how voavatar uses aboveJointPosThreshold
                             if (pJoint->aboveJointPosThreshold(joint_pos))
-                            {
+				{
                                 // valid override
                                 if (data.mPosOverrides.size() > 0
                                     && (data.mPosOverrides.begin()->second - joint_pos).lengthSquared() > (LL_JOINT_TRESHOLD_POS_OFFSET * LL_JOINT_TRESHOLD_POS_OFFSET))
-                                {
+					{
                                     // File contains multiple meshes with conflicting joint offsets
                                     // preview may be incorrect, upload result might wary (depends onto
                                     // mesh_id that hasn't been generated yet).
                                     data.mHasConflicts = true;
-                                }
+							}
                                 data.mPosOverrides[model->getName()] = joint_pos;
-                            }
-                            else
-                            {
+						}
+						else
+						{
                                 // default value, it won't be accounted for by avatar
                                 data.mModelsNoOverrides.insert(model->getName());
-                            }
-                        }
-                    }
-                }
-                else
-                {
+					}
+					}
+				}
+			}
+			else
+			{
                     for (U32 j = 0; j < joint_count; ++j)
-                    {
+				{				
                         LLJointOverrideData &data = mJointOverrides[display_lod][skin->mJointNames[j]];
                         data.mModelsNoOverrides.insert(model->getName());
                     }
                 }
-            }
-        }
-    }
+			}
+		}
+	}
 
     LLPanel *panel = mTabContainer->getPanelByName("rigging_panel");
     LLScrollListCtrl *joints_list = panel->getChild<LLScrollListCtrl>("joints_list");
 
     if (joints_list->isEmpty())
-    {
+	{
         // Populate table
 
-        std::map<std::string, std::string> joint_alias_map;
+    std::map<std::string, std::string> joint_alias_map;
         mModelPreview->getJointAliases(joint_alias_map);
-
+    
         S32 conflicts = 0;
         joint_override_data_map_t::iterator joint_iter = mJointOverrides[display_lod].begin();
         joint_override_data_map_t::iterator joint_end = mJointOverrides[display_lod].end();
         while (joint_iter != joint_end)
-        {
+	{
             const std::string& listName = joint_iter->first;
-
+        
             LLScrollListItem::Params item_params;
             item_params.value(listName);
 
@@ -1459,38 +1459,38 @@ void LLFloaterModelPreview::updateAvatarTab(bool highlight_overrides)
             cell_params.font = LLFontGL::getFontSansSerif();
             cell_params.value = listName;
             if (joint_alias_map.find(listName) == joint_alias_map.end())
-            {
+	{
                 // Missing names
                 cell_params.color = LLColor4::red;
-            }
+	}
             if (joint_iter->second.mHasConflicts)
-            {
+	{
                 // Conflicts
                 cell_params.color = LLColor4::orange;
                 conflicts++;
-            }
+	}
             if (highlight_overrides && joint_iter->second.mPosOverrides.size() > 0)
-            {
+	{
                 cell_params.font.style = "BOLD";
-            }
+	}
 
             item_params.columns.add(cell_params);
 
             joints_list->addRow(item_params, ADD_BOTTOM);
             joint_iter++;
-        }
+	}
         joints_list->selectFirstItem();
         LLScrollListItem *selected = joints_list->getFirstSelected();
         if (selected)
-        {
+{
             mSelectedJointName = selected->getValue().asString();
-        }
+	}
 
         LLTextBox *joint_conf_descr = panel->getChild<LLTextBox>("conflicts_description");
         joint_conf_descr->setTextArg("[CONFLICTS]", llformat("%d", conflicts));
         joint_conf_descr->setTextArg("[JOINTS_COUNT]", llformat("%d", mJointOverrides[display_lod].size()));
-    }
-}
+		}
+	}
 
 //-----------------------------------------------------------------------------
 // addStringToLogTab()
@@ -1498,52 +1498,52 @@ void LLFloaterModelPreview::updateAvatarTab(bool highlight_overrides)
 void LLFloaterModelPreview::addStringToLogTab(const std::string& str, bool flash)
 {
     if (str.empty())
-    {
-        return;
-    }
+		{
+		return;
+	}
 
     LLWString text = utf8str_to_wstring(str);
     S32 add_text_len = text.length() + 1; // newline
     S32 editor_max_len = mUploadLogText->getMaxTextLength();
     if (add_text_len > editor_max_len)
-    {
-        return;
-    }
+		{
+		return;
+	}
 
     // Make sure we have space for new string
     S32 editor_text_len = mUploadLogText->getLength();
     if (editor_max_len < (editor_text_len + add_text_len)
         && mUploadLogText->getLineCount() <= 0)
-    {
+	{
         mUploadLogText->getTextBoundingRect();// forces a reflow() to fix line count
-    }
+			}
     while (editor_max_len < (editor_text_len + add_text_len))
-    {
+		{
         S32 shift = mUploadLogText->removeFirstLine();
         if (shift > 0)
-        {
+	{
             // removed a line
             editor_text_len -= shift;
-        }
-        else
-        {
+}
+	else
+	{
             //nothing to remove?
             LL_WARNS() << "Failed to clear log lines" << LL_ENDL;
-            break;
-        }
-    }
+					break;
+				}
+			}
 
     mUploadLogText->appendText(str, true);
 
     if (flash)
-    {
+	{
         LLPanel* panel = mTabContainer->getPanelByName("logs_panel");
         if (mTabContainer->getCurrentPanel() != panel)
-        {
+		{
             mTabContainer->setTabPanelFlashing(panel, true);
-        }
-    }
-}
+		}
+	}
+	}
 
 void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)
 {
@@ -1551,15 +1551,15 @@ void LLFloaterModelPreview::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost,
 	childSetTextArg("import_dimensions", "[X]", llformat("%.3f", x));
 	childSetTextArg("import_dimensions", "[Y]", llformat("%.3f", y));
 	childSetTextArg("import_dimensions", "[Z]", llformat("%.3f", z));
-}
+		}
 
 void LLFloaterModelPreview::setPreviewLOD(S32 lod)
-{
+		{
 	if (mModelPreview)
 	{
 		mModelPreview->setPreviewLOD(lod);
-	}
-}
+								}
+							}
 
 void LLFloaterModelPreview::onBrowseLOD(S32 lod)
 {
@@ -1648,13 +1648,13 @@ void LLFloaterModelPreview::setCtrlLoadFromFile(S32 lod)
         }
     }
     else
-    {
+{
         LLComboBox* lod_combo = findChild<LLComboBox>("lod_source_" + lod_name[lod]);
         if (lod_combo)
-        {
+	{
             lod_combo->setCurrentByIndex(0);
-        }
-    }
+	}
+}
 }
 
 void LLFloaterModelPreview::setStatusMessage(const std::string& msg)
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 7bfba2a6d7081337ae290d31e5f247fc496bf219..a30c73768d508b1fed9ab050b2ff459006ca8ce8 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -746,9 +746,6 @@ LLSD LLFloaterReporter::gatherReport()
 	const char* platform = "Mac";
 #elif LL_LINUX
 	const char* platform = "Lnx";
-#elif LL_SOLARIS
-	const char* platform = "Sol";
-	const char* short_platform = "O:S";
 #else
 	const char* platform = "???";
 #endif
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 2cb27d85bcf01a0118d27da3678bd8ef01a59d12..efa4a7fd66b55b27643c8d0ef1d07b25efbb2da2 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -2253,52 +2253,91 @@ void renderBoundingBox(LLDrawable* drawable, BOOL set_color = TRUE)
 	}
 }
 
-void renderNormals(LLDrawable* drawablep)
+void renderNormals(LLDrawable *drawablep)
 {
-	LLVertexBuffer::unbind();
+    if (!drawablep->isVisible())
+        return;
 
-	LLVOVolume* vol = drawablep->getVOVolume();
-	if (vol)
-	{
-		LLVolume* volume = vol->getVolume();
-		gGL.pushMatrix();
-		gGL.multMatrix((F32*) vol->getRelativeXform().mMatrix);
-		
-		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+    LLVertexBuffer::unbind();
 
-		LLVector4a scale(gSavedSettings.getF32("RenderDebugNormalScale"));
+    LLVOVolume *vol = drawablep->getVOVolume();
 
-		for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
-		{
-			const LLVolumeFace& face = volume->getVolumeFace(i);
+    if (vol)
+    {
+        LLVolume *volume = vol->getVolume();
 
-			for (S32 j = 0; j < face.mNumVertices; ++j)
-			{
-				gGL.begin(LLRender::LINES);
-				LLVector4a n,p;
-				
-				n.setMul(face.mNormals[j], scale);
-				p.setAdd(face.mPositions[j], n);
-				
-				gGL.diffuseColor4f(1,1,1,1);
-				gGL.vertex3fv(face.mPositions[j].getF32ptr());
-				gGL.vertex3fv(p.getF32ptr());
-				
-				if (face.mTangents)
-				{
-					n.setMul(face.mTangents[j], scale);
-					p.setAdd(face.mPositions[j], n);
-				
-					gGL.diffuseColor4f(0,1,1,1);
-					gGL.vertex3fv(face.mPositions[j].getF32ptr());
-					gGL.vertex3fv(p.getF32ptr());
-				}	
-				gGL.end();
-			}
-		}
+        // Drawable's normals & tangents are stored in model space, i.e. before any scaling is applied.
+        //
+        // SL-13490, using pos + normal to compute the 2nd vertex of a normal line segment doesn't
+        // work when there's a non-uniform scale in the mix. Normals require MVP-inverse-transpose
+        // transform. We get that effect here by pre-applying the inverse scale (twice, because
+        // one forward scale will be re-applied via the MVP in the vertex shader)
 
-		gGL.popMatrix();
-	}
+        LLVector3  scale_v3 = vol->getScale();
+        float      scale_len = scale_v3.length();
+        LLVector4a obj_scale(scale_v3.mV[VX], scale_v3.mV[VY], scale_v3.mV[VZ]);
+        obj_scale.normalize3();
+
+        // Normals &tangent line segments get scaled along with the object. Divide by scale length
+        // to keep the as-viewed lengths (relatively) constant with the debug setting length
+        float draw_length = gSavedSettings.getF32("RenderDebugNormalScale") / scale_len;
+
+        // Create inverse-scale vector for normals
+        LLVector4a inv_scale(1.0 / scale_v3.mV[VX], 1.0 / scale_v3.mV[VY], 1.0 / scale_v3.mV[VZ]);
+        inv_scale.mul(inv_scale);  // Squared, to apply inverse scale twice
+        inv_scale.normalize3fast();
+
+        gGL.pushMatrix();
+        gGL.multMatrix((F32 *) vol->getRelativeXform().mMatrix);
+
+        gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+
+        for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
+        {
+            const LLVolumeFace &face = volume->getVolumeFace(i);
+
+            gGL.flush();
+            gGL.diffuseColor4f(1, 1, 0, 1);
+            gGL.begin(LLRender::LINES);
+            for (S32 j = 0; j < face.mNumVertices; ++j)
+            {
+                LLVector4a n, p;
+
+                n.setMul(face.mNormals[j], 1.0);
+                n.mul(inv_scale);  // Pre-scale normal, so it's left with an inverse-transpose xform after MVP
+                n.normalize3fast();
+                n.mul(draw_length);
+                p.setAdd(face.mPositions[j], n);
+
+                gGL.vertex3fv(face.mPositions[j].getF32ptr());
+                gGL.vertex3fv(p.getF32ptr());
+            }
+            gGL.end();
+
+            // Tangents are simple vectors and do not require reorientation via pre-scaling
+            if (face.mTangents)
+            {
+                gGL.flush();
+                gGL.diffuseColor4f(0, 1, 1, 1);
+                gGL.begin(LLRender::LINES);
+                for (S32 j = 0; j < face.mNumVertices; ++j)
+                {
+                    LLVector4a t, p;
+
+                    t.setMul(face.mTangents[j], 1.0f);
+                    t.normalize3fast();
+                    t.mul(draw_length);
+                    p.setAdd(face.mPositions[j], t);
+
+                    gGL.vertex3fv(face.mPositions[j].getF32ptr());
+                    gGL.vertex3fv(p.getF32ptr());
+                }
+                gGL.end();
+            }
+        }
+
+        gGL.popMatrix();
+    }
 }
 
 S32 get_physics_detail(const LLVolumeParams& volume_params, const LLVector3& scale)
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index 55048b03be7d77fc85b33804042070c9076eb5bf..c5d5be3509b166754396857c1bed38d4e09ff9d2 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -179,6 +179,7 @@
 #include "pipeline.h"
 #include "llappviewer.h"
 #include "llfasttimerview.h"
+#include "lltelemetry.h"
 #include "llfloatermap.h"
 #include "llweb.h"
 #include "llvoiceclient.h"
@@ -529,6 +530,8 @@ bool idle_startup()
 			}
 
 			#if LL_WINDOWS
+                LLPROFILE_STARTUP();
+
 				// On the windows dev builds, unpackaged, the message.xml file will 
 				// be located in indra/build-vc**/newview/<config>/app_settings.
 				std::string message_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message.xml");
diff --git a/indra/newview/lltelemetry.cpp b/indra/newview/lltelemetry.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0c63e2fede5d45b4b56949d9399d812a98c166f4
--- /dev/null
+++ b/indra/newview/lltelemetry.cpp
@@ -0,0 +1,145 @@
+ /**
+ * @file lltelemetry.cpp
+ * @brief Wrapper for Rad Game Tools Telemetry
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltelemetry.h"
+
+#if LLPROFILE_USE_RAD_TELEMETRY_PROFILER
+    #if LL_WINDOWS
+        #include "llwin32headers.h"
+
+        // build-vc120-64\packages\lib\release
+        // build-vc150-64\packages\lib\release
+        #ifdef _MSC_VER
+            #pragma comment(lib,"rad_tm_win64.lib")
+        #else
+            #pragma message "NOTE: Rad GameTools Telemetry requested but non-MSVC compiler not yet supported on Windows"
+        #endif
+    #endif // LL_WINDOWS
+
+    #if LL_DARWIN
+        #pragma message "NOTE: Rad Game Tools Telemetry requested but not yet supported on Darwin"
+    #endif
+
+    #if LL_LINUX
+        #pragma message "NOTE: Rad Game Tools Telemetry requested but not yet supported on Linux"
+    #endif
+
+//
+// local consts
+//
+static const tm_int32 TELEMETRY_BUFFER_SIZE  = 8 * 1024 * 1024;
+
+//
+// local globals
+//
+static char *gTelemetryBufferPtr = NULL; // Telemetry
+
+static const char *tm_status[ TMERR_INIT_NETWORKING_FAILED + 1 ] =
+{
+      "Telemetry pass: connected"                       // TM_OK
+    , "Telemetry FAIL: disabled via #define NTELEMETRY" // TMERR_DISABLED
+    , "Telemetry FAIL: invalid paramater"               // TMERR_INVALID_PARAM
+    , "Telemetry FAIL: DLL not found"                   // TMERR_NULL_API
+    , "Telemetry FAIL: out of resources"                // TMERR_OUT_OF_RESOURCES
+    , "Telemetry FAIL: tmInitialize() not called"       // TMERR_UNINITIALIZED
+    , "Telemetry FAIL: bad hostname"                    // TMERR_BAD_HOSTNAME
+    , "Telemetry FAIL: couldn't connect to server"      // TMERR_COULD_NOT_CONNECT
+    , "Telemetry FAIL: unknown network error"           // TMERR_UNKNOWN_NETWORK
+    , "Telemetry FAIL: tmShutdown() already called"     // TMERR_ALREADY_SHUTDOWN
+    , "Telemetry FAIL: memory buffer too small"         // TMERR_ARENA_TOO_SMALL
+    , "Telemetry FAIL: server handshake error"          // TMERR_BAD_HANDSHAKE
+    , "Telemetry FAIL: unaligned parameters"            // TMERR_UNALIGNED
+    , "Telemetry FAIL: network not initialized"         // TMERR_NETWORK_NOT_INITIALIZED -- WSAStartup not called before tmOpen()
+    , "Telemetry FAIL: bad version"                     // TMERR_BAD_VERSION
+    , "Telemetry FAIL: timer too large"                 // TMERR_BAD_TIMER
+    , "Telemetry FAIL: tmOpen() already called"         // TMERR_ALREADY_OPENED
+    , "Telemetry FAIL: tmInitialize() already called"   // TMERR_ALREADY_INITIALIZED
+    , "Telemetry FAIL: could't open file"               // TMERR_FILE_OPEN_FAILED
+    , "Telemetry FAIL: tmOpen() failed networking"      // TMERR_INIT_NETWORKING_FAILED
+};
+
+//
+// exported functionality
+//
+
+void telemetry_shutdown()
+{
+    #if LL_WINDOWS
+        if (gTelemetryBufferPtr)
+        {
+            tmClose(0);
+            tmShutdown();
+
+            delete[] gTelemetryBufferPtr;
+            gTelemetryBufferPtr = NULL;
+        }
+    #endif
+}
+
+void telemetry_startup()
+{
+    #if LL_WINDOWS
+        tmLoadLibrary(TM_RELEASE); // Loads .dll
+
+        gTelemetryBufferPtr = new char[ TELEMETRY_BUFFER_SIZE ];
+        tmInitialize(TELEMETRY_BUFFER_SIZE, gTelemetryBufferPtr);
+
+        tm_error telemetry_status = tmOpen(
+            0,                     // unused
+            "SecondLife",          // app name
+            __DATE__ " " __TIME__, // build identifier
+            "localhost",           // server name (or filename)
+            TMCT_TCP,              // connection type (or TMCT_FILE)
+            4719,                  // port
+            TMOF_INIT_NETWORKING,  // open flags
+            250 );                 // timeout ms
+
+        if (telemetry_status == TMERR_UNKNOWN)
+        {
+            LL_ERRS() << "Telemetry FAIL: unknown error" << LL_ENDL;
+        }
+        else if (telemetry_status && (telemetry_status <= TMERR_INIT_NETWORKING_FAILED))
+        {
+            LL_INFOS() << tm_status[ telemetry_status ] << LL_ENDL;
+            free(gTelemetryBufferPtr);
+            gTelemetryBufferPtr = NULL;
+        }
+    #endif // LL_WINDOWS
+}
+
+// Called after we render a frame
+void telemetry_update()
+{
+    #if LL_WINDOWS
+        if (gTelemetryBufferPtr)
+        {
+            tmTick(0);
+        }
+    #endif
+}
+#endif // LLPROFILE_USE_RAD_TELEMETRY_PROFILER
diff --git a/indra/newview/lltelemetry.h b/indra/newview/lltelemetry.h
new file mode 100644
index 0000000000000000000000000000000000000000..a73e5fcfa27aef28cdd4ad71f6a273885bbba7b1
--- /dev/null
+++ b/indra/newview/lltelemetry.h
@@ -0,0 +1,81 @@
+/**
+ * @file lltelemetry.h
+ * @brief Wrapper for Rad Game Tools Telemetry
+ *
+ * $LicenseInfo:firstyear=2020&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2020, 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$
+ */
+
+/*
+To use:
+
+1. Uncomment #define LLPROFILE_USE_RAD_TELEMETRY_PROFILER below
+
+2. Include this header file
+    #include "lltelemetry.h"
+
+3. Add zones to the functions you wish to profile
+    void onFoo()
+    {
+        LLPROFILE_ZONE("Foo");
+    }
+*/
+//#define LLPROFILE_USE_RAD_TELEMETRY_PROFILER 1
+
+// Default NO local telemetry profiling
+#ifndef LLPROFILE_USE_RAD_TELEMETRY_PROFILER
+    #define LLPROFILE_USE_RAD_TELEMETRY_PROFILER 0
+    #define LLPROFILE_SHUTDOWN( ...) {}
+    #define LLPROFILE_STARTUP(  ...) {}
+    #define LLPROFILE_UPDATE(   ...) {}
+
+    #define LLPROFILE_AUTO_CPU_MARKER_COLOR(r, g, b)
+    #define LLPROFILE_ENTER(name)
+    #define LLPROFILE_ENTER_FORMAT(format, ...)
+    #define LLPROFILE_FUNCTION
+    #define LLPROFILE_LEAVE()
+    #define LLPROFILE_THREAD_NAME(name)
+    #define LLPROFILE_ZONE(name)
+    #define LLPROFILE_ZONE_FORMAT(format, ...)
+#else
+    #include <rad_tm.h>
+
+    #define LLPROFILE_SHUTDOWN                       telemetry_shutdown
+    #define LLPROFILE_STARTUP                        telemetry_startup
+    #define LLPROFILE_UPDATE                         telemetry_update
+
+    #define LLPROFILE_AUTO_CPU_MARKER_COLOR(r, g, b) tmZoneColor(r, g, b)
+    #define LLPROFILE_ENTER(name)                    tmEnter(0, 0, name)
+    #define LLPROFILE_ENTER_FORMAT(format, ...)      tmEnter(0, 0, format, __VA_ARGS__)
+    #define LLPROFILE_FUNCTION                       tmFunction(0, 0)
+    #define LLPROFILE_LEAVE()                        tmLeave(0)
+    #define LLPROFILE_THREAD_NAME(name)              tmThreadName(0, 0, name)
+    #define LLPROFILE_ZONE(name)                     tmZone(0, 0, name)
+    #define LLPROFILE_ZONE_FORMAT(format, ...)       tmZone(0, 0, format, __VA_ARGS__)
+#endif // LLPROFILE_USE_RAD_TELEMETRY_PROFILER
+
+//
+// exported functionality
+//
+
+extern void telemetry_startup();
+extern void telemetry_shutdown();
+extern void telemetry_update(); // called after every frame update
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 5679c3c3253780b96cd6ca60811de111380d3761..066c874eb8a7c0a84f61f19bbc75cca20dce96e0 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -754,10 +754,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
 				glViewport(0,0,512,512);
 				LLVOAvatar::updateFreezeCounter() ;
 
-				if(!LLPipeline::sMemAllocationThrottled)
-				{		
-					LLVOAvatar::updateImpostors();
-				}
+				LLVOAvatar::updateImpostors();
 
 				set_current_projection(proj);
 				set_current_modelview(mod);
diff --git a/indra/newview/llviewerjoint.cpp b/indra/newview/llviewerjoint.cpp
index a448a95904bee8bcf65690f13b3da612164fe901..9653e80b536c68810a43d16162be0a9f2cd62348 100644
--- a/indra/newview/llviewerjoint.cpp
+++ b/indra/newview/llviewerjoint.cpp
@@ -143,8 +143,10 @@ U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass, BOOL is_dummy )
 	//----------------------------------------------------------------
 	for (LLJoint* j : mChildren)
 	{
-		LLAvatarJoint* joint = dynamic_cast<LLAvatarJoint*>(j);
-		F32 jointLOD = joint ? joint->getLOD() : 0;
+		// LLViewerJoint is derived from LLAvatarJoint,
+		// all children of LLAvatarJoint are assumed to be LLAvatarJoint
+		LLAvatarJoint* joint = static_cast<LLAvatarJoint*>(j);
+		F32 jointLOD = joint->getLOD();
 		if (pixelArea >= jointLOD || sDisableLOD)
 		{
 			triangle_count += joint->render( pixelArea, TRUE, is_dummy );
diff --git a/indra/newview/llviewerjointmesh.cpp b/indra/newview/llviewerjointmesh.cpp
index fdfd22c1170da310609a381ff2cd172f968e7271..63ad708e59bd1f43e826c724f892b2683af9724e 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -56,7 +56,7 @@
 #include "m4math.h"
 #include "llmatrix4a.h"
 
-#if !LL_DARWIN && !LL_LINUX && !LL_SOLARIS
+#if !LL_DARWIN && !LL_LINUX
 extern PFNGLWEIGHTPOINTERARBPROC glWeightPointerARB;
 extern PFNGLWEIGHTFVARBPROC glWeightfvARB;
 extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 395dd0495f932c796094a4107c22c69addbf3c07..b88baf6aa72f3b3b5f8cacdb4eee85778f637b67 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -4880,78 +4880,22 @@ void LLViewerObject::refreshBakeTexture()
 	}
 }
 
-void LLViewerObject::updateDiffuseMatParams(const U8 te, LLMaterial* mat, LLViewerTexture *imagep, bool baked_texture)
-{
-    // Objects getting non-alpha texture and alpha mask can result in graphical bugs, like white or red alphas.
-    // To resolve the issue this function provides image format to material and based on format material's
-    // getDiffuseAlphaModeRender() function will decide what value to provide to render
-    //
-    // Unfortunately LLMaterial has no access to diffuse image, so we have to set this data in LLViewerObject
-    // regardles of object being used/seen or frequency of image-updates.
-    mat->setDiffuseBaked(baked_texture);
-
-    if (!baked_texture)
-    {
-        if (imagep->isMissingAsset())
-        {
-            mat->setDiffuseFormatPrimary(0);
-        }
-        else if (0 == imagep->getPrimaryFormat())
-        {
-            // We don't have information about this texture, wait for it
-            mWaitingTextureInfo.insert(uuid_material_mmap_t::value_type(imagep->getID(), material_info(LLRender::DIFFUSE_MAP, te)));
-            // Temporary assume RGBA image
-            mat->setDiffuseFormatPrimary(GL_RGBA);
-        }
-        else
-        {
-            mat->setDiffuseFormatPrimary(imagep->getPrimaryFormat());
-        }
-    }
-}
-
-S32 LLViewerObject::setDiffuseImageAndParams(const U8 te, LLViewerTexture *imagep)
-{
-    LLUUID new_id = imagep->getID();
-    S32 retval = LLPrimitive::setTETexture(te, new_id);
-
-    LLTextureEntry* tep = getTE(te);
-    LLUUID old_image_id = tep->getID();
-
-    LLViewerTexture* baked_texture = getBakedTextureForMagicId(new_id);
-    mTEImages[te] = baked_texture ? baked_texture : imagep;
-    updateAvatarMeshVisibility(new_id, old_image_id);
-
-    LLMaterial* mat = tep->getMaterialParams();
-    if (mat)
-    {
-        // Don't update format from texture (and don't shedule one) if material has no alpha mode set,
-        // just assume RGBA format, format will get updated with setTEMaterialParams call if mode changes
-        if (mat->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_NONE)
-        {
-            bool baked = baked_texture != NULL;
-            updateDiffuseMatParams(te, mat, imagep, baked);
-        }
-        else
-        {
-            mat->setDiffuseFormatPrimary(GL_RGBA);
-        }
-    }
-
-    setChanged(TEXTURE);
-    if (mDrawable.notNull())
-    {
-        gPipeline.markTextured(mDrawable);
-    }
-
-    return retval;
-}
-
 void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep)
 {
 	if (mTEImages[te] != imagep)
 	{
-        setDiffuseImageAndParams(te, imagep);
+		LLUUID old_image_id = getTE(te) ? getTE(te)->getID() : LLUUID::null;
+		
+		LLPrimitive::setTETexture(te, imagep->getID());
+
+		LLViewerTexture* baked_texture = getBakedTextureForMagicId(imagep->getID());
+		mTEImages[te] = baked_texture ? baked_texture : imagep;
+		updateAvatarMeshVisibility(imagep->getID(), old_image_id);
+		setChanged(TEXTURE);
+		if (mDrawable.notNull())
+		{
+			gPipeline.markTextured(mDrawable);
+		}
 	}
 }
 
@@ -4963,7 +4907,15 @@ S32 LLViewerObject::setTETextureCore(const U8 te, LLViewerTexture *image)
 	if (uuid != getTE(te)->getID() ||
 		uuid == LLUUID::null)
 	{
-		retval = setDiffuseImageAndParams(te, image);
+		retval = LLPrimitive::setTETexture(te, uuid);
+		LLViewerTexture* baked_texture = getBakedTextureForMagicId(uuid);
+		mTEImages[te] = baked_texture ? baked_texture : image;
+		updateAvatarMeshVisibility(uuid,old_image_id);
+		setChanged(TEXTURE);
+		if (mDrawable.notNull())
+		{
+			gPipeline.markTextured(mDrawable);
+		}
 	}
 	return retval;
 }
@@ -5258,29 +5210,6 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
 		return 0;
 	}
 
-    if (pMaterialParams.notNull()
-        && pMaterialParams->getDiffuseAlphaMode() != LLMaterial::DIFFUSE_ALPHA_MODE_NONE)
-    {
-        // Don't update if no alpha is set. If alpha changes, this function will run again,
-        // no point in sheduling additional texture callbacks (in updateDiffuseMatParams)
-        LLTextureEntry* tex_entry = getTE(te);
-        bool is_baked = tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID());
-
-        LLViewerTexture *img_diffuse = getTEImage(te);
-        llassert(NULL != img_diffuse);
-
-        if (NULL != img_diffuse)
-        {
-            // Will modify alpha mask provided to renderer to fit image
-            updateDiffuseMatParams(te, pMaterialParams.get(), img_diffuse, is_baked);
-        }
-        else
-        {
-            LLMaterial *mat = pMaterialParams.get(); // to avoid const
-            mat->setDiffuseFormatPrimary(0);
-        }
-    }
-
 	retval = LLPrimitive::setTEMaterialParams(te, pMaterialParams);
 	LL_DEBUGS("Material") << "Changing material params for te " << (S32)te
 							<< ", object " << mID
@@ -5293,84 +5222,6 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri
 	return retval;
 }
 
-bool LLViewerObject::notifyAboutCreatingTexture(LLViewerTexture *texture)
-{
-    // Confirmation about texture creation, check wait-list
-    // and make changes, or return false
-
-    std::pair<uuid_material_mmap_t::iterator, uuid_material_mmap_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
-
-    bool refresh_materials = false;
-
-    // RGB textures without alpha channels won't work right with alpha,
-    // we provide format to material for material to decide when to drop alpha
-    for (uuid_material_mmap_t::iterator range_it = range.first; range_it != range.second; ++range_it)
-    {
-        LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
-        if (cur_material.notNull()
-            && LLRender::DIFFUSE_MAP == range_it->second.map)
-        {
-            U32 format = texture->getPrimaryFormat();
-            if (format != cur_material->getDiffuseFormatPrimary())
-            {
-                cur_material->setDiffuseFormatPrimary(format);
-                refresh_materials = true;
-            }
-        }
-    } //for
-
-    if (refresh_materials)
-    {
-        LLViewerObject::refreshMaterials();
-    }
-
-    //clear wait-list
-    mWaitingTextureInfo.erase(range.first, range.second);
-
-    return refresh_materials;
-}
-
-bool LLViewerObject::notifyAboutMissingAsset(LLViewerTexture *texture)
-{
-    // When waiting information about texture it turned out to be missing.
-    // Confirm the state, update values accordingly
-    std::pair<uuid_material_mmap_t::iterator, uuid_material_mmap_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
-    if (range.first == range.second) return false;
-
-    bool refresh_materials = false;
-
-    for (uuid_material_mmap_t::iterator range_it = range.first; range_it != range.second; ++range_it)
-    {
-        LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
-        if (cur_material.isNull())
-            continue;
-
-        if (range_it->second.map == LLRender::DIFFUSE_MAP)
-        {
-            LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
-            if (cur_material.notNull()
-                && LLRender::DIFFUSE_MAP == range_it->second.map)
-            {
-                if (0 != cur_material->getDiffuseFormatPrimary())
-                {
-                    cur_material->setDiffuseFormatPrimary(0);
-                    refresh_materials = true;
-                }
-            }
-        }
-    } //for
-
-    if (refresh_materials)
-    {
-        LLViewerObject::refreshMaterials();
-    }
-
-    //clear wait-list
-    mWaitingTextureInfo.erase(range.first, range.second);
-
-    return refresh_materials;
-}
-
 void LLViewerObject::refreshMaterials()
 {
 	setChanged(TEXTURE);
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 9444c4f788fe6940cd82641993be19b7834219fe..250c4ac32867d62071dc3e87a32e01d017d55d7d 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -768,12 +768,7 @@ class LLViewerObject
 	void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id, bool legacy);
 	void deleteParticleSource();
 	void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id);
-
-    // Helper function to modify alpha mask provided to render according to image (ex: RGB image will drop alpha mask)
-    void updateDiffuseMatParams(const U8 te, LLMaterial* mat, LLViewerTexture *imagep, bool baked_texture);
-    // Shared part of code from setTEImage and setTETextureCore
-    S32 setDiffuseImageAndParams(const U8 te, LLViewerTexture *imagep);
-
+	
 private:
 	void setNameValueList(const std::string& list);		// clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string
 	void deleteTEImages(); // correctly deletes list of images
@@ -906,27 +901,10 @@ class LLViewerObject
 
     LLJointRiggingInfoTab mJointRiggingInfoTab;
 
-    bool notifyAboutCreatingTexture(LLViewerTexture *texture);
-    bool notifyAboutMissingAsset(LLViewerTexture *texture);
-
 private:
 	LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory.
 	EObjectUpdateType	mLastUpdateType;
 	BOOL	mLastUpdateCached;
-
-    struct material_info
-    {
-        LLRender::eTexIndex map;
-        U8 te;
-
-        material_info(LLRender::eTexIndex map_, U8 te_)
-            : map(map_)
-            , te(te_)
-        {}
-    };
-
-    typedef std::multimap<LLUUID, material_info> uuid_material_mmap_t;
-    uuid_material_mmap_t mWaitingTextureInfo;
 };
 
 ///////////////////
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 20a22ba45e02b91e21e23303918bba21a5f94f73..ca01bb46aaa3958e6f8a6b36acc0a012020179e7 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -3314,13 +3314,6 @@ void LLViewerLODTexture::processTextureStats()
 	{
 		mDesiredDiscardLevel = llmin(mDesiredDiscardLevel, (S8)mDesiredSavedRawDiscardLevel);
 	}
-	else if(LLPipeline::sMemAllocationThrottled)//release memory of large textures by decrease their resolutions.
-	{
-		if(scaleDown())
-		{
-			mDesiredDiscardLevel = mCachedRawDiscardLevel;
-		}
-	}
 }
 
 bool LLViewerLODTexture::scaleDown()
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 0f96a0b06c8e8cfd8451c3d062796bfc786c452b..21985d5a8a7cca36f07ed647cd8cc13bd61f6e62 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -312,6 +312,99 @@ RecordToChatConsole::RecordToChatConsole():
     mRecorder->showMultiline(true);
 }
 
+////////////////////////////////////////////////////////////////////////////
+//
+// Print Utility
+//
+
+// Convert a normalized float (-1.0 <= x <= +1.0) to a fixed 1.4 format string:
+//
+//    s#.####
+//
+// Where:
+//    s  sign character; space if x is positiv, minus if negative
+//    #  decimal digits
+//
+// This is similar to printf("%+.4f") except positive numbers are NOT cluttered with a leading '+' sign.
+// NOTE: This does NOT null terminate the output
+void normalized_float_to_string(const float x, char *out_str)
+{
+    static const unsigned char DECIMAL_BCD2[] =
+    {
+        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
+        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
+        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
+        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+        0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+        0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+        0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+        0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99
+    };
+
+    int neg = (x < 0);
+    int rem = neg
+            ? (int)(x * -10000.)
+            : (int)(x *  10000.);
+
+    int d10 = rem % 100; rem /= 100;
+    int d32 = rem % 100; rem /= 100;
+
+    out_str[6] = '0' + ((DECIMAL_BCD2[ d10 ] >> 0) & 0xF);
+    out_str[5] = '0' + ((DECIMAL_BCD2[ d10 ] >> 4) & 0xF);
+    out_str[4] = '0' + ((DECIMAL_BCD2[ d32 ] >> 0) & 0xF);
+    out_str[3] = '0' + ((DECIMAL_BCD2[ d32 ] >> 4) & 0xF);
+    out_str[2] = '.';
+    out_str[1] = '0' + (rem & 1);
+    out_str[0] = " -"[neg]; // Could always show '+' for positive but this clutters up the common case
+}
+
+// normalized float
+//    printf("%-.4f    %-.4f    %-.4f")
+// Params:
+//   float  &matrix_row[4]
+//   int    matrix_cell_index
+//   string out_buffer (size 32)
+// Note: The buffer is assumed to be pre-filled with spaces
+#define MATRIX_ROW_N32_TO_STR(matrix_row, i, out_buffer)          \
+    normalized_float_to_string(matrix_row[i+0], out_buffer +  0); \
+    normalized_float_to_string(matrix_row[i+1], out_buffer + 11); \
+    normalized_float_to_string(matrix_row[i+2], out_buffer + 22); \
+    out_buffer[31] = 0;
+
+
+// regular float
+//    sprintf(buffer, "%-8.2f  %-8.2f  %-8.2f", matrix_row[i+0], matrix_row[i+1], matrix_row[i+2]);
+// Params:
+//   float  &matrix_row[4]
+//   int    matrix_cell_index
+//   char   out_buffer[32]
+// Note: The buffer is assumed to be pre-filled with spaces
+#define MATRIX_ROW_F32_TO_STR(matrix_row, i, out_buffer) {                       \
+    static const char *format[3] = {                                             \
+        "%-8.2f"  ,  /* 0 */                                                     \
+        ">  99K  ",  /* 1 */                                                     \
+        "< -99K  "   /* 2 */                                                     \
+    };                                                                           \
+                                                                                 \
+    F32 temp_0 = matrix_row[i+0];                                                \
+    F32 temp_1 = matrix_row[i+1];                                                \
+    F32 temp_2 = matrix_row[i+2];                                                \
+                                                                                 \
+    U8 flag_0 = (((U8)(temp_0 < -99999.99)) << 1) | ((U8)(temp_0 > 99999.99));   \
+    U8 flag_1 = (((U8)(temp_1 < -99999.99)) << 1) | ((U8)(temp_1 > 99999.99));   \
+    U8 flag_2 = (((U8)(temp_2 < -99999.99)) << 1) | ((U8)(temp_2 > 99999.99));   \
+                                                                                 \
+    if (temp_0 < 0.f) out_buffer[ 0] = '-';                                      \
+    if (temp_1 < 0.f) out_buffer[11] = '-';                                      \
+    if (temp_2 < 0.f) out_buffer[22] = '-';                                      \
+                                                                                 \
+    sprintf(out_buffer+ 1,format[flag_0],fabsf(temp_0)); out_buffer[ 1+8] = ' '; \
+    sprintf(out_buffer+12,format[flag_1],fabsf(temp_1)); out_buffer[12+8] = ' '; \
+    sprintf(out_buffer+23,format[flag_2],fabsf(temp_2)); out_buffer[23+8] =  0 ; \
+}
+
 ////////////////////////////////////////////////////////////////////////////
 //
 // LLDebugText
@@ -334,7 +427,11 @@ class LLDebugText
 	typedef std::vector<Line> line_list_t;
 	line_list_t mLineList;
 	LLColor4 mTextColor;
-	
+
+	LLColor4 mBackColor;
+	LLRect mBackRectCamera1;
+	LLRect mBackRectCamera2;
+
 	void addText(S32 x, S32 y, const std::string &text) 
 	{
 		mLineList.push_back(Line(text, x, y));
@@ -376,11 +473,22 @@ class LLDebugText
 		mTextColor = LLColor4( 0.86f, 0.86f, 0.86f, 1.f );
 
 		// Draw stuff growing up from right lower corner of screen
-		S32 xpos = mWindow->getWorldViewWidthScaled() - 400;
+		S32 x_right = mWindow->getWorldViewWidthScaled();
+		S32 xpos = x_right - 400;
 		xpos = llmax(xpos, 0);
 		S32 ypos = 64;
 		const S32 y_inc = 20;
 
+		// Camera matrix text is hard to see again a white background
+		// Add a dark background underneath the matrices for readability (contrast)
+		mBackRectCamera1.mLeft   = xpos;
+		mBackRectCamera1.mRight  = x_right;
+		mBackRectCamera1.mTop    = -1;
+		mBackRectCamera1.mBottom = -1;
+		mBackRectCamera2 = mBackRectCamera1;
+
+		mBackColor = LLUIColorTable::instance().getColor( "MenuDefaultBgColor" );
+
 		clearText();
 		
 		if (gSavedSettings.getBOOL("DebugShowTime"))
@@ -716,48 +824,45 @@ class LLDebugText
 		}
 		if (gSavedSettings.getBOOL("DebugShowRenderMatrices"))
 		{
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[12], gGLProjection[13], gGLProjection[14], gGLProjection[15]));
-			ypos += y_inc;
+			char camera_lines[8][32];
+			memset(camera_lines, ' ', sizeof(camera_lines));
 
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[8], gGLProjection[9], gGLProjection[10], gGLProjection[11]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[4], gGLProjection[5], gGLProjection[6], gGLProjection[7]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLProjection[0], gGLProjection[1], gGLProjection[2], gGLProjection[3]));
-			ypos += y_inc;
+			// Projection last column is always <0,0,-1.0001,0>
+			// Projection last row is always <0,0,-0.2>
+			mBackRectCamera1.mBottom = ypos - y_inc + 2;
+			MATRIX_ROW_N32_TO_STR(gGLProjection, 12,camera_lines[7]); addText(xpos, ypos, std::string(camera_lines[7])); ypos += y_inc;
+			MATRIX_ROW_N32_TO_STR(gGLProjection,  8,camera_lines[6]); addText(xpos, ypos, std::string(camera_lines[6])); ypos += y_inc;
+			MATRIX_ROW_N32_TO_STR(gGLProjection,  4,camera_lines[5]); addText(xpos, ypos, std::string(camera_lines[5])); ypos += y_inc; mBackRectCamera1.mTop    = ypos + 2;
+			MATRIX_ROW_N32_TO_STR(gGLProjection,  0,camera_lines[4]); addText(xpos, ypos, std::string(camera_lines[4])); ypos += y_inc; mBackRectCamera2.mBottom = ypos + 2;
 
 			addText(xpos, ypos, "Projection Matrix");
 			ypos += y_inc;
 
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[12], gGLModelView[13], gGLModelView[14], gGLModelView[15]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[8], gGLModelView[9], gGLModelView[10], gGLModelView[11]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[4], gGLModelView[5], gGLModelView[6], gGLModelView[7]));
-			ypos += y_inc;
-
-			addText(xpos, ypos, llformat("%.4f    .%4f    %.4f    %.4f", gGLModelView[0], gGLModelView[1], gGLModelView[2], gGLModelView[3]));
-			ypos += y_inc;
+			// View last column is always <0,0,0,1>
+			MATRIX_ROW_F32_TO_STR(gGLModelView, 12,camera_lines[3]); addText(xpos, ypos, std::string(camera_lines[3])); ypos += y_inc;
+			MATRIX_ROW_N32_TO_STR(gGLModelView,  8,camera_lines[2]); addText(xpos, ypos, std::string(camera_lines[2])); ypos += y_inc;
+			MATRIX_ROW_N32_TO_STR(gGLModelView,  4,camera_lines[1]); addText(xpos, ypos, std::string(camera_lines[1])); ypos += y_inc; mBackRectCamera2.mTop = ypos + 2;
+			MATRIX_ROW_N32_TO_STR(gGLModelView,  0,camera_lines[0]); addText(xpos, ypos, std::string(camera_lines[0])); ypos += y_inc;
 
 			addText(xpos, ypos, "View Matrix");
 			ypos += y_inc;
 		}
 		// disable use of glReadPixels which messes up nVidia nSight graphics debugging
-		if (gSavedSettings.getBOOL("DebugShowColor") && !LLRender::sNsightDebugSupport)
-		{
-			U8 color[4];
-			LLCoordGL coord = gViewerWindow->getCurrentMouse();
-			glReadPixels(coord.mX, coord.mY, 1,1,GL_RGBA, GL_UNSIGNED_BYTE, color);
-			addText(xpos, ypos, llformat("%d %d %d %d", color[0], color[1], color[2], color[3]));
-			ypos += y_inc;
-		}
+        if (gSavedSettings.getBOOL("DebugShowColor") && !LLRender::sNsightDebugSupport)
+        {
+            U8 color[4];
+            LLCoordGL coord = gViewerWindow->getCurrentMouse();
 
-		// only display these messages if we are actually rendering beacons at this moment
+            // Convert x,y to raw pixel coords
+            S32 x_raw = llround(coord.mX * gViewerWindow->getWindowWidthRaw() / (F32) gViewerWindow->getWindowWidthScaled());
+            S32 y_raw = llround(coord.mY * gViewerWindow->getWindowHeightRaw() / (F32) gViewerWindow->getWindowHeightScaled());
+            
+            glReadPixels(x_raw, y_raw, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, color);
+            addText(xpos, ypos, llformat("Pixel <%1d, %1d> R:%1d G:%1d B:%1d A:%1d", x_raw, y_raw, color[0], color[1], color[2], color[3]));
+            ypos += y_inc;
+        }
+
+        // only display these messages if we are actually rendering beacons at this moment
 		if (LLPipeline::getRenderBeacons() && LLFloaterReg::instanceVisible("beacons"))
 		{
 			if (LLPipeline::getRenderMOAPBeacons())
@@ -884,6 +989,18 @@ class LLDebugText
 	void draw()
 	{
 		LL_RECORD_BLOCK_TIME(FTM_DISPLAY_DEBUG_TEXT);
+
+		// Camera matrix text is hard to see again a white background
+		// Add a dark background underneath the matrices for readability (contrast)
+		if (mBackRectCamera1.mTop >= 0)
+		{
+			mBackColor.setAlpha( 0.75f );
+			gl_rect_2d(mBackRectCamera1, mBackColor, true);
+
+			mBackColor.setAlpha( 0.66f );
+			gl_rect_2d(mBackRectCamera2, mBackColor, true);
+		}
+
 		for (line_list_t::iterator iter = mLineList.begin();
 			 iter != mLineList.end(); ++iter)
 		{
@@ -892,7 +1009,6 @@ class LLDebugText
 											 LLFontGL::LEFT, LLFontGL::TOP,
 											 LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE);
 		}
-		mLineList.clear();
 	}
 
 };
@@ -1800,8 +1916,8 @@ LLViewerWindow::LLViewerWindow(const Params& p)
 		ms_sleep(5000) ; //wait for 5 seconds.
 
 		LLSplashScreen::update(LLTrans::getString("ShuttingDown"));
-#if LL_LINUX || LL_SOLARIS
-		LL_WARNS() << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly.  See README-linux.txt or README-solaris.txt for further information."
+#if LL_LINUX
+		LL_WARNS() << "Unable to create window, be sure screen is set at 32-bit color and your graphics driver is configured correctly.  See README-linux.txt for further information."
 				<< LL_ENDL;
 #else
 		LL_WARNS("Window") << "Unable to create window, be sure screen is set at 32-bit color in Control Panels->Display->Settings"
@@ -4735,10 +4851,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
 		return FALSE;
 	}
 	//check if there is enough memory for the snapshot image
-	if(LLPipeline::sMemAllocationThrottled)
-	{
-		return FALSE ; //snapshot taking is disabled due to memory restriction.
-	}
 	if(image_width * image_height > (1 << 22)) //if snapshot image is larger than 2K by 2K
 	{
 		if(!LLMemory::tryToAlloc(NULL, image_width * image_height * 3))
diff --git a/indra/newview/llvoicevivox.cpp b/indra/newview/llvoicevivox.cpp
index f9ffefd4a25f390adebde873cbfdf9378361c3c0..b0f57beff862b90e6cfa92361b03e2f748baec0e 100644
--- a/indra/newview/llvoicevivox.cpp
+++ b/indra/newview/llvoicevivox.cpp
@@ -359,7 +359,7 @@ LLVivoxVoiceClient::LLVivoxVoiceClient() :
 //	gMuteListp->addObserver(&mutelist_listener);
 
 	
-#if LL_DARWIN || LL_LINUX || LL_SOLARIS
+#if LL_DARWIN || LL_LINUX
 		// HACK: THIS DOES NOT BELONG HERE
 		// When the vivox daemon dies, the next write attempt on our socket generates a SIGPIPE, which kills us.
 		// This should cause us to ignore SIGPIPE and handle the error through proper channels.
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 2037aca7e97d5d2ba5b03e07cfde9c94e412ef95..878d7287ede083fa1b371d42f9934da2343b6a7d 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -209,14 +209,7 @@ void LLSkyTex::create()
 
 void LLSkyTex::createGLImage(S32 which)
 {	
-    if (mIsShiny)
-    {
-        mTexture[which]->setExplicitFormat(GL_RGBA8, GL_RGBA);
-    }
-    else
-    {
-        mTexture[which]->setExplicitFormat(GL_SRGB8_ALPHA8, GL_RGBA);
-    }
+	mTexture[which]->setExplicitFormat(GL_RGBA8, GL_RGBA);
 	mTexture[which]->createGLTexture(0, mImageRaw[which], 0, TRUE, LLGLTexture::LOCAL);
 	mTexture[which]->setAddressMode(LLTexUnit::TAM_CLAMP);
 }
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 2d1a882a7ee154c5937485ded90f8304751a0040..3bdb8a2981d2cda2baa65cea40cacfb5d47380cc 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -2295,11 +2295,243 @@ S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID)
 	return res;
 }
 
+bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture)
+{ //Ok, here we have confirmation about texture creation, check our wait-list
+  //and make changes, or return false
+
+	std::pair<mmap_UUID_MAP_t::iterator, mmap_UUID_MAP_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
+
+	typedef std::map<U8, LLMaterialPtr> map_te_material;
+	map_te_material new_material;
+
+	for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it)
+	{
+		LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
+
+		//here we just interesting in DIFFUSE_MAP only!
+		if(NULL != cur_material.get() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat())
+		{ //ok let's check the diffuse mode
+			switch(cur_material->getDiffuseAlphaMode())
+			{
+			case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
+			case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
+			case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
+				{ //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE
+
+					LLMaterialPtr mat = NULL;
+					map_te_material::iterator it = new_material.find(range_it->second.te);
+					if(new_material.end() == it) {
+						mat = new LLMaterial(cur_material->asLLSD());
+						new_material.insert(map_te_material::value_type(range_it->second.te, mat));
+					} else {
+						mat = it->second;
+					}
+
+					mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
+
+				} break;
+			} //switch
+		} //if
+	} //for
+
+	//setup new materials
+	for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
+	{
+		LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second);
+		LLViewerObject::setTEMaterialParams(it->first, it->second);
+	}
+
+	//clear wait-list
+	mWaitingTextureInfo.erase(range.first, range.second);
+
+	return 0 != new_material.size();
+}
+
+bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture)
+{ //Ok, here if we wait information about texture and it's missing
+  //then depending from the texture map (diffuse, normal, or specular)
+  //make changes in material and confirm it. If not return false.
+	std::pair<mmap_UUID_MAP_t::iterator, mmap_UUID_MAP_t::iterator> range = mWaitingTextureInfo.equal_range(texture->getID());
+	if(range.first == range.second) return false;
+
+	typedef std::map<U8, LLMaterialPtr> map_te_material;
+	map_te_material new_material;
+	
+	for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it)
+	{
+		LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te);
+		if (cur_material.isNull())
+			continue;
+
+		switch(range_it->second.map)
+		{
+		case LLRender::DIFFUSE_MAP:
+			{
+				if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode())
+				{ //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE
+					LLMaterialPtr mat = NULL;
+					map_te_material::iterator it = new_material.find(range_it->second.te);
+					if(new_material.end() == it) {
+						mat = new LLMaterial(cur_material->asLLSD());
+						new_material.insert(map_te_material::value_type(range_it->second.te, mat));
+					} else {
+						mat = it->second;
+					}
+
+					mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
+				}
+			} break;
+		case LLRender::NORMAL_MAP:
+			{ //missing texture => reset material texture id
+				LLMaterialPtr mat = NULL;
+				map_te_material::iterator it = new_material.find(range_it->second.te);
+				if(new_material.end() == it) {
+					mat = new LLMaterial(cur_material->asLLSD());
+					new_material.insert(map_te_material::value_type(range_it->second.te, mat));
+				} else {
+					mat = it->second;
+				}
+
+				mat->setNormalID(LLUUID::null);
+			} break;
+		case LLRender::SPECULAR_MAP:
+			{ //missing texture => reset material texture id
+				LLMaterialPtr mat = NULL;
+				map_te_material::iterator it = new_material.find(range_it->second.te);
+				if(new_material.end() == it) {
+					mat = new LLMaterial(cur_material->asLLSD());
+					new_material.insert(map_te_material::value_type(range_it->second.te, mat));
+				} else {
+					mat = it->second;
+				}
+
+				mat->setSpecularID(LLUUID::null);
+			} break;
+		case LLRender::NUM_TEXTURE_CHANNELS:
+				//nothing to do, make compiler happy
+			break;
+		} //switch
+	} //for
+
+	//setup new materials
+	for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it)
+	{
+		LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), it->second);
+		LLViewerObject::setTEMaterialParams(it->first, it->second);
+	}
+
+	//clear wait-list
+	mWaitingTextureInfo.erase(range.first, range.second);
+
+	return 0 != new_material.size();
+}
+
 S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams)
 {
-	S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams);
+	LLMaterialPtr pMaterial = const_cast<LLMaterialPtr&>(pMaterialParams);
+
+	if(pMaterialParams)
+	{ //check all of them according to material settings
+
+		LLViewerTexture *img_diffuse = getTEImage(te);
+		LLViewerTexture *img_normal = getTENormalMap(te);
+		LLViewerTexture *img_specular = getTESpecularMap(te);
+
+		llassert(NULL != img_diffuse);
+
+		LLMaterialPtr new_material = NULL;
+
+		//diffuse
+		if(NULL != img_diffuse)
+		{ //guard
+			if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset())
+			{ //ok here we don't have information about texture, let's belief and leave material settings
+			  //but we remember this case
+				mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te)));
+			}
+			else
+			{
+				bool bSetDiffuseNone = false;
+				if(img_diffuse->isMissingAsset())
+				{
+					bSetDiffuseNone = true;
+				}
+				else
+				{
+					switch(pMaterialParams->getDiffuseAlphaMode())
+					{
+					case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND:
+					case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE:
+					case LLMaterial::DIFFUSE_ALPHA_MODE_MASK:
+						{ //all of them modes available only for 32 bit textures
+							LLTextureEntry* tex_entry = getTE(te);
+							bool bIsBakedImageId = false;
+							if (tex_entry && LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(tex_entry->getID()))
+							{
+								bIsBakedImageId = true;
+							}
+							if (GL_RGBA != img_diffuse->getPrimaryFormat() && !bIsBakedImageId)
+							{
+								bSetDiffuseNone = true;
+							}
+						} break;
+					}
+				} //else
+
+
+				if(bSetDiffuseNone)
+				{ //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE
+					new_material = new LLMaterial(pMaterialParams->asLLSD());
+					new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE);
+				}
+			}
+		}
+
+		//normal
+		if(LLUUID::null != pMaterialParams->getNormalID())
+		{
+			if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID())
+			{
+				if(!new_material) {
+					new_material = new LLMaterial(pMaterialParams->asLLSD());
+				}
+				new_material->setNormalID(LLUUID::null);
+			}
+			else if(NULL == img_normal || 0 == img_normal->getPrimaryFormat())
+			{ //ok here we don't have information about texture, let's belief and leave material settings
+				//but we remember this case
+				mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getNormalID(), material_info(LLRender::NORMAL_MAP,te)));
+			}
+
+		}
+
+
+		//specular
+		if(LLUUID::null != pMaterialParams->getSpecularID())
+		{
+			if(img_specular && img_specular->isMissingAsset() && img_specular->getID() == pMaterialParams->getSpecularID())
+			{
+				if(!new_material) {
+					new_material = new LLMaterial(pMaterialParams->asLLSD());
+				}
+				new_material->setSpecularID(LLUUID::null);
+			}
+			else if(NULL == img_specular || 0 == img_specular->getPrimaryFormat())
+			{ //ok here we don't have information about texture, let's belief and leave material settings
+				//but we remember this case
+				mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getSpecularID(), material_info(LLRender::SPECULAR_MAP, te)));
+			}
+		}
+
+		if(new_material) {
+			pMaterial = new_material;
+			LLMaterialMgr::getInstance()->setLocalMaterial(getRegion()->getRegionID(), pMaterial);
+		}
+	}
+
+	S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial);
 
-	LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res
+	LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res
 							 << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast<LLVOVolume*>(this), te) ? " selected" : " not selected" )
 							 << LL_ENDL;
 	setChanged(ALL_CHANGED);
@@ -4366,7 +4598,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector4a& start, const LLVector4a&
 					LLMaterial* mat = te->getMaterialParams();
 					if (mat)
 					{
-						U8 mode = mat->getDiffuseAlphaModeRender();
+						U8 mode = mat->getDiffuseAlphaMode();
 
 						if (mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE
 							|| mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE
@@ -5012,7 +5244,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
 			}
 
 			draw_info->mAlphaMaskCutoff = mat->getAlphaMaskCutoff() * (1.f / 255.f);
-			draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaModeRender();
+			draw_info->mDiffuseAlphaMode = mat->getDiffuseAlphaMode();
 			draw_info->mNormalMap = facep->getViewerObject()->getTENormalMap(facep->getTEOffset());
 		}
 		else 
@@ -5374,7 +5606,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 
 						if (mat && LLPipeline::sRenderDeferred)
 						{
-							U8 alpha_mode = mat->getDiffuseAlphaModeRender();
+							U8 alpha_mode = mat->getDiffuseAlphaMode();
 
 							bool is_alpha = type == LLDrawPool::POOL_ALPHA &&
 								(alpha_mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND ||
@@ -5403,7 +5635,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 						else if (mat)
 						{							
 							bool is_alpha = type == LLDrawPool::POOL_ALPHA;
-							U8 mode = mat->getDiffuseAlphaModeRender();
+							U8 mode = mat->getDiffuseAlphaMode();
 							bool can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
 												mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
 							
@@ -6301,7 +6533,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 			bool can_be_shiny = true;
 			if (mat)
 			{
-				U8 mode = mat->getDiffuseAlphaModeRender();
+				U8 mode = mat->getDiffuseAlphaMode();
 				can_be_shiny = mode == LLMaterial::DIFFUSE_ALPHA_MODE_NONE ||
 								mode == LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE;
 			}
@@ -6323,7 +6555,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 				//
 				if (te->getFullbright())
 				{
-					if (mat->getDiffuseAlphaModeRender() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
+					if (mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
 					{
 						if (opaque)
 						{
@@ -6408,7 +6640,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 			}
 			else if (mat)
 			{
-				U8 mode = mat->getDiffuseAlphaModeRender();
+				U8 mode = mat->getDiffuseAlphaMode();
 
                 is_alpha = (is_alpha || (mode == LLMaterial::DIFFUSE_ALPHA_MODE_BLEND));
 
@@ -6507,7 +6739,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 				}
 				else if (fullbright || bake_sunlight)
 				{ //fullbright
-					if (mat && mat->getDiffuseAlphaModeRender() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
+					if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
 					{
 						registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT_ALPHA_MASK);
 					}
@@ -6529,7 +6761,7 @@ U32 LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace
 					else
 					{ //all around simple
 						llassert(mask & LLVertexBuffer::MAP_NORMAL);
-						if (mat && mat->getDiffuseAlphaModeRender() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
+						if (mat && mat->getDiffuseAlphaMode() == LLMaterial::DIFFUSE_ALPHA_MODE_MASK)
 						{ //material alpha mask can be respected in non-deferred
 							registerFace(group, facep, LLRenderPass::PASS_ALPHA_MASK);
 						}
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 97888ed8690043d6e2754d5e056d962135752781..ce400a34986b8c2e56e32def745e354cfefb1a9c 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -441,6 +441,26 @@ class LLVOVolume : public LLViewerObject
 	static S32 sNumLODChanges;
 
 	friend class LLVolumeImplFlexible;
+
+public:
+	bool notifyAboutCreatingTexture(LLViewerTexture *texture);
+	bool notifyAboutMissingAsset(LLViewerTexture *texture);
+
+private:
+	struct material_info 
+	{
+		LLRender::eTexIndex map;
+		U8 te;
+
+		material_info(LLRender::eTexIndex map_, U8 te_)
+			: map(map_)
+			, te(te_)
+		{}
+	};
+
+	typedef std::multimap<LLUUID, material_info> mmap_UUID_MAP_t;
+	mmap_UUID_MAP_t	mWaitingTextureInfo;
+
 };
 
 #endif // LL_LLVOVOLUME_H
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index bd667acb53f366f33aacadc30af8d192e04513dc..cd1b9c7c694c7c38cc19571c080ee08f0b127e10 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -129,6 +129,16 @@
 //
 #define MATERIALS_IN_REFLECTIONS 0
 
+// NOTE: Keep in sync with indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+// NOTE: Unused consts are commented out since some compilers (on macOS) may complain about unused variables.
+//  const S32 WATER_REFLECT_NONE_WATER_OPAQUE       = -2;
+    const S32 WATER_REFLECT_NONE_WATER_TRANSPARENT  = -1;
+    const S32 WATER_REFLECT_MINIMAL                 =  0;
+//  const S32 WATER_REFLECT_TERRAIN                 =  1;
+    const S32 WATER_REFLECT_STATIC_OBJECTS          =  2;
+    const S32 WATER_REFLECT_AVATARS                 =  3;
+    const S32 WATER_REFLECT_EVERYTHING              =  4;
+
 bool gShiftFrame = false;
 
 //cached settings
@@ -348,7 +358,6 @@ bool	LLPipeline::sRenderFrameTest = false;
 bool	LLPipeline::sRenderAttachedLights = true;
 bool	LLPipeline::sRenderAttachedParticles = true;
 bool	LLPipeline::sRenderDeferred = false;
-bool    LLPipeline::sMemAllocationThrottled = false;
 S32		LLPipeline::sVisibleLightCount = 0;
 F32		LLPipeline::sMinRenderSize = 0.f;
 bool	LLPipeline::sRenderingHUDs;
@@ -718,24 +727,6 @@ void LLPipeline::destroyGL()
 
 static LLTrace::BlockTimerStatHandle FTM_RESIZE_SCREEN_TEXTURE("Resize Screen Texture");
 
-//static
-void LLPipeline::throttleNewMemoryAllocation(bool disable)
-{
-	if(sMemAllocationThrottled != disable)
-	{
-		sMemAllocationThrottled = disable ;
-
-		if(sMemAllocationThrottled)
-		{
-			//send out notification
-			LLNotification::Params params("LowMemory");
-			LLNotifications::instance().add(params);
-
-			//release some memory.
-		}
-	}
-}
-
 void LLPipeline::requestResizeScreenTexture()
 {
     gResizeScreenTexture = TRUE;
@@ -1677,7 +1668,7 @@ U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerTexture* ima
 
 	if (alpha && mat)
 	{
-		switch (mat->getDiffuseAlphaModeRender())
+		switch (mat->getDiffuseAlphaMode())
 		{
 			case 1:
 				alpha = true; // Material's alpha mode is set to blend.  Toss it into the alpha draw pool.
@@ -9270,30 +9261,29 @@ inline float sgn(float a)
 }
 
 void LLPipeline::generateWaterReflection(LLCamera& camera_in)
-{	
-	if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
-	{
-		bool skip_avatar_update = false;
-		if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
-		{
-			skip_avatar_update = true;
-		}
-		
-        LLCamera camera = camera_in;
+{
+    if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
+    {
+        bool skip_avatar_update = false;
+        if (!isAgentAvatarValid() || gAgentCamera.getCameraAnimating() || gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK || !LLVOAvatar::sVisibleInFirstPerson)
+        {
+            skip_avatar_update = true;
+        }
 
+        LLCamera camera = camera_in;
         camera.setFar(camera_in.getFar() * 0.75f);
 
         bool camera_is_underwater = LLViewerCamera::getInstance()->cameraUnderWater();
 
-		LLPipeline::sReflectionRender = true;
-		
-		gPipeline.pushRenderTypeMask();
+        LLPipeline::sReflectionRender = true;
+
+        gPipeline.pushRenderTypeMask();
 
         glh::matrix4f saved_modelview  = get_current_modelview();
         glh::matrix4f saved_projection = get_current_projection();
-		glh::matrix4f mat;
+        glh::matrix4f mat;
 
-        S32 detail = RenderReflectionDetail;
+        S32 reflection_detail  = RenderReflectionDetail;
 
         F32 water_height      = gAgent.getRegion()->getWaterHeight(); 
         F32 camera_height     = camera_in.getOrigin().mV[VZ];
@@ -9307,32 +9297,34 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 
         camera.setOriginAndLookAt(reflect_origin, LLVector3::z_axis, reflect_interest_point);
 
-		//plane params
+        //plane params
         LLPlane plane;
-		LLVector3 pnorm;
-		S32 water_clip = 0;
+        LLVector3 pnorm;
+        S32 water_clip = 0;
         if (!camera_is_underwater)
-		{ //camera is above water, clip plane points up
-			pnorm.setVec(0,0,1);
+        {
+            //camera is above water, clip plane points up
+            pnorm.setVec(0,0,1);
             plane.setVec(pnorm, -water_height);
             water_clip = 1;
-		}
-		else
-		{	//camera is below water, clip plane points down
-			pnorm = LLVector3(0,0,-1);
+        }
+        else
+        {
+            //camera is below water, clip plane points down
+            pnorm = LLVector3(0,0,-1);
             plane.setVec(pnorm, water_height);
             water_clip = -1;
-		}
+        }
 
         S32 occlusion = LLPipeline::sUseOcclusion;
 
-			//disable occlusion culling for reflection map for now
-			LLPipeline::sUseOcclusion = 0;
+        //disable occlusion culling for reflection map for now
+        LLPipeline::sUseOcclusion = 0;
 
         if (!camera_is_underwater)
-        {   //generate planar reflection map
-
-			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0;
+        {
+            //generate planar reflection map
+            LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0;
 
             gGL.matrixMode(LLRender::MM_MODELVIEW);
             gGL.pushMatrix();
@@ -9345,9 +9337,9 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
             mReflectionModelView = mat;
 
             set_current_modelview(mat);
-			gGL.loadMatrix(mat.m);
+            gGL.loadMatrix(mat.m);
 
-			LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
+            LLViewerCamera::updateFrustumPlanes(camera, FALSE, TRUE);
 
             glh::vec3f    origin(0, 0, 0);
             glh::matrix4f inv_mat = mat.inverse();
@@ -9355,10 +9347,10 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
 
             camera.setOrigin(origin.v);
 
-			glCullFace(GL_FRONT);
+            glCullFace(GL_FRONT);
 
-			if (LLDrawPoolWater::sNeedsReflectionUpdate)
-			{
+            if (LLDrawPoolWater::sNeedsReflectionUpdate)
+            {
                 gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
                 glClearColor(0,0,0,0);
                 mWaterRef.bindTarget();
@@ -9368,106 +9360,127 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
                 gGL.setColorMask(true, false);
                 mWaterRef.getViewport(gGLViewport);
 
-				//initial sky pass (no user clip plane)
-				{ //mask out everything but the sky
-					gPipeline.pushRenderTypeMask();
-					gPipeline.andRenderTypeMask(LLPipeline::RENDER_TYPE_SKY,
-						LLPipeline::RENDER_TYPE_WL_SKY,
-						LLPipeline::RENDER_TYPE_CLOUDS,
-						LLPipeline::END_RENDER_TYPES);
+                //initial sky pass (no user clip plane)
+                //mask out everything but the sky
+                gPipeline.pushRenderTypeMask();
+                {
+                    if (reflection_detail >= WATER_REFLECT_MINIMAL)
+                    {
+                        gPipeline.andRenderTypeMask(
+                            LLPipeline::RENDER_TYPE_SKY,
+                            LLPipeline::RENDER_TYPE_WL_SKY,
+                            LLPipeline::RENDER_TYPE_CLOUDS,
+                            LLPipeline::END_RENDER_TYPES);
+                    }
+                    else
+                    {
+                        gPipeline.andRenderTypeMask(
+                            LLPipeline::RENDER_TYPE_SKY,
+                            LLPipeline::RENDER_TYPE_WL_SKY,
+                            LLPipeline::END_RENDER_TYPES);
+                    }
 
                     updateCull(camera, mSky);
                     stateSort(camera, mSky);
-						renderGeom(camera, TRUE);
-
-					gPipeline.popRenderTypeMask();
-				}
+                    renderGeom(camera, TRUE);
+                }
+                gPipeline.popRenderTypeMask();
 
-				gPipeline.pushRenderTypeMask();
+                if (reflection_detail >= WATER_REFLECT_NONE_WATER_TRANSPARENT)
+                {
+                    gPipeline.pushRenderTypeMask();
+                    {
+                        clearRenderTypeMask(
+                            LLPipeline::RENDER_TYPE_WATER,
+                            LLPipeline::RENDER_TYPE_VOIDWATER,
+                            LLPipeline::RENDER_TYPE_GROUND,
+                            LLPipeline::RENDER_TYPE_SKY,
+                            LLPipeline::RENDER_TYPE_CLOUDS,
+                            LLPipeline::END_RENDER_TYPES);
+
+                        if (reflection_detail > WATER_REFLECT_MINIMAL)
+                        { //mask out selected geometry based on reflection detail
+                            if (reflection_detail < WATER_REFLECT_EVERYTHING)
+                            {
+                                clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
+                                if (reflection_detail < WATER_REFLECT_AVATARS)
+                                {
+                                    clearRenderTypeMask(
+                                        LLPipeline::RENDER_TYPE_AVATAR,
+                                        LLPipeline::RENDER_TYPE_CONTROL_AV,
+                                        END_RENDER_TYPES);
+                                    if (reflection_detail < WATER_REFLECT_STATIC_OBJECTS)
+                                    {
+                                        clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
+                                    }
+                                }
+                            }
 
-				clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
-					LLPipeline::RENDER_TYPE_VOIDWATER,
-					LLPipeline::RENDER_TYPE_GROUND,
-					LLPipeline::RENDER_TYPE_SKY,
-					LLPipeline::RENDER_TYPE_CLOUDS,
-					LLPipeline::END_RENDER_TYPES);	
-
-				if (detail > 0)
-				{ //mask out selected geometry based on reflection detail
-					if (detail < 4)
-					{
-						clearRenderTypeMask(LLPipeline::RENDER_TYPE_PARTICLES, END_RENDER_TYPES);
-						if (detail < 3)
-						{
-                            clearRenderTypeMask(LLPipeline::RENDER_TYPE_AVATAR, LLPipeline::RENDER_TYPE_CONTROL_AV, END_RENDER_TYPES);
-							if (detail < 2)
-							{
-								clearRenderTypeMask(LLPipeline::RENDER_TYPE_VOLUME, END_RENDER_TYPES);
-							}
-						}
-					}
+                            LLGLUserClipPlane clip_plane(plane, mReflectionModelView, saved_projection);
+                            LLGLDisable cull(GL_CULL_FACE);
+                            updateCull(camera, mReflectedObjects, -water_clip, &plane);
+                            stateSort(camera, mReflectedObjects);
+                            renderGeom(camera);
+                        }
+                    }
+                    gPipeline.popRenderTypeMask();
+                }
 
-                    LLGLUserClipPlane clip_plane(plane, mReflectionModelView, saved_projection);
-					LLGLDisable cull(GL_CULL_FACE);
-                    updateCull(camera, mReflectedObjects, -water_clip, &plane);
-                    stateSort(camera, mReflectedObjects);
-							renderGeom(camera);
-						}
-                gPipeline.popRenderTypeMask();
                 mWaterRef.flush();
-				}
+            }
 
-			glCullFace(GL_BACK);
+            glCullFace(GL_BACK);
             gGL.matrixMode(LLRender::MM_MODELVIEW);
-			gGL.popMatrix();
-            
+            gGL.popMatrix();
+
             set_current_modelview(saved_modelview);
-		}
+        }
 
         //LLPipeline::sUseOcclusion = occlusion;
 
-		camera.setOrigin(camera_in.getOrigin());
-		//render distortion map
-		static bool last_update = true;
-		if (last_update)
-		{
+        camera.setOrigin(camera_in.getOrigin());
+        //render distortion map
+        static bool last_update = true;
+        if (last_update)
+        {
             gPipeline.pushRenderTypeMask();
 
-			camera.setFar(camera_in.getFar());
-			clearRenderTypeMask(LLPipeline::RENDER_TYPE_WATER,
-								LLPipeline::RENDER_TYPE_VOIDWATER,
-								LLPipeline::RENDER_TYPE_GROUND,
-								END_RENDER_TYPES);	
+            camera.setFar(camera_in.getFar());
+            clearRenderTypeMask(
+                LLPipeline::RENDER_TYPE_WATER,
+                LLPipeline::RENDER_TYPE_VOIDWATER,
+                LLPipeline::RENDER_TYPE_GROUND,
+                END_RENDER_TYPES);
 
             // intentionally inverted so that distortion map contents (objects under the water when we're above it)
             // will properly include water fog effects
             LLPipeline::sUnderWaterRender = !camera_is_underwater;
 
-			if (LLPipeline::sUnderWaterRender)
-			{
+            if (LLPipeline::sUnderWaterRender)
+            {
                 clearRenderTypeMask(
-                                    LLPipeline::RENDER_TYPE_GROUND,
-									LLPipeline::RENDER_TYPE_SKY,
-									LLPipeline::RENDER_TYPE_CLOUDS,
-									LLPipeline::RENDER_TYPE_WL_SKY,
-									END_RENDER_TYPES);		
-			}
-			LLViewerCamera::updateFrustumPlanes(camera);
+                    LLPipeline::RENDER_TYPE_GROUND,
+                    LLPipeline::RENDER_TYPE_SKY,
+                    LLPipeline::RENDER_TYPE_CLOUDS,
+                    LLPipeline::RENDER_TYPE_WL_SKY,
+                    END_RENDER_TYPES);
+            }
+            LLViewerCamera::updateFrustumPlanes(camera);
+
+            gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
 
-			gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-			
             if (LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsDistortionUpdate)
             {
                 LLPipeline::sDistortionRender = true;
 
                 LLColor3 col = LLEnvironment::instance().getCurrentWater()->getWaterFogColor();
-			glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
+                glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
+
+                LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1;
 
-			LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1;
-			
                 mWaterDis.bindTarget();
-			mWaterDis.getViewport(gGLViewport);
-			
+                mWaterDis.getViewport(gGLViewport);
+
                 gGL.setColorMask(true, true);
                 mWaterDis.clear();
                 gGL.setColorMask(true, false);
@@ -9479,66 +9492,69 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
                 LLPlane plane(-pnorm, water_dist);
                 LLGLUserClipPlane clip_plane(plane, saved_modelview, saved_projection);
 
-				gGL.setColorMask(true, true);
-				mWaterDis.clear();
-				gGL.setColorMask(true, false);
+                gGL.setColorMask(true, true);
+                mWaterDis.clear();
+                gGL.setColorMask(true, false);
 
                 // ignore clip plane if we're underwater and viewing distortion map of objects above waterline
                 if (camera_is_underwater)
-				{
+                {
                     clip_plane.disable();
-				}
+                }
 
-                updateCull(camera, mRefractedObjects, water_clip, &plane);
-                stateSort(camera, mRefractedObjects);
-					renderGeom(camera);
+                if (reflection_detail >= WATER_REFLECT_NONE_WATER_TRANSPARENT)
+                {
+                    updateCull(camera, mRefractedObjects, water_clip, &plane);
+                    stateSort(camera, mRefractedObjects);
+                    renderGeom(camera);
+                }
 
-					if (LLGLSLShader::sNoFixedFunction)
-					{
-						gUIProgram.bind();
-					}
-					
-					LLWorld::getInstance()->renderPropertyLines();
-					
-					if (LLGLSLShader::sNoFixedFunction)
-					{
-						gUIProgram.unbind();
-					}
+                if (LLGLSLShader::sNoFixedFunction)
+                {
+                    gUIProgram.bind();
+                }
+
+                LLWorld::getInstance()->renderPropertyLines();
+
+                if (LLGLSLShader::sNoFixedFunction)
+                {
+                    gUIProgram.unbind();
+                }
 
                 mWaterDis.flush();
-			}
+            }
 
             LLPipeline::sDistortionRender = false;
-			
+
             gPipeline.popRenderTypeMask();
-		}
-		last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
+        }
+        last_update = LLDrawPoolWater::sNeedsReflectionUpdate && LLDrawPoolWater::sNeedsDistortionUpdate;
 
         gPipeline.popRenderTypeMask();
 
         LLPipeline::sUseOcclusion     = occlusion;
         LLPipeline::sUnderWaterRender = false;
-		LLPipeline::sReflectionRender = false;
+        LLPipeline::sReflectionRender = false;
 
         LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
         LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
 
-		if (!LLRenderTarget::sUseFBO)
-		{
-			glClear(GL_DEPTH_BUFFER_BIT);
-		}
-		glClearColor(0.f, 0.f, 0.f, 0.f);
-		gViewerWindow->setup3DViewport();
-		
-		LLGLState::checkStates();
+        if (!LLRenderTarget::sUseFBO)
+        {
+            glClear(GL_DEPTH_BUFFER_BIT);
+        }
+        glClearColor(0.f, 0.f, 0.f, 0.f);
+        gViewerWindow->setup3DViewport();
 
-		if (!skip_avatar_update)
-		{
-			gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
-		}
+        LLGLState::checkStates();
 
-		LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-	}
+        if (!skip_avatar_update)
+        {
+            gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode());
+        }
+
+        LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
+    }
 }
 
 glh::matrix4f look(const LLVector3 pos, const LLVector3 dir, const LLVector3 up)
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index 52fd51cd80d9375a7efa6d3bd8275f662c7d03a4..0eaa6b141d8b51d3fe68123ad6362776133c8757 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -414,10 +414,6 @@ class LLPipeline
 	static void updateRenderDeferred();
 	static void refreshCachedSettings();
 
-	static void throttleNewMemoryAllocation(bool disable);
-
-	
-
 	void addDebugBlip(const LLVector3& position, const LLColor4& color);
 
 	void hidePermanentObjects( std::vector<U32>& restoreList );
@@ -600,7 +596,6 @@ class LLPipeline
 	static bool				sRenderAttachedLights;
 	static bool				sRenderAttachedParticles;
 	static bool				sRenderDeferred;
-	static bool             sMemAllocationThrottled;
 	static S32				sVisibleLightCount;
 	static F32				sMinRenderSize;
 	static bool				sRenderingHUDs;
diff --git a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
index e282f1b179c10935c715565147af7fa0d5aa77d9..3cc99b28c933af98a8ac012af6fb9534f2898779 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences_graphics_advanced.xml
@@ -723,6 +723,14 @@
     top_delta="0"
     name="Reflections"
     width="150">
+      <combo_box.item
+        label="None; opaque"
+        name="0"
+        value="-2"/>
+      <combo_box.item
+        label="None; transparent"
+        name="0"
+        value="-1"/>
       <combo_box.item
         label="Minimal"
         name="0"
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 4a47ccf23b6d572b2e5321e83781030ec20633bc..4a02b576c2f2c0fe974ca4d79912586e3543a685 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -9624,6 +9624,12 @@ You do not appear to have the proper hardware requirements for [APP_NAME]. [APP_
 If you continue to have problems, please visit the [SUPPORT_SITE].
   </global>
 
+  <global name="UnsupportedIntelDriver">
+The installed Intel graphics driver for [GPUNAME], version [VERSION], is significantly out of date and is known to cause excessive rates of program crashes. You are strongly advised to update to a current Intel driver
+
+Do you want to check the Intel driver website?
+  </global>
+
   <global name="UnsupportedCPUAmount">
 796
   </global>