diff --git a/etc/message.xml b/etc/message.xml
index 847f483aa..04cdbc8f2 100644
--- a/etc/message.xml
+++ b/etc/message.xml
@@ -673,9 +673,6 @@
FetchInventoryDescendents
false
- WebFetchInventoryDescendents
- true
-
FetchInventory
true
diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake
index 2bddb9517..eaa8a6dc2 100644
--- a/indra/cmake/Linking.cmake
+++ b/indra/cmake/Linking.cmake
@@ -42,6 +42,7 @@ if (WINDOWS)
wldap32
gdi32
user32
+ dbghelp
)
else (WINDOWS)
set(WINDOWS_LIBRARIES "")
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt
index dbd1f092d..47cddfdba 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -63,6 +63,7 @@ set(llcommon_SOURCE_FILES
llsdutil.cpp
llsecondlifeurls.cpp
llstat.cpp
+ llstacktrace.cpp
llstreamtools.cpp
llstring.cpp
llstringtable.cpp
@@ -92,12 +93,12 @@ set(llcommon_HEADER_FILES
linden_common.h
linked_lists.h
llagentconstants.h
+ llavatarname.h
llapp.h
llapr.h
llassettype.h
llassoclist.h
llavatarconstants.h
- llavatarname.h
llbase32.h
llbase64.h
llboost.h
@@ -173,6 +174,7 @@ set(llcommon_HEADER_FILES
llskiplist.h
llskipmap.h
llstack.h
+ llstacktrace.h
llstat.h
llstatenums.h
llstl.h
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp
index b747b6ee1..d3783c582 100644
--- a/indra/llcommon/llfasttimer.cpp
+++ b/indra/llcommon/llfasttimer.cpp
@@ -33,13 +33,18 @@
#include "llfasttimer.h"
+#include "llmemory.h"
#include "llprocessor.h"
#if LL_WINDOWS
+#define WIN32_LEAN_AND_MEAN
+#include
+#include "lltimer.h"
#elif LL_LINUX || LL_SOLARIS
#include
#include
+#include "lltimer.h"
#elif LL_DARWIN
#include
#include "lltimer.h" // get_clock_count()
@@ -65,7 +70,7 @@ S32 LLFastTimer::sLastFrameIndex = -1;
int LLFastTimer::sPauseHistory = 0;
int LLFastTimer::sResetHistory = 0;
-F64 LLFastTimer::sCPUClockFrequency = 0.0;
+#define USE_RDTSC 0
#if LL_LINUX || LL_SOLARIS
U64 LLFastTimer::sClockResolution = 1000000000; // 1e9, Nanosecond resolution
@@ -73,81 +78,34 @@ U64 LLFastTimer::sClockResolution = 1000000000; // 1e9, Nanosecond resolution
U64 LLFastTimer::sClockResolution = 1000000; // 1e6, Microsecond resolution
#endif
-//////////////////////////////////////////////////////////////////////////////
-
-//
-// CPU clock/other clock frequency and count functions
-//
-
-#if LL_WINDOWS
-
-U64 get_cpu_clock_count()
-{ U32 hi,lo;
-
- __asm
- {
- _emit 0x0f
- _emit 0x31
- mov lo,eax
- mov hi,edx
- }
-
- U64 ret = hi;
- ret *= 4294967296L;
- ret |= lo;
- return ret;
-};
-
-#endif // LL_WINDOWS
-
-#if LL_LINUX || LL_SOLARIS
-// Try to use the MONOTONIC clock if available, this is a constant time counter
-// with nanosecond resolution (but not necessarily accuracy) and attempts are made
-// to synchronize this value between cores at kernel start. It should not be affected
-// by CPU frequency. If not available use the REALTIME clock, but this may be affected by
-// NTP adjustments or other user activity affecting the system time.
-U64 get_cpu_clock_count()
-{
- struct timespec tp;
-
-#ifdef CLOCK_MONOTONIC
- clock_gettime(CLOCK_MONOTONIC,&tp);
-#else
- clock_gettime(CLOCK_REALTIME,&tp);
-#endif
- return (tp.tv_sec*LLFastTimer::sClockResolution)+tp.tv_nsec;
-}
-#endif // (LL_LINUX || LL_SOLARIS))
-
-#if LL_DARWIN
-//
-// Mac implementation of CPU clock
-//
-// Just use gettimeofday implementation for now
-
-U64 get_cpu_clock_count()
-{
- return get_clock_count();
-}
-#endif
-
-//////////////////////////////////////////////////////////////////////////////
//static
-#if LL_DARWIN || LL_LINUX || LL_SOLARIS
-U64 LLFastTimer::countsPerSecond()
+#if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
+U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
{
- return sClockResolution;
+ return sClockResolution >> 8;
}
-#else
-U64 LLFastTimer::countsPerSecond()
+#else // windows or x86-mac or x86-linux or x86-solaris
+U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer
{
- if (!sCPUClockFrequency)
+#if USE_RDTSC || !LL_WINDOWS
+ //getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz
+ static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0);
+
+ // we drop the low-order byte in our timers, so report a lower frequency
+#else
+ // If we're not using RDTSC, each fasttimer tick is just a performance counter tick.
+ // Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency())
+ // since that would change displayed MHz stats for CPUs
+ static bool firstcall = true;
+ static U64 sCPUClockFrequency;
+ if (firstcall)
{
- CProcessor proc;
- sCPUClockFrequency = proc.GetCPUFrequency(50);
+ QueryPerformanceFrequency((LARGE_INTEGER*)&sCPUClockFrequency);
+ firstcall = false;
}
- return U64(sCPUClockFrequency);
+#endif
+ return sCPUClockFrequency >> 8;
}
#endif
@@ -200,3 +158,143 @@ void LLFastTimer::reset()
}
//////////////////////////////////////////////////////////////////////////////
+//
+// Important note: These implementations must be FAST!
+//
+
+
+#if LL_WINDOWS
+//
+// Windows implementation of CPU clock
+//
+
+//
+// NOTE: put back in when we aren't using platform sdk anymore
+//
+// because MS has different signatures for these functions in winnt.h
+// need to rename them to avoid conflicts
+//#define _interlockedbittestandset _renamed_interlockedbittestandset
+//#define _interlockedbittestandreset _renamed_interlockedbittestandreset
+//#include
+//#undef _interlockedbittestandset
+//#undef _interlockedbittestandreset
+
+//inline U32 LLFastTimer::getCPUClockCount32()
+//{
+// U64 time_stamp = __rdtsc();
+// return (U32)(time_stamp >> 8);
+//}
+//
+//// return full timer value, *not* shifted by 8 bits
+//inline U64 LLFastTimer::getCPUClockCount64()
+//{
+// return __rdtsc();
+//}
+
+// shift off lower 8 bits for lower resolution but longer term timing
+// on 1Ghz machine, a 32-bit word will hold ~1000 seconds of timing
+#if USE_RDTSC
+U32 LLFastTimer::getCPUClockCount32()
+{
+ U32 ret_val;
+ __asm
+ {
+ _emit 0x0f
+ _emit 0x31
+ shr eax,8
+ shl edx,24
+ or eax, edx
+ mov dword ptr [ret_val], eax
+ }
+ return ret_val;
+}
+
+// return full timer value, *not* shifted by 8 bits
+U64 LLFastTimer::getCPUClockCount64()
+{
+ U64 ret_val;
+ __asm
+ {
+ _emit 0x0f
+ _emit 0x31
+ mov eax,eax
+ mov edx,edx
+ mov dword ptr [ret_val+4], edx
+ mov dword ptr [ret_val], eax
+ }
+ return ret_val;
+}
+
+std::string LLFastTimer::sClockType = "rdtsc";
+
+#else
+//LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp
+// These use QueryPerformanceCounter, which is arguably fine and also works on amd architectures.
+U32 LLFastTimer::getCPUClockCount32()
+{
+ return (U32)(get_clock_count()>>8);
+}
+
+U64 LLFastTimer::getCPUClockCount64()
+{
+ return get_clock_count();
+}
+
+std::string LLFastTimer::sClockType = "QueryPerformanceCounter";
+#endif
+
+#endif
+
+
+#if (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
+//
+// Linux and Solaris 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
+// with nanosecond resolution (but not necessarily accuracy) and attempts are
+// made to synchronize this value between cores at kernel start. It should not
+// be affected by CPU frequency. If not available use the REALTIME clock, but
+// this may be affected by NTP adjustments or other user activity affecting
+// the system time.
+U64 LLFastTimer::getCPUClockCount64()
+{
+ struct timespec tp;
+
+#ifdef CLOCK_MONOTONIC // MONOTONIC supported at build-time?
+ if (-1 == clock_gettime(CLOCK_MONOTONIC,&tp)) // if MONOTONIC isn't supported at runtime then ouch, try REALTIME
+#endif
+ clock_gettime(CLOCK_REALTIME,&tp);
+
+ return (tp.tv_sec*LLFastTimer::sClockResolution)+tp.tv_nsec;
+}
+
+U32 LLFastTimer::getCPUClockCount32()
+{
+ return (U32)(LLFastTimer::getCPUClockCount64() >> 8);
+}
+
+std::string LLFastTimer::sClockType = "clock_gettime";
+
+#endif // (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))
+
+
+#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
+//
+// Mac+Linux+Solaris FAST x86 implementation of CPU clock
+U32 LLFastTimer::getCPUClockCount32()
+{
+ U64 x;
+ __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+ return (U32)(x >> 8);
+}
+
+U64 LLFastTimer::getCPUClockCount64()
+{
+ U64 x;
+ __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+ return x;
+}
+
+std::string LLFastTimer::sClockType = "rdtsc";
+#endif
\ No newline at end of file
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index 5cb654a46..c1fea04b3 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -35,7 +35,6 @@
#define FAST_TIMER_ON 1
-LL_COMMON_API U64 get_cpu_clock_count();
class LL_COMMON_API LLFastTimer
{
@@ -107,7 +106,23 @@ public:
FTM_RENDER_BLOOM,
FTM_RENDER_BLOOM_FBO,
FTM_RENDER_FONTS,
-
+
+ // deferred rendering
+ FTM_RENDER_DEFERRED,
+ FTM_BIND_DEFERRED,
+ FTM_SUN_SHADOW,
+ FTM_SOFTEN_SHADOW,
+ FTM_EDGE_DETECTION,
+ FTM_GI_TRACE,
+ FTM_GI_GATHER,
+ FTM_ATMOSPHERICS,
+ FTM_LOCAL_LIGHTS,
+ FTM_FULLSCREEN_LIGHTS,
+ FTM_PROJECTORS,
+ FTM_POST,
+
+ FTM_VISIBLE_CLOUD,
+
// newview specific
FTM_MESSAGES,
FTM_MOUSEHANDLER,
@@ -211,7 +226,7 @@ public:
//gTimerBins[gCurTimerBin]++;
//LLTimer::sNumTimerCalls++;
- U64 cpu_clocks = get_cpu_clock_count();
+ U64 cpu_clocks = getCPUClockCount64();
sStart[sCurDepth] = cpu_clocks;
sCurDepth++;
@@ -226,7 +241,7 @@ public:
// These don't get counted, because they use CPU clockticks
//gTimerBins[gCurTimerBin]++;
//LLTimer::sNumTimerCalls++;
- end = get_cpu_clock_count();
+ end = getCPUClockCount64();
sCurDepth--;
delta = end - sStart[sCurDepth];
@@ -241,6 +256,7 @@ public:
static void reset();
static U64 countsPerSecond();
+ static std::string sClockType;
public:
static int sCurDepth;
static U64 sStart[FTM_MAX_DEPTH];
@@ -250,14 +266,17 @@ public:
static U64 sCallAverage[FTM_NUM_TYPES];
static U64 sCountHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES];
static U64 sCallHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES];
- static S32 sCurFrameIndex;
- static S32 sLastFrameIndex;
+
static int sPauseHistory;
static int sResetHistory;
- static F64 sCPUClockFrequency;
- static U64 sClockResolution;
-private:
+ static U32 getCPUClockCount32();
+ static U64 getCPUClockCount64();
+
+ static U64 sClockResolution;
+ static S32 sCurFrameIndex;
+ static S32 sLastFrameIndex;
+
EFastTimerType mType;
};
diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp
index 88c49a10c..f255e5a8b 100644
--- a/indra/llcommon/llprocessor.cpp
+++ b/indra/llcommon/llprocessor.cpp
@@ -30,49 +30,351 @@
* $/LicenseInfo$
*/
-// Filename: Processor.cpp
-// =======================
-// Author: Benjamin Jurke
-// File history: 27.02.2002 - File created. Support for Intel and AMD processors
-// 05.03.2002 - Fixed the CPUID bug: On Pre-Pentium CPUs the CPUID
-// command is not available
-// - The CProcessor::WriteInfoTextFile function do not
-// longer use Win32 file functions (-> os independend)
-// - Optional include of the windows.h header which is
-// still need for CProcessor::GetCPUFrequency.
-// 06.03.2002 - My birthday (18th :-))
-// - Replaced the '\r\n' line endings in function
-// CProcessor::CPUInfoToText by '\n'
-// - Replaced unsigned __int64 by signed __int64 for
-// solving some compiler conversion problems
-// - Fixed a bug at family=6, model=6 (Celeron -> P2)
-//////////////////////////////////////////////////////////////////////////////////
#include "linden_common.h"
#include "llprocessor.h"
-#include
+#include "llerror.h"
+
+//#include
#if LL_WINDOWS
# define WIN32_LEAN_AND_MEAN
# include
# include
+# define _interlockedbittestandset _renamed_interlockedbittestandset
+# define _interlockedbittestandreset _renamed_interlockedbittestandreset
+# include
+# undef _interlockedbittestandset
+# undef _interlockedbittestandreset
#endif
-#if !LL_DARWIN && !LL_SOLARIS
+#include "llsd.h"
-#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
-// We need the QueryPerformanceCounter and Sleep functions
-#define FORCEINLINE __forceinline
-#else
-#define FORCEINLINE
+#if LL_MSVC && _M_X64
+# define LL_X86_64 1
+# define LL_X86 1
+#elif LL_MSVC && _M_IX86
+# define LL_X86 1
+#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) )
+# define LL_X86_64 1
+# define LL_X86 1
+#elif LL_GNUC && ( defined(__i386__) )
+# define LL_X86 1
+#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) )
+# define LL_PPC 1
#endif
+class LLProcessorInfoImpl; // foward declaration for the mImpl;
-// Some macros we often need
-////////////////////////////
-#define CheckBit(var, bit) ((var & (1 << bit)) ? true : false)
+namespace
+{
+ enum cpu_info
+ {
+ eBrandName = 0,
+ eFrequency,
+ eVendor,
+ eStepping,
+ eFamily,
+ eExtendedFamily,
+ eModel,
+ eExtendedModel,
+ eType,
+ eBrandID,
+ eFamilyName
+ };
+
+
+ const char* cpu_info_names[] =
+ {
+ "Processor Name",
+ "Frequency",
+ "Vendor",
+ "Stepping",
+ "Family",
+ "Extended Family",
+ "Model",
+ "Extended Model",
+ "Type",
+ "Brand ID",
+ "Family Name"
+ };
+
+ enum cpu_config
+ {
+ eMaxID,
+ eMaxExtID,
+ eCLFLUSHCacheLineSize,
+ eAPICPhysicalID,
+ eCacheLineSize,
+ eL2Associativity,
+ eCacheSizeK,
+ eFeatureBits,
+ eExtFeatureBits
+ };
+
+ const char* cpu_config_names[] =
+ {
+ "Max Supported CPUID level",
+ "Max Supported Ext. CPUID level",
+ "CLFLUSH cache line size",
+ "APIC Physical ID",
+ "Cache Line Size",
+ "L2 Associativity",
+ "Cache Size",
+ "Feature Bits",
+ "Ext. Feature Bits"
+ };
+
+
+
+ // *NOTE:Mani - this contains the elements we reference directly and extensions beyond the first 32.
+ // The rest of the names are referenced by bit maks returned from cpuid.
+ enum cpu_features
+ {
+ eSSE_Ext=25,
+ eSSE2_Ext=26,
+
+ eSSE3_Features=32,
+ eMONTIOR_MWAIT=33,
+ eCPLDebugStore=34,
+ eThermalMonitor2=35,
+ eAltivec=36
+ };
+
+ const char* cpu_feature_names[] =
+ {
+ "x87 FPU On Chip",
+ "Virtual-8086 Mode Enhancement",
+ "Debugging Extensions",
+ "Page Size Extensions",
+ "Time Stamp Counter",
+ "RDMSR and WRMSR Support",
+ "Physical Address Extensions",
+ "Machine Check Exception",
+ "CMPXCHG8B Instruction",
+ "APIC On Chip",
+ "Unknown1",
+ "SYSENTER and SYSEXIT",
+ "Memory Type Range Registers",
+ "PTE Global Bit",
+ "Machine Check Architecture",
+ "Conditional Move/Compare Instruction",
+ "Page Attribute Table",
+ "Page Size Extension",
+ "Processor Serial Number",
+ "CFLUSH Extension",
+ "Unknown2",
+ "Debug Store",
+ "Thermal Monitor and Clock Ctrl",
+ "MMX Technology",
+ "FXSAVE/FXRSTOR",
+ "SSE Extensions",
+ "SSE2 Extensions",
+ "Self Snoop",
+ "Hyper-threading Technology",
+ "Thermal Monitor",
+ "Unknown4",
+ "Pend. Brk. EN.", // 31 End of FeatureInfo bits
+
+ "SSE3 New Instructions", // 32
+ "MONITOR/MWAIT",
+ "CPL Qualified Debug Store",
+ "Thermal Monitor 2",
+
+ "Altivec"
+ };
+
+ std::string intel_CPUFamilyName(int composed_family)
+ {
+ switch(composed_family)
+ {
+ case 3: return "Intel i386";
+ case 4: return "Intel i486";
+ case 5: return "Intel Pentium";
+ case 6: return "Intel Pentium Pro/2/3, Core";
+ case 7: return "Intel Itanium (IA-64)";
+ case 0xF: return "Intel Pentium 4";
+ case 0x10: return "Intel Itanium 2 (IA-64)";
+ }
+ return "Unknown";
+ }
+
+ std::string amd_CPUFamilyName(int composed_family)
+ {
+ switch(composed_family)
+ {
+ case 4: return "AMD 80486/5x86";
+ case 5: return "AMD K5/K6";
+ case 6: return "AMD K7";
+ case 0xF: return "AMD K8";
+ case 0x10: return "AMD K8L";
+ }
+ return "Unknown";
+ }
+
+ std::string compute_CPUFamilyName(const char* cpu_vendor, int composed_family)
+ {
+ const char* intel_string = "GenuineIntel";
+ const char* amd_string = "AuthenticAMD";
+ if(!strncmp(cpu_vendor, intel_string, strlen(intel_string)))
+ {
+ return intel_CPUFamilyName(composed_family);
+ }
+ else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string)))
+ {
+ return amd_CPUFamilyName(composed_family);
+ }
+ return "Unknown";
+ }
+
+ std::string compute_CPUFamilyName(const char* cpu_vendor, int family, int ext_family)
+ {
+ const char* intel_string = "GenuineIntel";
+ const char* amd_string = "AuthenticAMD";
+ if(!strncmp(cpu_vendor, intel_string, strlen(intel_string)))
+ {
+ U32 composed_family = family + ext_family;
+ return intel_CPUFamilyName(composed_family);
+ }
+ else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string)))
+ {
+ U32 composed_family = (family == 0xF)
+ ? family + ext_family
+ : family;
+ return amd_CPUFamilyName(composed_family);
+ }
+ return "Unknown";
+ }
+
+} // end unnamed namespace
+
+// The base class for implementations.
+// Each platform should override this class.
+class LLProcessorInfoImpl
+{
+public:
+ LLProcessorInfoImpl()
+ {
+ mProcessorInfo["info"] = LLSD::emptyMap();
+ mProcessorInfo["config"] = LLSD::emptyMap();
+ mProcessorInfo["extension"] = LLSD::emptyMap();
+ }
+ virtual ~LLProcessorInfoImpl() {}
+
+ F64 getCPUFrequency() const
+ {
+ return getInfo(eFrequency, 0).asReal();
+ }
+
+ bool hasSSE() const
+ {
+ return hasExtension(cpu_feature_names[eSSE_Ext]);
+ }
+
+ bool hasSSE2() const
+ {
+ return hasExtension(cpu_feature_names[eSSE2_Ext]);
+ }
+
+ bool hasAltivec() const
+ {
+ return hasExtension("Altivec");
+ }
+
+ std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unknown").asString(); }
+ std::string getCPUBrandName() const { return getInfo(eBrandName, "Unknown").asString(); }
+
+ // This is virtual to support a different linux format.
+ // *NOTE:Mani - I didn't want to screw up server use of this data...
+ virtual std::string getCPUFeatureDescription() const
+ {
+ std::ostringstream out;
+ out << std::endl << std::endl;
+ out << "// CPU General Information" << std::endl;
+ out << "//////////////////////////" << std::endl;
+ out << "Processor Name: " << getCPUBrandName() << std::endl;
+ out << "Frequency: " << getCPUFrequency() << " MHz" << std::endl;
+ out << "Vendor: " << getInfo(eVendor, "Unknown").asString() << std::endl;
+ out << "Family: " << getCPUFamilyName() << " (" << getInfo(eFamily, 0) << ")" << std::endl;
+ out << "Extended family: " << getInfo(eExtendedFamily, 0) << std::endl;
+ out << "Model: " << getInfo(eModel, 0) << std::endl;
+ out << "Extended model: " << getInfo(eExtendedModel, 0) << std::endl;
+ out << "Type: " << getInfo(eType, 0) << std::endl;
+ out << "Brand ID: " << getInfo(eBrandID, 0) << std::endl;
+ out << std::endl;
+ out << "// CPU Configuration" << std::endl;
+ out << "//////////////////////////" << std::endl;
+
+ // Iterate through the dictionary of configuration options.
+ LLSD configs = mProcessorInfo["config"];
+ for(LLSD::map_const_iterator cfgItr = configs.beginMap(); cfgItr != configs.endMap(); ++cfgItr)
+ {
+ out << cfgItr->first << " = " << cfgItr->second << std::endl;
+ }
+ out << std::endl;
+
+ out << "// CPU Extensions" << std::endl;
+ out << "//////////////////////////" << std::endl;
+
+ for(LLSD::map_const_iterator itr = mProcessorInfo["extension"].beginMap(); itr != mProcessorInfo["extension"].endMap(); ++itr)
+ {
+ out << " " << itr->first << std::endl;
+ }
+ return out.str();
+ }
+
+protected:
+ void setInfo(cpu_info info_type, const LLSD& value)
+ {
+ setInfo(cpu_info_names[info_type], value);
+ }
+ LLSD getInfo(cpu_info info_type, const LLSD& defaultVal) const
+ {
+ return getInfo(cpu_info_names[info_type], defaultVal);
+ }
+
+ void setConfig(cpu_config config_type, const LLSD& value)
+ {
+ setConfig(cpu_config_names[config_type], value);
+ }
+ LLSD getConfig(cpu_config config_type, const LLSD& defaultVal) const
+ {
+ return getConfig(cpu_config_names[config_type], defaultVal);
+ }
+
+ void setExtension(const std::string& name) { mProcessorInfo["extension"][name] = "true"; }
+ bool hasExtension(const std::string& name) const
+ {
+ return mProcessorInfo["extension"].has(name);
+ }
+
+private:
+ void setInfo(const std::string& name, const LLSD& value) { mProcessorInfo["info"][name]=value; }
+ LLSD getInfo(const std::string& name, const LLSD& defaultVal) const
+ {
+ if(mProcessorInfo["info"].has(name))
+ {
+ return mProcessorInfo["info"][name];
+ }
+ return defaultVal;
+ }
+ void setConfig(const std::string& name, const LLSD& value) { mProcessorInfo["config"][name]=value; }
+ LLSD getConfig(const std::string& name, const LLSD& defaultVal) const
+ {
+ LLSD r = mProcessorInfo["config"].get(name);
+ return r.isDefined() ? r : defaultVal;
+ }
+
+private:
+
+ LLSD mProcessorInfo;
+};
+
+
+#ifdef LL_MSVC
+// LL_MSVC and not LLWINDOWS because some of the following code
+// uses the MSVC compiler intrinsics __cpuid() and __rdtsc().
-#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
// Delays for the specified amount of milliseconds
static void _Delay(unsigned int ms)
{
@@ -95,63 +397,22 @@ static void _Delay(unsigned int ms)
}while(c2.QuadPart-c1.QuadPart < x);
// Loop while (second-first < x)
}
-#endif
-// CProcessor::CProcessor
-// ======================
-// Class constructor:
-/////////////////////////
-CProcessor::CProcessor()
+static F64 calculate_cpu_frequency(U32 measure_msecs)
{
- uqwFrequency = 0;
- strCPUName[0] = 0;
- memset(&CPUInfo, 0, sizeof(CPUInfo));
-}
-
-// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
-// =========================================================================
-// Function to measure the current CPU frequency
-////////////////////////////////////////////////////////////////////////////
-F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
-{
-#ifndef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
- return 0;
-#else
- // If there are invalid measure time parameters, zero msecs for example,
- // we've to exit the function
- if (uiMeasureMSecs < 1)
+ if(measure_msecs == 0)
{
- // If theres already a measured frequency available, we return it
- if (uqwFrequency > 0)
- return uqwFrequency;
- else
- return 0;
- }
-
- // Now we check if the CPUID command is available
- if (!CheckCPUIDPresence())
return 0;
-
- // First we get the CPUID standard level 0x00000001
- unsigned long reg;
- __asm
- {
- mov eax, 1
- cpuid
- mov reg, edx
}
- // Then we check, if the RDTSC (Real Date Time Stamp Counter) is available.
- // This function is necessary for our measure process.
- if (!(reg & (1 << 4)))
- return 0;
-
// After that we declare some vars and check the frequency of the high
// resolution timer for the measure process.
- // If there's no high-res timer, we exit.
- __int64 starttime, endtime, timedif, freq, start, end, dif;
+ // If there"s no high-res timer, we exit.
+ unsigned __int64 starttime, endtime, timedif, freq, start, end, dif;
if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq))
+ {
return 0;
+ }
// Now we can init the measure process. We set the process and thread priority
// to the highest available level (Realtime priority). Also we focus the
@@ -167,35 +428,27 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);
SetProcessAffinityMask(hProcess, dwNewMask);
- // Now we call a CPUID to ensure, that all other prior called functions are
- // completed now (serialization)
- __asm cpuid
+ //// Now we call a CPUID to ensure, that all other prior called functions are
+ //// completed now (serialization)
+ //__asm cpuid
+ int cpu_info[4] = {-1};
+ __cpuid(cpu_info, 0);
// We ask the high-res timer for the start time
QueryPerformanceCounter((LARGE_INTEGER *) &starttime);
// Then we get the current cpu clock and store it
- __asm
- {
- rdtsc
- mov dword ptr [start+4], edx
- mov dword ptr [start], eax
- }
+ start = __rdtsc();
// Now we wart for some msecs
- _Delay(uiMeasureMSecs);
-// Sleep(uiMeasureMSecs);
+ _Delay(measure_msecs);
+ // Sleep(uiMeasureMSecs);
// We ask for the end time
QueryPerformanceCounter((LARGE_INTEGER *) &endtime);
// And also for the end cpu clock
- __asm
- {
- rdtsc
- mov dword ptr [end+4], edx
- mov dword ptr [end], eax
- }
+ end = __rdtsc();
// Now we can restore the default process and thread priorities
SetProcessAffinityMask(hProcess, dwProcessMask);
@@ -208,2074 +461,433 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
// And finally the frequency is the clock difference divided by the time
// difference.
- uqwFrequency = (F64)dif / (((F64)timedif) / freq);
+ F64 frequency = (F64)dif / (((F64)timedif) / freq);
// At last we just return the frequency that is also stored in the call
- // member var uqwFrequency
- return uqwFrequency;
-#endif
+ // member var uqwFrequency - converted to MHz
+ return frequency / (F64)1000000;
}
-// bool CProcessor::AnalyzeIntelProcessor()
-// ========================================
-// Private class function for analyzing an Intel processor
-//////////////////////////////////////////////////////////
-bool CProcessor::AnalyzeIntelProcessor()
+// Windows implementation
+class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl
{
-#if LL_WINDOWS
- unsigned long eaxreg, ebxreg, edxreg;
-
- // First we check if the CPUID command is available
- if (!CheckCPUIDPresence())
- return false;
-
- // Now we get the CPUID standard level 0x00000001
- __asm
+public:
+ LLProcessorInfoWindowsImpl()
{
- mov eax, 1
- cpuid
- mov eaxreg, eax
- mov ebxreg, ebx
- mov edxreg, edx
+ getCPUIDInfo();
+ setInfo(eFrequency, calculate_cpu_frequency(50));
}
-
- // Then get the cpu model, family, type, stepping and brand id by masking
- // the eax and ebx register
- CPUInfo.uiStepping = eaxreg & 0xF;
- CPUInfo.uiModel = (eaxreg >> 4) & 0xF;
- CPUInfo.uiFamily = (eaxreg >> 8) & 0xF;
- CPUInfo.uiType = (eaxreg >> 12) & 0x3;
- CPUInfo.uiBrandID = ebxreg & 0xF;
- static const char* INTEL_BRAND[] =
+private:
+ void getCPUIDInfo()
{
- /* 0x00 */ "",
- /* 0x01 */ "0.18 micron Intel Celeron",
- /* 0x02 */ "0.18 micron Intel Pentium III",
- /* 0x03 */ "0.13 micron Intel Celeron",
- /* 0x04 */ "0.13 micron Intel Pentium III",
- /* 0x05 */ "",
- /* 0x06 */ "0.13 micron Intel Pentium III Mobile",
- /* 0x07 */ "0.13 micron Intel Celeron Mobile",
- /* 0x08 */ "0.18 micron Intel Pentium 4",
- /* 0x09 */ "0.13 micron Intel Pentium 4",
- /* 0x0A */ "0.13 micron Intel Celeron",
- /* 0x0B */ "0.13 micron Intel Pentium 4 Xeon",
- /* 0x0C */ "Intel Xeon MP",
- /* 0x0D */ "",
- /* 0x0E */ "0.18 micron Intel Pentium 4 Xeon",
- /* 0x0F */ "Mobile Intel Celeron",
- /* 0x10 */ "",
- /* 0x11 */ "Mobile Genuine Intel",
- /* 0x12 */ "Intel Celeron M",
- /* 0x13 */ "Mobile Intel Celeron",
- /* 0x14 */ "Intel Celeron",
- /* 0x15 */ "Mobile Genuine Intel",
- /* 0x16 */ "Intel Pentium M",
- /* 0x17 */ "Mobile Intel Celeron",
- };
+ // http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx
- // Only override the brand if we have it in the lookup table. We should
- // already have a string here from GetCPUInfo(). JC
- if ( CPUInfo.uiBrandID < LL_ARRAY_SIZE(INTEL_BRAND) )
- {
- strcpy(CPUInfo.strBrandID, INTEL_BRAND[CPUInfo.uiBrandID]);
+ // __cpuid with an InfoType argument of 0 returns the number of
+ // valid Ids in cpu_info[0] and the CPU identification string in
+ // the other three array elements. The CPU identification string is
+ // not in linear order. The code below arranges the information
+ // in a human readable form.
+ int cpu_info[4] = {-1};
+ __cpuid(cpu_info, 0);
+ unsigned int ids = (unsigned int)cpu_info[0];
+ setConfig(eMaxID, (S32)ids);
- if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6)
+ char cpu_vendor[0x20];
+ memset(cpu_vendor, 0, sizeof(cpu_vendor));
+ *((int*)cpu_vendor) = cpu_info[1];
+ *((int*)(cpu_vendor+4)) = cpu_info[3];
+ *((int*)(cpu_vendor+8)) = cpu_info[2];
+ setInfo(eVendor, cpu_vendor);
+
+ // Get the information associated with each valid Id
+ for(unsigned int i=0; i<=ids; ++i)
{
- strcpy(CPUInfo.strBrandID, "0.18 micron Intel Pentium III Xeon");
- }
- }
+ __cpuid(cpu_info, i);
- // Then we translate the cpu family
- switch (CPUInfo.uiFamily)
- {
- case 3: // Family = 3: i386 (80386) processor family
- strcpy(CPUInfo.strFamily, "Intel i386"); /* Flawfinder: ignore */
- break;
- case 4: // Family = 4: i486 (80486) processor family
- strcpy(CPUInfo.strFamily, "Intel i486"); /* Flawfinder: ignore */
- break;
- case 5: // Family = 5: Pentium (80586) processor family
- strcpy(CPUInfo.strFamily, "Intel Pentium"); /* Flawfinder: ignore */
- break;
- case 6: // Family = 6: Pentium Pro (80686) processor family
- strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core"); /* Flawfinder: ignore */
- break;
- case 15: // Family = 15: Extended family specific
- // Masking the extended family
- CPUInfo.uiExtendedFamily = (eaxreg >> 20) & 0xFF;
- switch (CPUInfo.uiExtendedFamily)
+ // Interpret CPU feature information.
+ if (i == 1)
{
- case 0: // Family = 15, Ext. Family = 0: Pentium 4 (80786 ??) processor family
- strcpy(CPUInfo.strFamily, "Intel Pentium 4"); /* Flawfinder: ignore */
- break;
- case 1: // Family = 15, Ext. Family = 1: McKinley (64-bit) processor family
- strcpy(CPUInfo.strFamily, "Intel McKinley (IA-64)"); /* Flawfinder: ignore */
- break;
- default: // Sure is sure
- strcpy(CPUInfo.strFamily, "Unknown Intel Pentium 4+"); /* Flawfinder: ignore */
- break;
- }
- break;
- default: // Failsave
- strcpy(CPUInfo.strFamily, "Unknown"); /* Flawfinder: ignore */
- break;
- }
+ setInfo(eStepping, cpu_info[0] & 0xf);
+ setInfo(eModel, (cpu_info[0] >> 4) & 0xf);
+ int family = (cpu_info[0] >> 8) & 0xf;
+ setInfo(eFamily, family);
+ setInfo(eType, (cpu_info[0] >> 12) & 0x3);
+ setInfo(eExtendedModel, (cpu_info[0] >> 16) & 0xf);
+ int ext_family = (cpu_info[0] >> 20) & 0xff;
+ setInfo(eExtendedFamily, ext_family);
+ setInfo(eBrandID, cpu_info[1] & 0xff);
- // Now we come to the big deal, the exact model name
- switch (CPUInfo.uiFamily)
- {
- case 3: // i386 (80386) processor family
- strcpy(CPUInfo.strModel, "Unknown Intel i386"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i386", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 4: // i486 (80486) processor family
- switch (CPUInfo.uiModel)
- {
- case 0: // Model = 0: i486 DX-25/33 processor model
- strcpy(CPUInfo.strModel, "Intel i486 DX-25/33"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i486 DX-25/33", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 1: // Model = 1: i486 DX-50 processor model
- strcpy(CPUInfo.strModel, "Intel i486 DX-50"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i486 DX-50", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 2: // Model = 2: i486 SX processor model
- strcpy(CPUInfo.strModel, "Intel i486 SX"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i486 SX", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 3: // Model = 3: i486 DX2 (with i487 numeric coprocessor) processor model
- strcpy(CPUInfo.strModel, "Intel i486 487/DX2"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i486 DX2 with i487 numeric coprocessor", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 4: // Model = 4: i486 SL processor model (never heard ?!?)
- strcpy(CPUInfo.strModel, "Intel i486 SL"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i486 SL", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 5: // Model = 5: i486 SX2 processor model
- strcpy(CPUInfo.strModel, "Intel i486 SX2"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i486 SX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 7: // Model = 7: i486 write-back enhanced DX2 processor model
- strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX2"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i486 write-back enhanced DX2", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 8: // Model = 8: i486 DX4 processor model
- strcpy(CPUInfo.strModel, "Intel i486 DX4"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 9: // Model = 9: i486 write-back enhanced DX4 processor model
- strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX4"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- default: // ...
- strcpy(CPUInfo.strModel, "Unknown Intel i486"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel i486 (Unknown model)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- }
- break;
- case 5: // Pentium (80586) processor family
- switch (CPUInfo.uiModel)
- {
- case 0: // Model = 0: Pentium (P5 A-Step) processor model
- strcpy(CPUInfo.strModel, "Intel Pentium (P5 A-Step)"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel Pentium (P5 A-Step core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break; // Famous for the DIV bug, as far as I know
- case 1: // Model = 1: Pentium 60/66 processor model
- strcpy(CPUInfo.strModel, "Intel Pentium 60/66 (P5)"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel Pentium 60/66 (P5 core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 2: // Model = 2: Pentium 75-200 (P54C) processor model
- strcpy(CPUInfo.strModel, "Intel Pentium 75-200 (P54C)"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel Pentium 75-200 (P54C core)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- case 3: // Model = 3: Pentium overdrive for 486 systems processor model
- strcpy(CPUInfo.strModel, "Intel Pentium for 486 system (P24T Overdrive)"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel Pentium for 486 (P24T overdrive core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 4: // Model = 4: Pentium MMX processor model
- strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C)"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 7: // Model = 7: Pentium processor model (don't know difference to Model=2)
- strcpy(CPUInfo.strModel, "Intel Pentium (P54C)"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 8: // Model = 8: Pentium MMX (0.25 micron) processor model
- strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C), 0.25 micron"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium MMX (P55C core), 0.25 micron", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- default: // ...
- strcpy(CPUInfo.strModel, "Unknown Intel Pentium"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium (Unknown P5-model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- }
- break;
- case 6: // Pentium Pro (80686) processor family
- switch (CPUInfo.uiModel)
- {
- case 0: // Model = 0: Pentium Pro (P6 A-Step) processor model
- strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6 A-Step)"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium Pro (P6 A-Step core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 1: // Model = 1: Pentium Pro
- strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6)"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium Pro (P6 core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 3: // Model = 3: Pentium II (66 MHz FSB, I think) processor model
- strcpy(CPUInfo.strModel, "Intel Pentium II Model 3, 0.28 micron"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium II (Model 3 core, 0.28 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 5: // Model = 5: Pentium II/Xeon/Celeron (0.25 micron) processor model
- strcpy(CPUInfo.strModel, "Intel Pentium II Model 5/Xeon/Celeron, 0.25 micron"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium II/Xeon/Celeron (Model 5 core, 0.25 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 6: // Model = 6: Pentium II with internal L2 cache
- strcpy(CPUInfo.strModel, "Intel Pentium II - internal L2 cache"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium II with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 7: // Model = 7: Pentium III/Xeon (extern L2 cache) processor model
- strcpy(CPUInfo.strModel, "Intel Pentium III/Pentium III Xeon - external L2 cache, 0.25 micron"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium III/Pentium III Xeon (0.25 micron process) with external L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 8: // Model = 8: Pentium III/Xeon/Celeron (256 KB on-die L2 cache) processor model
- strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/
- // We want to know it exactly:
- switch (CPUInfo.uiBrandID)
+ setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family));
+
+ setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
+ setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
+
+ if(cpu_info[2] & 0x1)
+ {
+ setExtension(cpu_feature_names[eSSE3_Features]);
+ }
+
+ if(cpu_info[2] & 0x8)
+ {
+ setExtension(cpu_feature_names[eMONTIOR_MWAIT]);
+ }
+
+ if(cpu_info[2] & 0x10)
+ {
+ setExtension(cpu_feature_names[eCPLDebugStore]);
+ }
+
+ if(cpu_info[2] & 0x100)
+ {
+ setExtension(cpu_feature_names[eThermalMonitor2]);
+ }
+
+ unsigned int feature_info = (unsigned int) cpu_info[3];
+ for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1)
+ {
+ if(feature_info & bit)
{
- case 1: // Model = 8, Brand id = 1: Celeron (on-die L2 cache) processor model
- strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 2: // Model = 8, Brand id = 2: Pentium III (on-die L2 cache) processor model (my current cpu :-))
- strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 3: // Model = 8, Brand id = 3: Pentium III Xeon (on-die L2 cache) processor model
- strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- default: // ...
- strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
+ setExtension(cpu_feature_names[index]);
}
- break;
- case 9: // Model = 9: Intel Pentium M processor, Intel Celeron M processor, model 9
- strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 0xA: // Model = 0xA: Pentium III/Xeon/Celeron (1 or 2 MB on-die L2 cache) processor model
- strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron"); /*Flawfinder: ignore*/
- // Exact detection:
- switch (CPUInfo.uiBrandID)
- {
- case 1: // Model = 0xA, Brand id = 1: Celeron (1 or 2 MB on-die L2 cache (does it exist??)) processor model
- strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 2: // Model = 0xA, Brand id = 2: Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model
- strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 3: // Model = 0xA, Brand id = 3: Pentium III Xeon (1 or 2 MB on-die L2 cache) processor model
- strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- default: // Getting bored of this............
- strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- }
- break;
- case 0xB: // Model = 0xB: Pentium III/Xeon/Celeron (Tualatin core, on-die cache) processor model
- strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.13 micron"); /*Flawfinder: ignore*/
- // Omniscient: ;-)
- switch (CPUInfo.uiBrandID)
- {
- case 3: // Model = 0xB, Brand id = 3: Celeron (Tualatin core) processor model
- strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 4: // Model = 0xB, Brand id = 4: Pentium III (Tualatin core) processor model
- strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 7: // Model = 0xB, Brand id = 7: Celeron mobile (Tualatin core) processor model
- strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- default: // *bored*
- strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- }
- break;
- case 0xD: // Model = 0xD: Intel Pentium M processor, Intel Celeron M processor, model D
- strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 0xE: // Model = 0xE: Intel Core Duo processor, Intel Core Solo processor, model E
- strcpy(CPUInfo.strModel, "Intel Core Series Processor"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- case 0xF: // Model = 0xF: Intel Core 2 Duo processor, model F
- strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
- default: // *more bored*
- strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- break;
+ }
}
- break;
- case 15: // Extended processor family
- // Masking the extended model
- CPUInfo.uiExtendedModel = (eaxreg >> 16) & 0xFF;
- switch (CPUInfo.uiModel)
+ }
+
+ // Calling __cpuid with 0x80000000 as the InfoType argument
+ // gets the number of valid extended IDs.
+ __cpuid(cpu_info, 0x80000000);
+ unsigned int ext_ids = cpu_info[0];
+ setConfig(eMaxExtID, 0);
+
+ char cpu_brand_string[0x40];
+ memset(cpu_brand_string, 0, sizeof(cpu_brand_string));
+
+ // Get the information associated with each extended ID.
+ for(unsigned int i=0x80000000; i<=ext_ids; ++i)
+ {
+ __cpuid(cpu_info, i);
+
+ // Interpret CPU brand string and cache information.
+ if (i == 0x80000002)
+ memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info));
+ else if (i == 0x80000003)
+ memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info));
+ else if (i == 0x80000004)
{
- case 0: // Model = 0: Pentium 4 Willamette (A-Step) core
- if ((CPUInfo.uiBrandID) == 8) // Brand id = 8: P4 Willamette
- {
- strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette (A-Step)"); /*Flawfinder: ignore*/
- strncat(strCPUName, "Intel Pentium 4 Willamette (A-Step)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/
- }
- else // else Xeon
- {
- strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon (A-Step)"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel Pentium 4 Willamette Xeon (A-Step)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
- }
- break;
- case 1: // Model = 1: Pentium 4 Willamette core
- if ((CPUInfo.uiBrandID) == 8) // Brand id = 8: P4 Willamette
- {
- strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
- }
- else // else Xeon
- {
- strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
- }
- break;
- case 2: // Model = 2: Pentium 4 Northwood core
- if (((CPUInfo.uiBrandID) == 9) || ((CPUInfo.uiBrandID) == 0xA)) // P4 Willamette
- {
- strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel Pentium 4 Northwood", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
- }
- else // Xeon
- {
- strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood Xeon"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel Pentium 4 Northwood Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
- }
- break;
- default: // Silly stupid never used failsave option
- strcpy(CPUInfo.strModel, "Unknown Intel Pentium 4"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel Pentium 4 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
- break;
+ memcpy(cpu_brand_string + 32, cpu_info, sizeof(cpu_info));
+ setInfo(eBrandName, cpu_brand_string);
}
- break;
- default: // *grmpf*
- strcpy(CPUInfo.strModel, "Unknown Intel model"); /* Flawfinder: ignore */
- strncat(strCPUName, "Intel (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1); /* Flawfinder: ignore */
- break;
- }
-
- // After the long processor model block we now come to the processors serial
- // number.
- // First of all we check if the processor supports the serial number
- if (CPUInfo.MaxSupportedLevel >= 3)
- {
- // If it supports the serial number CPUID level 0x00000003 we read the data
- unsigned long sig1, sig2, sig3;
- __asm
- {
- mov eax, 1
- cpuid
- mov sig1, eax
- mov eax, 3
- cpuid
- mov sig2, ecx
- mov sig3, edx
- }
- // Then we convert the data to a readable string
- snprintf( /* Flawfinder: ignore */
- CPUInfo.strProcessorSerial,
- sizeof(CPUInfo.strProcessorSerial),
- "%04lX-%04lX-%04lX-%04lX-%04lX-%04lX",
- sig1 >> 16,
- sig1 & 0xFFFF,
- sig3 >> 16,
- sig3 & 0xFFFF,
- sig2 >> 16, sig2 & 0xFFFF);
- }
- else
- {
- // If there's no serial number support we just put "No serial number"
- snprintf( /* Flawfinder: ignore */
- CPUInfo.strProcessorSerial,
- sizeof(CPUInfo.strProcessorSerial),
- "No Processor Serial Number");
- }
-
- // Now we get the standard processor extensions
- GetStandardProcessorExtensions();
-
- // And finally the processor configuration (caches, TLBs, ...) and translate
- // the data to readable strings
- GetStandardProcessorConfiguration();
- TranslateProcessorConfiguration();
-
- // At last...
- return true;
-#else
- return FALSE;
-#endif
-}
-
-// bool CProcessor::AnalyzeAMDProcessor()
-// ======================================
-// Private class function for analyzing an AMD processor
-////////////////////////////////////////////////////////
-bool CProcessor::AnalyzeAMDProcessor()
-{
-#if LL_WINDOWS
- unsigned long eaxreg, ebxreg, ecxreg, edxreg;
-
- // First of all we check if the CPUID command is available
- if (!CheckCPUIDPresence())
- return 0;
-
- // Now we get the CPUID standard level 0x00000001
- __asm
- {
- mov eax, 1
- cpuid
- mov eaxreg, eax
- mov ebxreg, ebx
- mov edxreg, edx
- }
-
- // Then we mask the model, family, stepping and type (AMD does not support brand id)
- CPUInfo.uiStepping = eaxreg & 0xF;
- CPUInfo.uiModel = (eaxreg >> 4) & 0xF;
- CPUInfo.uiFamily = (eaxreg >> 8) & 0xF;
- CPUInfo.uiType = (eaxreg >> 12) & 0x3;
-
- // Now we check if the processor supports the brand id string extended CPUID level
- if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000004)
- {
- // If it supports the extended CPUID level 0x80000004 we read the data
- char tmp[52]; /* Flawfinder: ignore */
- memset(tmp, 0, sizeof(tmp));
- __asm
- {
- mov eax, 0x80000002
- cpuid
- mov dword ptr [tmp], eax
- mov dword ptr [tmp+4], ebx
- mov dword ptr [tmp+8], ecx
- mov dword ptr [tmp+12], edx
- mov eax, 0x80000003
- cpuid
- mov dword ptr [tmp+16], eax
- mov dword ptr [tmp+20], ebx
- mov dword ptr [tmp+24], ecx
- mov dword ptr [tmp+28], edx
- mov eax, 0x80000004
- cpuid
- mov dword ptr [tmp+32], eax
- mov dword ptr [tmp+36], ebx
- mov dword ptr [tmp+40], ecx
- mov dword ptr [tmp+44], edx
- }
- // And copy it to the brand id string
- strncpy(CPUInfo.strBrandID, tmp,sizeof(CPUInfo.strBrandID)-1);
- CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
- }
- else
- {
- // Or just tell there is no brand id string support
- strcpy(CPUInfo.strBrandID, ""); /* Flawfinder: ignore */
- }
-
- // After that we translate the processor family
- switch(CPUInfo.uiFamily)
- {
- case 4: // Family = 4: 486 (80486) or 5x86 (80486) processor family
- switch (CPUInfo.uiModel)
+ else if (i == 0x80000006)
{
- case 3: // Thanks to AMD for this nice form of family
- case 7: // detection.... *grmpf*
- case 8:
- case 9:
- strcpy(CPUInfo.strFamily, "AMD 80486"); /* Flawfinder: ignore */
- break;
- case 0xE:
- case 0xF:
- strcpy(CPUInfo.strFamily, "AMD 5x86"); /* Flawfinder: ignore */
- break;
- default:
- strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */
- break;
- }
- break;
- case 5: // Family = 5: K5 or K6 processor family
- switch (CPUInfo.uiModel)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- strcpy(CPUInfo.strFamily, "AMD K5"); /* Flawfinder: ignore */
- break;
- case 6:
- case 7:
- case 8:
- case 9:
- strcpy(CPUInfo.strFamily, "AMD K6"); /* Flawfinder: ignore */
- break;
- default:
- strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */
- break;
- }
- break;
- case 6: // Family = 6: K7 (Athlon, ...) processor family
- strcpy(CPUInfo.strFamily, "AMD K7"); /* Flawfinder: ignore */
- break;
- default: // For security
- strcpy(CPUInfo.strFamily, "Unknown family"); /* Flawfinder: ignore */
- break;
- }
-
- // After the family detection we come to the specific processor model
- // detection
- switch (CPUInfo.uiFamily)
- {
- case 4: // Family = 4: 486 (80486) or 5x85 (80486) processor family
- switch (CPUInfo.uiModel)
- {
- case 3: // Model = 3: 80486 DX2
- strcpy(CPUInfo.strModel, "AMD 80486 DX2"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD 80486 DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 7: // Model = 7: 80486 write-back enhanced DX2
- strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX2"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD 80486 write-back enhanced DX2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 8: // Model = 8: 80486 DX4
- strcpy(CPUInfo.strModel, "AMD 80486 DX4"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD 80486 DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 9: // Model = 9: 80486 write-back enhanced DX4
- strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX4"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD 80486 write-back enhanced DX4", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 0xE: // Model = 0xE: 5x86
- strcpy(CPUInfo.strModel, "AMD 5x86"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD 5x86", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 0xF: // Model = 0xF: 5x86 write-back enhanced (oh my god.....)
- strcpy(CPUInfo.strModel, "AMD 5x86 write-back enhanced"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD 5x86 write-back enhanced", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- default: // ...
- strcpy(CPUInfo.strModel, "Unknown AMD 80486 or 5x86 model"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD 80486 or 5x86 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- }
- break;
- case 5: // Family = 5: K5 / K6 processor family
- switch (CPUInfo.uiModel)
- {
- case 0: // Model = 0: K5 SSA 5 (Pentium Rating *ggg* 75, 90 and 100 Mhz)
- strcpy(CPUInfo.strModel, "AMD K5 SSA5 (PR75, PR90, PR100)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K5 SSA5 (PR75, PR90, PR100)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 1: // Model = 1: K5 5k86 (PR 120 and 133 MHz)
- strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR120, PR133)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K5 5k86 (PR120, PR133)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 2: // Model = 2: K5 5k86 (PR 166 MHz)
- strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR166)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K5 5k86 (PR166)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 3: // Model = 3: K5 5k86 (PR 200 MHz)
- strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR200)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K5 5k86 (PR200)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 6: // Model = 6: K6
- strcpy(CPUInfo.strModel, "AMD K6 (0.30 micron)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K6 (0.30 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 7: // Model = 7: K6 (0.25 micron)
- strcpy(CPUInfo.strModel, "AMD K6 (0.25 micron)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K6 (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 8: // Model = 8: K6-2
- strcpy(CPUInfo.strModel, "AMD K6-2"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K6-2", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 9: // Model = 9: K6-III
- strcpy(CPUInfo.strModel, "AMD K6-III"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K6-III", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 0xD: // Model = 0xD: K6-2+ / K6-III+
- strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- default: // ...
- strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K5 or K6 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- }
- break;
- case 6: // Family = 6: K7 processor family (AMDs first good processors)
- switch (CPUInfo.uiModel)
- {
- case 1: // Athlon
- strcpy(CPUInfo.strModel, "AMD Athlon (0.25 micron)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD Athlon (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 2: // Athlon (0.18 micron)
- strcpy(CPUInfo.strModel, "AMD Athlon (0.18 micron)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD Athlon (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 3: // Duron (Spitfire core)
- strcpy(CPUInfo.strModel, "AMD Duron (Spitfire)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD Duron (Spitfire core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 4: // Athlon (Thunderbird core)
- strcpy(CPUInfo.strModel, "AMD Athlon (Thunderbird)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD Athlon (Thunderbird core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 6: // Athlon MP / Mobile Athlon (Palomino core)
- strcpy(CPUInfo.strModel, "AMD Athlon MP/Mobile Athlon (Palomino)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD Athlon MP/Mobile Athlon (Palomino core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- case 7: // Mobile Duron (Morgan core)
- strcpy(CPUInfo.strModel, "AMD Mobile Duron (Morgan)"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD Mobile Duron (Morgan core)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- default: // ...
- strcpy(CPUInfo.strModel, "Unknown AMD K7 model"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD K7 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- }
- break;
- default: // ...
- strcpy(CPUInfo.strModel, "Unknown AMD model"); /* Flawfinder: ignore */
- strncat(strCPUName, "AMD (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1); /* Flawfinder: ignore */
- break;
- }
-
- // Now we read the standard processor extension that are stored in the same
- // way the Intel standard extensions are
- GetStandardProcessorExtensions();
-
- // Then we check if theres an extended CPUID level support
- if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000001)
- {
- // If we can access the extended CPUID level 0x80000001 we get the
- // edx register
- __asm
- {
- mov eax, 0x80000001
- cpuid
- mov edxreg, edx
- }
-
- // Now we can mask some AMD specific cpu extensions
- CPUInfo._Ext.EMMX_MultimediaExtensions = CheckBit(edxreg, 22);
- CPUInfo._Ext.AA64_AMD64BitArchitecture = CheckBit(edxreg, 29);
- CPUInfo._Ext._E3DNOW_InstructionExtensions = CheckBit(edxreg, 30);
- CPUInfo._Ext._3DNOW_InstructionExtensions = CheckBit(edxreg, 31);
- }
-
- // After that we check if the processor supports the ext. CPUID level
- // 0x80000006
- if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000006)
- {
- // If it's present, we read it out
- __asm
- {
- mov eax, 0x80000005
- cpuid
- mov eaxreg, eax
- mov ebxreg, ebx
- mov ecxreg, ecx
- mov edxreg, edx
- }
-
- // Then we mask the L1 Data TLB information
- if ((ebxreg >> 16) && (eaxreg >> 16))
- {
- CPUInfo._Data.bPresent = true;
- strcpy(CPUInfo._Data.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/
- CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF;
- CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF;
- }
- else if (eaxreg >> 16)
- {
- CPUInfo._Data.bPresent = true;
- strcpy(CPUInfo._Data.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/
- CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF;
- CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF;
- }
- else if (ebxreg >> 16)
- {
- CPUInfo._Data.bPresent = true;
- strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/
- CPUInfo._Data.uiAssociativeWays = (ebxreg >> 24) & 0xFF;
- CPUInfo._Data.uiEntries = (ebxreg >> 16) & 0xFF;
- }
- if (CPUInfo._Data.uiAssociativeWays == 0xFF)
- CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
-
- // Now the L1 Instruction/Code TLB information
- if ((ebxreg & 0xFFFF) && (eaxreg & 0xFFFF))
- {
- CPUInfo._Instruction.bPresent = true;
- strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4MB"); /*Flawfinder: ignore*/
- CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF;
- CPUInfo._Instruction.uiEntries = eaxreg & 0xFF;
- }
- else if (eaxreg & 0xFFFF)
- {
- CPUInfo._Instruction.bPresent = true;
- strcpy(CPUInfo._Instruction.strPageSize, "2 MB / 4MB"); /*Flawfinder: ignore*/
- CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF;
- CPUInfo._Instruction.uiEntries = eaxreg & 0xFF;
- }
- else if (ebxreg & 0xFFFF)
- {
- CPUInfo._Instruction.bPresent = true;
- strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/
- CPUInfo._Instruction.uiAssociativeWays = (ebxreg >> 8) & 0xFF;
- CPUInfo._Instruction.uiEntries = ebxreg & 0xFF;
- }
- if (CPUInfo._Instruction.uiAssociativeWays == 0xFF)
- CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
-
- // Then we read the L1 data cache information
- if ((ecxreg >> 24) > 0)
- {
- CPUInfo._L1.Data.bPresent = true;
- snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", ecxreg >> 24); /* Flawfinder: ignore */
- CPUInfo._L1.Data.uiAssociativeWays = (ecxreg >> 15) & 0xFF;
- CPUInfo._L1.Data.uiLineSize = ecxreg & 0xFF;
- }
- // After that we read the L2 instruction/code cache information
- if ((edxreg >> 24) > 0)
- {
- CPUInfo._L1.Instruction.bPresent = true;
- snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", edxreg >> 24); /* Flawfinder: ignore */
- CPUInfo._L1.Instruction.uiAssociativeWays = (edxreg >> 15) & 0xFF;
- CPUInfo._L1.Instruction.uiLineSize = edxreg & 0xFF;
- }
-
- // Note: I'm not absolutely sure that the L1 page size code (the
- // 'if/else if/else if' structs above) really detects the real page
- // size for the TLB. Somebody should check it....
-
- // Now we read the ext. CPUID level 0x80000006
- __asm
- {
- mov eax, 0x80000006
- cpuid
- mov eaxreg, eax
- mov ebxreg, ebx
- mov ecxreg, ecx
- }
-
- // We only mask the unified L2 cache masks (never heard of an
- // L2 cache that is divided in data and code parts)
- if (((ecxreg >> 12) & 0xF) > 0)
- {
- CPUInfo._L2.bPresent = true;
- snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", ecxreg >> 16); /* Flawfinder: ignore */
- switch ((ecxreg >> 12) & 0xF)
- {
- case 1:
- CPUInfo._L2.uiAssociativeWays = 1;
- break;
- case 2:
- CPUInfo._L2.uiAssociativeWays = 2;
- break;
- case 4:
- CPUInfo._L2.uiAssociativeWays = 4;
- break;
- case 6:
- CPUInfo._L2.uiAssociativeWays = 8;
- break;
- case 8:
- CPUInfo._L2.uiAssociativeWays = 16;
- break;
- case 0xF:
- CPUInfo._L2.uiAssociativeWays = (unsigned int) -1;
- break;
- default:
- CPUInfo._L2.uiAssociativeWays = 0;
- break;
- }
- CPUInfo._L2.uiLineSize = ecxreg & 0xFF;
- }
- }
- else
- {
- // If we could not detect the ext. CPUID level 0x80000006 we
- // try to read the standard processor configuration.
- GetStandardProcessorConfiguration();
- }
- // After reading we translate the configuration to strings
- TranslateProcessorConfiguration();
-
- // And finally exit
- return true;
-#else
- return FALSE;
-#endif
-}
-
-// bool CProcessor::AnalyzeUnknownProcessor()
-// ==========================================
-// Private class function to analyze an unknown (No Intel or AMD) processor
-///////////////////////////////////////////////////////////////////////////
-bool CProcessor::AnalyzeUnknownProcessor()
-{
-#if LL_WINDOWS
- unsigned long eaxreg, ebxreg;
-
- // We check if the CPUID command is available
- if (!CheckCPUIDPresence())
- return false;
-
- // First of all we read the standard CPUID level 0x00000001
- // This level should be available on every x86-processor clone
- __asm
- {
- mov eax, 1
- cpuid
- mov eaxreg, eax
- mov ebxreg, ebx
- }
- // Then we mask the processor model, family, type and stepping
- CPUInfo.uiStepping = eaxreg & 0xF;
- CPUInfo.uiModel = (eaxreg >> 4) & 0xF;
- CPUInfo.uiFamily = (eaxreg >> 8) & 0xF;
- CPUInfo.uiType = (eaxreg >> 12) & 0x3;
-
- // To have complete information we also mask the brand id
- CPUInfo.uiBrandID = ebxreg & 0xF;
-
- // Then we get the standard processor extensions
- GetStandardProcessorExtensions();
-
- // Now we mark everything we do not know as unknown
- strcpy(strCPUName, "Unknown"); /*Flawfinder: ignore*/
-
- strcpy(CPUInfo._Data.strTLB, "Unknown"); /*Flawfinder: ignore*/
- strcpy(CPUInfo._Instruction.strTLB, "Unknown"); /*Flawfinder: ignore*/
-
- strcpy(CPUInfo._Trace.strCache, "Unknown"); /*Flawfinder: ignore*/
- strcpy(CPUInfo._L1.Data.strCache, "Unknown"); /*Flawfinder: ignore*/
- strcpy(CPUInfo._L1.Instruction.strCache, "Unknown"); /*Flawfinder: ignore*/
- strcpy(CPUInfo._L2.strCache, "Unknown"); /*Flawfinder: ignore*/
- strcpy(CPUInfo._L3.strCache, "Unknown"); /*Flawfinder: ignore*/
-
- strcpy(CPUInfo.strProcessorSerial, "Unknown / Not supported"); /*Flawfinder: ignore*/
-
- // For the family, model and brand id we can only print the numeric value
- snprintf(CPUInfo.strBrandID, sizeof(CPUInfo.strBrandID), "Brand-ID number %d", CPUInfo.uiBrandID); /* Flawfinder: ignore */
- snprintf(CPUInfo.strFamily, sizeof(CPUInfo.strFamily), "Family number %d", CPUInfo.uiFamily); /* Flawfinder: ignore */
- snprintf(CPUInfo.strModel, sizeof(CPUInfo.strModel), "Model number %d", CPUInfo.uiModel); /* Flawfinder: ignore */
-
- // And thats it
- return true;
-#else
- return FALSE;
-#endif
-}
-
-// bool CProcessor::CheckCPUIDPresence()
-// =====================================
-// This function checks if the CPUID command is available on the current
-// processor
-////////////////////////////////////////////////////////////////////////
-bool CProcessor::CheckCPUIDPresence()
-{
-#if LL_WINDOWS
- unsigned long BitChanged;
-
- // We've to check if we can toggle the flag register bit 21
- // If we can't the processor does not support the CPUID command
- __asm
- {
- pushfd
- pop eax
- mov ebx, eax
- xor eax, 0x00200000
- push eax
- popfd
- pushfd
- pop eax
- xor eax,ebx
- mov BitChanged, eax
- }
-
- return ((BitChanged) ? true : false);
-#else
- return FALSE;
-#endif
-}
-
-// void CProcessor::DecodeProcessorConfiguration(unsigned int cfg)
-// ===============================================================
-// This function (or switch ?!) just translates a one-byte processor configuration
-// byte to understandable values
-//////////////////////////////////////////////////////////////////////////////////
-void CProcessor::DecodeProcessorConfiguration(unsigned int cfg)
-{
- // First we ensure that there's only one single byte
- cfg &= 0xFF;
-
- // Then we do a big switch
- switch(cfg)
- {
- case 0: // cfg = 0: Unused
- break;
- case 0x1: // cfg = 0x1: code TLB present, 4 KB pages, 4 ways, 32 entries
- CPUInfo._Instruction.bPresent = true;
- strcpy(CPUInfo._Instruction.strPageSize, "4 KB"); /*Flawfinder: ignore*/
- CPUInfo._Instruction.uiAssociativeWays = 4;
- CPUInfo._Instruction.uiEntries = 32;
- break;
- case 0x2: // cfg = 0x2: code TLB present, 4 MB pages, fully associative, 2 entries
- CPUInfo._Instruction.bPresent = true;
- strcpy(CPUInfo._Instruction.strPageSize, "4 MB"); /*Flawfinder: ignore*/
- CPUInfo._Instruction.uiAssociativeWays = 4;
- CPUInfo._Instruction.uiEntries = 2;
- break;
- case 0x3: // cfg = 0x3: data TLB present, 4 KB pages, 4 ways, 64 entries
- CPUInfo._Data.bPresent = true;
- strcpy(CPUInfo._Data.strPageSize, "4 KB"); /*Flawfinder: ignore*/
- CPUInfo._Data.uiAssociativeWays = 4;
- CPUInfo._Data.uiEntries = 64;
- break;
- case 0x4: // cfg = 0x4: data TLB present, 4 MB pages, 4 ways, 8 entries
- CPUInfo._Data.bPresent = true;
- strcpy(CPUInfo._Data.strPageSize, "4 MB"); /*Flawfinder: ignore*/
- CPUInfo._Data.uiAssociativeWays = 4;
- CPUInfo._Data.uiEntries = 8;
- break;
- case 0x6: // cfg = 0x6: code L1 cache present, 8 KB, 4 ways, 32 byte lines
- CPUInfo._L1.Instruction.bPresent = true;
- strcpy(CPUInfo._L1.Instruction.strSize, "8 KB"); /*Flawfinder: ignore*/
- CPUInfo._L1.Instruction.uiAssociativeWays = 4;
- CPUInfo._L1.Instruction.uiLineSize = 32;
- break;
- case 0x8: // cfg = 0x8: code L1 cache present, 16 KB, 4 ways, 32 byte lines
- CPUInfo._L1.Instruction.bPresent = true;
- strcpy(CPUInfo._L1.Instruction.strSize, "16 KB"); /*Flawfinder: ignore*/
- CPUInfo._L1.Instruction.uiAssociativeWays = 4;
- CPUInfo._L1.Instruction.uiLineSize = 32;
- break;
- case 0xA: // cfg = 0xA: data L1 cache present, 8 KB, 2 ways, 32 byte lines
- CPUInfo._L1.Data.bPresent = true;
- strcpy(CPUInfo._L1.Data.strSize, "8 KB"); /*Flawfinder: ignore*/
- CPUInfo._L1.Data.uiAssociativeWays = 2;
- CPUInfo._L1.Data.uiLineSize = 32;
- break;
- case 0xC: // cfg = 0xC: data L1 cache present, 16 KB, 4 ways, 32 byte lines
- CPUInfo._L1.Data.bPresent = true;
- strcpy(CPUInfo._L1.Data.strSize, "16 KB"); /*Flawfinder: ignore*/
- CPUInfo._L1.Data.uiAssociativeWays = 4;
- CPUInfo._L1.Data.uiLineSize = 32;
- break;
- case 0x22: // cfg = 0x22: code and data L3 cache present, 512 KB, 4 ways, 64 byte lines, sectored
- CPUInfo._L3.bPresent = true;
- strcpy(CPUInfo._L3.strSize, "512 KB"); /*Flawfinder: ignore*/
- CPUInfo._L3.uiAssociativeWays = 4;
- CPUInfo._L3.uiLineSize = 64;
- CPUInfo._L3.bSectored = true;
- break;
- case 0x23: // cfg = 0x23: code and data L3 cache present, 1024 KB, 8 ways, 64 byte lines, sectored
- CPUInfo._L3.bPresent = true;
- strcpy(CPUInfo._L3.strSize, "1024 KB"); /*Flawfinder: ignore*/
- CPUInfo._L3.uiAssociativeWays = 8;
- CPUInfo._L3.uiLineSize = 64;
- CPUInfo._L3.bSectored = true;
- break;
- case 0x25: // cfg = 0x25: code and data L3 cache present, 2048 KB, 8 ways, 64 byte lines, sectored
- CPUInfo._L3.bPresent = true;
- strcpy(CPUInfo._L3.strSize, "2048 KB"); /*Flawfinder: ignore*/
- CPUInfo._L3.uiAssociativeWays = 8;
- CPUInfo._L3.uiLineSize = 64;
- CPUInfo._L3.bSectored = true;
- break;
- case 0x29: // cfg = 0x29: code and data L3 cache present, 4096 KB, 8 ways, 64 byte lines, sectored
- CPUInfo._L3.bPresent = true;
- strcpy(CPUInfo._L3.strSize, "4096 KB"); /*Flawfinder: ignore*/
- CPUInfo._L3.uiAssociativeWays = 8;
- CPUInfo._L3.uiLineSize = 64;
- CPUInfo._L3.bSectored = true;
- break;
- case 0x40: // cfg = 0x40: no integrated L2 cache (P6 core) or L3 cache (P4 core)
- break;
- case 0x41: // cfg = 0x41: code and data L2 cache present, 128 KB, 4 ways, 32 byte lines
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "128 KB"); /*Flawfinder: ignore*/
- CPUInfo._L2.uiAssociativeWays = 4;
- CPUInfo._L2.uiLineSize = 32;
- break;
- case 0x42: // cfg = 0x42: code and data L2 cache present, 256 KB, 4 ways, 32 byte lines
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "256 KB"); /*Flawfinder: ignore*/
- CPUInfo._L2.uiAssociativeWays = 4;
- CPUInfo._L2.uiLineSize = 32;
- break;
- case 0x43: // cfg = 0x43: code and data L2 cache present, 512 KB, 4 ways, 32 byte lines
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 4;
- CPUInfo._L2.uiLineSize = 32;
- break;
- case 0x44: // cfg = 0x44: code and data L2 cache present, 1024 KB, 4 ways, 32 byte lines
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 4;
- CPUInfo._L2.uiLineSize = 32;
- break;
- case 0x45: // cfg = 0x45: code and data L2 cache present, 2048 KB, 4 ways, 32 byte lines
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "2 MB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 4;
- CPUInfo._L2.uiLineSize = 32;
- break;
- case 0x50: // cfg = 0x50: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 64 entries
- CPUInfo._Instruction.bPresent = true;
- strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */
- CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
- CPUInfo._Instruction.uiEntries = 64;
- break;
- case 0x51: // cfg = 0x51: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 128 entries
- CPUInfo._Instruction.bPresent = true;
- strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */
- CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
- CPUInfo._Instruction.uiEntries = 128;
- break;
- case 0x52: // cfg = 0x52: code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 256 entries
- CPUInfo._Instruction.bPresent = true;
- strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB"); /* Flawfinder: ignore */
- CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1;
- CPUInfo._Instruction.uiEntries = 256;
- break;
- case 0x5B: // cfg = 0x5B: data TLB present, 4 KB / 4 MB pages, fully associative, 64 entries
- CPUInfo._Data.bPresent = true;
- strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */
- CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
- CPUInfo._Data.uiEntries = 64;
- break;
- case 0x5C: // cfg = 0x5C: data TLB present, 4 KB / 4 MB pages, fully associative, 128 entries
- CPUInfo._Data.bPresent = true;
- strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */
- CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
- CPUInfo._Data.uiEntries = 128;
- break;
- case 0x5d: // cfg = 0x5D: data TLB present, 4 KB / 4 MB pages, fully associative, 256 entries
- CPUInfo._Data.bPresent = true;
- strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB"); /* Flawfinder: ignore */
- CPUInfo._Data.uiAssociativeWays = (unsigned int) -1;
- CPUInfo._Data.uiEntries = 256;
- break;
- case 0x66: // cfg = 0x66: data L1 cache present, 8 KB, 4 ways, 64 byte lines, sectored
- CPUInfo._L1.Data.bPresent = true;
- strcpy(CPUInfo._L1.Data.strSize, "8 KB"); /* Flawfinder: ignore */
- CPUInfo._L1.Data.uiAssociativeWays = 4;
- CPUInfo._L1.Data.uiLineSize = 64;
- break;
- case 0x67: // cfg = 0x67: data L1 cache present, 16 KB, 4 ways, 64 byte lines, sectored
- CPUInfo._L1.Data.bPresent = true;
- strcpy(CPUInfo._L1.Data.strSize, "16 KB"); /* Flawfinder: ignore */
- CPUInfo._L1.Data.uiAssociativeWays = 4;
- CPUInfo._L1.Data.uiLineSize = 64;
- break;
- case 0x68: // cfg = 0x68: data L1 cache present, 32 KB, 4 ways, 64 byte lines, sectored
- CPUInfo._L1.Data.bPresent = true;
- strcpy(CPUInfo._L1.Data.strSize, "32 KB"); /* Flawfinder: ignore */
- CPUInfo._L1.Data.uiAssociativeWays = 4;
- CPUInfo._L1.Data.uiLineSize = 64;
- break;
- case 0x70: // cfg = 0x70: trace L1 cache present, 12 KuOPs, 4 ways
- CPUInfo._Trace.bPresent = true;
- strcpy(CPUInfo._Trace.strSize, "12 K-micro-ops"); /* Flawfinder: ignore */
- CPUInfo._Trace.uiAssociativeWays = 4;
- break;
- case 0x71: // cfg = 0x71: trace L1 cache present, 16 KuOPs, 4 ways
- CPUInfo._Trace.bPresent = true;
- strcpy(CPUInfo._Trace.strSize, "16 K-micro-ops"); /* Flawfinder: ignore */
- CPUInfo._Trace.uiAssociativeWays = 4;
- break;
- case 0x72: // cfg = 0x72: trace L1 cache present, 32 KuOPs, 4 ways
- CPUInfo._Trace.bPresent = true;
- strcpy(CPUInfo._Trace.strSize, "32 K-micro-ops"); /* Flawfinder: ignore */
- CPUInfo._Trace.uiAssociativeWays = 4;
- break;
- case 0x79: // cfg = 0x79: code and data L2 cache present, 128 KB, 8 ways, 64 byte lines, sectored
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "128 KB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 8;
- CPUInfo._L2.uiLineSize = 64;
- CPUInfo._L2.bSectored = true;
- break;
- case 0x7A: // cfg = 0x7A: code and data L2 cache present, 256 KB, 8 ways, 64 byte lines, sectored
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "256 KB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 8;
- CPUInfo._L2.uiLineSize = 64;
- CPUInfo._L2.bSectored = true;
- break;
- case 0x7B: // cfg = 0x7B: code and data L2 cache present, 512 KB, 8 ways, 64 byte lines, sectored
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 8;
- CPUInfo._L2.uiLineSize = 64;
- CPUInfo._L2.bSectored = true;
- break;
- case 0x7C: // cfg = 0x7C: code and data L2 cache present, 1024 KB, 8 ways, 64 byte lines, sectored
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 8;
- CPUInfo._L2.uiLineSize = 64;
- CPUInfo._L2.bSectored = true;
- break;
- case 0x81: // cfg = 0x81: code and data L2 cache present, 128 KB, 8 ways, 32 byte lines
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "128 KB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 8;
- CPUInfo._L2.uiLineSize = 32;
- break;
- case 0x82: // cfg = 0x82: code and data L2 cache present, 256 KB, 8 ways, 32 byte lines
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "256 KB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 8;
- CPUInfo._L2.uiLineSize = 32;
- break;
- case 0x83: // cfg = 0x83: code and data L2 cache present, 512 KB, 8 ways, 32 byte lines
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "512 KB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 8;
- CPUInfo._L2.uiLineSize = 32;
- break;
- case 0x84: // cfg = 0x84: code and data L2 cache present, 1024 KB, 8 ways, 32 byte lines
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "1 MB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 8;
- CPUInfo._L2.uiLineSize = 32;
- break;
- case 0x85: // cfg = 0x85: code and data L2 cache present, 2048 KB, 8 ways, 32 byte lines
- CPUInfo._L2.bPresent = true;
- strcpy(CPUInfo._L2.strSize, "2 MB"); /* Flawfinder: ignore */
- CPUInfo._L2.uiAssociativeWays = 8;
- CPUInfo._L2.uiLineSize = 32;
- break;
- }
-}
-
-FORCEINLINE static char *TranslateAssociativeWays(unsigned int uiWays, char *buf)
-{
- // We define 0xFFFFFFFF (= -1) as fully associative
- if (uiWays == ((unsigned int) -1))
- strcpy(buf, "fully associative"); /* Flawfinder: ignore */
- else
- {
- if (uiWays == 1) // A one way associative cache is just direct mapped
- strcpy(buf, "direct mapped"); /* Flawfinder: ignore */
- else if (uiWays == 0) // This should not happen...
- strcpy(buf, "unknown associative ways"); /* Flawfinder: ignore */
- else // The x-way associative cache
- sprintf(buf, "%d ways associative", uiWays); /* Flawfinder: ignore */
- }
- // To ease the function use we return the buffer
- return buf;
-}
-FORCEINLINE static void TranslateTLB(ProcessorTLB *tlb)
-{
- char buf[64]; /* Flawfinder: ignore */
-
- // We just check if the TLB is present
- if (tlb->bPresent)
- snprintf(tlb->strTLB,sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries); /* Flawfinder: ignore */
- else
- strcpy(tlb->strTLB, "Not present"); /* Flawfinder: ignore */
-}
-FORCEINLINE static void TranslateCache(ProcessorCache *cache)
-{
- char buf[64]; /* Flawfinder: ignore */
-
- // We just check if the cache is present
- if (cache->bPresent)
- {
- // If present we construct the string
- snprintf(cache->strCache, sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */
- if (cache->bSectored)
- strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1); /* Flawfinder: ignore */
- }
- else
- {
- // Else we just say "Not present"
- strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */
- }
-}
-
-// void CProcessor::TranslateProcessorConfiguration()
-// ==================================================
-// Private class function to translate the processor configuration values
-// to strings
-/////////////////////////////////////////////////////////////////////////
-void CProcessor::TranslateProcessorConfiguration()
-{
- // We just call the small functions defined above
- TranslateTLB(&CPUInfo._Data);
- TranslateTLB(&CPUInfo._Instruction);
-
- TranslateCache(&CPUInfo._Trace);
-
- TranslateCache(&CPUInfo._L1.Instruction);
- TranslateCache(&CPUInfo._L1.Data);
- TranslateCache(&CPUInfo._L2);
- TranslateCache(&CPUInfo._L3);
-}
-
-// void CProcessor::GetStandardProcessorConfiguration()
-// ====================================================
-// Private class function to read the standard processor configuration
-//////////////////////////////////////////////////////////////////////
-void CProcessor::GetStandardProcessorConfiguration()
-{
-#if LL_WINDOWS
- unsigned long eaxreg, ebxreg, ecxreg, edxreg;
-
- // We check if the CPUID function is available
- if (!CheckCPUIDPresence())
- return;
-
- // First we check if the processor supports the standard
- // CPUID level 0x00000002
- if (CPUInfo.MaxSupportedLevel >= 2)
- {
- // Now we go read the std. CPUID level 0x00000002 the first time
- unsigned long count, num = 255;
- for (count = 0; count < num; count++)
- {
- __asm
- {
- mov eax, 2
- cpuid
- mov eaxreg, eax
- mov ebxreg, ebx
- mov ecxreg, ecx
- mov edxreg, edx
- }
- // We have to repeat this reading for 'num' times
- num = eaxreg & 0xFF;
-
- // Then we call the big decode switch function
- DecodeProcessorConfiguration(eaxreg >> 8);
- DecodeProcessorConfiguration(eaxreg >> 16);
- DecodeProcessorConfiguration(eaxreg >> 24);
-
- // If ebx contains additional data we also decode it
- if ((ebxreg & 0x80000000) == 0)
- {
- DecodeProcessorConfiguration(ebxreg);
- DecodeProcessorConfiguration(ebxreg >> 8);
- DecodeProcessorConfiguration(ebxreg >> 16);
- DecodeProcessorConfiguration(ebxreg >> 24);
- }
- // And also the ecx register
- if ((ecxreg & 0x80000000) == 0)
- {
- DecodeProcessorConfiguration(ecxreg);
- DecodeProcessorConfiguration(ecxreg >> 8);
- DecodeProcessorConfiguration(ecxreg >> 16);
- DecodeProcessorConfiguration(ecxreg >> 24);
- }
- // At last the edx processor register
- if ((edxreg & 0x80000000) == 0)
- {
- DecodeProcessorConfiguration(edxreg);
- DecodeProcessorConfiguration(edxreg >> 8);
- DecodeProcessorConfiguration(edxreg >> 16);
- DecodeProcessorConfiguration(edxreg >> 24);
+ setConfig(eCacheLineSize, cpu_info[2] & 0xff);
+ setConfig(eL2Associativity, (cpu_info[2] >> 12) & 0xf);
+ setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff);
}
}
}
-#endif
-}
+};
-// void CProcessor::GetStandardProcessorExtensions()
-// =================================================
-// Private class function to read the standard processor extensions
-///////////////////////////////////////////////////////////////////
-void CProcessor::GetStandardProcessorExtensions()
-{
-#if LL_WINDOWS
- unsigned long ebxreg, edxreg;
-
- // We check if the CPUID command is available
- if (!CheckCPUIDPresence())
- return;
- // We just get the standard CPUID level 0x00000001 which should be
- // available on every x86 processor
- __asm
- {
- mov eax, 1
- cpuid
- mov ebxreg, ebx
- mov edxreg, edx
- }
-
- // Then we mask some bits
- CPUInfo._Ext.FPU_FloatingPointUnit = CheckBit(edxreg, 0);
- CPUInfo._Ext.VME_Virtual8086ModeEnhancements = CheckBit(edxreg, 1);
- CPUInfo._Ext.DE_DebuggingExtensions = CheckBit(edxreg, 2);
- CPUInfo._Ext.PSE_PageSizeExtensions = CheckBit(edxreg, 3);
- CPUInfo._Ext.TSC_TimeStampCounter = CheckBit(edxreg, 4);
- CPUInfo._Ext.MSR_ModelSpecificRegisters = CheckBit(edxreg, 5);
- CPUInfo._Ext.PAE_PhysicalAddressExtension = CheckBit(edxreg, 6);
- CPUInfo._Ext.MCE_MachineCheckException = CheckBit(edxreg, 7);
- CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = CheckBit(edxreg, 8);
- CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController = CheckBit(edxreg, 9);
- CPUInfo._Ext.APIC_ID = (ebxreg >> 24) & 0xFF;
- CPUInfo._Ext.SEP_FastSystemCall = CheckBit(edxreg, 11);
- CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters = CheckBit(edxreg, 12);
- CPUInfo._Ext.PGE_PTE_GlobalFlag = CheckBit(edxreg, 13);
- CPUInfo._Ext.MCA_MachineCheckArchitecture = CheckBit(edxreg, 14);
- CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions = CheckBit(edxreg, 15);
- CPUInfo._Ext.FGPAT_PageAttributeTable = CheckBit(edxreg, 16);
- CPUInfo._Ext.PSE36_36bitPageSizeExtension = CheckBit(edxreg, 17);
- CPUInfo._Ext.PN_ProcessorSerialNumber = CheckBit(edxreg, 18);
- CPUInfo._Ext.CLFSH_CFLUSH_Instruction = CheckBit(edxreg, 19);
- CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize = (ebxreg >> 8) & 0xFF;
- CPUInfo._Ext.DS_DebugStore = CheckBit(edxreg, 21);
- CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl = CheckBit(edxreg, 22);
- CPUInfo._Ext.MMX_MultimediaExtensions = CheckBit(edxreg, 23);
- CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = CheckBit(edxreg, 24);
- CPUInfo._Ext.SSE_StreamingSIMD_Extensions = CheckBit(edxreg, 25);
- CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = CheckBit(edxreg, 26);
- CPUInfo._Ext.Altivec_Extensions = false;
- CPUInfo._Ext.SS_SelfSnoop = CheckBit(edxreg, 27);
- CPUInfo._Ext.HT_HyperThreading = CheckBit(edxreg, 28);
- CPUInfo._Ext.HT_HyterThreadingSiblings = (ebxreg >> 16) & 0xFF;
- CPUInfo._Ext.TM_ThermalMonitor = CheckBit(edxreg, 29);
- CPUInfo._Ext.IA64_Intel64BitArchitecture = CheckBit(edxreg, 30);
-#endif
-}
-
-// const ProcessorInfo *CProcessor::GetCPUInfo()
-// =============================================
-// Calls all the other detection function to create an detailed
-// processor information
-///////////////////////////////////////////////////////////////
-const ProcessorInfo *CProcessor::GetCPUInfo()
-{
-#if LL_WINDOWS
- unsigned long eaxreg, ebxreg, ecxreg, edxreg;
-
- // First of all we check if the CPUID command is available
- if (!CheckCPUIDPresence())
- return NULL;
-
- // We read the standard CPUID level 0x00000000 which should
- // be available on every x86 processor
- __asm
- {
- mov eax, 0
- cpuid
- mov eaxreg, eax
- mov ebxreg, ebx
- mov edxreg, edx
- mov ecxreg, ecx
- }
- // Then we connect the single register values to the vendor string
- *((unsigned long *) CPUInfo.strVendor) = ebxreg;
- *((unsigned long *) (CPUInfo.strVendor+4)) = edxreg;
- *((unsigned long *) (CPUInfo.strVendor+8)) = ecxreg;
- // Null terminate for string comparisons below.
- CPUInfo.strVendor[12] = 0;
-
- // We can also read the max. supported standard CPUID level
- CPUInfo.MaxSupportedLevel = eaxreg & 0xFFFF;
-
- // Then we read the ext. CPUID level 0x80000000
- __asm
- {
- mov eax, 0x80000000
- cpuid
- mov eaxreg, eax
- }
- // ...to check the max. supportted extended CPUID level
- CPUInfo.MaxSupportedExtendedLevel = eaxreg;
-
- // Then we switch to the specific processor vendors
- // See http://www.sandpile.org/ia32/cpuid.htm
- if (!strcmp(CPUInfo.strVendor, "GenuineIntel"))
- {
- AnalyzeIntelProcessor();
- }
- else if (!strcmp(CPUInfo.strVendor, "AuthenticAMD"))
- {
- AnalyzeAMDProcessor();
- }
- else if (!strcmp(CPUInfo.strVendor, "UMC UMC UMC"))
- {
- AnalyzeUnknownProcessor();
- }
- else if (!strcmp(CPUInfo.strVendor, "CyrixInstead"))
- {
- AnalyzeUnknownProcessor();
- }
- else if (!strcmp(CPUInfo.strVendor, "NexGenDriven"))
- {
- AnalyzeUnknownProcessor();
- }
- else if (!strcmp(CPUInfo.strVendor, "CentaurHauls"))
- {
- AnalyzeUnknownProcessor();
- }
- else if (!strcmp(CPUInfo.strVendor, "RiseRiseRise"))
- {
- AnalyzeUnknownProcessor();
- }
- else if (!strcmp(CPUInfo.strVendor, "SiS SiS SiS"))
- {
- AnalyzeUnknownProcessor();
- }
- else if (!strcmp(CPUInfo.strVendor, "GenuineTMx86"))
- {
- // Transmeta
- AnalyzeUnknownProcessor();
- }
- else if (!strcmp(CPUInfo.strVendor, "Geode by NSC"))
- {
- AnalyzeUnknownProcessor();
- }
- else
- {
- AnalyzeUnknownProcessor();
- }
-#endif
- // After all we return the class CPUInfo member var
- return (&CPUInfo);
-}
-
-#elif LL_SOLARIS
-#include
-
-#if defined(__i386)
-#include
-#endif
-
-// ======================
-// Class constructor:
-/////////////////////////
-CProcessor::CProcessor()
-{
- uqwFrequency = 0;
- strCPUName[0] = 0;
- memset(&CPUInfo, 0, sizeof(CPUInfo));
-}
-
-// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
-// =========================================================================
-// Function to query the current CPU frequency
-////////////////////////////////////////////////////////////////////////////
-F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/)
-{
- if(uqwFrequency == 0){
- GetCPUInfo();
- }
-
- return uqwFrequency;
-}
-
-// const ProcessorInfo *CProcessor::GetCPUInfo()
-// =============================================
-// Calls all the other detection function to create an detailed
-// processor information
-///////////////////////////////////////////////////////////////
-const ProcessorInfo *CProcessor::GetCPUInfo()
-{
- // In Solaris the CPU info is in the kstats
- // try "psrinfo" or "kstat cpu_info" to see all
- // that's available
- int ncpus=0, i;
- kstat_ctl_t *kc;
- kstat_t *ks;
- kstat_named_t *ksinfo, *ksi;
- kstat_t *CPU_stats_list;
-
- kc = kstat_open();
-
- if((int)kc == -1){
- llwarns << "kstat_open(0 failed!" << llendl;
- return (&CPUInfo);
- }
-
- for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next) {
- if (strncmp(ks->ks_module, "cpu_info", 8) == 0 &&
- strncmp(ks->ks_name, "cpu_info", 8) == 0)
- ncpus++;
- }
-
- if(ncpus < 1){
- llwarns << "No cpus found in kstats!" << llendl;
- return (&CPUInfo);
- }
-
- for (ks = kc->kc_chain; ks; ks = ks->ks_next) {
- if (strncmp(ks->ks_module, "cpu_info", 8) == 0
- && strncmp(ks->ks_name, "cpu_info", 8) == 0
- && kstat_read(kc, ks, NULL) != -1){
- CPU_stats_list = ks; // only looking at the first CPU
-
- break;
- }
- }
-
- if(ncpus > 1)
- snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpus);
-
- kstat_read(kc, CPU_stats_list, NULL);
- ksinfo = (kstat_named_t *)CPU_stats_list->ks_data;
- for(i=0; i < (int)(CPU_stats_list->ks_ndata); ++i){ // Walk the kstats for this cpu gathering what we need
- ksi = ksinfo++;
- if(!strcmp(ksi->name, "brand")){
- strncat(strCPUName, (char *)KSTAT_NAMED_STR_PTR(ksi),
- sizeof(strCPUName)-strlen(strCPUName)-1);
- strncat(CPUInfo.strFamily, (char *)KSTAT_NAMED_STR_PTR(ksi),
- sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);
- strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1);
- CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
- // DEBUG llinfos << "CPU brand: " << strCPUName << llendl;
- continue;
- }
-
- if(!strcmp(ksi->name, "clock_MHz")){
-#if defined(__sparc)
- llinfos << "Raw kstat clock rate is: " << ksi->value.l << llendl;
- uqwFrequency = (F64)(ksi->value.l * 1000000);
-#else
- uqwFrequency = (F64)(ksi->value.i64 * 1000000);
-#endif
- //DEBUG llinfos << "CPU frequency: " << uqwFrequency << llendl;
- continue;
- }
-
-#if defined(__i386)
- if(!strcmp(ksi->name, "vendor_id")){
- strncpy(CPUInfo.strVendor, (char *)KSTAT_NAMED_STR_PTR(ksi), sizeof(CPUInfo.strVendor)-1);
- // DEBUG llinfos << "CPU vendor: " << CPUInfo.strVendor << llendl;
- continue;
- }
-#endif
- }
-
- kstat_close(kc);
-
-#if defined(__sparc) // SPARC does not define a vendor string in kstat
- strncpy(CPUInfo.strVendor, "Sun Microsystems, Inc.", sizeof(CPUInfo.strVendor)-1);
-#endif
-
- // DEBUG llinfo << "The system has " << ncpus << " CPUs with a clock rate of " << uqwFrequency << "MHz." << llendl;
-
-#if defined (__i386) // we really don't care about the CPU extensions on SPARC but on x86...
-
- // Now get cpu extensions
-
- uint_t ui;
-
- (void) getisax(&ui, 1);
-
- if(ui & AV_386_FPU)
- CPUInfo._Ext.FPU_FloatingPointUnit = true;
- if(ui & AV_386_CX8)
- CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = true;
- if(ui & AV_386_MMX)
- CPUInfo._Ext.MMX_MultimediaExtensions = true;
- if(ui & AV_386_AMD_MMX)
- CPUInfo._Ext.MMX_MultimediaExtensions = true;
- if(ui & AV_386_FXSR)
- CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = true;
- if(ui & AV_386_SSE)
- CPUInfo._Ext.SSE_StreamingSIMD_Extensions = true;
- if(ui & AV_386_SSE2)
- CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = true;
-/* Left these here since they may get used later
- if(ui & AV_386_SSE3)
- CPUInfo._Ext.... = true;
- if(ui & AV_386_AMD_3DNow)
- CPUInfo._Ext.... = true;
- if(ui & AV_386_AMD_3DNowx)
- CPUInfo._Ext.... = true;
-*/
-#endif
- return (&CPUInfo);
-}
-
-#else
-// LL_DARWIN
+#elif LL_DARWIN
#include
#include
-static char *TranslateAssociativeWays(unsigned int uiWays, char *buf)
+class LLProcessorInfoDarwinImpl : public LLProcessorInfoImpl
{
- // We define 0xFFFFFFFF (= -1) as fully associative
- if (uiWays == ((unsigned int) -1))
- strcpy(buf, "fully associative"); /* Flawfinder: ignore */
- else
+public:
+ LLProcessorInfoDarwinImpl()
{
- if (uiWays == 1) // A one way associative cache is just direct mapped
- strcpy(buf, "direct mapped"); /* Flawfinder: ignore */
- else if (uiWays == 0) // This should not happen...
- strcpy(buf, "unknown associative ways"); /* Flawfinder: ignore */
- else // The x-way associative cache
- sprintf(buf, "%d ways associative", uiWays); /* Flawfinder: ignore */
+ getCPUIDInfo();
+ uint64_t frequency = getSysctlInt64("hw.cpufrequency");
+ setInfo(eFrequency, (F64)frequency / (F64)1000000);
}
- // To ease the function use we return the buffer
- return buf;
-}
-static void TranslateTLB(ProcessorTLB *tlb)
-{
- char buf[64]; /* Flawfinder: ignore */
- // We just check if the TLB is present
- if (tlb->bPresent)
- snprintf(tlb->strTLB, sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries); /* Flawfinder: ignore */
- else
- strcpy(tlb->strTLB, "Not present"); /* Flawfinder: ignore */
-}
-static void TranslateCache(ProcessorCache *cache)
-{
- char buf[64]; /* Flawfinder: ignore */
+ virtual ~LLProcessorInfoDarwinImpl() {}
- // We just check if the cache is present
- if (cache->bPresent)
+private:
+ int getSysctlInt(const char* name)
+ {
+ int result = 0;
+ size_t len = sizeof(int);
+ int error = sysctlbyname(name, (void*)&result, &len, NULL, 0);
+ return error == -1 ? 0 : result;
+ }
+
+ uint64_t getSysctlInt64(const char* name)
+ {
+ uint64_t value = 0;
+ size_t size = sizeof(value);
+ int result = sysctlbyname(name, (void*)&value, &size, NULL, 0);
+ if ( result == 0 )
+ {
+ if ( size == sizeof( uint64_t ) )
+ ;
+ else if ( size == sizeof( uint32_t ) )
+ value = (uint64_t)(( uint32_t *)&value);
+ else if ( size == sizeof( uint16_t ) )
+ value = (uint64_t)(( uint16_t *)&value);
+ else if ( size == sizeof( uint8_t ) )
+ value = (uint64_t)(( uint8_t *)&value);
+ else
+ {
+ LL_WARNS("Unknown type returned from sysctl!") << LL_ENDL;
+ }
+ }
+
+ return result == -1 ? 0 : value;
+ }
+
+ void getCPUIDInfo()
{
- // If present we construct the string
- snprintf(cache->strCache,sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize); /* Flawfinder: ignore */
- if (cache->bSectored)
- strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1); /* Flawfinder: ignore */
+ size_t len = 0;
+
+ char cpu_brand_string[0x40];
+ len = sizeof(cpu_brand_string);
+ memset(cpu_brand_string, 0, len);
+ sysctlbyname("machdep.cpu.brand_string", (void*)cpu_brand_string, &len, NULL, 0);
+ cpu_brand_string[0x3f] = 0;
+ setInfo(eBrandName, cpu_brand_string);
+
+ char cpu_vendor[0x20];
+ len = sizeof(cpu_vendor);
+ memset(cpu_vendor, 0, len);
+ sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0);
+ cpu_vendor[0x1f] = 0;
+ setInfo(eVendor, cpu_vendor);
+
+ setInfo(eStepping, getSysctlInt("machdep.cpu.stepping"));
+ setInfo(eModel, getSysctlInt("machdep.cpu.model"));
+ int family = getSysctlInt("machdep.cpu.family");
+ int ext_family = getSysctlInt("machdep.cpu.extfamily");
+ setInfo(eFamily, family);
+ setInfo(eExtendedFamily, ext_family);
+ setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family));
+ setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel"));
+ setInfo(eBrandID, getSysctlInt("machdep.cpu.brand"));
+ setInfo(eType, 0); // ? where to find this?
+
+ //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
+ //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
+ setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize"));
+ setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity"));
+ setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size"));
+
+ uint64_t feature_info = getSysctlInt64("machdep.cpu.feature_bits");
+ S32 *feature_infos = (S32*)(&feature_info);
+
+ setConfig(eFeatureBits, feature_infos[0]);
+
+ for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1)
+ {
+ if(feature_info & bit)
+ {
+ setExtension(cpu_feature_names[index]);
+ }
+ }
+
+ // *NOTE:Mani - I didn't find any docs that assure me that machdep.cpu.feature_bits will always be
+ // The feature bits I think it is. Here's a test:
+#ifndef LL_RELEASE_FOR_DOWNLOAD
+ #if defined(__i386__) && defined(__PIC__)
+ /* %ebx may be the PIC register. */
+ #define __cpuid(level, a, b, c, d) \
+ __asm__ ("xchgl\t%%ebx, %1\n\t" \
+ "cpuid\n\t" \
+ "xchgl\t%%ebx, %1\n\t" \
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+ : "0" (level))
+ #else
+ #define __cpuid(level, a, b, c, d) \
+ __asm__ ("cpuid\n\t" \
+ : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
+ : "0" (level))
+ #endif
+
+ unsigned int eax, ebx, ecx, edx;
+ __cpuid(0x1, eax, ebx, ecx, edx);
+ if(feature_infos[0] != (S32)edx)
+ {
+ llerrs << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << llendl;
+ }
+#endif // LL_RELEASE_FOR_DOWNLOAD
+
+
+ uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits");
+ S32 *ext_feature_infos = (S32*)(&ext_feature_info);
+ setConfig(eExtFeatureBits, ext_feature_infos[0]);
}
- else
+};
+
+#elif LL_LINUX
+const char CPUINFO_FILE[] = "/proc/cpuinfo";
+
+class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl
+{
+public:
+ LLProcessorInfoLinuxImpl()
{
- // Else we just say "Not present"
- strcpy(cache->strCache, "Not present"); /* Flawfinder: ignore */
+ get_proc_cpuinfo();
+ }
+
+ virtual ~LLProcessorInfoLinuxImpl() {}
+private:
+
+ void get_proc_cpuinfo()
+ {
+ std::map< std::string, std::string > cpuinfo;
+ LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb");
+ if(cpuinfo_fp)
+ {
+ char line[MAX_STRING];
+ memset(line, 0, MAX_STRING);
+ while(fgets(line, MAX_STRING, cpuinfo_fp))
+ {
+ // /proc/cpuinfo on Linux looks like:
+ // name\t*: value\n
+ char* tabspot = strchr( line, '\t' );
+ if (tabspot == NULL)
+ continue;
+ char* colspot = strchr( tabspot, ':' );
+ if (colspot == NULL)
+ continue;
+ char* spacespot = strchr( colspot, ' ' );
+ if (spacespot == NULL)
+ continue;
+ char* nlspot = strchr( line, '\n' );
+ if (nlspot == NULL)
+ nlspot = line + strlen( line ); // Fallback to terminating NUL
+ std::string linename( line, tabspot );
+ std::string llinename(linename);
+ LLStringUtil::toLower(llinename);
+ std::string lineval( spacespot + 1, nlspot );
+ cpuinfo[ llinename ] = lineval;
+ }
+ fclose(cpuinfo_fp);
+ }
+# if LL_X86
+
+// *NOTE:Mani - eww, macros! srry.
+#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \
+ if (!cpuinfo[cpuinfo_id].empty()) \
+ { setInfo(llpi_id, cpuinfo[cpuinfo_id]);}
+
+#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \
+ {\
+ S32 result; \
+ if (!cpuinfo[cpuinfo_id].empty() \
+ && LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result)) \
+ { setInfo(llpi_id, result);} \
+ }
+
+ F64 mhz;
+ if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz)
+ && 200.0 < mhz && mhz < 10000.0)
+ {
+ setInfo(eFrequency,(F64)(mhz));
+ }
+
+ LLPI_SET_INFO_STRING(eBrandName, "model name");
+ LLPI_SET_INFO_STRING(eVendor, "vendor_id");
+
+ LLPI_SET_INFO_INT(eStepping, "stepping");
+ LLPI_SET_INFO_INT(eModel, "model");
+
+
+ S32 family;
+ if (!cpuinfo["cpu family"].empty()
+ && LLStringUtil::convertToS32(cpuinfo["cpu family"], family))
+ {
+ setInfo(eFamily, family);
+ }
+
+ setInfo(eFamilyName, compute_CPUFamilyName(cpuinfo["vendor_id"].c_str(), family));
+
+ // setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel"));
+ // setInfo(eBrandID, getSysctlInt("machdep.cpu.brand"));
+ // setInfo(eType, 0); // ? where to find this?
+
+ //setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8);
+ //setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff);
+ //setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize"));
+ //setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity"));
+ //setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size"));
+
+ // Read extensions
+ std::string flags = " " + cpuinfo["flags"] + " ";
+ LLStringUtil::toLower(flags);
+
+ if( flags.find( " sse " ) != std::string::npos )
+ {
+ setExtension(cpu_feature_names[eSSE_Ext]);
+ }
+
+ if( flags.find( " sse2 " ) != std::string::npos )
+ {
+ setExtension(cpu_feature_names[eSSE2_Ext]);
+ }
+
+# endif // LL_X86
+ }
+
+ std::string getCPUFeatureDescription() const
+ {
+ std::ostringstream s;
+
+ // *NOTE:Mani - This is for linux only.
+ LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb");
+ if(cpuinfo)
+ {
+ char line[MAX_STRING];
+ memset(line, 0, MAX_STRING);
+ while(fgets(line, MAX_STRING, cpuinfo))
+ {
+ line[strlen(line)-1] = ' ';
+ s << line;
+ s << std::endl;
+ }
+ fclose(cpuinfo);
+ s << std::endl;
+ }
+ else
+ {
+ s << "Unable to collect processor information" << std::endl;
+ }
+ return s.str();
+ }
+
+};
+
+
+#endif // LL_MSVC elif LL_DARWIN elif LL_LINUX
+
+//////////////////////////////////////////////////////
+// Interface definition
+LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
+{
+ // *NOTE:Mani - not thread safe.
+ if(!mImpl)
+ {
+#ifdef LL_MSVC
+ static LLProcessorInfoWindowsImpl the_impl;
+ mImpl = &the_impl;
+#elif LL_DARWIN
+ static LLProcessorInfoDarwinImpl the_impl;
+ mImpl = &the_impl;
+#else
+ static LLProcessorInfoLinuxImpl the_impl;
+ mImpl = &the_impl;
+#endif // LL_MSVC
}
}
-// void CProcessor::TranslateProcessorConfiguration()
-// ==================================================
-// Private class function to translate the processor configuration values
-// to strings
-/////////////////////////////////////////////////////////////////////////
-void CProcessor::TranslateProcessorConfiguration()
-{
- // We just call the small functions defined above
- TranslateTLB(&CPUInfo._Data);
- TranslateTLB(&CPUInfo._Instruction);
- TranslateCache(&CPUInfo._Trace);
+LLProcessorInfo::~LLProcessorInfo() {}
+F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
+bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); }
+bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); }
+bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); }
+std::string LLProcessorInfo::getCPUFamilyName() const { return mImpl->getCPUFamilyName(); }
+std::string LLProcessorInfo::getCPUBrandName() const { return mImpl->getCPUBrandName(); }
+std::string LLProcessorInfo::getCPUFeatureDescription() const { return mImpl->getCPUFeatureDescription(); }
- TranslateCache(&CPUInfo._L1.Instruction);
- TranslateCache(&CPUInfo._L1.Data);
- TranslateCache(&CPUInfo._L2);
- TranslateCache(&CPUInfo._L3);
-}
-
-// CProcessor::CProcessor
-// ======================
-// Class constructor:
-/////////////////////////
-CProcessor::CProcessor()
-{
- uqwFrequency = 0;
- strCPUName[0] = 0;
- memset(&CPUInfo, 0, sizeof(CPUInfo));
-}
-
-// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)
-// =========================================================================
-// Function to query the current CPU frequency
-////////////////////////////////////////////////////////////////////////////
-F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/)
-{
- U64 frequency = 0;
- size_t len = sizeof(frequency);
-
- if(sysctlbyname("hw.cpufrequency", &frequency, &len, NULL, 0) == 0)
- {
- uqwFrequency = (F64)frequency;
- }
-
- return uqwFrequency;
-}
-
-static bool hasFeature(const char *name)
-{
- bool result = false;
- int val = 0;
- size_t len = sizeof(val);
-
- if(sysctlbyname(name, &val, &len, NULL, 0) == 0)
- {
- if(val != 0)
- result = true;
- }
-
- return result;
-}
-
-// const ProcessorInfo *CProcessor::GetCPUInfo()
-// =============================================
-// Calls all the other detection function to create an detailed
-// processor information
-///////////////////////////////////////////////////////////////
-const ProcessorInfo *CProcessor::GetCPUInfo()
-{
- int pagesize = 0;
- int cachelinesize = 0;
- int l1icachesize = 0;
- int l1dcachesize = 0;
- int l2settings = 0;
- int l2cachesize = 0;
- int l3settings = 0;
- int l3cachesize = 0;
- int ncpu = 0;
- int cpusubtype = 0;
-
- // sysctl knows all.
- int mib[2];
- size_t len;
- mib[0] = CTL_HW;
-
- mib[1] = HW_PAGESIZE;
- len = sizeof(pagesize);
- sysctl(mib, 2, &pagesize, &len, NULL, 0);
-
- mib[1] = HW_CACHELINE;
- len = sizeof(cachelinesize);
- sysctl(mib, 2, &cachelinesize, &len, NULL, 0);
-
- mib[1] = HW_L1ICACHESIZE;
- len = sizeof(l1icachesize);
- sysctl(mib, 2, &l1icachesize, &len, NULL, 0);
-
- mib[1] = HW_L1DCACHESIZE;
- len = sizeof(l1dcachesize);
- sysctl(mib, 2, &l1dcachesize, &len, NULL, 0);
-
- mib[1] = HW_L2SETTINGS;
- len = sizeof(l2settings);
- sysctl(mib, 2, &l2settings, &len, NULL, 0);
-
- mib[1] = HW_L2CACHESIZE;
- len = sizeof(l2cachesize);
- sysctl(mib, 2, &l2cachesize, &len, NULL, 0);
-
- mib[1] = HW_L3SETTINGS;
- len = sizeof(l3settings);
- sysctl(mib, 2, &l3settings, &len, NULL, 0);
-
- mib[1] = HW_L3CACHESIZE;
- len = sizeof(l3cachesize);
- sysctl(mib, 2, &l3cachesize, &len, NULL, 0);
-
- mib[1] = HW_NCPU;
- len = sizeof(ncpu);
- sysctl(mib, 2, &ncpu, &len, NULL, 0);
-
- sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0);
-
- strCPUName[0] = 0;
-
- if((ncpu == 0) || (ncpu == 1))
- {
- // Uhhh...
- }
- else if(ncpu == 2)
- {
- strncat(strCPUName, "Dual ", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- }
- else
- {
- snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpu); /* Flawfinder: ignore */
- }
-
-#if __ppc__
- switch(cpusubtype)
- {
- case CPU_SUBTYPE_POWERPC_601:// ((cpu_subtype_t) 1)
- strncat(strCPUName, "PowerPC 601", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
-
- break;
- case CPU_SUBTYPE_POWERPC_602:// ((cpu_subtype_t) 2)
- strncat(strCPUName, "PowerPC 602", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
- case CPU_SUBTYPE_POWERPC_603:// ((cpu_subtype_t) 3)
- strncat(strCPUName, "PowerPC 603", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
- case CPU_SUBTYPE_POWERPC_603e:// ((cpu_subtype_t) 4)
- strncat(strCPUName, "PowerPC 603e", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
- case CPU_SUBTYPE_POWERPC_603ev:// ((cpu_subtype_t) 5)
- strncat(strCPUName, "PowerPC 603ev", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
- case CPU_SUBTYPE_POWERPC_604:// ((cpu_subtype_t) 6)
- strncat(strCPUName, "PowerPC 604", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
- case CPU_SUBTYPE_POWERPC_604e:// ((cpu_subtype_t) 7)
- strncat(strCPUName, "PowerPC 604e", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
- case CPU_SUBTYPE_POWERPC_620:// ((cpu_subtype_t) 8)
- strncat(strCPUName, "PowerPC 620", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
- case CPU_SUBTYPE_POWERPC_750:// ((cpu_subtype_t) 9)
- strncat(strCPUName, "PowerPC 750", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC G3", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
- case CPU_SUBTYPE_POWERPC_7400:// ((cpu_subtype_t) 10)
- strncat(strCPUName, "PowerPC 7400", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
- case CPU_SUBTYPE_POWERPC_7450:// ((cpu_subtype_t) 11)
- strncat(strCPUName, "PowerPC 7450", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
- case CPU_SUBTYPE_POWERPC_970:// ((cpu_subtype_t) 100)
- strncat(strCPUName, "PowerPC 970", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- strncat(CPUInfo.strFamily, "PowerPC G5", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); /* Flawfinder: ignore */
- break;
-
- default:
- strncat(strCPUName, "PowerPC (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- }
-
- CPUInfo._Ext.EMMX_MultimediaExtensions =
- CPUInfo._Ext.MMX_MultimediaExtensions =
- CPUInfo._Ext.SSE_StreamingSIMD_Extensions =
- CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = false;
-
- CPUInfo._Ext.Altivec_Extensions = hasFeature("hw.optional.altivec");
-
-#endif
-
-#if __i386__
- // MBW -- XXX -- TODO -- make this call AnalyzeIntelProcessor()?
- switch(cpusubtype)
- {
- default:
- strncat(strCPUName, "i386 (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1); /* Flawfinder: ignore */
- break;
- }
-
- CPUInfo._Ext.EMMX_MultimediaExtensions = hasFeature("hw.optional.mmx"); // MBW -- XXX -- this may be wrong...
- CPUInfo._Ext.MMX_MultimediaExtensions = hasFeature("hw.optional.mmx");
- CPUInfo._Ext.SSE_StreamingSIMD_Extensions = hasFeature("hw.optional.sse");
- CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = hasFeature("hw.optional.sse2");
- CPUInfo._Ext.Altivec_Extensions = false;
- CPUInfo._Ext.AA64_AMD64BitArchitecture = hasFeature("hw.optional.x86_64");
-
-#endif
-
- // Terse CPU info uses this string...
- strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1); /* Flawfinder: ignore */
- CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0';
-
- // Fun cache config stuff...
-
- if(l1dcachesize != 0)
- {
- CPUInfo._L1.Data.bPresent = true;
- snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", l1dcachesize / 1024); /* Flawfinder: ignore */
-// CPUInfo._L1.Data.uiAssociativeWays = ???;
- CPUInfo._L1.Data.uiLineSize = cachelinesize;
- }
-
- if(l1icachesize != 0)
- {
- CPUInfo._L1.Instruction.bPresent = true;
- snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", l1icachesize / 1024); /* Flawfinder: ignore */
-// CPUInfo._L1.Instruction.uiAssociativeWays = ???;
- CPUInfo._L1.Instruction.uiLineSize = cachelinesize;
- }
-
- if(l2cachesize != 0)
- {
- CPUInfo._L2.bPresent = true;
- snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l2cachesize / 1024); /* Flawfinder: ignore */
-// CPUInfo._L2.uiAssociativeWays = ???;
- CPUInfo._L2.uiLineSize = cachelinesize;
- }
-
- if(l3cachesize != 0)
- {
- CPUInfo._L2.bPresent = true;
- snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l3cachesize / 1024); /* Flawfinder: ignore */
-// CPUInfo._L2.uiAssociativeWays = ???;
- CPUInfo._L2.uiLineSize = cachelinesize;
- }
-
- CPUInfo._Ext.FPU_FloatingPointUnit = hasFeature("hw.optional.floatingpoint");
-
-// printf("pagesize = 0x%x\n", pagesize);
-// printf("cachelinesize = 0x%x\n", cachelinesize);
-// printf("l1icachesize = 0x%x\n", l1icachesize);
-// printf("l1dcachesize = 0x%x\n", l1dcachesize);
-// printf("l2settings = 0x%x\n", l2settings);
-// printf("l2cachesize = 0x%x\n", l2cachesize);
-// printf("l3settings = 0x%x\n", l3settings);
-// printf("l3cachesize = 0x%x\n", l3cachesize);
-
- // After reading we translate the configuration to strings
- TranslateProcessorConfiguration();
-
- // After all we return the class CPUInfo member var
- return (&CPUInfo);
-}
-
-#endif // LL_DARWIN
-
-// bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen)
-// ======================================================================
-// Gets the frequency and processor information and writes it to a string
-/////////////////////////////////////////////////////////////////////////
-bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen)
-{
-#define LENCHECK len = (unsigned int) strlen(buf); if (len >= uiMaxLen) return false; strcpy(strBuffer, buf); strBuffer += len; /*Flawfinder: ignore*/
-#define COPYADD(str) strcpy(buf, str); LENCHECK; /* Flawfinder: ignore */
-#define FORMATADD(format, var) sprintf(buf, format, var); LENCHECK; /* Flawfinder: ignore */
-#define BOOLADD(str, boolvar) COPYADD(str); if (boolvar) { COPYADD(" Yes\n"); } else { COPYADD(" No\n"); }
-
- char buf[1024]; /* Flawfinder: ignore */
- unsigned int len;
-
- // First we have to get the frequency
- GetCPUFrequency(50);
-
- // Then we get the processor information
- GetCPUInfo();
-
- // Now we construct the string (see the macros at function beginning)
- strBuffer[0] = 0;
-
- COPYADD("// CPU General Information\n//////////////////////////\n");
- FORMATADD("Processor name: %s\n", strCPUName);
- FORMATADD("Frequency: %.2f MHz\n\n", (float) uqwFrequency / 1000000.0f);
- FORMATADD("Vendor: %s\n", CPUInfo.strVendor);
- FORMATADD("Family: %s\n", CPUInfo.strFamily);
- FORMATADD("Extended family: %d\n", CPUInfo.uiExtendedFamily);
- FORMATADD("Model: %s\n", CPUInfo.strModel);
- FORMATADD("Extended model: %d\n", CPUInfo.uiExtendedModel);
- FORMATADD("Type: %s\n", CPUInfo.strType);
- FORMATADD("Brand ID: %s\n", CPUInfo.strBrandID);
- if (CPUInfo._Ext.PN_ProcessorSerialNumber)
- {
- FORMATADD("Processor Serial: %s\n", CPUInfo.strProcessorSerial);
- }
- else
- {
- COPYADD("Processor Serial: Disabled\n");
- }
-#if !LL_SOLARIS // NOTE: Why bother printing all this when it's irrelavent
-
- COPYADD("\n\n// CPU Configuration\n////////////////////\n");
- FORMATADD("L1 instruction cache: %s\n", CPUInfo._L1.Instruction.strCache);
- FORMATADD("L1 data cache: %s\n", CPUInfo._L1.Data.strCache);
- FORMATADD("L2 cache: %s\n", CPUInfo._L2.strCache);
- FORMATADD("L3 cache: %s\n", CPUInfo._L3.strCache);
- FORMATADD("Trace cache: %s\n", CPUInfo._Trace.strCache);
- FORMATADD("Instruction TLB: %s\n", CPUInfo._Instruction.strTLB);
- FORMATADD("Data TLB: %s\n", CPUInfo._Data.strTLB);
- FORMATADD("Max Supported CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedLevel);
- FORMATADD("Max Supported Ext. CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedExtendedLevel);
-
- COPYADD("\n\n// CPU Extensions\n/////////////////\n");
- BOOLADD("AA64 AMD 64-bit Architecture: ", CPUInfo._Ext.AA64_AMD64BitArchitecture);
- BOOLADD("ACPI Thermal Monitor And Clock Control: ", CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl);
- BOOLADD("APIC Advanced Programmable Interrupt Controller: ", CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController);
- FORMATADD(" APIC-ID: %d\n", CPUInfo._Ext.APIC_ID);
- BOOLADD("CLFSH CLFLUSH Instruction Presence: ", CPUInfo._Ext.CLFSH_CFLUSH_Instruction);
- FORMATADD(" CLFLUSH Instruction Cache Line Size: %d\n", CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize);
- BOOLADD("CMOV Conditional Move And Compare Instructions: ", CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions);
- BOOLADD("CX8 COMPXCHG8B Instruction: ", CPUInfo._Ext.CX8_COMPXCHG8B_Instruction);
- BOOLADD("DE Debugging Extensions: ", CPUInfo._Ext.DE_DebuggingExtensions);
- BOOLADD("DS Debug Store: ", CPUInfo._Ext.DS_DebugStore);
- BOOLADD("FGPAT Page Attribute Table: ", CPUInfo._Ext.FGPAT_PageAttributeTable);
- BOOLADD("FPU Floating Point Unit: ", CPUInfo._Ext.FPU_FloatingPointUnit);
- BOOLADD("FXSR Fast Streaming SIMD Extensions Save/Restore:", CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore);
- BOOLADD("HT Hyper Threading: ", CPUInfo._Ext.HT_HyperThreading);
- BOOLADD("IA64 Intel 64-Bit Architecture: ", CPUInfo._Ext.IA64_Intel64BitArchitecture);
- BOOLADD("MCA Machine Check Architecture: ", CPUInfo._Ext.MCA_MachineCheckArchitecture);
- BOOLADD("MCE Machine Check Exception: ", CPUInfo._Ext.MCE_MachineCheckException);
- BOOLADD("MMX Multimedia Extensions: ", CPUInfo._Ext.MMX_MultimediaExtensions);
- BOOLADD("MMX+ Multimedia Extensions: ", CPUInfo._Ext.EMMX_MultimediaExtensions);
- BOOLADD("MSR Model Specific Registers: ", CPUInfo._Ext.MSR_ModelSpecificRegisters);
- BOOLADD("MTRR Memory Type Range Registers: ", CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters);
- BOOLADD("PAE Physical Address Extension: ", CPUInfo._Ext.PAE_PhysicalAddressExtension);
- BOOLADD("PGE PTE Global Flag: ", CPUInfo._Ext.PGE_PTE_GlobalFlag);
- if (CPUInfo._Ext.PN_ProcessorSerialNumber)
- {
- FORMATADD("PN Processor Serial Number: %s\n", CPUInfo.strProcessorSerial);
- }
- else
- {
- COPYADD("PN Processor Serial Number: Disabled\n");
- }
- BOOLADD("PSE Page Size Extensions: ", CPUInfo._Ext.PSE_PageSizeExtensions);
- BOOLADD("PSE36 36-bit Page Size Extension: ", CPUInfo._Ext.PSE36_36bitPageSizeExtension);
- BOOLADD("SEP Fast System Call: ", CPUInfo._Ext.SEP_FastSystemCall);
- BOOLADD("SS Self Snoop: ", CPUInfo._Ext.SS_SelfSnoop);
- BOOLADD("SSE Streaming SIMD Extensions: ", CPUInfo._Ext.SSE_StreamingSIMD_Extensions);
- BOOLADD("SSE2 Streaming SIMD 2 Extensions: ", CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions);
- BOOLADD("ALTVEC Altivec Extensions: ", CPUInfo._Ext.Altivec_Extensions);
- BOOLADD("TM Thermal Monitor: ", CPUInfo._Ext.TM_ThermalMonitor);
- BOOLADD("TSC Time Stamp Counter: ", CPUInfo._Ext.TSC_TimeStampCounter);
- BOOLADD("VME Virtual 8086 Mode Enhancements: ", CPUInfo._Ext.VME_Virtual8086ModeEnhancements);
- BOOLADD("3DNow! Instructions: ", CPUInfo._Ext._3DNOW_InstructionExtensions);
- BOOLADD("Enhanced 3DNow! Instructions: ", CPUInfo._Ext._E3DNOW_InstructionExtensions);
-#endif
- // Yippie!!!
- return true;
-}
-
-// bool CProcessor::WriteInfoTextFile(const std::string& strFilename)
-// ===========================================================
-// Takes use of CProcessor::CPUInfoToText and saves the string to a
-// file
-///////////////////////////////////////////////////////////////////
-bool CProcessor::WriteInfoTextFile(const std::string& strFilename)
-{
- char buf[16384]; /* Flawfinder: ignore */
-
- // First we get the string
- if (!CPUInfoToText(buf, 16383))
- return false;
-
- // Then we create a new file (CREATE_ALWAYS)
- LLFILE *file = LLFile::fopen(strFilename, "w"); /* Flawfinder: ignore */
- if (!file)
- return false;
-
- // After that we write the string to the file
- unsigned long dwBytesToWrite, dwBytesWritten;
- dwBytesToWrite = (unsigned long) strlen(buf); /*Flawfinder: ignore*/
- dwBytesWritten = (unsigned long) fwrite(buf, 1, dwBytesToWrite, file);
- fclose(file);
- if (dwBytesToWrite != dwBytesWritten)
- return false;
-
- // Done
- return true;
-}
diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h
index 746d007a7..00cd5a555 100644
--- a/indra/llcommon/llprocessor.h
+++ b/indra/llcommon/llprocessor.h
@@ -30,166 +30,26 @@
* $/LicenseInfo$
*/
-// Author: Benjamin Jurke
-// File history: 27.02.2002 File created.
-///////////////////////////////////////////
-
#ifndef LLPROCESSOR_H
#define LLPROCESSOR_H
+class LLProcessorInfoImpl;
-// Options:
-///////////
-#if LL_WINDOWS
-#define PROCESSOR_FREQUENCY_MEASURE_AVAILABLE
-#endif
-
-#if LL_MSVC && _M_X64
-# define LL_X86_64 1
-# define LL_X86 1
-#elif LL_MSVC && _M_IX86
-# define LL_X86 1
-#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) )
-# define LL_X86_64 1
-# define LL_X86 1
-#elif LL_GNUC && ( defined(__i386__) )
-# define LL_X86 1
-#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) )
-# define LL_PPC 1
-#endif
-
-
-struct ProcessorExtensions
+class LL_COMMON_API LLProcessorInfo
{
- bool FPU_FloatingPointUnit;
- bool VME_Virtual8086ModeEnhancements;
- bool DE_DebuggingExtensions;
- bool PSE_PageSizeExtensions;
- bool TSC_TimeStampCounter;
- bool MSR_ModelSpecificRegisters;
- bool PAE_PhysicalAddressExtension;
- bool MCE_MachineCheckException;
- bool CX8_COMPXCHG8B_Instruction;
- bool APIC_AdvancedProgrammableInterruptController;
- unsigned int APIC_ID;
- bool SEP_FastSystemCall;
- bool MTRR_MemoryTypeRangeRegisters;
- bool PGE_PTE_GlobalFlag;
- bool MCA_MachineCheckArchitecture;
- bool CMOV_ConditionalMoveAndCompareInstructions;
- bool FGPAT_PageAttributeTable;
- bool PSE36_36bitPageSizeExtension;
- bool PN_ProcessorSerialNumber;
- bool CLFSH_CFLUSH_Instruction;
- unsigned int CLFLUSH_InstructionCacheLineSize;
- bool DS_DebugStore;
- bool ACPI_ThermalMonitorAndClockControl;
- bool EMMX_MultimediaExtensions;
- bool MMX_MultimediaExtensions;
- bool FXSR_FastStreamingSIMD_ExtensionsSaveRestore;
- bool SSE_StreamingSIMD_Extensions;
- bool SSE2_StreamingSIMD2_Extensions;
- bool Altivec_Extensions;
- bool SS_SelfSnoop;
- bool HT_HyperThreading;
- unsigned int HT_HyterThreadingSiblings;
- bool TM_ThermalMonitor;
- bool IA64_Intel64BitArchitecture;
- bool _3DNOW_InstructionExtensions;
- bool _E3DNOW_InstructionExtensions;
- bool AA64_AMD64BitArchitecture;
-};
-
-struct ProcessorCache
-{
- bool bPresent;
- char strSize[32]; /* Flawfinder: ignore */
- unsigned int uiAssociativeWays;
- unsigned int uiLineSize;
- bool bSectored;
- char strCache[128]; /* Flawfinder: ignore */
-};
-
-struct ProcessorL1Cache
-{
- ProcessorCache Instruction;
- ProcessorCache Data;
-};
-
-struct ProcessorTLB
-{
- bool bPresent;
- char strPageSize[32]; /* Flawfinder: ignore */
- unsigned int uiAssociativeWays;
- unsigned int uiEntries;
- char strTLB[128]; /* Flawfinder: ignore */
-};
-
-struct ProcessorInfo
-{
- char strVendor[16]; /* Flawfinder: ignore */
- unsigned int uiFamily;
- unsigned int uiExtendedFamily;
- char strFamily[64]; /* Flawfinder: ignore */
- unsigned int uiModel;
- unsigned int uiExtendedModel;
- char strModel[128]; /* Flawfinder: ignore */
- unsigned int uiStepping;
- unsigned int uiType;
- char strType[64]; /* Flawfinder: ignore */
- unsigned int uiBrandID;
- char strBrandID[64]; /* Flawfinder: ignore */
- char strProcessorSerial[64]; /* Flawfinder: ignore */
- unsigned long MaxSupportedLevel;
- unsigned long MaxSupportedExtendedLevel;
- ProcessorExtensions _Ext;
- ProcessorL1Cache _L1;
- ProcessorCache _L2;
- ProcessorCache _L3;
- ProcessorCache _Trace;
- ProcessorTLB _Instruction;
- ProcessorTLB _Data;
-};
-
-
-// CProcessor
-// ==========
-// Class for detecting the processor name, type and available
-// extensions as long as it's speed.
-/////////////////////////////////////////////////////////////
-class CProcessor
-{
-// Constructor / Destructor:
-////////////////////////////
public:
- CProcessor();
+ LLProcessorInfo();
+ ~LLProcessorInfo();
-// Private vars:
-////////////////
-public:
- F64 uqwFrequency;
- char strCPUName[128]; /* Flawfinder: ignore */
- ProcessorInfo CPUInfo;
-
-// Private functions:
-/////////////////////
+ F64 getCPUFrequency() const;
+ bool hasSSE() const;
+ bool hasSSE2() const;
+ bool hasAltivec() const;
+ std::string getCPUFamilyName() const;
+ std::string getCPUBrandName() const;
+ std::string getCPUFeatureDescription() const;
private:
- bool AnalyzeIntelProcessor();
- bool AnalyzeAMDProcessor();
- bool AnalyzeUnknownProcessor();
- bool CheckCPUIDPresence();
- void DecodeProcessorConfiguration(unsigned int cfg);
- void TranslateProcessorConfiguration();
- void GetStandardProcessorConfiguration();
- void GetStandardProcessorExtensions();
-
-// Public functions:
-////////////////////
-public:
- F64 GetCPUFrequency(unsigned int uiMeasureMSecs);
- const ProcessorInfo *GetCPUInfo();
- bool CPUInfoToText(char *strBuffer, unsigned int uiMaxLen);
- bool WriteInfoTextFile(const std::string& strFilename);
+ LLProcessorInfoImpl* mImpl;
};
diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp
new file mode 100644
index 000000000..e0446c5d0
--- /dev/null
+++ b/indra/llcommon/llstacktrace.cpp
@@ -0,0 +1,143 @@
+/**
+ * @file llstacktrace.cpp
+ * @brief stack tracing functionality
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ *
+ */
+
+#include "linden_common.h"
+#include "llstacktrace.h"
+
+#ifdef LL_WINDOWS
+
+#include
+#include
+
+#include "windows.h"
+#include "Dbghelp.h"
+
+typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
+ IN ULONG frames_to_skip,
+ IN ULONG frames_to_capture,
+ OUT PVOID *backtrace,
+ OUT PULONG backtrace_hash);
+
+static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn =
+ (RtlCaptureStackBackTrace_Function*)
+ GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace");
+
+bool ll_get_stack_trace(std::vector& lines)
+{
+ const S32 MAX_STACK_DEPTH = 32;
+ const S32 STRING_NAME_LENGTH = 200;
+ const S32 FRAME_SKIP = 2;
+ static BOOL symbolsLoaded = false;
+ static BOOL firstCall = true;
+
+ HANDLE hProc = GetCurrentProcess();
+
+ // load the symbols if they're not loaded
+ if(!symbolsLoaded && firstCall)
+ {
+ symbolsLoaded = SymInitialize(hProc, NULL, true);
+ firstCall = false;
+ }
+
+ // if loaded, get the call stack
+ if(symbolsLoaded)
+ {
+ // create the frames to hold the addresses
+ void* frames[MAX_STACK_DEPTH];
+ memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH);
+ S32 depth = 0;
+
+ // get the addresses
+ depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL);
+
+ IMAGEHLP_LINE64 line;
+ memset(&line, 0, sizeof(IMAGEHLP_LINE64));
+ line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
+
+ // create something to hold address info
+ PIMAGEHLP_SYMBOL64 pSym;
+ pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
+ memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH);
+ pSym->MaxNameLength = STRING_NAME_LENGTH;
+ pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64);
+
+ // get address info for each address frame
+ // and store
+ for(S32 i=0; i < depth; i++)
+ {
+ std::stringstream stack_line;
+ BOOL ret;
+
+ DWORD64 addr = (DWORD64)frames[i];
+ ret = SymGetSymFromAddr64(hProc, addr, 0, pSym);
+ if(ret)
+ {
+ stack_line << pSym->Name << " ";
+ }
+
+ DWORD dummy;
+ ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line);
+ if(ret)
+ {
+ std::string file_name = line.FileName;
+ std::string::size_type index = file_name.rfind("\\");
+ stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber;
+ }
+
+ lines.push_back(stack_line.str());
+ }
+
+ free(pSym);
+
+ // TODO: figure out a way to cleanup symbol loading
+ // Not hugely necessary, however.
+ //SymCleanup(hProc);
+ return true;
+ }
+ else
+ {
+ lines.push_back("Stack Trace Failed. PDB symbol info not loaded");
+ }
+
+ return false;
+}
+
+#else
+
+bool ll_get_stack_trace(std::vector& lines)
+{
+ return false;
+}
+
+#endif
+
diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h
new file mode 100644
index 000000000..93883b8b3
--- /dev/null
+++ b/indra/llcommon/llstacktrace.h
@@ -0,0 +1,45 @@
+/**
+ * @file llstacktrace.h
+ * @brief stack trace functions
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2010, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlife.com/developers/opensource/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlife.com/developers/opensource/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ *
+ */
+
+
+#ifndef LL_LLSTACKTRACE_H
+#define LL_LLSTACKTRACE_H
+
+#include "stdtypes.h"
+#include
+#include
+
+LL_COMMON_API bool ll_get_stack_trace(std::vector& lines);
+
+#endif
+
diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp
index d729d9883..82366453a 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -52,13 +52,13 @@
# include
# include
# include
+//# include May be needed?
#elif LL_LINUX
# include
# include
# include
# include
const char MEMINFO_FILE[] = "/proc/meminfo";
-const char CPUINFO_FILE[] = "/proc/cpuinfo";
#elif LL_SOLARIS
# include
# include
@@ -325,7 +325,58 @@ LLOSInfo::LLOSInfo() :
}
mOSString += compatibility_mode;
+#elif LL_DARWIN
+
+ // Initialize mOSStringSimple to something like:
+ // "Mac OS X 10.6.7"
+ {
+ const char * DARWIN_PRODUCT_NAME = "Mac OS X";
+
+ SInt32 major_version, minor_version, bugfix_version;
+ OSErr r1 = Gestalt(gestaltSystemVersionMajor, &major_version);
+ OSErr r2 = Gestalt(gestaltSystemVersionMinor, &minor_version);
+ OSErr r3 = Gestalt(gestaltSystemVersionBugFix, &bugfix_version);
+
+ if((r1 == noErr) && (r2 == noErr) && (r3 == noErr))
+ {
+ mMajorVer = major_version;
+ mMinorVer = minor_version;
+ mBuild = bugfix_version;
+
+ std::stringstream os_version_string;
+ os_version_string << DARWIN_PRODUCT_NAME << " " << mMajorVer << "." << mMinorVer << "." << mBuild;
+
+ // Put it in the OS string we are compiling
+ mOSStringSimple.append(os_version_string.str());
+ }
+ else
+ {
+ mOSStringSimple.append("Unable to collect OS info");
+ }
+ }
+
+ // Initialize mOSString to something like:
+ // "Mac OS X 10.6.7 Darwin Kernel Version 10.7.0: Sat Jan 29 15:17:16 PST 2011; root:xnu-1504.9.37~1/RELEASE_I386 i386"
+ struct utsname un;
+ if(uname(&un) != -1)
+ {
+ mOSString = mOSStringSimple;
+ mOSString.append(" ");
+ mOSString.append(un.sysname);
+ mOSString.append(" ");
+ mOSString.append(un.release);
+ mOSString.append(" ");
+ mOSString.append(un.version);
+ mOSString.append(" ");
+ mOSString.append(un.machine);
+ }
+ else
+ {
+ mOSString = mOSStringSimple;
+ }
+
#else
+
struct utsname un;
if(uname(&un) != -1)
{
@@ -341,15 +392,7 @@ LLOSInfo::LLOSInfo() :
// Simplify 'Simple'
std::string ostype = mOSStringSimple.substr(0, mOSStringSimple.find_first_of(" ", 0));
- if (ostype == "Darwin")
- {
- // Only care about major Darwin versions, truncate at first '.'
- S32 idx1 = mOSStringSimple.find_first_of(".", 0);
- std::string simple = mOSStringSimple.substr(0, idx1);
- if (simple.length() > 0)
- mOSStringSimple = simple;
- }
- else if (ostype == "Linux")
+ if (ostype == "Linux")
{
// Only care about major and minor Linux versions, truncate at second '.'
std::string::size_type idx1 = mOSStringSimple.find_first_of(".", 0);
@@ -513,71 +556,21 @@ U32 LLOSInfo::getProcessResidentSizeKB()
LLCPUInfo::LLCPUInfo()
{
std::ostringstream out;
- CProcessor proc;
- const ProcessorInfo* info = proc.GetCPUInfo();
+ LLProcessorInfo proc;
// proc.WriteInfoTextFile("procInfo.txt");
- mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions;
- mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions;
- mHasAltivec = info->_Ext.Altivec_Extensions;
- mCPUMHz = (F64)(proc.GetCPUFrequency(50)/1000000.0);
- mFamily.assign( info->strFamily );
+ mHasSSE = proc.hasSSE();
+ mHasSSE2 = proc.hasSSE2();
+ mHasAltivec = proc.hasAltivec();
+ mCPUMHz = (F64)proc.getCPUFrequency();
+ mFamily = proc.getCPUFamilyName();
mCPUString = "Unknown";
-#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
- out << proc.strCPUName;
+ out << proc.getCPUBrandName();
if (200 < mCPUMHz && mCPUMHz < 10000) // *NOTE: cpu speed is often way wrong, do a sanity check
{
out << " (" << mCPUMHz << " MHz)";
}
mCPUString = out.str();
-
-#elif LL_LINUX
- std::map< std::string, std::string > cpuinfo;
- LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb");
- if(cpuinfo_fp)
- {
- char line[MAX_STRING];
- memset(line, 0, MAX_STRING);
- while(fgets(line, MAX_STRING, cpuinfo_fp))
- {
- // /proc/cpuinfo on Linux looks like:
- // name\t*: value\n
- char* tabspot = strchr( line, '\t' );
- if (tabspot == NULL)
- continue;
- char* colspot = strchr( tabspot, ':' );
- if (colspot == NULL)
- continue;
- char* spacespot = strchr( colspot, ' ' );
- if (spacespot == NULL)
- continue;
- char* nlspot = strchr( line, '\n' );
- if (nlspot == NULL)
- nlspot = line + strlen( line ); // Fallback to terminating NUL
- std::string linename( line, tabspot );
- std::string llinename(linename);
- LLStringUtil::toLower(llinename);
- std::string lineval( spacespot + 1, nlspot );
- cpuinfo[ llinename ] = lineval;
- }
- fclose(cpuinfo_fp);
- }
-# if LL_X86
- std::string flags = " " + cpuinfo["flags"] + " ";
- LLStringUtil::toLower(flags);
- mHasSSE = ( flags.find( " sse " ) != std::string::npos );
- mHasSSE2 = ( flags.find( " sse2 " ) != std::string::npos );
-
- F64 mhz;
- if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz)
- && 200.0 < mhz && mhz < 10000.0)
- {
- mCPUMHz = (F64)llrint(mhz);
- }
- if (!cpuinfo["model name"].empty())
- mCPUString = cpuinfo["model name"];
-# endif // LL_X86
-#endif // LL_LINUX
}
bool LLCPUInfo::hasAltivec() const
@@ -607,38 +600,9 @@ std::string LLCPUInfo::getCPUString() const
void LLCPUInfo::stream(std::ostream& s) const
{
-#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS
// gather machine information.
- char proc_buf[CPUINFO_BUFFER_SIZE]; /* Flawfinder: ignore */
- CProcessor proc;
- if(proc.CPUInfoToText(proc_buf, CPUINFO_BUFFER_SIZE))
- {
- s << proc_buf;
- }
- else
- {
- s << "Unable to collect processor information" << std::endl;
- }
-#else
- // *NOTE: This works on linux. What will it do on other systems?
- LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb");
- if(cpuinfo)
- {
- char line[MAX_STRING];
- memset(line, 0, MAX_STRING);
- while(fgets(line, MAX_STRING, cpuinfo))
- {
- line[strlen(line)-1] = ' ';
- s << line;
- }
- fclose(cpuinfo);
- s << std::endl;
- }
- else
- {
- s << "Unable to collect processor information" << std::endl;
- }
-#endif
+ s << LLProcessorInfo().getCPUFeatureDescription();
+
// These are interesting as they reflect our internal view of the
// CPU's attributes regardless of platform
s << "->mHasSSE: " << (U32)mHasSSE << std::endl;
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index e34b7f305..673bc4b9e 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -45,10 +45,12 @@
#include "llrender.h"
#include "llerror.h"
+#include "llerrorcontrol.h"
#include "llquaternion.h"
#include "llmath.h"
#include "m4math.h"
#include "llstring.h"
+#include "llstacktrace.h"
#include "llglheaders.h"
@@ -56,10 +58,49 @@
//#define GL_STATE_VERIFY
#endif
+
+BOOL gDebugSession = FALSE;
BOOL gDebugGL = FALSE;
BOOL gClothRipple = FALSE;
BOOL gNoRender = FALSE;
BOOL gGLActive = FALSE;
+
+std::ofstream gFailLog;
+
+void ll_init_fail_log(std::string filename)
+{
+ gFailLog.open(filename.c_str());
+}
+
+
+void ll_fail(std::string msg)
+{
+
+ if (gDebugSession)
+ {
+ std::vector lines;
+
+ gFailLog << LLError::utcTime() << " " << msg << std::endl;
+
+ gFailLog << "Stack Trace:" << std::endl;
+
+ ll_get_stack_trace(lines);
+
+ for(size_t i = 0; i < lines.size(); ++i)
+ {
+ gFailLog << lines[i] << std::endl;
+ }
+
+ gFailLog << "End of Stack Trace." << std::endl << std::endl;
+
+ gFailLog.flush();
+ }
+};
+
+void ll_close_fail_log()
+{
+ gFailLog.close();
+}
LLMatrix4 gGLObliqueProjectionInverse;
#define LL_GL_NAME_POOLING 0
@@ -133,12 +174,9 @@ PFNGLFRAMEBUFFERTEXTURE3DEXTPROC glFramebufferTexture3DEXT = NULL;
PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC glFramebufferRenderbufferEXT = NULL;
PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC glGetFramebufferAttachmentParameterivEXT = NULL;
PFNGLGENERATEMIPMAPEXTPROC glGenerateMipmapEXT = NULL;
-
-// GL_EXT_framebuffer_multisample
-PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL;
-
-// GL_EXT_framebuffer_blit
PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT = NULL;
+PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT = NULL;
+PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC glFramebufferTextureLayerEXT = NULL;
// GL_EXT_blend_func_separate
PFNGLBLENDFUNCSEPARATEEXTPROC glBlendFuncSeparateEXT = NULL;
@@ -277,6 +315,8 @@ LLGLManager::LLGLManager() :
mIsDisabled(FALSE),
mHasMultitexture(FALSE),
+ mHasATIMemInfo(FALSE),
+ mHasNVXMemInfo(FALSE),
mNumTextureUnits(1),
mHasMipMapGeneration(FALSE),
mHasCompressedTextures(FALSE),
@@ -289,6 +329,7 @@ LLGLManager::LLGLManager() :
mHasShaderObjects(FALSE),
mHasVertexShader(FALSE),
mHasFragmentShader(FALSE),
+ mNumTextureImageUnits(0),
mHasOcclusionQuery(FALSE),
mHasOcclusionQuery2(FALSE),
mHasPointParameters(FALSE),
@@ -460,6 +501,20 @@ bool LLGLManager::initGL()
// This is called here because it depends on the setting of mIsGF2or4MX, and sets up mHasMultitexture.
initExtensions();
+ if (mHasATIMemInfo)
+ { //ask the gl how much vram is free at startup and attempt to use no more than half of that
+ S32 meminfo[4];
+ glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
+
+ mVRAM = meminfo[0]/1024;
+ }
+ else if (mHasNVXMemInfo)
+ {
+ S32 dedicated_memory;
+ glGetIntegerv(GL_GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX, &dedicated_memory);
+ mVRAM = dedicated_memory/1024;
+ }
+
if (mHasMultitexture)
{
GLint num_tex_units;
@@ -479,6 +534,12 @@ bool LLGLManager::initGL()
return false;
}
+ if (mHasFragmentShader)
+ {
+ GLint num_tex_image_units;
+ glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &num_tex_image_units);
+ mNumTextureImageUnits = num_tex_image_units;
+ }
initGLStates();
return true;
@@ -504,14 +565,13 @@ void LLGLManager::getGLInfo(LLSD& info)
std::string LLGLManager::getGLInfoString()
{
std::string info_str;
- std::string all_exts, line;
info_str += std::string("GL_VENDOR ") + ll_safe_string((const char *)glGetString(GL_VENDOR)) + std::string("\n");
info_str += std::string("GL_RENDERER ") + ll_safe_string((const char *)glGetString(GL_RENDERER)) + std::string("\n");
info_str += std::string("GL_VERSION ") + ll_safe_string((const char *)glGetString(GL_VERSION)) + std::string("\n");
#if !LL_MESA_HEADLESS
- all_exts = (const char *)gGLHExts.mSysExts;
+ std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
LLStringUtil::replaceChar(all_exts, ' ', '\n');
info_str += std::string("GL_EXTENSIONS:\n") + all_exts + std::string("\n");
#endif
@@ -522,14 +582,13 @@ std::string LLGLManager::getGLInfoString()
void LLGLManager::printGLInfoString()
{
std::string info_str;
- std::string all_exts, line;
LL_INFOS("RenderInit") << "GL_VENDOR: " << ((const char *)glGetString(GL_VENDOR)) << LL_ENDL;
LL_INFOS("RenderInit") << "GL_RENDERER: " << ((const char *)glGetString(GL_RENDERER)) << LL_ENDL;
LL_INFOS("RenderInit") << "GL_VERSION: " << ((const char *)glGetString(GL_VERSION)) << LL_ENDL;
#if !LL_MESA_HEADLESS
- all_exts = std::string(gGLHExts.mSysExts);
+ std::string all_exts= ll_safe_string(((const char *)gGLHExts.mSysExts));
LLStringUtil::replaceChar(all_exts, ' ', '\n');
LL_DEBUGS("RenderInit") << "GL_EXTENSIONS:\n" << all_exts << LL_ENDL;
#endif
@@ -615,6 +674,8 @@ void LLGLManager::initExtensions()
mHasTextureRectangle = FALSE;
#else // LL_MESA_HEADLESS
mHasMultitexture = glh_init_extensions("GL_ARB_multitexture");
+ mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts);
+ mHasNVXMemInfo = ExtensionExists("GL_NVX_gpu_memory_info", gGLHExts.mSysExts);
mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap");
mHasSeparateSpecularColor = glh_init_extensions("GL_EXT_separate_specular_color");
mHasAnisotropic = glh_init_extensions("GL_EXT_texture_filter_anisotropic");
@@ -626,9 +687,15 @@ void LLGLManager::initExtensions()
mHasOcclusionQuery2 = ExtensionExists("GL_ARB_occlusion_query2", gGLHExts.mSysExts);
mHasVertexBufferObject = ExtensionExists("GL_ARB_vertex_buffer_object", gGLHExts.mSysExts);
mHasDepthClamp = ExtensionExists("GL_ARB_depth_clamp", gGLHExts.mSysExts) || ExtensionExists("GL_NV_depth_clamp", gGLHExts.mSysExts);
- // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
- mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts)
- && ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
+ // mask out FBO support when packed_depth_stencil isn't there 'cause we need it for LLRenderTarget -Brad
+#ifdef GL_ARB_framebuffer_object
+ mHasFramebufferObject = ExtensionExists("GL_ARB_framebuffer_object", gGLHExts.mSysExts);
+#else
+ mHasFramebufferObject = ExtensionExists("GL_EXT_framebuffer_object", gGLHExts.mSysExts) &&
+ ExtensionExists("GL_EXT_framebuffer_blit", gGLHExts.mSysExts) &&
+ ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts) &&
+ ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts);
+#endif
mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts);
mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts);
mHasBlendFuncSeparate = ExtensionExists("GL_EXT_blend_func_separate", gGLHExts.mSysExts);
@@ -832,11 +899,9 @@ void LLGLManager::initExtensions()
glFramebufferRenderbufferEXT = (PFNGLFRAMEBUFFERRENDERBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferRenderbufferEXT");
glGetFramebufferAttachmentParameterivEXT = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGetFramebufferAttachmentParameterivEXT");
glGenerateMipmapEXT = (PFNGLGENERATEMIPMAPEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glGenerateMipmapEXT");
- }
- if (mHasFramebufferMultisample)
- {
- glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisampleEXT");
glBlitFramebufferEXT = (PFNGLBLITFRAMEBUFFEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glBlitFramebufferEXT");
+ glRenderbufferStorageMultisampleEXT = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) GLH_EXT_GET_PROC_ADDRESS("glRenderbufferStorageMultisampleEXT");
+ glFramebufferTextureLayerEXT = (PFNGLFRAMEBUFFERTEXTURELAYEREXTPROC) GLH_EXT_GET_PROC_ADDRESS("glFramebufferTextureLayerEXT");
}
if (mHasDrawBuffers)
{
@@ -1008,12 +1073,35 @@ void flush_glerror()
glGetError();
}
-void assert_glerror()
+//this function outputs gl error to the log file, does not crash the code.
+void log_glerror()
{
- if (gNoRender || !gDebugGL)
+ if (LL_UNLIKELY(!gGLManager.mInited))
{
- return;
+ return ;
}
+ // Create or update texture to be used with this data
+ GLenum error;
+ error = glGetError();
+ while (LL_UNLIKELY(error))
+ {
+ GLubyte const * gl_error_msg = gluErrorString(error);
+ if (NULL != gl_error_msg)
+ {
+ llwarns << "GL Error: " << error << " GL Error String: " << gl_error_msg << llendl ;
+ }
+ else
+ {
+ // gluErrorString returns NULL for some extensions' error codes.
+ // you'll probably have to grep for the number in glext.h.
+ llwarns << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << llendl;
+ }
+ error = glGetError();
+ }
+}
+
+void do_assert_glerror()
+{
if (LL_UNLIKELY(!gGLManager.mInited))
{
LL_ERRS("RenderInit") << "GL not initialized" << LL_ENDL;
@@ -1025,29 +1113,65 @@ void assert_glerror()
while (LL_UNLIKELY(error))
{
quit = TRUE;
-#ifndef LL_LINUX // *FIX: ! This should be an error for linux as well.
GLubyte const * gl_error_msg = gluErrorString(error);
if (NULL != gl_error_msg)
{
LL_WARNS("RenderState") << "GL Error:" << error<< LL_ENDL;
LL_WARNS("RenderState") << "GL Error String:" << gl_error_msg << LL_ENDL;
+
+ if (gDebugSession)
+ {
+ gFailLog << "GL Error:" << gl_error_msg << std::endl;
+ }
}
else
{
// gluErrorString returns NULL for some extensions' error codes.
// you'll probably have to grep for the number in glext.h.
LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL;
+
+ if (gDebugSession)
+ {
+ gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl;
+ }
}
error = glGetError();
-#endif
}
if (quit)
{
- llerrs << "One or more unhandled GL errors." << llendl;
+ if (gDebugSession)
+ {
+ ll_fail("assert_glerror failed");
+ }
+ else
+ {
+ llerrs << "One or more unhandled GL errors." << llendl;
+ }
}
}
+void assert_glerror()
+{
+ if (gNoRender)
+ return;
+ if (!gGLActive)
+ {
+ //llwarns << "GL used while not active!" << llendl;
+
+ if (gDebugSession)
+ {
+ //ll_fail("GL used while not active");
+ }
+ }
+
+ if (gDebugGL)
+ {
+ do_assert_glerror();
+ }
+}
+
+
void clear_glerror()
{
// Create or update texture to be used with this data
@@ -1130,9 +1254,19 @@ void LLGLState::checkStates(const std::string& msg)
glGetIntegerv(GL_BLEND_SRC, &src);
glGetIntegerv(GL_BLEND_DST, &dst);
+ BOOL error = FALSE;
+
if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA)
{
- LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << std::endl;
+ error = TRUE;
+ }
+ else
+ {
+ LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL;
+ }
}
for (boost::unordered_map::iterator iter = sStateMap.begin();
@@ -1144,10 +1278,22 @@ void LLGLState::checkStates(const std::string& msg)
if(cur_state != gl_state)
{
dumpStates();
- LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << llformat("LLGLState error. State: 0x%04x",state) << std::endl;
+ error = TRUE;
+ }
+ else
+ {
+ LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL;
+ }
}
}
+ if (error)
+ {
+ ll_fail("LLGLState::checkStates failed.");
+ }
stop_glerror();
}
@@ -1158,9 +1304,12 @@ void LLGLState::checkTextureChannels(const std::string& msg)
return;
}
+ stop_glerror();
+
GLint activeTexture;
glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture);
-
+ stop_glerror();
+
BOOL error = FALSE;
if (activeTexture == GL_TEXTURE0_ARB)
@@ -1168,15 +1317,22 @@ void LLGLState::checkTextureChannels(const std::string& msg)
GLint tex_env_mode = 0;
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env_mode);
+ stop_glerror();
+
if (tex_env_mode != GL_MODULATE)
{
error = TRUE;
LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << std::endl;
+ }
}
}
GLint maxTextureUnits = 0;
glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits);
+ stop_glerror();
static const char* label[] =
{
@@ -1205,35 +1361,44 @@ void LLGLState::checkTextureChannels(const std::string& msg)
};
GLint stackDepth = 0;
+
glh::matrix4f mat;
glh::matrix4f identity;
identity.identity();
-// LLMatrix4 identity;
-// LLMatrix4 matrix;
for (GLint i = 1; i < maxTextureUnits; i++)
{
gGL.getTexUnit(i)->activate();
glClientActiveTextureARB(GL_TEXTURE0_ARB+i);
-
+ stop_glerror();
glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth);
+ stop_glerror();
if (stackDepth != 1)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL;
+
+ if (gDebugSession)
+ {
+ gFailLog << "Texture matrix stack corrupted." << std::endl;
+ }
}
- //glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) matrix.mMatrix);
glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) mat.m);
+ stop_glerror();
- //if (matrix != identity)
if (mat != identity)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl;
+ }
}
+
for (S32 j = (i == 0 ? 1 : 0);
j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++)
{
@@ -1241,24 +1406,42 @@ void LLGLState::checkTextureChannels(const std::string& msg)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl;
+ }
}
+ stop_glerror();
}
glGetFloatv(GL_TEXTURE_MATRIX, mat.m);
+ stop_glerror();
if (mat != identity)
{
error = TRUE;
LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "Texture matrix " << i << " is not identity." << std::endl;
+ }
}
}
gGL.getTexUnit(0)->activate();
glClientActiveTextureARB(GL_TEXTURE0_ARB);
+ stop_glerror();
if (error)
{
- LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL;
+ if (gDebugSession)
+ {
+ ll_fail("LLGLState::checkTextureChannels failed.");
+ }
+ else
+ {
+ LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL;
+ }
}
}
@@ -1278,6 +1461,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
if (active_texture != GL_TEXTURE0_ARB)
{
llwarns << "Client active texture corrupted: " << active_texture << llendl;
+ if (gDebugSession)
+ {
+ gFailLog << "Client active texture corrupted: " << active_texture << std::endl;
+ }
error = TRUE;
}
@@ -1285,6 +1472,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
if (active_texture != GL_TEXTURE0_ARB)
{
llwarns << "Active texture corrupted: " << active_texture << llendl;
+ if (gDebugSession)
+ {
+ gFailLog << "Active texture corrupted: " << active_texture << std::endl;
+ }
error = TRUE;
}
@@ -1321,6 +1512,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL still has " << label[j] << " enabled." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL still has " << label[j] << " enabled." << std::endl;
+ }
}
}
else
@@ -1329,6 +1524,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL does not have " << label[j] << " enabled." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL does not have " << label[j] << " enabled." << std::endl;
+ }
}
}
}
@@ -1341,6 +1540,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl;
+ }
}
}
else
@@ -1349,6 +1552,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl;
+ }
}
}
@@ -1358,6 +1565,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL still has GL_TEXTURE_2D enabled on channel 1." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL still has GL_TEXTURE_2D enabled on channel 1." << std::endl;
+ }
}
}
else
@@ -1366,6 +1577,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_2D enabled on channel 1." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl;
+ }
}
}
@@ -1384,13 +1599,24 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask)
{
error = TRUE;
LL_WARNS("RenderState") << "GL still has vertex attrib array " << i << " enabled." << LL_ENDL;
+ if (gDebugSession)
+ {
+ gFailLog << "GL still has vertex attrib array " << i << " enabled." << std::endl;
+ }
}
}
}
if (error)
{
+ if (gDebugSession)
+ {
+ ll_fail("LLGLState::checkClientArrays failed.");
+ }
+ else
+ {
LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL;
+ }
}
}
@@ -1441,7 +1667,17 @@ LLGLState::~LLGLState()
{
if (gDebugGL)
{
+ if (!gDebugSession)
+ {
llassert_always(sStateMap[mState] == glIsEnabled(mState));
+ }
+ else
+ {
+ if (sStateMap[mState] != glIsEnabled(mState))
+ {
+ ll_fail("GL enabled state does not match expected");
+ }
+ }
}
if (mIsEnabled != mWasEnabled)
@@ -1839,6 +2075,11 @@ void LLGLDepthTest::checkState()
sWriteEnabled != mask ||
sDepthFunc != func)
{
+ if (gDebugSession)
+ {
+ gFailLog << "Unexpected depth testing state." << std::endl;
+ }
+ else
{
LL_GL_ERRS << "Unexpected depth testing state." << LL_ENDL;
}
diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h
index 217b6f26e..2e0ca22e5 100644
--- a/indra/llrender/llgl.h
+++ b/indra/llrender/llgl.h
@@ -37,7 +37,7 @@
#include
#include
-#include
+
+ debugsession
+
rotate
+ CameraFocusTransitionTime
+
+ Comment
+ How many seconds it takes the camera to transition between focal distances
+ Persist
+ 1
+ Type
+ F32
+ Value
+ 0.5
+
+
+ CameraFNumber
+
+ Comment
+ Camera f-number value for DoF effect
+ Persist
+ 1
+ Type
+ F32
+ Value
+ 9.0
+
+
+ CameraFocalLength
+
+ Comment
+ Camera focal length for DoF effect (in millimeters)
+ Persist
+ 1
+ Type
+ F32
+ Value
+ 50
+
+
+ CameraFieldOfView
+
+ Comment
+ Vertical camera field of view for DoF effect (in degrees)
+ Persist
+ 1
+ Type
+ F32
+ Value
+ 60.0
+
+
+ CameraAspectRatio
+
+ Comment
+ Camera aspect ratio for DoF effect
+ Persist
+ 1
+ Type
+ F32
+ Value
+ 1.5
+
ChatBarStealsFocus
Comment
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl
deleted file mode 100644
index ff64a6b0c..000000000
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaF.glsl
+++ /dev/null
@@ -1,68 +0,0 @@
-/**
- * @file avatarAlphaF.glsl
- *
- * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
- * $License$
- */
-
-uniform sampler2D diffuseMap;
-uniform sampler2DShadow shadowMap0;
-uniform sampler2DShadow shadowMap1;
-uniform sampler2DShadow shadowMap2;
-uniform sampler2DShadow shadowMap3;
-uniform sampler2D noiseMap;
-
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-
-vec3 atmosLighting(vec3 light);
-vec3 scaleSoftClip(vec3 light);
-
-varying vec3 vary_ambient;
-varying vec3 vary_directional;
-varying vec4 vary_position;
-varying vec3 vary_normal;
-
-void main()
-{
- float shadow = 1.0;
- vec4 pos = vary_position;
- vec3 norm = normalize(vary_normal);
-
- vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz;
-
- if (pos.z > -shadow_clip.w)
- {
-
- if (pos.z < -shadow_clip.z)
- {
- vec4 lpos = shadow_matrix[3]*pos;
- shadow = shadow2DProj(shadowMap3, lpos).x;
- }
- else if (pos.z < -shadow_clip.y)
- {
- vec4 lpos = shadow_matrix[2]*pos;
- shadow = shadow2DProj(shadowMap2, lpos).x;
- }
- else if (pos.z < -shadow_clip.x)
- {
- vec4 lpos = shadow_matrix[1]*pos;
- shadow = shadow2DProj(shadowMap1, lpos).x;
- }
- else
- {
- vec4 lpos = shadow_matrix[0]*pos;
- shadow = shadow2DProj(shadowMap0, lpos).x;
- }
- }
-
-
- vec4 col = vec4(vary_ambient + vary_directional*shadow, gl_Color.a);
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col;
-
- color.rgb = atmosLighting(color.rgb);
-
- color.rgb = scaleSoftClip(color.rgb);
-
- gl_FragColor = color;
-}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
index 7fc763fa0..616990560 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/avatarAlphaV.glsl
@@ -19,10 +19,38 @@ vec3 atmosAffectDirectionalLight(float lightIntensity);
vec3 scaleDownLight(vec3 light);
vec3 scaleUpLight(vec3 light);
-varying vec4 vary_position;
+varying vec3 vary_position;
varying vec3 vary_ambient;
varying vec3 vary_directional;
-varying vec3 vary_normal;
+varying vec3 vary_fragcoord;
+varying vec3 vary_pointlight_col;
+
+uniform float near_clip;
+
+float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
+{
+ //get light vector
+ vec3 lv = lp.xyz-v;
+
+ //get distance
+ float d = length(lv);
+
+ //normalize light vector
+ lv *= 1.0/d;
+
+ //distance attenuation
+ float dist2 = d*d/(la*la);
+ float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
+
+ //angular attenuation
+ da *= calcDirectionalLight(n, lv);
+
+ return da;
+}
void main()
{
@@ -42,9 +70,10 @@ void main()
norm.z = dot(trans[2].xyz, gl_Normal);
norm = normalize(norm);
- gl_Position = gl_ProjectionMatrix * pos;
- vary_position = pos;
- vary_normal = norm;
+ vec4 frag_pos = gl_ProjectionMatrix * pos;
+ gl_Position = frag_pos;
+
+ vary_position = pos.xyz;
calcAtmospherics(pos.xyz);
@@ -52,18 +81,20 @@ void main()
vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a);
- // Collect normal lights (need to be divided by two, as we later multiply by 2)
- col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a);
- col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a);
- col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a);
- col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a);
- col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a);
- col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a);
- col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
- col.rgb = scaleDownLight(col.rgb);
+ // Collect normal lights
+ col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a);
+ col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a);
+ col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a);
+ col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a);
+ col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a);
+ col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a);
+ vary_pointlight_col = col.rgb*gl_Color.rgb;
+
+ col.rgb = vec3(0,0,0);
+
// Add windlight lights
- col.rgb += atmosAmbient(vec3(0.));
+ col.rgb = atmosAmbient(vec3(0.));
vary_ambient = col.rgb*gl_Color.rgb;
vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
@@ -73,7 +104,8 @@ void main()
gl_FrontColor = col;
gl_FogFragCoord = pos.z;
-
+
+ vary_fragcoord.xyz = frag_pos.xyz + vec3(0,0,near_clip);
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
index 6e732fa54..d04bfb3ad 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/blurLightF.glsl
@@ -39,44 +39,50 @@ vec4 getPosition(vec2 pos_screen)
void main()
{
- vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
+ vec2 tc = vary_fragcoord.xy;
+ vec3 norm = texture2DRect(normalMap, tc).xyz;
norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
- vec3 pos = getPosition(vary_fragcoord.xy).xyz;
- vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba;
+ vec3 pos = getPosition(tc).xyz;
+ vec4 ccol = texture2DRect(lightMap, tc).rgba;
vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
-
dlt /= max(-pos.z*dist_factor, 1.0);
vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
vec4 col = defined_weight.xyxx * ccol;
-
+
+ // relax tolerance according to distance to avoid speckling artifacts, as angles and distances are a lot more abrupt within a small screen area at larger distances
+ float pointplanedist_tolerance_pow2 = pos.z*pos.z*0.00005;
+
+ // perturb sampling origin slightly in screen-space to hide edge-ghosting artifacts where smoothing radius is quite large
+ //This causes some pretty nasty artifacting, so disabling for now.
+ //tc += ( (mod(tc.x+tc.y,2) - 0.5) * kern[1].z * dlt * 0.5 );
+
for (int i = 1; i < 4; i++)
{
- vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
- vec3 samppos = getPosition(tc).xyz;
+ vec2 samptc = tc + kern[i].z*dlt;
+ vec3 samppos = getPosition(samptc).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
- if (d*d <= 0.003)
+ if (d*d <= pointplanedist_tolerance_pow2)
{
- col += texture2DRect(lightMap, tc)*kern[i].xyxx;
+ col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
defined_weight += kern[i].xy;
}
}
for (int i = 1; i < 4; i++)
{
- vec2 tc = vary_fragcoord.xy - kern[i].z*dlt;
- vec3 samppos = getPosition(tc).xyz;
+ vec2 samptc = tc - kern[i].z*dlt;
+ vec3 samppos = getPosition(samptc).xyz;
float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
- if (d*d <= 0.003)
+ if (d*d <= pointplanedist_tolerance_pow2)
{
- col += texture2DRect(lightMap, tc)*kern[i].xyxx;
+ col += texture2DRect(lightMap, samptc)*kern[i].xyxx;
defined_weight += kern[i].xy;
}
}
-
-
col /= defined_weight.xyxx;
+ col.y *= col.y;
gl_FragColor = col;
}
diff --git a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
index 7e41b07f8..77f1b2224 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/postDeferredF.glsl
@@ -10,50 +10,128 @@
#extension GL_ARB_texture_rectangle : enable
uniform sampler2DRect diffuseRect;
-uniform sampler2DRect localLightMap;
-uniform sampler2DRect sunLightMap;
-uniform sampler2DRect giLightMap;
-uniform sampler2D luminanceMap;
-uniform sampler2DRect lightMap;
+uniform sampler2DRect edgeMap;
+uniform sampler2DRect depthMap;
+uniform sampler2DRect normalMap;
+uniform sampler2D bloomMap;
-uniform vec3 lum_quad;
-uniform float lum_lod;
-uniform vec4 ambient;
-
-uniform vec3 gi_quad;
+uniform float depth_cutoff;
+uniform float norm_cutoff;
+uniform float focal_distance;
+uniform float blur_constant;
+uniform float tan_pixel_angle;
+uniform float magnification;
+uniform mat4 inv_proj;
uniform vec2 screen_res;
+
varying vec2 vary_fragcoord;
+float getDepth(vec2 pos_screen)
+{
+ float z = texture2DRect(depthMap, pos_screen.xy).a;
+ z = z*2.0-1.0;
+ vec4 ndc = vec4(0.0, 0.0, z, 1.0);
+ vec4 p = inv_proj*ndc;
+ return p.z/p.w;
+}
+
+float calc_cof(float depth)
+{
+ float sc = abs(depth-focal_distance)/-depth*blur_constant;
+
+ sc /= magnification;
+
+ // tan_pixel_angle = pixel_length/-depth;
+ float pixel_length = tan_pixel_angle*-focal_distance;
+
+ sc = sc/pixel_length;
+ sc *= 1.414;
+
+ return sc;
+}
+
+void dofSampleNear(inout vec4 diff, inout float w, float cur_sc, vec2 tc)
+{
+ float d = getDepth(tc);
+
+ float sc = calc_cof(d);
+
+ float wg = 0.25;
+
+ vec4 s = texture2DRect(diffuseRect, tc);
+ // de-weight dull areas to make highlights 'pop'
+ wg += s.r+s.g+s.b;
+
+ diff += wg*s;
+
+ w += wg;
+}
+
+void dofSample(inout vec4 diff, inout float w, float min_sc, float cur_depth, vec2 tc)
+{
+ float d = getDepth(tc);
+
+ float sc = calc_cof(d);
+
+ if (sc > min_sc //sampled pixel is more "out of focus" than current sample radius
+ || d < cur_depth) //sampled pixel is further away than current pixel
+ {
+ float wg = 0.25;
+
+ vec4 s = texture2DRect(diffuseRect, tc);
+ // de-weight dull areas to make highlights 'pop'
+ wg += s.r+s.g+s.b;
+
+ diff += wg*s;
+
+ w += wg;
+ }
+}
+
+
void main()
{
+ vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
+ norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
+
vec2 tc = vary_fragcoord.xy;
- vec3 lum = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb;
- float luminance = lum.r;
- luminance = luminance*lum_quad.y+lum_quad.z;
-
+
+ float depth = getDepth(tc);
+
vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
+
+ {
+ float w = 1.0;
+
+ float sc = calc_cof(depth);
+ sc = min(abs(sc), 10.0);
+
+ float fd = depth*0.5f;
+
+ float PI = 3.14159265358979323846264;
- float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g;
-
- vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
- gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb;
- gi_col *= diff;
-
- vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy);
-
- vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb;
+ // sample quite uniformly spaced points within a circle, for a circular 'bokeh'
+ //if (depth < focal_distance)
+ {
+ while (sc > 0.5)
+ {
+ int its = int(max(1.0,(sc*3.7)));
+ for (int i=0; i 0.0) // specular reflection
@@ -288,7 +284,6 @@ void main()
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
-
/*
// screen-space cheap fakey reflection map
//
diff --git a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class1/deferred/softenLightNoSSAOF.glsl
similarity index 92%
rename from indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
rename to indra/newview/app_settings/shaders/class1/deferred/softenLightNoSSAOF.glsl
index 0160e8427..bca692cab 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/softenLightNoSSAOF.glsl
@@ -1,8 +1,8 @@
/**
* @file softenLightF.glsl
*
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * $/LicenseInfo$
+ * Copyright (c) 2007-$CurrentYear$, Linden Research, Inc.
+ * $License$
*/
#version 120
@@ -12,12 +12,8 @@
uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect normalMap;
-uniform sampler2DRect lightMap;
uniform sampler2DRect depthMap;
-uniform sampler2D noiseMap;
-uniform samplerCube environmentMap;
uniform sampler2D lightFunc;
-uniform vec3 gi_quad;
uniform float blur_size;
uniform float blur_fidelity;
@@ -41,12 +37,10 @@ uniform vec4 max_y;
uniform vec4 glow;
uniform float scene_light_strength;
uniform vec3 env_mat[3];
-uniform vec4 shadow_clip;
+//uniform mat4 shadow_matrix[3];
+//uniform vec4 shadow_clip;
uniform mat3 ssao_effect_mat;
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
varying vec4 vary_light;
varying vec2 vary_fragcoord;
@@ -57,6 +51,9 @@ vec3 vary_AmblitColor;
vec3 vary_AdditiveColor;
vec3 vary_AtmosAttenuation;
+uniform mat4 inv_proj;
+uniform vec2 screen_res;
+
vec4 getPosition_d(vec2 pos_screen, float depth)
{
vec2 sc = pos_screen.xy*2.0;
@@ -269,14 +266,10 @@ void main()
vec4 diffuse = texture2DRect(diffuseRect, tc);
vec4 spec = texture2DRect(specularRect, vary_fragcoord.xy);
- vec2 scol_ambocc = texture2DRect(lightMap, vary_fragcoord.xy).rg;
- float scol = max(scol_ambocc.r, diffuse.a);
- float ambocc = scol_ambocc.g;
-
- calcAtmospherics(pos.xyz, ambocc);
+ calcAtmospherics(pos.xyz, 1.0);
vec3 col = atmosAmbient(vec3(0));
- col += atmosAffectDirectionalLight(max(min(da, scol), diffuse.a));
+ col += atmosAffectDirectionalLight(max(min(da, 1.0), diffuse.a));
col *= diffuse.rgb;
@@ -286,7 +279,7 @@ void main()
//
vec3 refnormpersp = normalize(reflect(pos.xyz, norm.xyz));
float sa = dot(refnormpersp, vary_light.xyz);
- vec3 dumbshiny = vary_SunlitColor*scol_ambocc.r*texture2D(lightFunc, vec2(sa, spec.a)).a;
+ vec3 dumbshiny = vary_SunlitColor*texture2D(lightFunc, vec2(sa, spec.a)).a;
/*
// screen-space cheap fakey reflection map
@@ -312,20 +305,18 @@ void main()
texture2DRect(diffuseRect, ref2d + vec2(-checkoffset, 0.0)).rgb);
float refdepth = texture2DRect(depthMap, ref2d).a;
vec3 refpos = getPosition_d(ref2d, refdepth).xyz;
- float refshad = texture2DRect(lightMap, ref2d).r;
vec3 refn = texture2DRect(normalMap, ref2d).rgb;
- refn = vec3((refn.xy-0.5)*2.0,refn.z); // unpack norm
- refn = normalize(refn);
+ refn = normalize(vec3((refn.xy-0.5)*2.0,refn.z)); // unpack norm
// figure out how appropriate our guess actually was
float refapprop = max(0.0, dot(-refnorm, normalize(pos - refpos)));
// darken reflections from points which face away from the reflected ray - our guess was a back-face
//refapprop *= step(dot(refnorm, refn), 0.0);
refapprop = min(refapprop, max(0.0, -dot(refnorm, refn))); // more conservative variant
- // get appropriate light strength for guess-point
+ // get appropriate light strength for guess-point.
// reflect light direction to increase the illusion that
// these are reflections.
vec3 reflight = reflect(lightnorm.xyz, norm.xyz);
- float reflit = min(max(dot(refn, reflight.xyz), 0.0), refshad);
+ float reflit = max(dot(refn, reflight.xyz), 0.0);
// apply sun color to guess-point, dampen according to inappropriateness of guess
float refmod = min(refapprop, reflit);
vec3 refprod = vary_SunlitColor * refcol.rgb * refmod;
diff --git a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
index 3c936251f..cd91351ad 100644
--- a/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class1/deferred/sunLightSSAOF.glsl
@@ -51,57 +51,49 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)
{
float ret = 1.0;
- float dist = dot(pos.xyz,pos.xyz);
-
- if (dist < 64.0*64.0)
- {
- vec2 kern[8];
- // exponentially (^2) distant occlusion samples spread around origin
- kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
- kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
- kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
- kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
- kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
- kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
- kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
- kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
+ vec2 kern[8];
+ // exponentially (^2) distant occlusion samples spread around origin
+ kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+ kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+ kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+ kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+ kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+ kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
+ kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
+ kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
- vec2 pos_screen = vary_fragcoord.xy;
- vec3 pos_world = pos.xyz;
- vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
+ vec2 pos_screen = vary_fragcoord.xy;
+ vec3 pos_world = pos.xyz;
+ vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
- float angle_hidden = 0.0;
- int points = 0;
+ float angle_hidden = 0.0;
+ int points = 0;
- float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+ float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
- // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
- for (int i = 0; i < 8; i++)
- {
- vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
- vec3 samppos_world = getPosition(samppos_screen).xyz;
+ // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations unrolling?)
+ for (int i = 0; i < 8; i++)
+ {
+ vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
+ vec3 samppos_world = getPosition(samppos_screen).xyz;
- vec3 diff = pos_world - samppos_world;
- float dist2 = dot(diff, diff);
+ vec3 diff = pos_world - samppos_world;
+ float dist2 = dot(diff, diff);
- // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
- // --> solid angle shrinking by the square of distance
- //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
- //(k should vary inversely with # of samples, but this is taken care of later)
+ // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+ // --> solid angle shrinking by the square of distance
+ //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+ //(k should vary inversely with # of samples, but this is taken care of later)
- //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces
- // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor)
- angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+ angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
- // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
- points = points + int(diff.z > -1.0);
- }
-
- angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
-
- ret = (1.0 - (float(points != 0) * angle_hidden));
- ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0);
+ // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
+ points = points + int(diff.z > -1.0);
}
+
+ angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+
+ ret = (1.0 - (float(points != 0) * angle_hidden));
return min(ret, 1.0);
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl
deleted file mode 100644
index 5ecbbd2c4..000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaF.glsl
+++ /dev/null
@@ -1,98 +0,0 @@
-/**
- * @file avatarAlphaF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * $/LicenseInfo$
- */
-
-#extension GL_ARB_texture_rectangle : enable
-
-uniform sampler2D diffuseMap;
-uniform sampler2DRectShadow shadowMap0;
-uniform sampler2DRectShadow shadowMap1;
-uniform sampler2DRectShadow shadowMap2;
-uniform sampler2DRectShadow shadowMap3;
-uniform sampler2D noiseMap;
-
-uniform mat4 shadow_matrix[6];
-uniform vec4 shadow_clip;
-uniform vec2 screen_res;
-uniform vec2 shadow_res;
-
-vec3 atmosLighting(vec3 light);
-vec3 scaleSoftClip(vec3 light);
-
-varying vec3 vary_ambient;
-varying vec3 vary_directional;
-varying vec3 vary_position;
-varying vec3 vary_normal;
-
-uniform float shadow_bias;
-
-float pcfShadow(sampler2DRectShadow shadowMap, vec4 stc, float scl)
-{
- stc.xyz /= stc.w;
- stc.z += shadow_bias;
-
- float cs = shadow2DRect(shadowMap, stc.xyz).x;
- float shadow = cs;
-
- shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, scl, 0.0)).x, cs);
- shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(scl, -scl, 0.0)).x, cs);
- shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, scl, 0.0)).x, cs);
- shadow += max(shadow2DRect(shadowMap, stc.xyz+vec3(-scl, -scl, 0.0)).x, cs);
-
- return shadow/5.0;
-}
-
-void main()
-{
- float shadow = 1.0;
- vec4 pos = vec4(vary_position, 1.0);
- vec3 norm = normalize(vary_normal);
-
- //vec3 nz = texture2D(noiseMap, gl_FragCoord.xy/128.0).xyz;
-
- vec4 spos = pos;
-
- if (spos.z > -shadow_clip.w)
- {
- vec4 lpos;
-
- if (spos.z < -shadow_clip.z)
- {
- lpos = shadow_matrix[3]*spos;
- lpos.xy *= shadow_res;
- shadow = pcfShadow(shadowMap3, lpos, 1.5);
- shadow += max((pos.z+shadow_clip.z)/(shadow_clip.z-shadow_clip.w)*2.0-1.0, 0.0);
- }
- else if (spos.z < -shadow_clip.y)
- {
- lpos = shadow_matrix[2]*spos;
- lpos.xy *= shadow_res;
- shadow = pcfShadow(shadowMap2, lpos, 1.5);
- }
- else if (spos.z < -shadow_clip.x)
- {
- lpos = shadow_matrix[1]*spos;
- lpos.xy *= shadow_res;
- shadow = pcfShadow(shadowMap1, lpos, 1.5);
- }
- else
- {
- lpos = shadow_matrix[0]*spos;
- lpos.xy *= shadow_res;
- shadow = pcfShadow(shadowMap0, lpos, 1.5);
- }
- }
-
-
- vec4 col = vec4(vary_ambient + vary_directional*shadow, gl_Color.a);
- vec4 color = texture2D(diffuseMap, gl_TexCoord[0].xy) * col;
-
- color.rgb = atmosLighting(color.rgb);
-
- color.rgb = scaleSoftClip(color.rgb);
-
- gl_FragColor = color;
-}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
index 43a554b47..495e86c8d 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/avatarAlphaV.glsl
@@ -22,12 +22,38 @@ vec3 scaleUpLight(vec3 light);
varying vec3 vary_position;
varying vec3 vary_ambient;
varying vec3 vary_directional;
-varying vec3 vary_normal;
+varying vec3 vary_fragcoord;
+varying vec3 vary_pointlight_col;
uniform float near_clip;
uniform float shadow_offset;
uniform float shadow_bias;
+float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float fa, float is_pointlight)
+{
+ //get light vector
+ vec3 lv = lp.xyz-v;
+
+ //get distance
+ float d = length(lv);
+
+ //normalize light vector
+ lv *= 1.0/d;
+
+ //distance attenuation
+ float dist2 = d*d/(la*la);
+ float da = clamp(1.0-(dist2-1.0*(1.0-fa))/fa, 0.0, 1.0);
+
+ // spotlight coefficient.
+ float spot = max(dot(-ln, lv), is_pointlight);
+ da *= spot*spot; // GL_SPOT_EXPONENT=2
+
+ //angular attenuation
+ da *= calcDirectionalLight(n, lv);
+
+ return da;
+}
+
void main()
{
gl_TexCoord[0] = gl_MultiTexCoord0;
@@ -50,7 +76,6 @@ void main()
float dp_directional_light = max(0.0, dot(norm, gl_LightSource[0].position.xyz));
vary_position = pos.xyz + gl_LightSource[0].position.xyz * (1.0-dp_directional_light)*shadow_offset;
- vary_normal = norm;
calcAtmospherics(pos.xyz);
@@ -58,18 +83,20 @@ void main()
vec4 col = vec4(0.0, 0.0, 0.0, gl_Color.a);
- // Collect normal lights (need to be divided by two, as we later multiply by 2)
- col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].specular.a);
- col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].specular.a);
- col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].specular.a);
- col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].specular.a);
- col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].specular.a);
- col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].specular.a);
- col.rgb += gl_LightSource[1].diffuse.rgb*calcDirectionalLight(norm, gl_LightSource[1].position.xyz);
- col.rgb = scaleDownLight(col.rgb);
+ // Collect normal lights
+ col.rgb += gl_LightSource[2].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[2].position, gl_LightSource[2].spotDirection.xyz, gl_LightSource[2].linearAttenuation, gl_LightSource[2].quadraticAttenuation, gl_LightSource[2].specular.a);
+ col.rgb += gl_LightSource[3].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[3].position, gl_LightSource[3].spotDirection.xyz, gl_LightSource[3].linearAttenuation, gl_LightSource[3].quadraticAttenuation ,gl_LightSource[3].specular.a);
+ col.rgb += gl_LightSource[4].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[4].position, gl_LightSource[4].spotDirection.xyz, gl_LightSource[4].linearAttenuation, gl_LightSource[4].quadraticAttenuation, gl_LightSource[4].specular.a);
+ col.rgb += gl_LightSource[5].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[5].position, gl_LightSource[5].spotDirection.xyz, gl_LightSource[5].linearAttenuation, gl_LightSource[5].quadraticAttenuation, gl_LightSource[5].specular.a);
+ col.rgb += gl_LightSource[6].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[6].position, gl_LightSource[6].spotDirection.xyz, gl_LightSource[6].linearAttenuation, gl_LightSource[6].quadraticAttenuation, gl_LightSource[6].specular.a);
+ col.rgb += gl_LightSource[7].diffuse.rgb*calcPointLightOrSpotLight(pos.xyz, norm, gl_LightSource[7].position, gl_LightSource[7].spotDirection.xyz, gl_LightSource[7].linearAttenuation, gl_LightSource[7].quadraticAttenuation, gl_LightSource[7].specular.a);
+ vary_pointlight_col = col.rgb*gl_Color.rgb;
+
+ col.rgb = vec3(0,0,0);
+
// Add windlight lights
- col.rgb += atmosAmbient(vec3(0.));
+ col.rgb = atmosAmbient(vec3(0.));
vary_ambient = col.rgb*gl_Color.rgb;
vary_directional = gl_Color.rgb*atmosAffectDirectionalLight(max(calcDirectionalLight(norm, gl_LightSource[0].position.xyz), (1.0-gl_Color.a)*(1.0-gl_Color.a)));
@@ -79,7 +106,7 @@ void main()
gl_FrontColor = col;
gl_FogFragCoord = pos.z;
-
+ vary_fragcoord.xyz = pos.xyz + vec3(0,0,near_clip);
}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
deleted file mode 100644
index 258a9b7c4..000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
+++ /dev/null
@@ -1,81 +0,0 @@
-/**
- * @file blurLightF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * $/LicenseInfo$
- */
-
-#extension GL_ARB_texture_rectangle : enable
-
-uniform sampler2DRect depthMap;
-uniform sampler2DRect normalMap;
-uniform sampler2DRect lightMap;
-
-uniform float dist_factor;
-uniform float blur_size;
-uniform vec2 delta;
-uniform vec3 kern[4];
-uniform float kern_scale;
-
-varying vec2 vary_fragcoord;
-
-uniform mat4 inv_proj;
-uniform vec2 screen_res;
-
-vec4 getPosition(vec2 pos_screen)
-{
- float depth = texture2DRect(depthMap, pos_screen.xy).a;
- vec2 sc = pos_screen.xy*2.0;
- sc /= screen_res;
- sc -= vec2(1.0,1.0);
- vec4 ndc = vec4(sc.x, sc.y, 2.0*depth-1.0, 1.0);
- vec4 pos = inv_proj * ndc;
- pos /= pos.w;
- pos.w = 1.0;
- return pos;
-}
-
-void main()
-{
- vec3 norm = texture2DRect(normalMap, vary_fragcoord.xy).xyz;
- norm = vec3((norm.xy-0.5)*2.0,norm.z); // unpack norm
- vec3 pos = getPosition(vary_fragcoord.xy).xyz;
- vec4 ccol = texture2DRect(lightMap, vary_fragcoord.xy).rgba;
-
- vec2 dlt = kern_scale * delta / (1.0+norm.xy*norm.xy);
-
- dlt /= max(-pos.z*dist_factor, 1.0);
-
- vec2 defined_weight = kern[0].xy; // special case the first (centre) sample's weight in the blur; we have to sample it anyway so we get it for 'free'
- vec4 col = defined_weight.xyxx * ccol;
-
- for (int i = 1; i < 4; i++)
- {
- vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
- vec3 samppos = getPosition(tc).xyz;
- float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
- if (d*d <= 0.003)
- {
- col += texture2DRect(lightMap, tc)*kern[i].xyxx;
- defined_weight += kern[i].xy;
- }
- }
- for (int i = 1; i < 4; i++)
- {
- vec2 tc = vary_fragcoord.xy - kern[i].z*dlt;
- vec3 samppos = getPosition(tc).xyz;
- float d = dot(norm.xyz, samppos.xyz-pos.xyz);// dist from plane
- if (d*d <= 0.003)
- {
- col += texture2DRect(lightMap, tc)*kern[i].xyxx;
- defined_weight += kern[i].xy;
- }
- }
-
-
-
- col /= defined_weight.xyxx;
-
- gl_FragColor = col;
-}
-
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl
deleted file mode 100644
index b1b3f55f0..000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/blurLightV.glsl
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * @file blurLightF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * $/LicenseInfo$
- */
-
-varying vec2 vary_fragcoord;
-uniform vec2 screen_res;
-
-void main()
-{
- //transform vertex
- gl_Position = ftransform();
- vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
- vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
-}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl b/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl
deleted file mode 100644
index 757e3e7aa..000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/postDeferredF.glsl
+++ /dev/null
@@ -1,59 +0,0 @@
-/**
- * @file postDeferredF.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * $/LicenseInfo$
- */
-
-uniform sampler2DRect diffuseRect;
-uniform sampler2DRect localLightMap;
-uniform sampler2DRect sunLightMap;
-uniform sampler2DRect giLightMap;
-uniform sampler2D luminanceMap;
-uniform sampler2DRect lightMap;
-
-uniform vec3 gi_lum_quad;
-uniform vec3 sun_lum_quad;
-uniform vec3 lum_quad;
-uniform float lum_lod;
-uniform vec4 ambient;
-
-uniform vec3 gi_quad;
-
-uniform vec2 screen_res;
-varying vec2 vary_fragcoord;
-
-void main()
-{
- vec2 tc = vary_fragcoord.xy;
- vec3 lcol = texture2DLod(luminanceMap, tc/screen_res, lum_lod).rgb;
-
- float lum = sqrt(lcol.r)*lum_quad.x+lcol.r*lcol.r*lum_quad.y+lcol.r*lum_quad.z;
-
- vec4 diff = texture2DRect(diffuseRect, vary_fragcoord.xy);
-
- float ambocc = texture2DRect(lightMap, vary_fragcoord.xy).g;
-
- vec3 gi_col = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
- gi_col = gi_col*gi_col*gi_quad.x + gi_col*gi_quad.y+gi_quad.z*ambocc*ambient.rgb;
- gi_col *= diff;
-
- vec4 sun_col = texture2DRect(sunLightMap, vary_fragcoord.xy);
-
- vec3 local_col = texture2DRect(localLightMap, vary_fragcoord.xy).rgb;
-
-
- float sun_lum = 1.0-lum;
- sun_lum = sun_lum*sun_lum*sun_lum_quad.x + sun_lum*sun_lum_quad.y+sun_lum_quad.z;
-
- float gi_lum = lum;
- gi_lum = gi_lum*gi_lum*gi_lum_quad.x+gi_lum*gi_lum_quad.y+gi_lum_quad.z;
- gi_col *= 1.0/gi_lum;
-
- vec3 col = sun_col.rgb*(1.0+max(sun_lum,0.0))+gi_col+local_col;
-
- gl_FragColor.rgb = col.rgb;
- gl_FragColor.a = max(sun_lum*min(sun_col.r+sun_col.g+sun_col.b, 1.0), sun_col.a);
-
- //gl_FragColor.rgb = texture2DRect(giLightMap, vary_fragcoord.xy).rgb;
-}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl b/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl
deleted file mode 100644
index 0ec81dcb0..000000000
--- a/indra/newview/app_settings/shaders/class2/deferred/postDeferredV.glsl
+++ /dev/null
@@ -1,17 +0,0 @@
-/**
- * @file postDeferredV.glsl
- *
- * $LicenseInfo:firstyear=2007&license=viewerlgpl$
- * $/LicenseInfo$
- */
-
-varying vec2 vary_fragcoord;
-uniform vec2 screen_res;
-
-void main()
-{
- //transform vertex
- gl_Position = ftransform();
- vec4 pos = gl_ModelViewProjectionMatrix * gl_Vertex;
- vary_fragcoord = (pos.xy*0.5+0.5)*screen_res;
-}
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
index c457d0a3e..fcea7aaf1 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightSSAOF.glsl
@@ -63,15 +63,13 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)
float dist = dot(pos.xyz,pos.xyz);
- if (dist < 64.0*64.0)
- {
- vec2 kern[8];
- // exponentially (^2) distant occlusion samples spread around origin
- kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
- kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
- kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
- kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
- kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
+ vec2 kern[8];
+ // exponentially (^2) distant occlusion samples spread around origin
+ kern[0] = vec2(-1.0, 0.0) * 0.125*0.125;
+ kern[1] = vec2(1.0, 0.0) * 0.250*0.250;
+ kern[2] = vec2(0.0, 1.0) * 0.375*0.375;
+ kern[3] = vec2(0.0, -1.0) * 0.500*0.500;
+ kern[4] = vec2(0.7071, 0.7071) * 0.625*0.625;
kern[5] = vec2(-0.7071, -0.7071) * 0.750*0.750;
kern[6] = vec2(-0.7071, 0.7071) * 0.875*0.875;
kern[7] = vec2(0.7071, -0.7071) * 1.000*1.000;
@@ -80,38 +78,35 @@ float calcAmbientOcclusion(vec4 pos, vec3 norm)
vec3 pos_world = pos.xyz;
vec2 noise_reflect = texture2D(noiseMap, vary_fragcoord.xy/128.0).xy;
- float angle_hidden = 0.0;
- int points = 0;
+ float angle_hidden = 0.0;
+ int points = 0;
- float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
+ float scale = min(ssao_radius / -pos_world.z, ssao_max_radius);
- // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
- for (int i = 0; i < 8; i++)
- {
- vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
- vec3 samppos_world = getPosition(samppos_screen).xyz;
+ // it was found that keeping # of samples a constant was the fastest, probably due to compiler optimizations (unrolling?)
+ for (int i = 0; i < 8; i++)
+ {
+ vec2 samppos_screen = pos_screen + scale * reflect(kern[i], noise_reflect);
+ vec3 samppos_world = getPosition(samppos_screen).xyz;
- vec3 diff = pos_world - samppos_world;
- float dist2 = dot(diff, diff);
+ vec3 diff = pos_world - samppos_world;
+ float dist2 = dot(diff, diff);
- // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
- // --> solid angle shrinking by the square of distance
- //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
- //(k should vary inversely with # of samples, but this is taken care of later)
+ // assume each sample corresponds to an occluding sphere with constant radius, constant x-sectional area
+ // --> solid angle shrinking by the square of distance
+ //radius is somewhat arbitrary, can approx with just some constant k * 1 / dist^2
+ //(k should vary inversely with # of samples, but this is taken care of later)
- //if (dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) // -0.05*norm to shift sample point back slightly for flat surfaces
- // angle_hidden += min(1.0/dist2, ssao_factor_inv); // dist != 0 follows from conditional. max of 1.0 (= ssao_factor_inv * ssao_factor)
- angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
+ angle_hidden = angle_hidden + float(dot((samppos_world - 0.05*norm - pos_world), norm) > 0.0) * min(1.0/dist2, ssao_factor_inv);
- // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
- points = points + int(diff.z > -1.0);
- }
-
- angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
-
- ret = (1.0 - (float(points != 0) * angle_hidden));
- ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0);
+ // 'blocked' samples (significantly closer to camera relative to pos_world) are "no data", not "no occlusion"
+ points = points + int(diff.z > -1.0);
}
+
+ angle_hidden = min(ssao_factor*angle_hidden/float(points), 1.0);
+
+ ret = (1.0 - (float(points != 0) * angle_hidden));
+ ret += max((dist-32.0*32.0)/(32.0*32.0), 0.0);
return min(ret, 1.0);
}
diff --git a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
index ce32f6600..56f3f9697 100644
--- a/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
+++ b/indra/newview/app_settings/shaders/class3/deferred/softenLightF.glsl
@@ -13,8 +13,7 @@ uniform sampler2DRect diffuseRect;
uniform sampler2DRect specularRect;
uniform sampler2DRect normalMap;
uniform sampler2DRect lightMap;
-uniform sampler2D noiseMap;
-uniform samplerCube environmentMap;
+uniform sampler2DRect depthMap;
uniform sampler2D lightFunc;
uniform vec3 gi_quad;
@@ -43,7 +42,6 @@ uniform vec3 env_mat[3];
uniform vec4 shadow_clip;
uniform mat3 ssao_effect_mat;
-uniform sampler2DRect depthMap;
uniform mat4 inv_proj;
uniform vec2 screen_res;
diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp
index 2613e7149..8e3c01011 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -425,8 +425,6 @@ LLAgent::LLAgent() :
mAutoPilotRotationThreshold(0.f),
mAutoPilotFinishedCallback(NULL),
mAutoPilotCallbackData(NULL),
-
- mCapabilities(),
mEffectColor(0.f, 1.f, 1.f, 1.f),
@@ -7093,16 +7091,6 @@ void LLAgent::processAgentInitialWearablesUpdate( LLMessageSystem* mesgsys, void
// before we had wearables, or that the database has gotten messed up.
return;
}
- //else
- //{
- // // OGPX HACK: OGP authentication does not pass back login-flags,
- // // thus doesn't check for "gendered" flag
- // // so this isn't an ideal place for this because the check in idle_startup in STATE_WEARABLES_WAIT
- // // is happening *before* this call. That causes the welcomechoosesex dialog to be displayed
- // // but I'm torn on removing this commented out code because I'm unsure how the initial wearables
- // // code will work out.
- // gAgent.setGenderChosen(TRUE);
- //}
//lldebugs << "processAgentInitialWearablesUpdate()" << llendl;
// Add wearables
@@ -8544,43 +8532,6 @@ void LLAgent::userAttachMultipleAttachments(LLInventoryModel::item_array_t& obj_
}
}
-// OGPX - This code will change when capabilities get refactored.
-// Right now this is used for capabilities that we get from OGP agent domain
-void LLAgent::setCapability(const std::string& name, const std::string& url)
-{
-#if 0 // OGPX : I think (hope?) we don't need this
- // but I'm leaving it here commented out because I'm not quite
- // sure why the region capabilities code had it wedged in setCap call
- // Maybe the agent domain capabilities will need something like this as well
-
- if (name == "EventQueueGet")
- {
- delete mEventPoll;
- mEventPoll = NULL;
- mEventPoll = new LLEventPoll(url, getHost());
- }
- else if (name == "UntrustedSimulatorMessage")
- {
- LLHTTPSender::setSender(mHost, new LLCapHTTPSender(url));
- }
- else
-#endif
- {
- mCapabilities[name] = url;
- }
-}
-
-//OGPX : Agent Domain capabilities... this needs to be refactored
-std::string LLAgent::getCapability(const std::string& name) const
-{
- CapabilityMap::const_iterator iter = mCapabilities.find(name);
- if (iter == mCapabilities.end())
- {
- return "";
- }
- return iter->second;
-}
-
void LLAgent::showLureDestination(const std::string fromname, const int global_x, const int global_y, const int x, const int y, const int z, const std::string maturity)
{
const LLVector3d posglobal = LLVector3d(F64(global_x), F64(global_y), F64(0));
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 8fafdd7b9..f697e4778 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -376,15 +376,6 @@ public:
const LLColor4 &getEffectColor();
void setEffectColor(const LLColor4 &color);
- // OGPX : Moving capabilities off region to agent service means they end up in LLAgent
- // but, long term, this needs to be refactored into generalized Capabilities class
- // since we want more flexibility in gathering up where services come from.
- // Segmenting into region and agent domain caps might not make sense. Some implementations
- // might want to provide caps that are not on the region or the agent domain. This is
- // unsettled enough for now that we'll leave it as is.
- void setCapability(const std::string& name, const std::string& url);
- std::string getCapability(const std::string& name) const ;
-
//
// UTILITIES
//
@@ -538,11 +529,6 @@ public:
const LLVector3 &getTargetVelocity() const;
const std::string getTeleportSourceSLURL() const { return mTeleportSourceSLURL; }
- // OGPX : setTeleportSourceURL() is only used in agent domain case,
- // so also made function name go from SLURL->URL for OGPX.
- // This is what gets chatted into text chat when a teleport successfully completes.
- void setTeleportSourceURL(const std::string agentdTeleportURL){ mTeleportSourceSLURL = agentdTeleportURL;};
-
// Setting the ability for this avatar to proxy for another avatar.
//static void processAddModifyAbility(LLMessageSystem* msg, void**);
@@ -629,7 +615,6 @@ public:
TELEPORT_START_ARRIVAL = 4, // Transition to ARRIVING. Viewer has received avatar update, etc., from destination simulator
TELEPORT_ARRIVING = 5, // Make the user wait while content "pre-caches"
TELEPORT_LOCAL = 6, // Teleporting in-sim without showing the progress screen
- TELEPORT_PLACE_AVATAR = 7 // OGPX : Separate agent domain TP using place_avatar from legacy
};
ETeleportState getTeleportState() const { return mTeleportState; }
@@ -750,11 +735,12 @@ public:
// whether look-at reset after teleport
bool getTeleportKeepsLookAt() { return mbTeleportKeepsLookAt; }
+protected:
// stuff to do for any sort of teleport. Returns true if the
// teleport can proceed.
- bool teleportCore(bool is_local = false); //OGPX : now public method so agent domain TP can call
+ bool teleportCore(bool is_local = false);
+
-protected:
// helper function to prematurely age chat when agent is moving
void ageChat();
@@ -954,11 +940,6 @@ private:
std::set mProxyForAgents;
-
- //
- typedef std::map CapabilityMap; //OGPX TODO: refactor Caps to their own class
- CapabilityMap mCapabilities; // for caps that we have on the agent domain.
-
LLColor4 mEffectColor;
BOOL mHaveHomePosition;
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 2f8b41b73..95d419d6e 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -305,10 +305,6 @@ BOOL gCrashOnStartup = FALSE;
BOOL gLLErrorActivated = FALSE;
BOOL gLogoutInProgress = FALSE;
-static std::string gPlaceAvatarCap; //OGPX TODO: should belong elsewhere, as part of the llagent caps?
-
-
-
////////////////////////////////////////////////////////////
// Internal globals... that should be removed.
static std::string gArgs;
@@ -438,7 +434,6 @@ static void settings_to_globals()
LLFolderView::sAutoOpenTime = llmax(0.25f, gSavedSettings.getF32("FolderAutoOpenDelay"));
LLToolBar::sInventoryAutoOpenTime = gSavedSettings.getF32("InventoryAutoOpenDelay");
LLSelectMgr::sRectSelectInclusive = gSavedSettings.getBOOL("RectangleSelectInclusive");
- LLSelectMgr::sRenderSelectionHighlights = gSavedSettings.getBOOL("RenderHighlightSelections");
LLSelectMgr::sRenderHiddenSelections = gSavedSettings.getBOOL("RenderHiddenSelections");
LLSelectMgr::sRenderLightRadius = gSavedSettings.getBOOL("RenderLightRadius");
@@ -589,6 +584,7 @@ bool LLAppViewer::init()
LLCurl::initClass();
initThreads();
+ LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ; ;
writeSystemInfo();
@@ -736,12 +732,14 @@ bool LLAppViewer::init()
OSMB_OK);
return 1;
}
+ LL_INFOS("InitInfo") << "Cache initialization is done." << LL_ENDL ;
//
// Initialize the window
//
gGLActive = TRUE;
initWindow();
+ LL_INFOS("InitInfo") << "Window is initialized." << LL_ENDL ;
// initWindow also initializes the Feature List, so now we can initialize this global.
LLCubeMap::sUseCubeMaps = LLFeatureManager::getInstance()->isFeatureAvailable("RenderCubeMap");
@@ -784,6 +782,32 @@ bool LLAppViewer::init()
return 0;
}
+#if (_M_IX86_FP > 1 || defined(__SSE2__))
+ // Without SSE2 support we will crash almost immediately, warn here.
+ if (!gSysCPU.hasSSE2())
+ {
+ // can't use an alert here since we're exiting and
+ // all hell breaks lose.
+ OSMessageBox(
+ LLNotifications::instance().getGlobalString("UnsupportedCPUSSE2"),
+ LLStringUtil::null,
+ OSMB_OK);
+ return 0;
+ }
+#else if (_M_IX86_FP == 1 || defined(__SSE__))
+ // Without SSE support we will crash almost immediately, warn here.
+ if (!gSysCPU.hasSSE())
+ {
+ // can't use an alert here since we're exiting and
+ // all hell breaks lose.
+ OSMessageBox(
+ LLNotifications::instance().getGlobalString("UnsupportedCPUSSE"),
+ LLStringUtil::null,
+ OSMB_OK);
+ return 0;
+ }
+#endif
+
// alert the user if they are using unsupported hardware
if(!gSavedSettings.getBOOL("AlertedUnsupportedHardware"))
{
@@ -874,13 +898,33 @@ bool LLAppViewer::mainLoop()
LLMemType mt1(LLMemType::MTYPE_MAIN);
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
+ LLFrameTimer memCheckTimer;
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
joystick->setNeedsReset(true);
+
+ const F32 memory_check_interval = 1.0f ; //second
+
// Handle messages
while (!LLApp::isExiting())
{
LLFastTimer::reset(); // Should be outside of any timer instances
+
+ //clear call stack records
+ llclearcallstacks;
+
+ //check memory availability information
+ {
+ if(memory_check_interval < memCheckTimer.getElapsedTimeF32())
+ {
+ memCheckTimer.reset() ;
+
+ //update the availability of memory
+ LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
+ }
+ llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ;
+ llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ;
+ }
try
{
LLFastTimer t(LLFastTimer::FTM_FRAME);
@@ -914,9 +958,11 @@ bool LLAppViewer::mainLoop()
#endif
//memory leaking simulation
- if(LLFloaterMemLeak::getInstance())
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterMemLeak::getInstance();
+ if(mem_leak_instance)
{
- LLFloaterMemLeak::getInstance()->idle() ;
+ mem_leak_instance->idle() ;
}
if (!LLApp::isExiting())
@@ -1079,10 +1125,22 @@ bool LLAppViewer::mainLoop()
}
catch(std::bad_alloc)
{
- //stop memory leaking simulation
- if(LLFloaterMemLeak::getInstance())
{
- LLFloaterMemLeak::getInstance()->stop() ;
+ llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ;
+ llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ;
+
+ LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
+
+ llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ;
+ llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ;
+ }
+
+ //stop memory leaking simulation
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterMemLeak::getInstance();
+ if(mem_leak_instance)
+ {
+ mem_leak_instance->stop() ;
llwarns << "Bad memory allocation in LLAppViewer::mainLoop()!" << llendl ;
}
else
@@ -1107,9 +1165,11 @@ bool LLAppViewer::mainLoop()
llwarns << "Bad memory allocation when saveFinalSnapshot() is called!" << llendl ;
//stop memory leaking simulation
- if(LLFloaterMemLeak::getInstance())
+ LLFloaterMemLeak* mem_leak_instance =
+ LLFloaterMemLeak::getInstance();
+ if(mem_leak_instance)
{
- LLFloaterMemLeak::getInstance()->stop() ;
+ mem_leak_instance->stop() ;
}
}
}
@@ -1123,6 +1183,21 @@ bool LLAppViewer::mainLoop()
return true;
}
+void LLAppViewer::flushVFSIO()
+{
+ while (1)
+ {
+ S32 pending = LLVFSThread::updateClass(0);
+ pending += LLLFSThread::updateClass(0);
+ if (!pending)
+ {
+ break;
+ }
+ llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
+ ms_sleep(100);
+ }
+}
+
extern void cleanup_pose_stand(void);
bool LLAppViewer::cleanup()
@@ -1235,36 +1310,31 @@ bool LLAppViewer::cleanup()
removeCacheFiles("*.dsf");
removeCacheFiles("*.bodypart");
removeCacheFiles("*.clothing");
+
//
+ llinfos << "Cache files removed" << llendflush;
*/
//
- llinfos << "Cache files removed" << llendflush;
-
cleanup_menus();
// Wait for any pending VFS IO
- while (1)
- {
- S32 pending = LLVFSThread::updateClass(0);
- pending += LLLFSThread::updateClass(0);
- if (!pending)
- {
- break;
- }
- llinfos << "Waiting for pending IO to finish: " << pending << llendflush;
- ms_sleep(100);
- }
- llinfos << "Shutting down." << llendflush;
+ flushVFSIO();
+ llinfos << "Shutting down Views" << llendflush;
// Destroy the UI
if( gViewerWindow)
gViewerWindow->shutdownViews();
+
+ llinfos << "Cleaning up Selections" << llendflush;
+
// Clean up selection managers after UI is destroyed, as UI may be observing them.
// Clean up before GL is shut down because we might be holding on to objects with texture references
LLSelectMgr::cleanupGlobals();
+
+ llinfos << "Shutting down OpenGL" << llendflush;
// Shut down OpenGL
if( gViewerWindow)
@@ -1279,10 +1349,15 @@ bool LLAppViewer::cleanup()
llinfos << "ViewerWindow deleted" << llendflush;
}
+ llinfos << "Cleaning up Keyboard & Joystick" << llendflush;
+
// viewer UI relies on keyboard so keep it aound until viewer UI isa gone
delete gKeyboard;
gKeyboard = NULL;
+
+ llinfos << "Cleaning up Objects" << llendflush;
+
LLViewerObject::cleanupVOClasses();
LLWaterParamManager::cleanupClass();
@@ -1311,6 +1386,8 @@ bool LLAppViewer::cleanup()
}
LLPrimitive::cleanupVolumeManager();
+ llinfos << "Additional Cleanup..." << llendflush;
+
LLViewerParcelMgr::cleanupGlobals();
// *Note: this is where gViewerStats used to be deleted.
@@ -1330,8 +1407,10 @@ bool LLAppViewer::cleanup()
// Also after shutting down the messaging system since it has VFS dependencies
//
+ llinfos << "Cleaning up VFS" << llendflush;
LLVFile::cleanupClass();
- llinfos << "VFS cleaned up" << llendflush;
+
+ llinfos << "Saving Data" << llendflush;
// Quitting with "Remember Password" turned off should always stomp your
// saved password, whether or not you successfully logged in. JC
@@ -1347,10 +1426,17 @@ bool LLAppViewer::cleanup()
// save their rects on delete.
gSavedSettings.saveToFile(gSavedSettings.getString("ClientSettingsFile"), TRUE);
- // PerAccountSettingsFile should be empty if no use has been logged on.
+ // PerAccountSettingsFile should be empty if no user has been logged on.
// *FIX:Mani This should get really saved in a "logoff" mode.
- gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
- llinfos << "Saved settings" << llendflush;
+ if (gSavedSettings.getString("PerAccountSettingsFile").empty())
+ {
+ llinfos << "Not saving per-account settings; don't know the account name yet." << llendl;
+ }
+ else
+ {
+ gSavedPerAccountSettings.saveToFile(gSavedSettings.getString("PerAccountSettingsFile"), TRUE);
+ llinfos << "Saved settings" << llendflush;
+ }
std::string crash_settings_filename = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, CRASH_SETTINGS_FILE);
// save all settings, even if equals defaults
@@ -1383,6 +1469,11 @@ bool LLAppViewer::cleanup()
removeCacheFiles("*.dsf");
removeCacheFiles("*.bodypart");
removeCacheFiles("*.clothing");
+ llinfos << "Cache files removed" << llendflush;
+ }
+ else
+ {
+ llinfos << "Not removing cache files. Other viewer instance detected." << llendflush;
}
//
@@ -1391,6 +1482,8 @@ bool LLAppViewer::cleanup()
// Stop the plugin read thread if it's running.
LLPluginProcessParent::setUseReadThread(false);
+ llinfos << "Shutting down Threads" << llendflush;
+
// Let threads finish
LLTimer idleTimer;
idleTimer.reset();
@@ -1428,6 +1521,9 @@ bool LLAppViewer::cleanup()
delete sImageDecodeThread;
sImageDecodeThread = NULL;
+
+ llinfos << "Cleaning up Media and Textures" << llendflush;
+
//Note:
//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
//because some new image might be generated during cleaning up media. --bao
@@ -1490,7 +1586,10 @@ bool LLAppViewer::cleanup()
llinfos << "File launched." << llendflush;
}
- llinfos << "Goodbye" << llendflush;
+
+ ll_close_fail_log();
+
+ llinfos << "Goodbye!" << llendflush;
// return 0;
return true;
@@ -1958,6 +2057,14 @@ bool LLAppViewer::initConfiguration()
{
gCrashOnStartup = TRUE;
}
+
+ if (clp.hasOption("debugsession"))
+ {
+ gDebugSession = TRUE;
+ gDebugGL = TRUE;
+
+ ll_init_fail_log(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "test_failures.log"));
+ }
// Handle slurl use. NOTE: Don't let SL-55321 reappear.
@@ -2363,7 +2470,12 @@ void LLAppViewer::writeSystemInfo()
{
gDebugInfo["SLLog"] = LLError::logFileName();
-
+ gDebugInfo["ClientInfo"]["Name"] = LL_CHANNEL;
+
+ gDebugInfo["ClientInfo"]["MajorVersion"] = LL_VERSION_MAJOR;
+ gDebugInfo["ClientInfo"]["MinorVersion"] = LL_VERSION_MINOR;
+ gDebugInfo["ClientInfo"]["PatchVersion"] = LL_VERSION_PATCH;
+ gDebugInfo["ClientInfo"]["BuildVersion"] = LL_VERSION_BUILD;
gDebugInfo["CAFilename"] = gDirUtilp->getCAFile();
@@ -2428,6 +2540,8 @@ void LLAppViewer::handleViewerCrash()
{
llinfos << "Handle viewer crash entry." << llendl;
+ llinfos << "Last render pool type: " << LLPipeline::sCurRenderPoolType << llendl ;
+
//print out recorded call stacks if there are any.
LLError::LLCallStacks::print();
@@ -2873,45 +2987,54 @@ void LLAppViewer::migrateCacheDirectory()
#endif // LL_WINDOWS || LL_DARWIN
}
+//static
+U32 LLAppViewer::getTextureCacheVersion()
+{
+ //viewer texture cache version, change if the texture cache format changes.
+ static const U32 TEXTURE_CACHE_VERSION = 7;
+
+ return TEXTURE_CACHE_VERSION ;
+}
bool LLAppViewer::initCache()
{
mPurgeCache = false;
BOOL read_only = mSecondInstance ? TRUE : FALSE;
LLAppViewer::getTextureCache()->setReadOnly(read_only);
- BOOL texture_cache_mismatch = FALSE ;
- static const S32 cache_version = 7;
- if (gSavedSettings.getS32("LocalCacheVersion") != cache_version)
+ bool texture_cache_mismatch = false;
+ if (gSavedSettings.getS32("LocalCacheVersion") != LLAppViewer::getTextureCacheVersion())
{
- texture_cache_mismatch = TRUE ;
- if (!read_only)
+ texture_cache_mismatch = true;
+ if(!read_only)
{
- gSavedSettings.setS32("LocalCacheVersion", cache_version);
+ gSavedSettings.setS32("LocalCacheVersion", LLAppViewer::getTextureCacheVersion());
}
}
if (!read_only)
{
- // Purge cache if user requested it
- if (gSavedSettings.getBOOL("PurgeCacheOnStartup") ||
- gSavedSettings.getBOOL("PurgeCacheOnNextStartup"))
- {
- gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false);
- mPurgeCache = true;
- }
+ // Purge cache if user requested it
+ if (gSavedSettings.getBOOL("PurgeCacheOnStartup") ||
+ gSavedSettings.getBOOL("PurgeCacheOnNextStartup"))
+ {
+ gSavedSettings.setBOOL("PurgeCacheOnNextStartup", false);
+ mPurgeCache = true;
+ // STORM-1141 force purgeAllTextures to get called to prevent a crash here. -brad
+ texture_cache_mismatch = true;
+ }
- // We have moved the location of the cache directory over time.
- migrateCacheDirectory();
+ // We have moved the location of the cache directory over time.
+ migrateCacheDirectory();
- // Setup and verify the cache location
- std::string cache_location = gSavedSettings.getString("CacheLocation");
- std::string new_cache_location = gSavedSettings.getString("NewCacheLocation");
- if (new_cache_location != cache_location)
- {
- gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"));
- purgeCache(); // purge old cache
- gSavedSettings.setString("CacheLocation", new_cache_location);
- }
+ // Setup and verify the cache location
+ std::string cache_location = gSavedSettings.getString("CacheLocation");
+ std::string new_cache_location = gSavedSettings.getString("NewCacheLocation");
+ if (new_cache_location != cache_location)
+ {
+ gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation"));
+ purgeCache(); // purge old cache
+ gSavedSettings.setString("CacheLocation", new_cache_location);
+ }
}
if (!gDirUtilp->setCacheDir(gSavedSettings.getString("CacheLocation")))
@@ -3106,18 +3229,6 @@ const std::string& LLAppViewer::getWindowTitle() const
return gWindowTitle;
}
- // OGPX TODO: refactor caps code please, also "PlaceAvatar" is a bit dated, since
- // we have since changed the name of the cap
-void LLAppViewer::setPlaceAvatarCap(const std::string& uri)
-{
- gPlaceAvatarCap = uri;
-}
-
-const std::string& LLAppViewer::getPlaceAvatarCap() const
-{
- return gPlaceAvatarCap;
-}
-
// Callback from a dialog indicating user was logged out.
bool finish_disconnect(const LLSD& notification, const LLSD& response)
{
@@ -3238,6 +3349,7 @@ void LLAppViewer::loadNameCache()
// Phoenix: Wolfspirit: Loads the Display Name Cache. And set if we are using Display Names.
std::string filename =
gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "avatar_name_cache.xml");
+ LL_INFOS("AvNameCache") << filename << LL_ENDL;
llifstream name_cache_stream(filename);
if(name_cache_stream.is_open())
{
@@ -3767,39 +3879,6 @@ void LLAppViewer::idleShutdown()
}
}
-// OGPX : Instead of sending UDP messages to the sim, tell the Agent Domain about logoff
-//... This responder is used with rez_avatar/place when the specialized case
-//... of sending a null region name is sent to the agent domain. Null region name means
-//... log me off of agent domain. *But* what about cases where you want to be logged into
-//... agent domain, but not physically on a region?
-class LLLogoutResponder :
- public LLHTTPClient::Responder
-{
-public:
- LLLogoutResponder()
- {
- }
-
- ~LLLogoutResponder()
- {
- }
-
- void error(U32 statusNum, const std::string& reason)
- {
- // consider retries
- llinfos << "LLLogoutResponder error "
- << statusNum << " " << reason << llendl;
- }
-
- void result(const LLSD& content)
- {
- // perhaps logoutReply should come through this in the future
- llinfos << "LLLogoutResponder completed successfully" << llendl;
-
- }
-
-};
-
void LLAppViewer::idleNameCache()
{
// Neither old nor new name cache can function before agent has a region
@@ -3922,7 +4001,6 @@ void LLAppViewer::idleNetwork()
llpushcallstacks ;
LLTimer check_message_timer;
// Read all available packets from network
- stop_glerror();
const S64 frame_count = gFrameCount; // U32->S64
F32 total_time = 0.0f;
while (gMessageSystem->checkAllMessages(frame_count, gServicePump))
@@ -3934,7 +4012,6 @@ void LLAppViewer::idleNetwork()
// server going down, so this is OK.
break;
}
- stop_glerror();
total_decoded++;
gPacketsIn++;
@@ -3954,6 +4031,7 @@ void LLAppViewer::idleNetwork()
break;
#endif
}
+
// Handle per-frame message system processing.
gMessageSystem->processAcks();
@@ -3974,8 +4052,6 @@ void LLAppViewer::idleNetwork()
// we want to clear the control after sending out all necessary agent updates
gAgent.resetControlFlags();
- stop_glerror();
-
// Decode enqueued messages...
S32 remaining_possible_decodes = MESSAGE_MAX_PER_FRAME - total_decoded;
@@ -4130,7 +4206,7 @@ void LLAppViewer::forceErrorBadMemoryAccess()
return;
}
-void LLAppViewer::forceErrorInifiniteLoop()
+void LLAppViewer::forceErrorInfiniteLoop()
{
while(true)
{
diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h
index 933d4150a..d7f99c1bd 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -64,6 +64,7 @@ public:
virtual bool mainLoop(); // Override for the application main loop. Needs to at least gracefully notice the QUITTING state and exit.
// Application control
+ void flushVFSIO(); // waits for vfs transfers to complete
void forceQuit(); // Puts the viewer into 'shutting down without error' mode.
void requestQuit(); // Request a quit. A kinder, gentler quit.
void userQuit(); // The users asks to quit. Confirm, then requestQuit()
@@ -95,6 +96,7 @@ public:
static LLImageDecodeThread* getImageDecodeThread() { return sImageDecodeThread; }
static LLTextureFetch* getTextureFetch() { return sTextureFetch; }
+ static U32 getTextureCacheVersion();
const std::string& getSerialNumber() { return mSerialNumber; }
bool getPurgeCache() const { return mPurgeCache; }
@@ -111,13 +113,6 @@ public:
void loadNameCache();
void saveNameCache();
- // OGPX : rez_avatar/place cap is used on both initial login, and
- // ... then on teleports as well. The same cap should be good for the
- // ... life of the connection to an agent domain. This cap is used by the viewer
- // ... to request moving an agent between regions.
- void setPlaceAvatarCap(const std::string& uri); // OGPX TODO: this should be refactored into own class that handles caps
- const std::string& getPlaceAvatarCap() const; // OGPX TODO: ...as above...
-
void removeMarkerFile(bool leave_logout_marker = false);
// LLAppViewer testing helpers.
@@ -125,7 +120,7 @@ public:
virtual void forceErrorLLError();
virtual void forceErrorBreakpoint();
virtual void forceErrorBadMemoryAccess();
- virtual void forceErrorInifiniteLoop();
+ virtual void forceErrorInfiniteLoop();
virtual void forceErrorSoftwareException();
virtual void forceErrorDriverCrash();
@@ -197,8 +192,9 @@ private:
void idle();
void idleShutdown();
+ // update avatar SLID and display name caches
+ void idleNameCache();
void idleNetwork();
- void idleNameCache();
void sendLogoutRequest();
void disconnectViewer();
@@ -243,6 +239,10 @@ private:
bool mAgentRegionLastAlive;
LLUUID mAgentRegionLastID;
+
+ U32 mAvailPhysicalMemInKB ;
+ U32 mAvailVirtualMemInKB ;
+
public:
//some information for updater
typedef struct
diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp
index 051a5cdaa..b5a185a0c 100644
--- a/indra/newview/llappviewerwin32.cpp
+++ b/indra/newview/llappviewerwin32.cpp
@@ -244,6 +244,8 @@ int APIENTRY WINMAIN(HINSTANCE hInstance,
}
#endif
+ gGLActive = TRUE;
+
viewer_app_ptr->cleanup();
#if WINDOWS_CRT_MEM_CHECKS
@@ -498,7 +500,11 @@ bool LLAppViewerWin32::initHardwareTest()
LL_WARNS("AppInit") << " Someone took over my exception handler (post hardware probe)!" << LL_ENDL;
}
- gGLManager.mVRAM = gDXHardware.getVRAM();
+ if (gGLManager.mVRAM == 0)
+ {
+ gGLManager.mVRAM = gDXHardware.getVRAM();
+ }
+
LL_INFOS("AppInit") << "Detected VRAM: " << gGLManager.mVRAM << LL_ENDL;
return true;
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index fce802f77..64464f132 100644
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -118,6 +118,10 @@ void LLDrawable::initClass()
void LLDrawable::destroy()
{
+ if (gDebugGL)
+ {
+ gPipeline.checkReferences(this);
+ }
if (isDead())
{
sNumZombieDrawables--;
@@ -688,13 +692,15 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update)
LLVOVolume* volume = getVOVolume();
if (volume)
{
- volume->updateRelativeXform();
- pos = volume->getRelativeXform().getTranslation();
- if (isStatic())
+ if (getSpatialGroup())
{
- pos += volume->getRegion()->getOriginAgent();
+ pos.set(getPositionGroup());
}
-
+ else
+ {
+ pos = getPositionAgent();
+ }
+
if (isState(LLDrawable::HAS_ALPHA))
{
for (S32 i = 0; i < getNumFaces(); i++)
diff --git a/indra/newview/lldrawpoolsky.cpp b/indra/newview/lldrawpoolsky.cpp
index 4d34f7cd2..b5cc0d31d 100644
--- a/indra/newview/lldrawpoolsky.cpp
+++ b/indra/newview/lldrawpoolsky.cpp
@@ -69,6 +69,7 @@ void LLDrawPoolSky::prerender()
void LLDrawPoolSky::render(S32 pass)
{
+ gGL.flush();
if (mDrawFace.empty())
{
return;
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index 69e811905..2b93af7b1 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -45,7 +45,6 @@
#include "lldrawable.h"
#include "llface.h"
#include "llsky.h"
-#include "llviewercamera.h" // to get OGL_TO_CFR_ROTATION
#include "llviewertexturelist.h"
#include "llviewerregion.h"
#include "llvosky.h"
diff --git a/indra/newview/lldrawpoolwlsky.cpp b/indra/newview/lldrawpoolwlsky.cpp
index f72da554c..4a6321a69 100644
--- a/indra/newview/lldrawpoolwlsky.cpp
+++ b/indra/newview/lldrawpoolwlsky.cpp
@@ -42,7 +42,6 @@
#include "llwlparammanager.h"
#include "llsky.h"
#include "llvowlsky.h"
-#include "llagent.h"
#include "llviewerregion.h"
#include "llface.h"
#include "llrender.h"
diff --git a/indra/newview/llemote.cpp b/indra/newview/llemote.cpp
index bacf3daf5..c83846215 100644
--- a/indra/newview/llemote.cpp
+++ b/indra/newview/llemote.cpp
@@ -39,7 +39,6 @@
#include "llcharacter.h"
#include "m3math.h"
#include "llvoavatar.h"
-#include "llagent.h"
//-----------------------------------------------------------------------------
// Constants
diff --git a/indra/newview/lleventnotifier.cpp b/indra/newview/lleventnotifier.cpp
index 63cf2b16a..1e915a266 100644
--- a/indra/newview/lleventnotifier.cpp
+++ b/indra/newview/lleventnotifier.cpp
@@ -117,7 +117,6 @@ void LLEventNotifier::load(const LLUserAuth::options_t& event_options)
}
}
-
BOOL LLEventNotifier::hasNotification(const U32 event_id)
{
if (mEventNotifications.find(event_id) != mEventNotifications.end())
@@ -127,7 +126,6 @@ BOOL LLEventNotifier::hasNotification(const U32 event_id)
return FALSE;
}
-
void LLEventNotifier::add(LLEventInfo &event_info)
{
// We need to tell the simulator that we want to pay attention to
diff --git a/indra/newview/lleventpoll.cpp b/indra/newview/lleventpoll.cpp
index 8469bcda5..3114f2914 100644
--- a/indra/newview/lleventpoll.cpp
+++ b/indra/newview/lleventpoll.cpp
@@ -142,10 +142,7 @@ namespace
LLViewerRegion *regionp = gAgent.getRegion();
if (!regionp)
{
- // OGPX : Changed from llerrs to llwarns.
- // No longer an llerrs error, because we might be starting an event queue before we have a region.
-
- llwarns << "LLEventPoll initialized before region is added." << llendl;
+ llerrs << "LLEventPoll initialized before region is added." << llendl;
}
mSender = sender.getIPandPort();
llinfos << "LLEventPoll initialized with sender " << mSender << llendl;
@@ -239,12 +236,6 @@ namespace
if(gAgent.getRegion() && gAgent.getRegion()->getHost().getIPandPort() == mSender)
{
llwarns << "Forcing disconnect due to stalled main region event poll." << llendl;
- // OGPX - Is this valid in the OGPX case? forceDisconnect() pops up a dialog.
- // in the OGPX case, if we lose the connection to the region, we might still
- // have one to the Agent Domain.
- // Since the viewer doesn't currently implement any functionality that involves
- // being connected to the Agent Domain without also being connected to a region, leave the
- // call to forceDisconnect() here.
LLAppViewer::instance()->forceDisconnect(LLTrans::getString("AgentLostConnection"));
}
}
@@ -253,8 +244,8 @@ namespace
//virtual
void LLEventPollResponder::result(const LLSD& content)
{
- LL_DEBUGS("OGPX") << "LLEventPollResponder::result <" << mCount << ">"
- << (mDone ? " -- done" : "") << ll_pretty_print_sd(content) << LL_ENDL;
+ lldebugs << "LLEventPollResponder::result <" << mCount << ">"
+ << (mDone ? " -- done" : "") << ll_pretty_print_sd(content) << llendl;
if (mDone) return;
@@ -292,226 +283,6 @@ namespace
makeRequest();
}
-
- // OGPX : So this area of the code is an acknowledged mess... but...
- // it is also an area that will be changing a lot as OGPX changes and grows.
- // Leave the event queue code completely separate (agent vs region eq) so that
- // normal legacy region eq connections aren't subject to the thrashing
- // that agent eq code will have.
- //
- // Similar to the way a sim needs to invoke a request on the client without doing
- // an actual inbound http request, this is the similar mechanism for
- // the Agent Domain. One area of current investigation is how the viewer
- // might accomodate requests from multiple services (i.e., we shouldn't make
- // assumptions about how a particular OGPX grid or agent domain has carved up
- // the handling of different pieces of functionality).
-
-
- class LLAgentEventPollResponder : public LLHTTPClient::Responder
- {
- public:
-
- static LLHTTPClient::ResponderPtr start(const std::string& pollURL);
- void stop();
- virtual void makeRequest();
- virtual void makeRequest(const LLSD&);
-
- private:
- LLAgentEventPollResponder(const std::string& pollURL);
- ~LLAgentEventPollResponder();
-
- //void handleMessage(const LLSD& content);
- virtual void error(U32 status, const std::string& reason);
- virtual void result(const LLSD& content);
-
- private:
-
- bool mDone;
- int mAcknowledge ; // OGPX : id of request to send back along with the response to Agent Domain.
- // We will probably change the specifics of returning the result of
- // a resource request.
-
- std::string mPollURL;
-
- // these are only here for debugging so we can see which poller is which
- static int sCount;
- int mCount;
- };
-
-
- //static
- LLHTTPClient::ResponderPtr LLAgentEventPollResponder::start(
- const std::string& pollURL)
- {
- LLHTTPClient::ResponderPtr result = new LLAgentEventPollResponder(pollURL);
- LL_INFOS("OGPX") << "LLAgentEventPollResponder::start <" << sCount << "> "
- << pollURL << LL_ENDL;
- return result;
- }
-
- void LLAgentEventPollResponder::stop()
- {
- LL_INFOS("OGPX") << "LLAgentEventPollResponder::stop <" << mCount << "> "
- << mPollURL << LL_ENDL;
- // there should be a way to stop a LLHTTPClient request in progress
- mDone = true;
- }
-
- int LLAgentEventPollResponder::sCount = 0;
-
- LLAgentEventPollResponder::LLAgentEventPollResponder(const std::string& pollURL)
- : mDone(false),
- mPollURL(pollURL),
- mAcknowledge(0),
- mCount(++sCount)
- {
-
- makeRequest();
- }
-
- LLAgentEventPollResponder::~LLAgentEventPollResponder()
- {
- stop();
- LL_DEBUGS("OGPX") << "LLAgentEventPollResponder::~Impl <" << mCount << "> "
- << mPollURL << LL_ENDL;
- }
-
- // OGPX : Should LLAgentEventPollResponder inherits from normal EventPollResponder,
- // or will the two classes diverge as we figure out how AgentEventPoll will
- // actually work? Me thinks that event queue code will be changed so much that a clear
- // sharp division between the classes might not be such a bad thing right now.
- // It's especially important to minimize code changes to the XML-RPC legacy path while
- // adding OGP code, because that minimizes risk to breaking something in the legacy path.
- void LLAgentEventPollResponder::makeRequest()
- {
- LL_DEBUGS("OGPX") << "LLAgentEventPollResponder::makeRequest <" << mCount << "> "<< LL_ENDL;
- LLSD request;
- request["ack"] = mAcknowledge;
- request["done"] = mDone;
- LLHTTPClient::post(mPollURL, request, this);
- }
-
- // OGPX only function passes response back to agent domain.
- // This is our backward little way of responding to a request
- // for client side resources, and passing something back to the requestor
- // in the HTTP stream. The original makeRequest() is in place to provide a
- // regular way to 'tap' the agent domain and ask if there were any client side
- // resources it needed to request. This function adds the ability to also
- // pass back LLSD along with the 'tap'
- //
- // WARNING:
- // This area of the code will change a lot as OGPX is developed. When
- // client side resources are invoked, we need some way to pass back
- // a response on the event queue. This is one possible way.
- void LLAgentEventPollResponder::makeRequest(const LLSD& result_for_agentd)
- {
- LLSD args;
- args["ack"] = mAcknowledge;
- args["done"] = mDone;
- args["result"] = result_for_agentd;
- LL_DEBUGS("OGPX") << "LLAgentEventPollResponder::makeRequest <" << mCount << "> " << ll_pretty_print_sd(result_for_agentd) << LL_ENDL;
- LLHTTPClient::post(mPollURL, args, this);
- }
-
- // virtual
- void LLAgentEventPollResponder::error(U32 status, const std::string& reason)
- {
- if (mDone) return;
-
- if (status != 499)
- {
- LL_WARNS("OGPX") << "LLAgentEventPollResponder::error: <" << mCount << "> got "
- << status << " : " << reason
- << (mDone ? " -- done" : "") << LL_ENDL;
- stop();
- return;
- }
-
- makeRequest();
- }
-
-
- //virtual
- void LLAgentEventPollResponder::result(const LLSD& content)
- {
- LLSD result_for_agentd;
- LL_DEBUGS("OGPX") << "LLAgentEventPollResponder::result <" << mCount << ">"
- << (mDone ? " -- done" : "") << LL_ENDL;
-
- if (mDone) return;
-
- // was llinfos but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG
- LL_DEBUGS("OGPX") << "LLAgentEventPollResponder::completed <" << mCount << "> " << LL_ENDL;
-
-
- if (!content.get("events") ||
- !content.get("id"))
- {
- LL_INFOS("OGPX") << "Received event poll with no events or id key" << LL_ENDL; // was llwarns, but too frequent
- makeRequest();
- return;
- }
- mAcknowledge = 0;
- mAcknowledge = content["id"];
- LLSD events = content["events"];
-
- if (mAcknowledge!=0)
- {
- LL_WARNS("OGPX") << " : id undefined" << LL_ENDL;
- }
-
- // was llinfos but now that CoarseRegionUpdate is TCP @ 1/second, it'd be too verbose for viewer logs. -MG
- LL_DEBUGS("OGPX") << "LLEventPollResponder::completed <" << mCount << "> " << events.size() << "events (id "
- << LLSDXMLStreamer(mAcknowledge) << ")" << LL_ENDL;
-
- // twiddling with making the messaging system gobble up event queue requests
-#if OGPXEVENTHACK
- // OGPXEVENTHACK : An attempt at using the message_template.msg as a way to add HTTP messages that
- // are handled by the event queue (instead of coming across UDP, and being handled via UDP decoding).
- // I found that I was able to do this in a limited way (have a message decoded into LLSD,
- // and a handler called for it) for inbound EQ messages. Unsure it gives us the level of control
- // we need in OGPX to implement policy and trust between the viewer and other entities. The legacy
- // model was "trust everything from the region", and it won't be that way in OGPX.
- // Feels weird adding dead code to the patch, but I wanted a record of the experimentation
- // OGPX TODO: figure out proper building of services.
-
- // iterate over the requests sent by agent domain
- LLSD::array_const_iterator i = events.beginArray();
- LLSD::array_const_iterator end = events.endArray();
- for (; i != end; ++i)
- {
- if (i->has("message"))
- {
- std::string message = i->get("message");
- std::string path = "/message/" + message; // OGPX : mmmm....seems like we are gluing it together so traverse can tear it apart
- LLSD context;
- // so this tries to traverse over the things registered
- // in llhttpnode.cpp, but i had trouble getting anything other than message to work
- const LLHTTPNode* handler = messageRootNode().traverse(path, context);
- if (!handler)
- {
- LL_WARNS("Messaging") << " no handler for "<< path << LL_ENDL;
- return;
- }
-
- //lldebugs << "data: " << LLSDNotationStreamer(message) << llendl;
-
- // We've found a handler for the request, call its post() and get its LLSD response
- // so, changing from the post that was fussing with response pointer to simpler
- result_for_agentd = handler->post(*i);
- LL_DEBUGS("OGPX") << "after handling "<< ll_pretty_print_sd(*i) << " sending AD result: " << ll_pretty_print_sd(result_for_agentd) << LL_ENDL;
- }
- }
- // OGPXEVENTHACK end
-
- // OGPX : result_for_agentd is LLSD and passed back to agentd with the next 'tap'
- makeRequest(result_for_agentd);
-#else
- // OGPX :until eventqueue code is redesigned, just send back the regular 'tap'
- makeRequest();
-#endif
- }
-
}
LLEventPoll::LLEventPoll(const std::string& poll_url, const LLHost& sender)
@@ -525,16 +296,3 @@ LLEventPoll::~LLEventPoll()
if (event_poll_responder) event_poll_responder->stop();
}
-// OGPX : We maintain an event poll with the Agent Domain and with the region
-// while OGP9 svn branch tried to use a funky ReverseHTTP thing for the Responder,
-// for now we will revert to simpler code. This poll should remain active for the
-// life of the viewer session.
-LLAgentEventPoll::LLAgentEventPoll(const std::string& pollURL)
- : mImpl(LLAgentEventPollResponder::start(pollURL))
-{
-}
-
-
-LLAgentEventPoll::~LLAgentEventPoll()
-{
-}
diff --git a/indra/newview/lleventpoll.h b/indra/newview/lleventpoll.h
index db60f6bbf..5b0087a51 100644
--- a/indra/newview/lleventpoll.h
+++ b/indra/newview/lleventpoll.h
@@ -50,21 +50,4 @@ private:
LLHTTPClient::ResponderPtr mImpl;
};
-// Just like the region uses the event poll to invoke services on the viewer,
-// the agent domain also does. There will be lots of changes coming to this code,
-// for now a nice clean split from the region's event code.
-class LLAgentEventPoll //OGPX
- ///< implements the viewer side of server-to-viewer pushed events.
-{
-public:
- LLAgentEventPoll(const std::string& pollURL);
- ///< Start polling the URL.
-
- virtual ~LLAgentEventPoll();
- ///< will stop polling, cancelling any poll in progress.
-
-
-private:
- LLHTTPClient::ResponderPtr mImpl;
-};
#endif // LL_LLEVENTPOLL_H
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 6d66cd4c3..9c7420898 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -184,6 +184,11 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp)
void LLFace::destroy()
{
+ if (gDebugGL)
+ {
+ gPipeline.checkReferences(this);
+ }
+
if(mTexture.notNull())
{
mTexture->removeFace(this) ;
@@ -952,7 +957,7 @@ bool LLFace::canRenderAsMask()
) // do we want masks at all?
&&
(te->getColor().mV[3] == 1.0f) && // can't treat as mask if we have face alpha
- !(LLPipeline::sRenderDeferred && te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible in deferred rendering mode, need to figure out why - for now, avoid
+ //!(LLPipeline::sRenderDeferred && te->getFullbright()) && // hack: alpha masking renders fullbright faces invisible in deferred rendering mode, need to figure out why - for now, avoid
(te->getGlow() == 0.f) && // glowing masks are hard to implement - don't mask
getTexture()->getIsAlphaMask() // texture actually qualifies for masking (lazily recalculated but expensive)
diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp
index 5a6a3339d..ab0868237 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -195,6 +195,19 @@ static struct ft_display_info ft_display_table[] =
{ LLFastTimer::FTM_RENDER_FAKE_VBO_UPDATE," Fake VBO update", &LLColor4::red2, 0 },
{ LLFastTimer::FTM_RENDER_BLOOM, " Bloom", &LLColor4::blue4, 0 },
{ LLFastTimer::FTM_RENDER_BLOOM_FBO, " First FBO", &LLColor4::blue, 0 },
+ { LLFastTimer::FTM_RENDER_DEFERRED, " Deferred", &LLColor4::cyan4, 1 },
+ { LLFastTimer::FTM_BIND_DEFERRED, " Bind", &LLColor4::pink2, 0 },
+ { LLFastTimer::FTM_SUN_SHADOW, " Sun Shadow", &LLColor4::cyan5, 0 },
+ { LLFastTimer::FTM_SOFTEN_SHADOW, " Soften Shadow", &LLColor4::yellow1, 0 },
+ { LLFastTimer::FTM_EDGE_DETECTION, " Edge Detect", &LLColor4::cyan2, 0 },
+ { LLFastTimer::FTM_GI_TRACE, " GI Trace", &LLColor4::green6, 0 },
+ { LLFastTimer::FTM_GI_GATHER, " GI Gather", &LLColor4::cyan1, 0 },
+ { LLFastTimer::FTM_ATMOSPHERICS, " Atmos", &LLColor4::pink1, 0 },
+ { LLFastTimer::FTM_LOCAL_LIGHTS, " Local Lights", &LLColor4::blue2, 0 },
+ { LLFastTimer::FTM_FULLSCREEN_LIGHTS, " FS Lights", &LLColor4::purple4, 0 },
+ { LLFastTimer::FTM_PROJECTORS, " Project", &LLColor4::orange2, 0 },
+ { LLFastTimer::FTM_POST, " Postprocess", &LLColor4::red4, 0 },
+ { LLFastTimer::FTM_VISIBLE_CLOUD, " Visible Cloud", &LLColor4::blue5, 0 },
{ LLFastTimer::FTM_RENDER_UI, " UI", &LLColor4::cyan4, 1 },
{ LLFastTimer::FTM_RENDER_TIMER, " Timers", &LLColor4::cyan5, 1, 0 },
{ LLFastTimer::FTM_RENDER_FONTS, " Fonts", &LLColor4::pink1, 0 },
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 9614f639d..ce1c00d73 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -207,7 +207,7 @@ BOOL LLFeatureManager::maskFeatures(const std::string& name)
LL_DEBUGS("RenderInit") << "Unknown feature mask " << name << LL_ENDL;
return FALSE;
}
- LL_DEBUGS("RenderInit") << "Applying Feature Mask: " << name << LL_ENDL;
+ LL_INFOS("RenderInit") << "Applying GPU Feature list: " << name << LL_ENDL;
return maskList(*maskp);
}
@@ -221,22 +221,33 @@ BOOL LLFeatureManager::loadFeatureTables()
mSkippedFeatures.insert("RenderVBOEnable");
mSkippedFeatures.insert("RenderFogRatio");
- std::string data_path = gDirUtilp->getAppRODataDir();
+ // first table is install with app
+ std::string app_path = gDirUtilp->getAppRODataDir();
+ app_path += gDirUtilp->getDirDelimiter();
- data_path += gDirUtilp->getDirDelimiter();
+ std::string filename = FEATURE_TABLE_FILENAME;
- data_path += FEATURE_TABLE_FILENAME;
- lldebugs << "Looking for feature table in " << data_path << llendl;
+
+ app_path += filename;
+
+
+ return parseFeatureTable(app_path);
+}
+
+
+BOOL LLFeatureManager::parseFeatureTable(std::string filename)
+{
+ llinfos << "Looking for feature table in " << filename << llendl;
llifstream file;
std::string name;
U32 version;
- file.open(data_path); /*Flawfinder: ignore*/
+ file.open(filename); /*Flawfinder: ignore*/
if (!file)
{
- LL_WARNS("RenderInit") << "Unable to open feature table!" << LL_ENDL;
+ LL_WARNS("RenderInit") << "Unable to open feature table " << filename << LL_ENDL;
return FALSE;
}
@@ -245,7 +256,7 @@ BOOL LLFeatureManager::loadFeatureTables()
file >> version;
if (name != "version")
{
- LL_WARNS("RenderInit") << data_path << " does not appear to be a valid feature table!" << LL_ENDL;
+ LL_WARNS("RenderInit") << filename << " does not appear to be a valid feature table!" << LL_ENDL;
return FALSE;
}
@@ -284,6 +295,7 @@ BOOL LLFeatureManager::loadFeatureTables()
if (!flp)
{
LL_ERRS("RenderInit") << "Specified parameter before keyword!" << LL_ENDL;
+ return FALSE;
}
S32 available;
F32 recommended;
@@ -298,34 +310,41 @@ BOOL LLFeatureManager::loadFeatureTables()
void LLFeatureManager::loadGPUClass()
{
- std::string data_path = gDirUtilp->getAppRODataDir();
-
- data_path += gDirUtilp->getDirDelimiter();
-
- data_path += GPU_TABLE_FILENAME;
-
// defaults
mGPUClass = GPU_CLASS_UNKNOWN;
mGPUString = gGLManager.getRawGLString();
mGPUSupported = FALSE;
+ // first table is in the app dir
+ std::string app_path = gDirUtilp->getAppRODataDir();
+ app_path += gDirUtilp->getDirDelimiter();
+ app_path += GPU_TABLE_FILENAME;
+ parseGPUTable(app_path);
+}
+
+
+void LLFeatureManager::parseGPUTable(std::string filename)
+{
llifstream file;
- file.open(data_path); /*Flawfinder: ignore*/
+ file.open(filename);
if (!file)
{
- LL_WARNS("RenderInit") << "Unable to open GPU table: " << data_path << "!" << LL_ENDL;
+ LL_WARNS("RenderInit") << "Unable to open GPU table: " << filename << "!" << LL_ENDL;
return;
}
- std::string renderer = gGLManager.getRawGLString();
+ std::string rawRenderer = gGLManager.getRawGLString();
+ std::string renderer = rawRenderer;
for (std::string::iterator i = renderer.begin(); i != renderer.end(); ++i)
{
*i = tolower(*i);
}
-
- while (!file.eof())
+
+ bool gpuFound;
+ U32 lineNumber;
+ for (gpuFound = false, lineNumber = 0; !gpuFound && !file.eof(); lineNumber++)
{
char buffer[MAX_STRING]; /*Flawfinder: ignore*/
buffer[0] = 0;
@@ -372,6 +391,7 @@ void LLFeatureManager::loadGPUClass()
if (label.empty() || expr.empty() || cls.empty() || supported.empty())
{
+ LL_WARNS("RenderInit") << "invald gpu_table.txt:" << lineNumber << ": '" << buffer << "'" << LL_ENDL;
continue;
}
@@ -385,18 +405,26 @@ void LLFeatureManager::loadGPUClass()
if(boost::regex_search(renderer, re))
{
// if we found it, stop!
- file.close();
- LL_INFOS("RenderInit") << "GPU is " << label << llendl;
+ gpuFound = true;
mGPUString = label;
mGPUClass = (EGPUClass) strtol(cls.c_str(), NULL, 10);
mGPUSupported = (BOOL) strtol(supported.c_str(), NULL, 10);
- file.close();
- return;
}
}
file.close();
- LL_WARNS("RenderInit") << "Couldn't match GPU to a class: " << gGLManager.getRawGLString() << LL_ENDL;
+ if ( gpuFound )
+ {
+ LL_INFOS("RenderInit") << "GPU '" << rawRenderer << "' recognized as '" << mGPUString << "'" << LL_ENDL;
+ if (!mGPUSupported)
+ {
+ LL_INFOS("RenderInit") << "GPU '" << mGPUString << "' is not supported." << LL_ENDL;
+ }
+ }
+ else
+ {
+ LL_WARNS("RenderInit") << "GPU '" << rawRenderer << "' not recognized" << LL_ENDL;
+ }
}
void LLFeatureManager::cleanupFeatureTables()
@@ -579,6 +607,10 @@ void LLFeatureManager::applyBaseMasks()
{
maskFeatures("ATI");
}
+ if (gGLManager.mHasATIMemInfo && gGLManager.mVRAM < 256)
+ {
+ maskFeatures("ATIVramLT256");
+ }
if (gGLManager.mATIOldDriver)
{
maskFeatures("ATIOldDriver");
@@ -595,6 +627,14 @@ void LLFeatureManager::applyBaseMasks()
{
maskFeatures("OpenGLPre15");
}
+ if (gGLManager.mGLVersion < 3.f)
+ {
+ maskFeatures("OpenGLPre30");
+ }
+ if (gGLManager.mNumTextureImageUnits <= 8)
+ {
+ maskFeatures("TexUnit8orLess");
+ }
// now mask by gpu string
// Replaces ' ' with '_' in mGPUString to deal with inability for parser to handle spaces
diff --git a/indra/newview/llfeaturemanager.h b/indra/newview/llfeaturemanager.h
index 537bf0c6a..a9cb33598 100644
--- a/indra/newview/llfeaturemanager.h
+++ b/indra/newview/llfeaturemanager.h
@@ -98,8 +98,14 @@ protected:
class LLFeatureManager : public LLFeatureList, public LLSingleton
{
public:
- LLFeatureManager() :
- LLFeatureList("default"), mInited(FALSE), mTableVersion(0), mSafe(FALSE), mGPUClass(GPU_CLASS_UNKNOWN)
+ LLFeatureManager()
+ : LLFeatureList("default"),
+
+ mInited(FALSE),
+ mTableVersion(0),
+ mSafe(FALSE),
+ mGPUClass(GPU_CLASS_UNKNOWN),
+ mGPUSupported(FALSE)
{
}
~LLFeatureManager() {cleanupFeatureTables();}
@@ -139,6 +145,8 @@ public:
protected:
void loadGPUClass();
+ BOOL parseFeatureTable(std::string filename);
+ void parseGPUTable(std::string filename);
void initBaseMask();
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index ce55c7a69..317ad0eb9 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -368,8 +368,8 @@ void LLVolumeImplFlexible::doFlexibleUpdate()
LLPath *path = &volume->getPath();
if ((mSimulateRes == 0 || !mInitialized)) // if its uninitialized but not visible, what then? - Nyx
{
- if(!mVO->mDrawable->isVisible())
- return; //avoiding the assert below...
+ //if(mInitialized && !mVO->mDrawable->isVisible())
+ // return; //avoiding the assert below...
mVO->markForUpdate(TRUE);
if (!doIdleUpdate(gAgent, *LLWorld::getInstance(), 0.0))
{
diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index 62b0ee495..952b5d168 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -209,6 +209,14 @@ LLFloaterAbout::LLFloaterAbout()
support.append( gSysCPU.getCPUString() );
support.append("\n");
+ support.append("SSE Support:");
+ if(gSysCPU.hasSSE())
+ support.append(" SSE2\n");
+ else if(gSysCPU.hasSSE())
+ support.append(" SSE\n");
+ else
+ support.append(" None\n");
+
U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024;
// Moved hack adjustment to Windows memory size into llsys.cpp
@@ -243,21 +251,18 @@ LLFloaterAbout::LLFloaterAbout()
support.append("OpenGL Version: ");
support.append( (const char*) glGetString(GL_VERSION) );
- support.append("\n");
+ support.append("\n\n");
- std::string sse_ver = "None";
+ support.append("Viewer SSE Version: ");
#if _M_IX86_FP > 0 //Windows
- sse_ver = llformat("SSE%i", _M_IX86_FP );
+ support.append(llformat("SSE%i\n", _M_IX86_FP ));
#elif defined(__SSE2__) //GCC
- sse_ver = "SSE2";
+ support.append("SSE2\n");
#elif defined(__SSE__) //GCC
- sse_ver = "SSE";
+ support.append("SSE\n");
+#else
+ support.append("None\n");
#endif
- support.append("SSE Version: ");
- support.append(sse_ver);
- support.append("\n");
-
- support.append("\n");
support.append("libcurl Version: ");
support.append( LLCurl::getVersionString() );
diff --git a/indra/newview/llfloatercustomize.cpp b/indra/newview/llfloatercustomize.cpp
index f2a12f984..a7b31fa44 100644
--- a/indra/newview/llfloatercustomize.cpp
+++ b/indra/newview/llfloatercustomize.cpp
@@ -2840,13 +2840,6 @@ void LLFloaterCustomize::updateInventoryUI()
}
}
- // OGPX : In place because Assets are not currently supported in OGPX.
- // This was originally added as part of OGP9 svn branch because the viewer deeply deeply
- // assumes that there *will* be an inventory there. If you never get an inventory,
- // Make Outfit breaks badly.
- // OGPX TODO: When assets/inventory are supported, the check below can be removed.
- // OGPX test if (!gSavedSettings.getString("CmdLineRegionURI").empty()) {all_complete = FALSE;}
-
childSetEnabled("Make Outfit", all_complete);
}
diff --git a/indra/newview/llhudeffectlookat.cpp b/indra/newview/llhudeffectlookat.cpp
index 98814e882..bde58540f 100644
--- a/indra/newview/llhudeffectlookat.cpp
+++ b/indra/newview/llhudeffectlookat.cpp
@@ -67,7 +67,7 @@ const S32 PKT_SIZE = 57;
// throttle
const F32 MAX_SENDS_PER_SEC = 4.f;
-const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f;
+const F32 MIN_DELTAPOS_FOR_UPDATE_SQUARED = 0.05f * 0.05f;
const F32 MIN_TARGET_OFFSET_SQUARED = 0.0001f;
@@ -427,7 +427,7 @@ BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *objec
BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject);
// lookat position has moved a certain amount and we haven't just sent an update
- lookAtChanged = lookAtChanged || ((dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) &&
+ lookAtChanged = lookAtChanged || ((dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) &&
((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC)));
if (lookAtChanged)
diff --git a/indra/newview/llhudeffectpointat.cpp b/indra/newview/llhudeffectpointat.cpp
index 10409a95b..c566bd768 100644
--- a/indra/newview/llhudeffectpointat.cpp
+++ b/indra/newview/llhudeffectpointat.cpp
@@ -53,7 +53,7 @@ const S32 PKT_SIZE = 57;
// throttle
const F32 MAX_SENDS_PER_SEC = 4.f;
-const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f;
+const F32 MIN_DELTAPOS_FOR_UPDATE_SQUARED = 0.05f * 0.05f;
// timeouts
// can't use actual F32_MAX, because we add this to the current frametime
@@ -251,7 +251,7 @@ BOOL LLHUDEffectPointAt::setPointAt(EPointAtType target_type, LLViewerObject *ob
BOOL targetTypeChanged = (target_type != mTargetType) ||
(object != mTargetObject);
- BOOL targetPosChanged = (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) &&
+ BOOL targetPosChanged = (dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) &&
((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC));
if (targetTypeChanged || targetPosChanged)
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 69de63bb2..e65b75e01 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -1318,7 +1318,6 @@ void LLInventoryModel::mock(const LLUUID& root_id)
void LLInventoryModel::fetchInventoryResponder::result(const LLSD& content)
{
- LL_DEBUGS("Inventory") << " fetch http got " << ll_pretty_print_sd(content) << LL_ENDL; // OGPX
start_new_inventory_observer();
/*LLUUID agent_id;
@@ -1436,7 +1435,6 @@ class fetchDescendentsResponder: public LLHTTPClient::Responder
// Note: this is the handler for WebFetchInventoryDescendents and agent/inventory caps
void fetchDescendentsResponder::result(const LLSD& content)
{
- LL_DEBUGS("Inventory") << " fetch descendents got " << ll_pretty_print_sd(content) << LL_ENDL; // OGPX
if (content.has("folders"))
{
@@ -1658,11 +1656,7 @@ void LLInventoryModel::bulkFetch(std::string url)
folder_sd["fetch_items"] = (LLSD::Boolean)TRUE;
LL_DEBUGS("Inventory") << " fetching "<getUUID()<<" with cat owner "<getOwnerID()<<" and agent" << gAgent.getID() << LL_ENDL;
- //OGPX if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
- // for OGP it really doesnt make sense to have the decision about whether to fetch
- // from the library or user cap be determined by a hard coded UUID.
- // if it isnt an item that belongs to the agent, then fetch from the library
- if (gAgent.getID() != cat->getOwnerID()) //if i am not the owner, it must be in the library
+ if (ALEXANDRIA_LINDEN_ID == cat->getOwnerID())
body_lib["folders"].append(folder_sd);
else
body["folders"].append(folder_sd);
@@ -1696,14 +1690,12 @@ void LLInventoryModel::bulkFetch(std::string url)
sBulkFetchCount++;
if (body["folders"].size())
{
- LL_DEBUGS("Inventory") << " fetch descendents post to " << url << ": " << ll_pretty_print_sd(body) << LL_ENDL; // OGPX
LLHTTPClient::post(url, body, new fetchDescendentsResponder(body),300.0);
}
if (body_lib["folders"].size())
{
std::string url_lib;
url_lib = gAgent.getRegion()->getCapability("FetchLibDescendents");
- LL_DEBUGS("Inventory") << " fetch descendents lib post: " << ll_pretty_print_sd(body_lib) << LL_ENDL; // OGPX
LLHTTPClient::post(url_lib, body_lib, new fetchDescendentsResponder(body_lib),300.0);
}
sFetchTimer.reset();
@@ -1804,33 +1796,20 @@ void LLInventoryModel::backgroundFetch(void*)
{
if (sBackgroundFetchActive && gAgent.getRegion())
{
- // OGPX : agent/inventory is on gAgent for OGPX. I check both, and give
- // ...preference to the one on gAgent. That way the existing non OGP path will remain the same.
- // Q: How *should* I handle deciding which cap to use? Maybe I don't want to trust fetching inventory from the region
- // OGPX TODO: manage getting caps from more than one service securely.
- std::string url = gAgent.getCapability("agent/inventory"); // was WebFetchInventoryDescendents
- if (url.empty())
- {
- // OGPX : if we didn't get an agent/inventory cap from the Agent Domain, check to see if there was one on the region
- // If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
- // OGPX TODO: this should change when Capabilities are refactored.
- // ... this is a trust/security issue. if we have an agent/inventory from the Agent Domain,
- // maybe we shouldn't trust WFID from region.
- LL_DEBUGS("Inventory") << " no agent/inventory not on AD, checking fallback to region " << LL_ENDL;
- url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
- }
- if (!url.empty())
+ // If we'll be using the capability, we'll be sending batches and the background thing isn't as important.
+ std::string url = gAgent.getRegion()->getCapability("FetchInventoryDescendents");
+ if (false /*gSavedSettings.getBOOL("UseHTTPInventory")*/ && !url.empty())
{
bulkFetch(url);
return;
}
- // If there was no HTTP cap to fetch with, then do the UDP fetch
+#if 1
//DEPRECATED OLD CODE FOLLOWS.
// no more categories to fetch, stop fetch process
if (sFetchQueue.empty())
{
- LL_DEBUGS("Inventory") << "Inventory fetch completed" << LL_ENDL;
+ llinfos << "Inventory fetch completed" << llendl;
if (sFullFetchStarted)
{
sAllFoldersFetched = TRUE;
@@ -1846,7 +1825,7 @@ void LLInventoryModel::backgroundFetch(void*)
// double timeouts on failure
sMinTimeBetweenFetches = llmin(sMinTimeBetweenFetches * 2.f, 10.f);
sMaxTimeBetweenFetches = llmin(sMaxTimeBetweenFetches * 2.f, 120.f);
- LL_DEBUGS("Inventory") << "Inventory fetch times grown to (" << sMinTimeBetweenFetches << ", " << sMaxTimeBetweenFetches << ")" << LL_ENDL;
+ llinfos << "Inventory fetch times grown to (" << sMinTimeBetweenFetches << ", " << sMaxTimeBetweenFetches << ")" << llendl;
// fetch is no longer considered "timely" although we will wait for full time-out
sTimelyFetchPending = FALSE;
}
@@ -1941,6 +1920,11 @@ void LLInventoryModel::backgroundFetch(void*)
// not enough time has elapsed to do a new fetch
break;
}
+
+ //
+ // DEPRECATED OLD CODE
+ //--------------------------------------------------------------------------------
+#endif
}
}
@@ -2220,57 +2204,53 @@ bool LLInventoryModel::loadSkeleton(
const LLSD& options,
const LLUUID& owner_id)
{
- LL_INFOS("OGPX") << "importing inventory skeleton for " << owner_id << LL_ENDL;
- LL_DEBUGS("Inventory") << " skeleton is " << ll_pretty_print_sd(options) << LL_ENDL;
+ lldebugs << "importing inventory skeleton for " << owner_id << llendl;
typedef std::set, InventoryIDPtrLess> cat_set_t;
cat_set_t temp_cats;
-
- update_map_t child_counts;
-
- LLUUID id;
- LLAssetType::EType preferred_type;
bool rv = true;
- for (LLSD::array_const_iterator it = options.beginArray(); it < options.endArray(); ++it)
+
+ for(LLSD::array_const_iterator it = options.beginArray(),
+ end = options.endArray(); it != end; ++it)
{
- LLPointer cat = new LLViewerInventoryCategory(owner_id);
-
- LL_DEBUGS("Inventory") << "cat name, folder, parent, type " << (*it)["name"].asString() << " " << (*it)["folder_id"].asUUID() << " " << (*it)["parent_id"].asUUID() << " " << (*it)["type_default"].asString() << " " << LL_ENDL; // OGPX
- if ((*it)["name"].asString().empty()) goto clean_cat;
- cat->rename((*it)["name"].asString().c_str());
- if ((*it)["folder_id"].asUUID().isNull()) goto clean_cat;
- id = (*it)["folder_id"].asUUID();
- // if an id is null, it locks the viewer.
- if (id.isNull()) goto clean_cat;
- cat->setUUID(id);
- // OGPX : slight change in snowglobe non OGP handling of things with null parents vs OGP9 SVN branch
- // OGPX : so commented this line out for OGPX as well. if((*it)["parent_id"].asUUID().isNull()) goto clean_cat;
- id = (*it)["parent_id"].asUUID();
- cat->setParent(id);
- if ((*it)["type_default"].asString().empty())
+ LLSD name = (*it)["name"];
+ LLSD folder_id = (*it)["folder_id"];
+ LLSD parent_id = (*it)["parent_id"];
+ LLSD version = (*it)["version"];
+ if(name.isDefined()
+ && folder_id.isDefined()
+ && parent_id.isDefined()
+ && version.isDefined()
+ && folder_id.asUUID().notNull() // if an id is null, it locks the viewer.
+ )
{
- preferred_type = LLAssetType::AT_NONE;
+ LLPointer cat = new LLViewerInventoryCategory(owner_id);
+ cat->rename(name.asString());
+ cat->setUUID(folder_id.asUUID());
+ cat->setParent(parent_id.asUUID());
+
+ LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
+ LLSD type_default = (*it)["type_default"];
+ if(type_default.isDefined())
+ {
+ preferred_type = (LLAssetType::EType)type_default.asInteger();
+ }
+ cat->setPreferredType(preferred_type);
+ cat->setVersion(version.asInteger());
+ temp_cats.insert(cat);
}
else
{
- S32 t = (*it)["type_default"].asInteger();
- preferred_type = (LLAssetType::EType)t;
+ llwarns << "Unable to import near " << name.asString() << llendl;
+ rv = false;
}
- cat->setPreferredType(preferred_type);
- if ((*it)["version"].asString().empty()) goto clean_cat;
- cat->setVersion((*it)["version"].asInteger());
- temp_cats.insert(cat);
- continue;
- clean_cat:
- llwarns << "Unable to import near " << cat->getName() << llendl;
- rv = false;
- //delete cat; // automatic when cat is reasigned or destroyed
}
-
+
S32 cached_category_count = 0;
S32 cached_item_count = 0;
- if (!temp_cats.empty())
+ if(!temp_cats.empty())
{
+ update_map_t child_counts;
cat_array_t categories;
item_array_t items;
cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
@@ -2340,9 +2320,9 @@ bool LLInventoryModel::loadSkeleton(
}
// go ahead and add the cats returned during the download
- std::set::iterator not_cached_id = cached_ids.end();
+ std::set::const_iterator not_cached_id = cached_ids.end();
cached_category_count = cached_ids.size();
- for (cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
+ for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
{
if (cached_ids.find((*it)->getUUID()) == not_cached_id)
{
@@ -2358,30 +2338,32 @@ bool LLInventoryModel::loadSkeleton(
// Add all the items loaded which are parented to a
// category with a correctly cached parent
- count = items.count();
S32 bad_link_count = 0;
cat_map_t::iterator unparented = mCategoryMap.end();
- for (int i = 0; i < count; ++i)
+ for(item_array_t::const_iterator item_iter = items.begin();
+ item_iter != items.end();
+ ++item_iter)
{
- cat_map_t::iterator cit = mCategoryMap.find(items[i]->getParentUUID());
+ LLViewerInventoryItem *item = (*item_iter).get();
+ const cat_map_t::iterator cit = mCategoryMap.find(item->getParentUUID());
- if (cit != unparented)
+ if(cit != unparented)
{
- LLViewerInventoryCategory* cat = cit->second;
- if (cat->getVersion() != NO_VERSION)
+ const LLViewerInventoryCategory* cat = cit->second.get();
+ if(cat->getVersion() != NO_VERSION)
{
// This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
- if (items[i]->getIsBrokenLink())
+ if (item->getIsBrokenLink())
{
bad_link_count++;
lldebugs << "Attempted to add cached link item without baseobj present ( name: "
- << items[i]->getName() << " itemID: " << items[i]->getUUID()
- << " assetID: " << items[i]->getAssetUUID()
+ << item->getName() << " itemID: " << item->getUUID()
+ << " assetID: " << item->getAssetUUID()
<< " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
invalid_categories.insert(cit->second);
continue;
}
- addItem(items[i]);
+ addItem(item);
cached_item_count += 1;
++child_counts[cat->getUUID()];
}
@@ -2420,17 +2402,17 @@ bool LLInventoryModel::loadSkeleton(
// At this point, we need to set the known descendents for each
// category which successfully cached so that we do not
// needlessly fetch descendents for categories which we have.
- update_map_t::iterator no_child_counts = child_counts.end();
- update_map_t::iterator the_count;
- for (cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
+ update_map_t::const_iterator no_child_counts = child_counts.end();
+ for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
{
- LLViewerInventoryCategory* cat = (*it);
- if (cat->getVersion() != NO_VERSION)
+ LLViewerInventoryCategory* cat = (*it).get();
+ if(cat->getVersion() != NO_VERSION)
{
- the_count = child_counts.find(cat->getUUID());
- if (the_count != no_child_counts)
+ update_map_t::const_iterator the_count = child_counts.find(cat->getUUID());
+ if(the_count != no_child_counts)
{
- cat->setDescendentCount((*the_count).second.mValue);
+ const S32 num_descendents = (*the_count).second.mValue;
+ cat->setDescendentCount(num_descendents);
}
else
{
@@ -2453,341 +2435,30 @@ bool LLInventoryModel::loadSkeleton(
categories.clear(); // will unref and delete entries
}
- LL_DEBUGS("Inventory") << "Successfully loaded " << cached_category_count
+ llinfos << "Successfully loaded " << cached_category_count
<< " categories and " << cached_item_count << " items from cache."
- << LL_ENDL;
+ << llendl;
return rv;
}
+//OGPX crap. Since this function is actually functionally the same as its LLSD variant..
+// just convert options_t to LLSD and route to the LLSD version. Yuck.
bool LLInventoryModel::loadSkeleton(
const LLInventoryModel::options_t& options,
const LLUUID& owner_id)
{
- lldebugs << "importing inventory skeleton for " << owner_id << llendl;
-
- typedef std::set, InventoryIDPtrLess> cat_set_t;
- cat_set_t temp_cats;
-
- update_map_t child_counts;
-
- LLUUID id;
- LLAssetType::EType preferred_type;
- bool rv = true;
+ LLSD options_list;
for(options_t::const_iterator it = options.begin(); it < options.end(); ++it)
{
- LLPointer cat = new LLViewerInventoryCategory(owner_id);
- response_t::const_iterator no_response = (*it).end();
- response_t::const_iterator skel;
- skel = (*it).find("name");
- if(skel == no_response) goto clean_cat;
- cat->rename(std::string((*skel).second));
- skel = (*it).find("folder_id");
- if(skel == no_response) goto clean_cat;
- id.set((*skel).second);
- // if an id is null, it locks the viewer.
- if(id.isNull()) goto clean_cat;
- cat->setUUID(id);
- skel = (*it).find("parent_id");
- if(skel == no_response) goto clean_cat;
- id.set((*skel).second);
- cat->setParent(id);
- skel = (*it).find("type_default");
- if(skel == no_response)
+ LLSD entry;
+ for(response_t::const_iterator it2 = it->begin(); it2 != it->end(); ++it2)
{
- preferred_type = LLAssetType::AT_NONE;
+ entry[it2->first]=it2->second;
}
- else
- {
- S32 t = atoi((*skel).second.c_str());
- preferred_type = (LLAssetType::EType)t;
- }
- cat->setPreferredType(preferred_type);
- skel = (*it).find("version");
- if(skel == no_response) goto clean_cat;
- cat->setVersion(atoi((*skel).second.c_str()));
- temp_cats.insert(cat);
- continue;
- clean_cat:
- llwarns << "Unable to import near " << cat->getName() << llendl;
- rv = false;
- //delete cat; // automatic when cat is reasigned or destroyed
+ options_list.append(entry);
}
-
- S32 cached_category_count = 0;
- S32 cached_item_count = 0;
- if(!temp_cats.empty())
- {
- cat_array_t categories;
- item_array_t items;
- cat_set_t invalid_categories; // Used to mark categories that weren't successfully loaded.
- std::string owner_id_str;
- owner_id.toString(owner_id_str);
- std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, owner_id_str));
- std::string inventory_filename;
- inventory_filename = llformat(CACHE_FORMAT_STRING, path.c_str());
- const S32 NO_VERSION = LLViewerInventoryCategory::VERSION_UNKNOWN;
- std::string gzip_filename(inventory_filename);
- gzip_filename.append(".gz");
- LLFILE* fp = LLFile::fopen(gzip_filename, "rb");
- bool remove_inventory_file = false;
- if(fp)
- {
- fclose(fp);
- fp = NULL;
- if(gunzip_file(gzip_filename, inventory_filename))
- {
- // we only want to remove the inventory file if it was
- // gzipped before we loaded, and we successfully
- // gunziped it.
- remove_inventory_file = true;
- }
- else
- {
- llinfos << "Unable to gunzip " << gzip_filename << llendl;
- }
- }
- bool is_cache_obsolete = false;
- if (loadFromFile(inventory_filename, categories, items, is_cache_obsolete))
- {
- // We were able to find a cache of files. So, use what we
- // found to generate a set of categories we should add. We
- // will go through each category loaded and if the version
- // does not match, invalidate the version.
- S32 count = categories.count();
- cat_set_t::iterator not_cached = temp_cats.end();
- std::set cached_ids;
- for(S32 i = 0; i < count; ++i)
- {
- LLViewerInventoryCategory* cat = categories[i];
- cat_set_t::iterator cit = temp_cats.find(cat);
- if (cit == temp_cats.end())
- {
- continue; // cache corruption?? not sure why this happens -SJB
- }
- LLViewerInventoryCategory* tcat = *cit;
-
- // we can safely ignore anything loaded from file, but
- // not sent down in the skeleton.
- if(cit == not_cached)
- {
- continue;
- }
- if(cat->getVersion() != tcat->getVersion())
- {
- // if the cached version does not match the server version,
- // throw away the version we have so we can fetch the
- // correct contents the next time the viewer opens the folder.
- tcat->setVersion(NO_VERSION);
- }
- else
- {
- cached_ids.insert(tcat->getUUID());
- }
- }
-
- // go ahead and add the cats returned during the download
- std::set::iterator not_cached_id = cached_ids.end();
- cached_category_count = cached_ids.size();
- for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
- {
- if(cached_ids.find((*it)->getUUID()) == not_cached_id)
- {
- // this check is performed so that we do not
- // mark new folders in the skeleton (and not in cache)
- // as being cached.
- LLViewerInventoryCategory *llvic = (*it);
- llvic->setVersion(NO_VERSION);
- }
- addCategory(*it);
- ++child_counts[(*it)->getParentUUID()];
- }
-
- // Add all the items loaded which are parented to a
- // category with a correctly cached parent
- count = items.count();
- S32 bad_link_count = 0;
- cat_map_t::iterator unparented = mCategoryMap.end();
- for(int i = 0; i < count; ++i)
- {
- cat_map_t::iterator cit = mCategoryMap.find(items[i]->getParentUUID());
-
- if(cit != unparented)
- {
- LLViewerInventoryCategory* cat = cit->second;
- if(cat->getVersion() != NO_VERSION)
- {
- // This can happen if the linked object's baseobj is removed from the cache but the linked object is still in the cache.
- if (items[i]->getIsBrokenLink())
- {
- bad_link_count++;
- lldebugs << "Attempted to add cached link item without baseobj present ( name: "
- << items[i]->getName() << " itemID: " << items[i]->getUUID()
- << " assetID: " << items[i]->getAssetUUID()
- << " ). Ignoring and invalidating " << cat->getName() << " . " << llendl;
- invalid_categories.insert(cit->second);
- continue;
- }
- addItem(items[i]);
- cached_item_count += 1;
- ++child_counts[cat->getUUID()];
- }
- }
- }
- if (bad_link_count > 0)
- {
- llinfos << "Attempted to add " << bad_link_count
- << " cached link items without baseobj present. "
- << "The corresponding categories were invalidated." << llendl;
- }
- }
- else
- {
- // go ahead and add everything after stripping the version
- // information.
- for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
- {
- LLViewerInventoryCategory *llvic = (*it);
- llvic->setVersion(NO_VERSION);
- addCategory(*it);
- }
- }
-
- // Invalidate all categories that failed fetching descendents for whatever
- // reason (e.g. one of the descendents was a broken link).
- for (cat_set_t::iterator invalid_cat_it = invalid_categories.begin();
- invalid_cat_it != invalid_categories.end();
- invalid_cat_it++)
- {
- LLViewerInventoryCategory* cat = (*invalid_cat_it).get();
- cat->setVersion(NO_VERSION);
- llinfos << "Invalidating category name: " << cat->getName() << " UUID: " << cat->getUUID() << " due to invalid descendents cache" << llendl;
- }
-
- // At this point, we need to set the known descendents for each
- // category which successfully cached so that we do not
- // needlessly fetch descendents for categories which we have.
- update_map_t::iterator no_child_counts = child_counts.end();
- update_map_t::iterator the_count;
- for(cat_set_t::iterator it = temp_cats.begin(); it != temp_cats.end(); ++it)
- {
- LLViewerInventoryCategory* cat = (*it);
- if(cat->getVersion() != NO_VERSION)
- {
- the_count = child_counts.find(cat->getUUID());
- if(the_count != no_child_counts)
- {
- cat->setDescendentCount((*the_count).second.mValue);
- }
- else
- {
- cat->setDescendentCount(0);
- }
- }
- }
-
- if(remove_inventory_file)
- {
- // clean up the gunzipped file.
- LLFile::remove(inventory_filename);
- }
- if (is_cache_obsolete)
- {
- // If out of date, remove the gzipped file too.
- llwarns << "Inv cache out of date, removing" << llendl;
- LLFile::remove(gzip_filename);
- }
- categories.clear(); // will unref and delete entries
- }
-
- LL_DEBUGS("Inventory") << "Successfully loaded " << cached_category_count
- << " categories and " << cached_item_count << " items from cache."
- << LL_ENDL;
-
- return rv;
-}
-
-bool LLInventoryModel::loadMeat(
- const LLInventoryModel::options_t& options, const LLUUID& owner_id)
-{
- llinfos << "importing inventory for " << owner_id << llendl;
- LLPermissions default_perm;
- default_perm.init(LLUUID::null, owner_id, LLUUID::null, LLUUID::null);
- LLPointer item;
- LLUUID id;
- LLAssetType::EType type;
- LLInventoryType::EType inv_type;
- bool rv = true;
- for(options_t::const_iterator it = options.begin(); it < options.end(); ++it)
- {
- item = new LLViewerInventoryItem;
- response_t::const_iterator no_response = (*it).end();
- response_t::const_iterator meat;
- meat = (*it).find("name");
- if(meat == no_response) goto clean_item;
- item->rename(std::string((*meat).second));
- meat = (*it).find("item_id");
- if(meat == no_response) goto clean_item;
- id.set((*meat).second);
- item->setUUID(id);
- meat = (*it).find("parent_id");
- if(meat == no_response) goto clean_item;
- id.set((*meat).second);
- item->setParent(id);
- meat = (*it).find("type");
- if(meat == no_response) goto clean_item;
- type = (LLAssetType::EType)atoi((*meat).second.c_str());
- item->setType(type);
- meat = (*it).find("inv_type");
- if(meat != no_response)
- {
- inv_type = (LLInventoryType::EType)atoi((*meat).second.c_str());
- item->setInventoryType(inv_type);
- }
- meat = (*it).find("data_id");
- if(meat == no_response) goto clean_item;
- id.set((*meat).second);
- if(LLAssetType::AT_CALLINGCARD == type)
- {
- LLPermissions perm;
- perm.init(id, owner_id, LLUUID::null, LLUUID::null);
- item->setPermissions(perm);
- }
- else
- {
- meat = (*it).find("perm_mask");
- if(meat != no_response)
- {
- PermissionMask perm_mask = atoi((*meat).second.c_str());
- default_perm.initMasks(
- perm_mask, perm_mask, perm_mask, perm_mask, perm_mask);
- }
- else
- {
- default_perm.initMasks(
- PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE, PERM_NONE);
- }
- item->setPermissions(default_perm);
- item->setAssetUUID(id);
- }
- meat = (*it).find("flags");
- if(meat != no_response)
- {
- item->setFlags(strtoul((*meat).second.c_str(), NULL, 0));
- }
- meat = (*it).find("time");
- if(meat != no_response)
- {
- item->setCreationDate(atoi((*meat).second.c_str()));
- }
- addItem(item);
- continue;
- clean_item:
- llwarns << "Unable to import near " << item->getName() << llendl;
- rv = false;
- //delete item; // automatic when item is reassigned or destroyed
- }
- return rv;
+ return loadSkeleton(options_list,owner_id);
}
// This is a brute force method to rebuild the entire parent-child
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index a6dc0f31a..697d1e29a 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -386,13 +386,9 @@ public:
// during authentication. return true if everything parsed.
typedef std::map response_t;
typedef std::vector options_t;
- // OGPX : Two loadSkeleton(), one for the XML-RPC logins, one for LLSD
- //... The concept of a skeleton being different from the cap that
- //... we do inventory queries on should be examined, and the usage of
- //... the skeleton in querying the wearables needs to be examined as well.
- bool loadSkeleton(const options_t& options, const LLUUID& owner_id);
- bool loadMeat(const options_t& options, const LLUUID& owner_id);
+ //OGPX really screwed with the login process. This is needed until it's all sorted out.
+ bool loadSkeleton(const options_t& options, const LLUUID& owner_id);
/** Mutators
** **
*******************************************************************************/
diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp
index eb467f921..5da5ba0aa 100644
--- a/indra/newview/llmanipscale.cpp
+++ b/indra/newview/llmanipscale.cpp
@@ -222,8 +222,6 @@ void LLManipScale::render()
LLVector3 center_agent = gAgent.getPosAgentFromGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal());
- F32 range;
- F32 range_from_agent;
if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
{
mBoxHandleSize = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
@@ -231,25 +229,25 @@ void LLManipScale::render()
}
else
{
- range = dist_vec(gAgent.getCameraPositionAgent(), center_agent);
- range_from_agent = dist_vec(gAgent.getPositionAgent(), center_agent);
+ F32 range_squared = dist_vec_squared(gAgent.getCameraPositionAgent(), center_agent);
+ F32 range_from_agent_squared = dist_vec_squared(gAgent.getPositionAgent(), center_agent);
// Don't draw manip if object too far away
if (gSavedSettings.getBOOL("LimitSelectDistance"))
{
F32 max_select_distance = gSavedSettings.getF32("MaxSelectDistance");
- if (range_from_agent > max_select_distance)
+ if (range_from_agent_squared > max_select_distance * max_select_distance)
{
return;
}
}
- if (range > 0.001f)
+ if (range_squared > 0.001f * 0.001f)
{
// range != zero
F32 fraction_of_fov = BOX_HANDLE_BASE_SIZE / (F32) LLViewerCamera::getInstance()->getViewHeightInPixels();
F32 apparent_angle = fraction_of_fov * LLViewerCamera::getInstance()->getView(); // radians
- mBoxHandleSize = range * tan(apparent_angle) * BOX_HANDLE_BASE_FACTOR;
+ mBoxHandleSize = (F32) sqrtf(range_squared) * tan(apparent_angle) * BOX_HANDLE_BASE_FACTOR;
}
else
{
diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp
index 483b755de..7e340d369 100644
--- a/indra/newview/llpanelface.cpp
+++ b/indra/newview/llpanelface.cpp
@@ -389,6 +389,11 @@ struct LLPanelFaceSetAlignedTEFunctor : public LLSelectedTEFunctor
return true;
}
+ if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te)
+ {
+ return true;
+ }
+
bool set_aligned = true;
if (facep == mCenterFace)
{
@@ -431,6 +436,12 @@ struct LLPanelFaceGetIsAlignedTEFunctor : public LLSelectedTEFunctor
{
return false;
}
+
+ if (facep->getViewerObject()->getVolume()->getNumVolumeFaces() <= te)
+ { //volume face does not exist, can't be aligned
+ return false;
+ }
+
if (facep == mCenterFace)
{
return true;
diff --git a/indra/newview/llphysicsmotion.cpp b/indra/newview/llphysicsmotion.cpp
index 581043951..af775f59f 100644
--- a/indra/newview/llphysicsmotion.cpp
+++ b/indra/newview/llphysicsmotion.cpp
@@ -131,7 +131,8 @@ protected:
{
return sDefaultController[controller_key];
}
- return mCharacter->getVisualParamWeight((*entry).second.c_str());
+ const std::string& param_name = (*entry).second.c_str();
+ return mCharacter->getVisualParamWeight(param_name.c_str());
}
void setParamValue(LLViewerVisualParam *param,
const F32 new_value_local,
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 0ca376345..afe43a353 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -33,6 +33,7 @@
#include "llviewerprecompiledheaders.h"
// file include
+#define LLSELECTMGR_CPP
#include "llselectmgr.h"
// library includes
@@ -93,8 +94,6 @@
#include "rlvhandler.h"
// [/RLVa:KB]
-#include "llglheaders.h"
-
LLViewerObject* getSelectedParentObject(LLViewerObject *object) ;
//
// Consts
@@ -102,7 +101,6 @@ LLViewerObject* getSelectedParentObject(LLViewerObject *object) ;
const S32 NUM_SELECTION_UNDO_ENTRIES = 200;
const F32 SILHOUETTE_UPDATE_THRESHOLD_SQUARED = 0.02f;
-const S32 OWNERSHIP_COST_PER_OBJECT = 10; // Must be the same as economy_constants.price_object_claim in the database.
const S32 MAX_ACTION_QUEUE_SIZE = 20;
const S32 MAX_SILS_PER_FRAME = 50;
const S32 MAX_OBJECTS_PER_PACKET = 254;
@@ -112,13 +110,12 @@ const S32 TE_SELECT_MASK_ALL = 0xFFFFFFFF;
// Globals
//
-BOOL gDebugSelectMgr = FALSE;
+//BOOL gDebugSelectMgr = FALSE;
-BOOL gHideSelectedObjects = FALSE;
-BOOL gAllowSelectAvatar = FALSE;
+//BOOL gHideSelectedObjects = FALSE;
+//BOOL gAllowSelectAvatar = FALSE;
BOOL LLSelectMgr::sRectSelectInclusive = TRUE;
-BOOL LLSelectMgr::sRenderSelectionHighlights = TRUE;
BOOL LLSelectMgr::sRenderHiddenSelections = TRUE;
BOOL LLSelectMgr::sRenderLightRadius = FALSE;
F32 LLSelectMgr::sHighlightThickness = 0.f;
@@ -134,7 +131,6 @@ LLColor4 LLSelectMgr::sHighlightInspectColor;
LLColor4 LLSelectMgr::sHighlightParentColor;
LLColor4 LLSelectMgr::sHighlightChildColor;
LLColor4 LLSelectMgr::sContextSilhouetteColor;
-std::set LLSelectMgr::sObjectPropertiesFamilyRequests;
static LLObjectSelection *get_null_object_selection();
template<>
@@ -181,11 +177,17 @@ LLObjectSelection *get_null_object_selection()
return sNullSelection;
}
+// Build time optimization, generate this function once here
+template class LLSelectMgr* LLSingleton::getInstance();
//-----------------------------------------------------------------------------
// LLSelectMgr()
//-----------------------------------------------------------------------------
LLSelectMgr::LLSelectMgr()
+ : mHideSelectedObjects(LLCachedControl("HideSelectedObjects", false)),
+ mRenderHighlightSelections(LLCachedControl("RenderHighlightSelections", false)),
+ mAllowSelectAvatar( LLCachedControl("AllowSelectAvatar", false)),
+ mDebugSelectMgr(LLCachedControl( "DebugSelectMgr", false))
{
mTEMode = FALSE;
mLastCameraPos.clearVec();
@@ -564,6 +566,121 @@ BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id)
return object_found;
}
+bool LLSelectMgr::linkObjects()
+{
+ if (!LLSelectMgr::getInstance()->selectGetAllRootsValid())
+ {
+ LLNotifications::getInstance()->add("UnableToLinkWhileDownloading");
+ return true;
+ }
+
+ S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ if (object_count > MAX_CHILDREN_PER_TASK + 1)
+ {
+ LLSD args;
+ args["COUNT"] = llformat("%d", object_count);
+ int max = MAX_CHILDREN_PER_TASK+1;
+ args["MAX"] = llformat("%d", max);
+ LLNotifications::getInstance()->add("UnableToLinkObjects", args);
+ return true;
+ }
+
+ if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2)
+ {
+ LLNotifications::instance().add("CannotLinkIncompleteSet");
+ return true;
+ }
+
+ if (!LLSelectMgr::getInstance()->selectGetRootsModify())
+ {
+ LLNotifications::instance().add("CannotLinkModify");
+ return true;
+ }
+
+ LLUUID owner_id;
+ std::string owner_name;
+ if (!LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name))
+ {
+ // we don't actually care if you're the owner, but novices are
+ // the most likely to be stumped by this one, so offer the
+ // easiest and most likely solution.
+ LLNotifications::instance().add("CannotLinkDifferentOwners");
+ return true;
+ }
+
+ LLSelectMgr::getInstance()->sendLink();
+
+ return true;
+}
+
+bool LLSelectMgr::unlinkObjects()
+{
+// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.1.3b) | Modified: RLVa-0.2.0g | OK
+ if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStand()) )
+ {
+ // Allow only if the avie isn't sitting on any of the selected objects
+ LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection();
+ RlvSelectIsSittingOn f(gAgent.getAvatarObject()->getRoot());
+ if ( (hSel.notNull()) && (hSel->getFirstRootNode(&f, TRUE)) )
+ return true;
+ }
+// [/RLVa:KB]
+ LLSelectMgr::getInstance()->sendDelink();
+ return true;
+}
+
+// in order to link, all objects must have the same owner, and the
+// agent must have the ability to modify all of the objects. However,
+// we're not answering that question with this method. The question
+// we're answering is: does the user have a reasonable expectation
+// that a link operation should work? If so, return true, false
+// otherwise. this allows the handle_link method to more finely check
+// the selection and give an error message when the uer has a
+// reasonable expectation for the link to work, but it will fail.
+bool LLSelectMgr::enableLinkObjects()
+{
+ bool new_value = false;
+ // check if there are at least 2 objects selected, and that the
+ // user can modify at least one of the selected objects.
+
+ // in component mode, can't link
+ if (!gSavedSettings.getBOOL("EditLinkedParts"))
+ {
+ if(LLSelectMgr::getInstance()->selectGetAllRootsValid() && LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() >= 2)
+ {
+ struct f : public LLSelectedObjectFunctor
+ {
+ virtual bool apply(LLViewerObject* object)
+ {
+ return object->permModify();
+ }
+ } func;
+ const bool firstonly = true;
+ new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
+ }
+ }
+ return new_value;
+}
+
+bool LLSelectMgr::enableUnlinkObjects()
+{
+ LLViewerObject* first_editable_object = LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject();
+
+ bool new_value = LLSelectMgr::getInstance()->selectGetAllRootsValid() &&
+ first_editable_object &&
+ !first_editable_object->isAttachment();
+// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.1.3b) | Modified: RLVa-0.2.0g | OK
+ if ( (new_value) && (!gRlvHandler.canStand()) )
+ {
+ // Allow only if the avie isn't sitting on any of the selected objects
+ LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection();
+ RlvSelectIsSittingOn f(gAgent.getAvatarObject()->getRoot());
+ new_value = handleSel->getFirstRootNode(&f, TRUE) == NULL;
+ }
+// [/RLVa:KB]
+ return new_value;
+}
+
void LLSelectMgr::deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim, BOOL include_entire_object)
{
// bail if nothing selected or if object wasn't selected in the first place
@@ -690,7 +807,7 @@ void LLSelectMgr::addAsFamily(std::vector& objects, BOOL add_to
// Can't select yourself
if (objectp->mID == gAgentID
- && !gAllowSelectAvatar)
+ && !LLSelectMgr::getInstance()->mAllowSelectAvatar)
{
continue;
}
@@ -839,7 +956,12 @@ LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32
LLSelectNode *LLSelectMgr::getHoverNode()
{
- return getHoverObjects()->getFirstRootNode();
+ return mHoverObjects->getFirstRootNode();
+}
+
+LLSelectNode *LLSelectMgr::getPrimaryHoverNode()
+{
+ return mHoverObjects->mSelectNodeMap[mHoverObjects->mPrimaryObject];
}
void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
@@ -854,8 +976,8 @@ void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
return;
}
- if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner()) ||
- (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove()))
+ if ((gSavedSettings.getBOOL("SelectOwnedOnly") && !objectp->permYouOwner())
+ || (gSavedSettings.getBOOL("SelectMovableOnly") && !objectp->permMove()))
{
// only select my own objects
return;
@@ -2253,6 +2375,26 @@ BOOL LLSelectMgr::selectGetAllValid()
return TRUE;
}
+//-----------------------------------------------------------------------------
+// selectGetAllValidAndObjectsFound() - return TRUE if selections are
+// valid and objects are found.
+//
+// For EXT-3114 - same as selectGetModify() without the modify check.
+//-----------------------------------------------------------------------------
+BOOL LLSelectMgr::selectGetAllValidAndObjectsFound()
+{
+ for (LLObjectSelection::iterator iter = getSelection()->begin();
+ iter != getSelection()->end(); iter++ )
+ {
+ LLSelectNode* node = *iter;
+ LLViewerObject* object = node->getObject();
+ if( !object || !node->mValid )
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
//-----------------------------------------------------------------------------
// selectGetModify() - return TRUE if current agent can modify all
@@ -2382,6 +2524,7 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name)
}
if (first_id.isNull())
{
+ name.assign("Nobody");
return FALSE;
}
@@ -2664,11 +2807,6 @@ BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off)
-BOOL LLSelectMgr::selectGetOwnershipCost(S32* out_cost)
-{
- return mSelectedObjects->getOwnershipCost(*out_cost);
-}
-
BOOL LLSelectMgr::selectGetPermissions(LLPermissions& result_perm)
{
BOOL first = TRUE;
@@ -3517,7 +3655,7 @@ void LLSelectMgr::deselectAllIfTooFar()
if (select_dist_sq > deselect_dist_sq)
{
- if (gDebugSelectMgr)
+ if (mDebugSelectMgr)
{
llinfos << "Selection manager: auto-deselecting, select_dist = " << fsqrtf(select_dist_sq) << llendl;
llinfos << "agent pos global = " << gAgent.getPositionGlobal() << llendl;
@@ -3596,7 +3734,7 @@ void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info)
// Attachments
//----------------------------------------------------------------------
-void LLSelectMgr::sendAttach(U8 attachment_point)
+void LLSelectMgr::sendAttach(U8 attachment_point, bool replace)
{
LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject();
@@ -3610,7 +3748,7 @@ void LLSelectMgr::sendAttach(U8 attachment_point)
if (0 == attachment_point ||
get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, (S32)attachment_point, (LLViewerJointAttachment*)NULL))
{
- if (attachment_point != 0 && gHippoGridManager->getConnectedGrid()->supportsInvLinks())
+ if ((!replace || attachment_point != 0) && gHippoGridManager->getConnectedGrid()->supportsInvLinks())
{
// If we know the attachment point then we got here by clicking an
// "Attach to..." context menu item, so we should add, not replace.
@@ -4300,10 +4438,6 @@ void LLSelectMgr::sendListToRegions(const std::string& message_name,
void LLSelectMgr::requestObjectPropertiesFamily(LLViewerObject* object)
{
- // Remember that we asked the properties of this object.
- sObjectPropertiesFamilyRequests.insert(object->mID);
- //llinfos << "Registered an ObjectPropertiesFamily request for object " << object->mID << llendl;
-
LLMessageSystem* msg = gMessageSystem;
msg->newMessageFast(_PREHASH_RequestObjectPropertiesFamily);
@@ -4381,7 +4515,7 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data
msg->getStringFast(_PREHASH_ObjectData, _PREHASH_SitName, sit_name, i);
//unpack TE IDs
- std::vector texture_ids;
+ uuid_vec_t texture_ids;
S32 size = msg->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_TextureID);
if (size > 0)
{
@@ -4493,8 +4627,9 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data
// static
void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** user_data)
{
- U32 request_flags;
LLUUID id;
+
+ U32 request_flags;
LLUUID creator_id;
LLUUID owner_id;
LLUUID group_id;
@@ -4525,15 +4660,6 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use
std::string desc;
msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, desc);
- //llinfos << "Got ObjectPropertiesFamily reply for object " << id << llendl;
- if(sObjectPropertiesFamilyRequests.count(id) != 0 )
- {
- // Send to export floaters
- //LLFloaterExport::receiveObjectProperties(id, name, desc);
- // We got the reply, so remove the object from the list of pending requests
- sObjectPropertiesFamilyRequests.erase(id);
- }
-
// the reporter widget askes the server for info about picked objects
if (request_flags & (COMPLAINT_REPORT_REQUEST | BUG_REPORT_REQUEST))
{
@@ -4562,7 +4688,7 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use
return (node->getObject() && node->getObject()->mID == mID);
}
} func(id);
- LLSelectNode* node = LLSelectMgr::getInstance()->getHoverObjects()->getFirstNode(&func);
+ LLSelectNode* node = LLSelectMgr::getInstance()->mHoverObjects->getFirstNode(&func);
if (node)
{
@@ -4897,12 +5023,12 @@ void LLSelectMgr::updateSelectionSilhouette(LLObjectSelectionHandle object_handl
}
void LLSelectMgr::renderSilhouettes(BOOL for_hud)
{
- if (!mRenderSilhouettes || !LLSelectMgr::sRenderSelectionHighlights)
+ if (!mRenderSilhouettes || !mRenderHighlightSelections)
{
return;
}
- gGL.getTexUnit(0)->bind(mSilhouetteImagep.get());
+ gGL.getTexUnit(0)->bind(mSilhouetteImagep);
LLGLSPipelineSelection gls_select;
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.f);
LLGLEnable blend(GL_BLEND);
@@ -4932,7 +5058,8 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
if (mSelectedObjects->getNumNodes())
{
LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID();
-
+
+ LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getSelectedUUID();
//
//for (S32 pass = 0; pass < 2; pass++)
//{
@@ -4948,7 +5075,11 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
{
continue;
}
- if(objectp->getID() == inspect_item_id)
+ if (objectp->getID() == focus_item_id)
+ {
+ node->renderOneSilhouette(gFocusMgr.getFocusColor());
+ }
+ else if(objectp->getID() == inspect_item_id)
{
node->renderOneSilhouette(sHighlightInspectColor);
}
@@ -5118,13 +5249,14 @@ void LLSelectNode::selectTE(S32 te_index, BOOL selected)
{
return;
}
- if (selected)
- {
- mTESelectMask |= (0x1 << te_index);
+ S32 mask = 0x1 << te_index;
+ if(selected)
+ {
+ mTESelectMask |= mask;
}
else
{
- mTESelectMask &= ~(0x1 << te_index);
+ mTESelectMask &= ~mask;
}
mLastTESelected = te_index;
}
@@ -5178,13 +5310,13 @@ void LLSelectNode::saveColors()
}
}
-void LLSelectNode::saveTextures(const std::vector& textures)
+void LLSelectNode::saveTextures(const uuid_vec_t& textures)
{
if (mObject.notNull())
{
mSavedTextures.clear();
- for (std::vector::const_iterator texture_it = textures.begin();
+ for (uuid_vec_t::const_iterator texture_it = textures.begin();
texture_it != textures.end(); ++texture_it)
{
mSavedTextures.push_back(*texture_it);
@@ -5477,13 +5609,21 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
// Update everyone who cares about the selection list
void dialog_refresh_all()
+
{
+ // This is the easiest place to fire the update signal, as it will
+ // make cleaning up the functions below easier. Also, sometimes entities
+ // outside the selection manager change properties of selected objects
+ // and call into this function. Yuck.
+ LLSelectMgr::getInstance()->mUpdateSignal();
+
if (gNoRender)
{
return;
}
- //could refresh selected object info in toolbar here
+ // *TODO: Eliminate all calls into outside classes below, make those
+ // objects register with the update signal.
gFloaterTools->dirty();
@@ -5897,6 +6037,27 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom)
gAgent.mHUDCurZoom = current_zoom;
}
+/////////////////////////////////////////////////////////////////////////////
+// Object selection iterator helpers
+/////////////////////////////////////////////////////////////////////////////
+bool LLObjectSelection::is_root::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
+}
+
+bool LLObjectSelection::is_valid_root::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
+}
+
+bool LLObjectSelection::is_root_object::operator()(LLSelectNode *node)
+{
+ LLViewerObject* object = node->getObject();
+ return (object != NULL) && (object->isRootEdit() || object->isJointChild());
+}
+
LLObjectSelection::LLObjectSelection() :
LLRefCount(),
mSelectType(SELECT_TYPE_WORLD)
@@ -5988,16 +6149,6 @@ BOOL LLObjectSelection::isEmpty() const
return (mList.size() == 0);
}
-//-----------------------------------------------------------------------------
-// getOwnershipCost()
-//-----------------------------------------------------------------------------
-BOOL LLObjectSelection::getOwnershipCost(S32 &cost)
-{
- S32 count = getObjectCount();
- cost = count * OWNERSHIP_COST_PER_OBJECT;
- return (count > 0);
-}
-
//-----------------------------------------------------------------------------
// getObjectCount() - returns number of non null objects
@@ -6138,6 +6289,29 @@ bool LLObjectSelection::applyToRootNodes(LLSelectedNodeFunctor *func, bool first
return result;
}
+BOOL LLObjectSelection::isMultipleTESelected()
+{
+ BOOL te_selected = FALSE;
+ // ...all faces
+ for (LLObjectSelection::iterator iter = begin();
+ iter != end(); iter++)
+ {
+ LLSelectNode* nodep = *iter;
+ for (S32 i = 0; i < SELECT_MAX_TES; i++)
+ {
+ if(nodep->isTESelected(i))
+ {
+ if(te_selected)
+ {
+ return TRUE;
+ }
+ te_selected = TRUE;
+ }
+ }
+ }
+ return FALSE;
+}
+
//-----------------------------------------------------------------------------
// contains()
//-----------------------------------------------------------------------------
@@ -6404,23 +6578,24 @@ bool LLSelectMgr::selectionMove(const LLVector3& displ,
if (update_position)
{
// calculate the distance of the object closest to the camera origin
- F32 min_dist = 1e+30f;
+ F32 min_dist_squared = F32_MAX; // value will be overridden in the loop
+
LLVector3 obj_pos;
for (LLObjectSelection::root_iterator it = getSelection()->root_begin();
it != getSelection()->root_end(); ++it)
{
obj_pos = (*it)->getObject()->getPositionEdit();
- F32 obj_dist = dist_vec(obj_pos, LLViewerCamera::getInstance()->getOrigin());
- if (obj_dist < min_dist)
+ F32 obj_dist_squared = dist_vec_squared(obj_pos, LLViewerCamera::getInstance()->getOrigin());
+ if (obj_dist_squared < min_dist_squared)
{
- min_dist = obj_dist;
+ min_dist_squared = obj_dist_squared;
}
}
- // factor the distance inside the displacement vector. This will get us
+ // factor the distance into the displacement vector. This will get us
// equally visible movements for both close and far away selections.
- min_dist = sqrt(min_dist) / 2;
+ F32 min_dist = sqrt((F32) sqrtf(min_dist_squared)) / 2;
displ_global.setVec(displ.mV[0]*min_dist,
displ.mV[1]*min_dist,
displ.mV[2]*min_dist);
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 1ebe341bf..1472cc8b7 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -35,7 +35,6 @@
#include "llcharacter.h"
#include "lleditmenuhandler.h"
-#include "llstring.h"
#include "llundo.h"
#include "lluuid.h"
#include "llmemory.h"
@@ -47,14 +46,15 @@
#include "llframetimer.h"
#include "llbbox.h"
#include "llpermissions.h"
-#include "llviewerobject.h"
+#include "llcontrol.h"
+#include "llviewerobject.h" // LLObjectSelection::getSelectedTEValue template
#include
-#include "boost/iterator/filter_iterator.hpp"
+#include
+#include
class LLMessageSystem;
class LLViewerTexture;
-class LLViewerObject;
class LLColor4;
class LLVector3;
class LLSelectNode;
@@ -146,7 +146,7 @@ public:
void setObject(LLViewerObject* object);
// *NOTE: invalidate stored textures and colors when # faces change
void saveColors();
- void saveTextures(const std::vector& textures);
+ void saveTextures(const uuid_vec_t& textures);
void saveTextureScaleRatios();
BOOL allowOperationOnNode(PermissionBit op, U64 group_proxy_power) const;
@@ -182,7 +182,7 @@ public:
std::string mSitName;
U64 mCreationDate;
std::vector mSavedColors;
- std::vector mSavedTextures;
+ uuid_vec_t mSavedTextures;
std::vector mTextureScaleRatios;
std::vector mSilhouetteVertices; // array of vertices to render silhouette of object
std::vector mSilhouetteNormals; // array of normals to render silhouette of object
@@ -202,13 +202,9 @@ class LLObjectSelection : public LLRefCount
protected:
~LLObjectSelection();
- // List
public:
typedef std::list list_t;
-private:
- list_t mList;
-public:
// Iterators
struct is_non_null
{
@@ -234,11 +230,7 @@ public:
struct is_root
{
- bool operator()(LLSelectNode* node)
- {
- LLViewerObject* object = node->getObject();
- return (object != NULL) && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
- }
+ bool operator()(LLSelectNode* node);
};
typedef boost::filter_iterator root_iterator;
root_iterator root_begin() { return root_iterator(mList.begin(), mList.end()); }
@@ -246,11 +238,7 @@ public:
struct is_valid_root
{
- bool operator()(LLSelectNode* node)
- {
- LLViewerObject* object = node->getObject();
- return (object != NULL) && node->mValid && !node->mIndividualSelection && (object->isRootEdit() || object->isJointChild());
- }
+ bool operator()(LLSelectNode* node);
};
typedef boost::filter_iterator valid_root_iterator;
valid_root_iterator valid_root_begin() { return valid_root_iterator(mList.begin(), mList.end()); }
@@ -258,11 +246,7 @@ public:
struct is_root_object
{
- bool operator()(LLSelectNode* node)
- {
- LLViewerObject* object = node->getObject();
- return (object != NULL) && (object->isRootEdit() || object->isJointChild());
- }
+ bool operator()(LLSelectNode* node);
};
typedef boost::filter_iterator root_object_iterator;
root_object_iterator root_object_begin() { return root_object_iterator(mList.begin(), mList.end()); }
@@ -272,12 +256,9 @@ public:
LLObjectSelection();
void updateEffects();
- void cleanupNodes();
BOOL isEmpty() const;
- S32 getOwnershipCost(S32 &cost);
-
LLSelectNode* getFirstNode(LLSelectedNodeFunctor* func = NULL);
LLSelectNode* getFirstRootNode(LLSelectedNodeFunctor* func = NULL, BOOL non_root_ok = FALSE);
LLViewerObject* getFirstSelectedObject(LLSelectedNodeFunctor* func, BOOL get_parent = FALSE);
@@ -294,12 +275,8 @@ public:
// iterate through texture entries
template bool getSelectedTEValue(LLSelectedTEGetFunctor* func, T& res);
-
- void addNode(LLSelectNode *nodep);
- void addNodeAtEnd(LLSelectNode *nodep);
- void moveNodeToFront(LLSelectNode *nodep);
- void removeNode(LLSelectNode *nodep);
- void deleteAllNodes(); // Delete all nodes
+ template bool isMultipleTEValue(LLSelectedTEGetFunctor* func, const T& ignore_value);
+
S32 getNumNodes();
LLSelectNode* findNode(LLViewerObject* objectp);
@@ -308,6 +285,7 @@ public:
S32 getTECount();
S32 getRootObjectCount();
+ BOOL isMultipleTESelected();
BOOL contains(LLViewerObject* object);
BOOL contains(LLViewerObject* object, S32 te);
@@ -326,6 +304,16 @@ public:
ESelectType getSelectType() const { return mSelectType; }
private:
+ void addNode(LLSelectNode *nodep);
+ void addNodeAtEnd(LLSelectNode *nodep);
+ void moveNodeToFront(LLSelectNode *nodep);
+ void removeNode(LLSelectNode *nodep);
+ void deleteAllNodes();
+ void cleanupNodes();
+
+
+private:
+ list_t mList;
const LLObjectSelection &operator=(const LLObjectSelection &);
LLPointer mPrimaryObject;
@@ -335,11 +323,15 @@ private:
typedef LLSafeHandle LLObjectSelectionHandle;
+// Build time optimization, generate this once in .cpp file
+#ifndef LLSELECTMGR_CPP
+extern template class LLSelectMgr* LLSingleton::getInstance();
+#endif
+
class LLSelectMgr : public LLEditMenuHandler, public LLSingleton
{
public:
static BOOL sRectSelectInclusive; // do we need to surround an object to pick it?
- static BOOL sRenderSelectionHighlights; // do we show selection silhouettes?
static BOOL sRenderHiddenSelections; // do we show selection silhouettes that are occluded?
static BOOL sRenderLightRadius; // do we show the radius of selected lights?
static F32 sHighlightThickness;
@@ -356,6 +348,11 @@ public:
static LLColor4 sHighlightInspectColor;
static LLColor4 sContextSilhouetteColor;
+ LLCachedControl mHideSelectedObjects;
+ LLCachedControl mRenderHighlightSelections;
+ LLCachedControl mAllowSelectAvatar;
+ LLCachedControl mDebugSelectMgr;
+
public:
LLSelectMgr();
~LLSelectMgr();
@@ -394,13 +391,16 @@ public:
// Add
////////////////////////////////////////////////////////////////
+ // This method is meant to select an object, and then select all
+ // of the ancestors and descendants. This should be the normal behavior.
+ //
+ // *NOTE: You must hold on to the object selection handle, otherwise
+ // the objects will be automatically deselected in 1 frame.
+ LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE);
+
// For when you want just a child object.
LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES);
- // This method is meant to select an object, and then select all
- // of the ancestors and descendents. This should be the normal behavior.
- LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE);
-
// Same as above, but takes a list of objects. Used by rectangle select.
LLObjectSelectionHandle selectObjectAndFamily(const std::vector& object_list, BOOL send_to_sim = TRUE);
@@ -408,6 +408,8 @@ public:
LLObjectSelectionHandle selectHighlightedObjects();
LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp, S32 face = -1);
+ LLSelectNode *getHoverNode();
+ LLSelectNode *getPrimaryHoverNode();
void highlightObjectOnly(LLViewerObject *objectp);
void highlightObjectAndFamily(LLViewerObject *objectp);
@@ -439,16 +441,25 @@ public:
BOOL removeObjectFromSelections(const LLUUID &id);
+ ////////////////////////////////////////////////////////////////
+ // Selection editing
+ ////////////////////////////////////////////////////////////////
+ bool linkObjects();
+
+ bool unlinkObjects();
+
+ bool enableLinkObjects();
+
+ bool enableUnlinkObjects();
+
////////////////////////////////////////////////////////////////
// Selection accessors
////////////////////////////////////////////////////////////////
- LLObjectSelectionHandle getHoverObjects() { return mHoverObjects; }
LLObjectSelectionHandle getSelection() { return mSelectedObjects; }
// right now this just renders the selection with root/child colors instead of a single color
LLObjectSelectionHandle getEditSelection() { convertTransient(); return mSelectedObjects; }
LLObjectSelectionHandle getHighlightedObjects() { return mHighlightedObjects; }
-
- LLSelectNode *getHoverNode();
+ LLObjectSelectionHandle getHoverObjects() { return mHoverObjects; }
////////////////////////////////////////////////////////////////
// Grid manipulation
@@ -503,7 +514,7 @@ public:
void selectionSetTexGen( U8 texgen );
void selectionSetShiny( U8 shiny );
void selectionSetFullbright( U8 fullbright );
- void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url );
+ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_url);
void selectionSetClickAction(U8 action);
void selectionSetIncludeInSearch(bool include_in_search);
void selectionSetGlow(const F32 glow);
@@ -535,6 +546,7 @@ public:
// Returns TRUE if the viewer has information on all selected objects
BOOL selectGetAllRootsValid();
BOOL selectGetAllValid();
+ BOOL selectGetAllValidAndObjectsFound();
// returns TRUE if you can modify all selected objects.
BOOL selectGetRootsModify();
@@ -554,7 +566,6 @@ public:
// the value found if available.
BOOL selectGetGroup(LLUUID& id);
BOOL selectGetPerm( U8 which_perm, U32* mask_on, U32* mask_off); // TRUE if all have data, returns two masks, each indicating which bits are all on and all off
- BOOL selectGetOwnershipCost(S32* cost); // sum of all ownership costs
BOOL selectIsGroupOwned(); // TRUE if all root objects have valid data and are group owned.
@@ -610,7 +621,7 @@ public:
// verification only, if it doesn't match region info then sale is
// canceled
void sendBuy(const LLUUID& buyer_id, const LLUUID& category_id, const LLSaleInfo sale_info);
- void sendAttach(U8 attachment_point);
+ void sendAttach(U8 attachment_point, bool replace=true);
void sendDetach();
void sendDropAttachment();
void sendLink();
@@ -689,7 +700,13 @@ private:
static void packPermissionsHead(void* user_data);
static void packGodlikeHead(void* user_data);
static bool confirmDelete(const LLSD& notification, const LLSD& response, LLObjectSelectionHandle handle);
-
+
+public:
+ // Observer/callback support for when object selection changes or
+ // properties are received/updated
+ typedef boost::signals2::signal< void ()> update_signal_t;
+ update_signal_t mUpdateSignal;
+
private:
LLPointer mSilhouetteImagep;
LLObjectSelectionHandle mSelectedObjects;
@@ -719,12 +736,12 @@ private:
BOOL mForceSelection;
LLAnimPauseRequest mPauseRequest;
-
- static std::set sObjectPropertiesFamilyRequests;
};
-// Utilities
-void dialog_refresh_all(); // Update subscribers to the selection list
+// *DEPRECATED: For callbacks or observers, use
+// LLSelectMgr::getInstance()->mUpdateSignal.connect( callback )
+// Update subscribers to the selection list
+void dialog_refresh_all();
// Templates
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp
index b6f4dedbd..de99cb86f 100644
--- a/indra/newview/llsky.cpp
+++ b/indra/newview/llsky.cpp
@@ -52,7 +52,6 @@
#include "llviewerobject.h"
#include "llviewercamera.h"
#include "pipeline.h"
-#include "llagent.h"
#include "lldrawpool.h"
#include "llvosky.h"
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 9546e3b04..ca70e52e6 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -286,6 +286,10 @@ LLSpatialGroup::~LLSpatialGroup()
llerrs << "Illegal deletion of LLSpatialGroup!" << llendl;
}*/
+ if (gDebugGL)
+ {
+ gPipeline.checkReferences(this);
+ }
if (isState(DEAD))
{
sZombieGroups--;
@@ -293,9 +297,15 @@ LLSpatialGroup::~LLSpatialGroup()
sNodeCount--;
- if (gGLManager.mHasOcclusionQuery && mOcclusionQuery[LLViewerCamera::sCurCameraID])
+ if (gGLManager.mHasOcclusionQuery)
{
- sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
+ for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i)
+ {
+ if (mOcclusionQuery[i])
+ {
+ sQueryPool.release(mOcclusionQuery[i]);
+ }
+ }
}
delete [] mOcclusionVerts;
@@ -317,7 +327,7 @@ BOOL LLSpatialGroup::isRecentlyVisible() const
BOOL LLSpatialGroup::isVisible() const
{
- return mVisible[LLViewerCamera::sCurCameraID] == LLDrawable::getCurrentFrame() ? TRUE : FALSE;
+ return mVisible[LLViewerCamera::sCurCameraID] >= LLDrawable::getCurrentFrame() ? TRUE : FALSE;
}
void LLSpatialGroup::setVisible()
@@ -767,13 +777,14 @@ void LLSpatialGroup::shift(const LLVector3 &offset)
if (mOcclusionVerts)
{
- for (U32 i = 0; i < 8; i++)
+ setState(OCCLUSION_DIRTY);
+ /*for (U32 i = 0; i < 8; i++)
{
F32* v = mOcclusionVerts+i*3;
v[0] += offset.mV[0];
v[1] += offset.mV[1];
v[2] += offset.mV[2];
- }
+ }*/
}
}
@@ -969,12 +980,23 @@ void LLSpatialGroup::setOcclusionState(eOcclusionState state, S32 mode)
for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++)
{
mOcclusionState[i] |= state;
+
+ if ((state & DISCARD_QUERY) && mOcclusionQuery[i])
+ {
+ sQueryPool.release(mOcclusionQuery[i]);
+ mOcclusionQuery[i] = 0;
+ }
}
}
}
else
{
mOcclusionState[LLViewerCamera::sCurCameraID] |= state;
+ if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
+ {
+ sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
+ mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
+ }
}
}
@@ -1053,6 +1075,9 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) :
sNodeCount++;
LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION);
+ mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] =
+ mObjectExtents[0] = mObjectExtents[1] = mViewAngle;
+
sg_assert(mOctreeNode->getListenerCount() == 0);
mOctreeNode->addListener(this);
setState(SG_INITIAL_STATE_MASK);
@@ -1117,9 +1142,9 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera)
{
if (!group->mSpatialPartition->isBridge())
{
- LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0),
+ LLVector3 view_angle = eye;/*LLVector3(eye * LLVector3(1,0,0), //WTF is this?
eye * LLVector3(0,1,0),
- eye * LLVector3(0,0,1));
+ eye * LLVector3(0,0,1));*/
if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f)
{
@@ -1174,7 +1199,9 @@ F32 LLSpatialGroup::getUpdateUrgency() const
}
else
{
- return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance;
+ //return (gFrameTimeSeconds - mLastUpdateTime+4.f)/mDistance;
+ F32 time = gFrameTimeSeconds-mLastUpdateTime+4.f;
+ return (time + (mObjectBounds[1]*mObjectBounds[1]) + 1.f)/mDistance;
}
}
@@ -1185,7 +1212,7 @@ BOOL LLSpatialGroup::needsUpdate()
BOOL LLSpatialGroup::changeLOD()
{
- if (isState(ALPHA_DIRTY))
+ if (isState(ALPHA_DIRTY | OBJECT_DIRTY))
{ ///an alpha sort is going to happen, update distance and LOD
return TRUE;
}
@@ -1199,7 +1226,8 @@ BOOL LLSpatialGroup::changeLOD()
return TRUE;
}
- if (mDistance > mRadius)
+ //if (mDistance > mRadius)
+ if (mDistance > mRadius*2.f)
{
return FALSE;
}
@@ -1398,12 +1426,29 @@ void LLSpatialGroup::checkOcclusion()
}
else if (isOcclusionState(QUERY_PENDING))
{ //otherwise, if a query is pending, read it back
+ GLuint available = 0;
+ if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
+ {
+ glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available);
+ }
+ else
+ {
+ available = 1;
+ }
+
+ if (available)
+ { //result is available, read it back, otherwise wait until next frame
GLuint res = 1;
if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID])
{
glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res);
- }
-
+ }
+ else if (mOcclusionQuery[LLViewerCamera::sCurCameraID])
+ { //delete the query to avoid holding onto hundreds of pending queries
+ sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]);
+ mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0;
+ }
+
if (isOcclusionState(DISCARD_QUERY))
{
res = 2;
@@ -1423,6 +1468,7 @@ void LLSpatialGroup::checkOcclusion()
}
clearOcclusionState(QUERY_PENDING | DISCARD_QUERY);
+ }
}
else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLSpatialGroup::OCCLUDED))
{ //check occlusion has been issued for occluded node that has not had a query issued
@@ -1439,8 +1485,9 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
{
//static const LLCachedControl render_water_void_culling("RenderWaterVoidCulling", TRUE);
// Don't cull hole/edge water, unless RenderWaterVoidCulling is set and we have the GL_ARB_depth_clamp extension.
- if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) ||
- earlyFail(camera, this))
+ //if ((mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER && !gGLManager.mHasDepthClamp) ||
+ // earlyFail(camera, this))
+ if (earlyFail(camera, this))
{
setOcclusionState(LLSpatialGroup::DISCARD_QUERY);
assert_states_valid(this);
@@ -1449,54 +1496,83 @@ void LLSpatialGroup::doOcclusion(LLCamera* camera)
}
else
{
+ if (!isOcclusionState(QUERY_PENDING) || isOcclusionState(DISCARD_QUERY))
{
- LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION);
+ { //no query pending, or previous query to be discarded
+ //LLFastTimer t(FTM_RENDER_OCCLUSION);
- if (!mOcclusionQuery[LLViewerCamera::sCurCameraID])
- {
- mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate();
- }
+ if (!mOcclusionQuery[LLViewerCamera::sCurCameraID])
+ {
+ mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate();
+ }
- if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY))
- {
- buildOcclusion();
- }
+ if (!mOcclusionVerts || isState(LLSpatialGroup::OCCLUSION_DIRTY))
+ {
+ buildOcclusion();
+ }
- // Depth clamp all water to avoid it being culled as a result of being
- // behind the far clip plane, and in the case of edge water to avoid
- // it being culled while still visible.
- bool const use_depth_clamp = gGLManager.mHasDepthClamp &&
- (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER ||
- mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER);
- if (use_depth_clamp)
- {
- glEnable(GL_DEPTH_CLAMP);
+ // Depth clamp all water to avoid it being culled as a result of being
+ // behind the far clip plane, and in the case of edge water to avoid
+ // it being culled while still visible.
+ bool const use_depth_clamp = gGLManager.mHasDepthClamp &&
+ (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER ||
+ mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER);
+
+ LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0);
+
+#if !LL_DARWIN
+ U32 mode = gGLManager.mHasOcclusionQuery2 ? /*GL_ANY_SAMPLES_PASSED*/0x8C2F : GL_SAMPLES_PASSED_ARB;
+#else
+ U32 mode = GL_SAMPLES_PASSED_ARB;
+#endif
+
+ {
+ //LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS);
+ glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
+ glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);
+ if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER)
+ {
+ LLGLSquashToFarClip squash(glh_get_current_projection(), 1);
+ if (camera->getOrigin().isExactlyZero())
+ { //origin is invalid, draw entire box
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, sOcclusionIndices);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8);
+ }
+ else
+ {
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
+ }
+ }
+ else
+ {
+ if (camera->getOrigin().isExactlyZero())
+ { //origin is invalid, draw entire box
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, sOcclusionIndices);
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8);
+
+ }
+ else
+ {
+ glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
+ GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
+ }
+ }
+
+ glEndQueryARB(mode);
+ }
}
- glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQuery[LLViewerCamera::sCurCameraID]);
- glVertexPointer(3, GL_FLOAT, 0, mOcclusionVerts);
- if (camera->getOrigin().isExactlyZero())
- { //origin is invalid, draw entire box
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
- GL_UNSIGNED_BYTE, sOcclusionIndices);
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
- GL_UNSIGNED_BYTE, sOcclusionIndices+b111*8);
- }
- else
{
- glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
- GL_UNSIGNED_BYTE, get_box_fan_indices(camera, mBounds[0]));
- }
- glEndQueryARB(GL_SAMPLES_PASSED_ARB);
-
- if (use_depth_clamp)
- {
- glDisable(GL_DEPTH_CLAMP);
+ //LLFastTimer t(FTM_SET_OCCLUSION_STATE);
+ setOcclusionState(LLSpatialGroup::QUERY_PENDING);
+ clearOcclusionState(LLSpatialGroup::DISCARD_QUERY);
}
}
-
- setOcclusionState(LLSpatialGroup::QUERY_PENDING);
- clearOcclusionState(LLSpatialGroup::DISCARD_QUERY);
}
}
}
@@ -1624,13 +1700,12 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL
class LLSpatialShift : public LLSpatialGroup::OctreeTraveler
{
public:
- LLSpatialShift(LLVector3 offset) : mOffset(offset) { }
+ const LLVector3& mOffset;
+ LLSpatialShift(const LLVector3 &offset) : mOffset(offset) { }
virtual void visit(const LLSpatialGroup::OctreeNode* branch)
{
((LLSpatialGroup*) branch->getListener(0))->shift(mOffset);
}
-
- LLVector3 mOffset;
};
void LLSpatialPartition::shift(const LLVector3 &offset)
@@ -2354,7 +2429,11 @@ void renderOctree(LLSpatialGroup* group)
}
gGL.color4fv(col.mV);
- drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
+
+ {
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE);
+ drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f));
+ }
gGL.setSceneBlendType(LLRender::BT_ALPHA);
@@ -2663,7 +2742,6 @@ void renderPoints(LLDrawable* drawablep)
{
gGL.begin(LLRender::POINTS);
gGL.color3f(1,1,1);
- LLVector3 center(drawablep->getPositionGroup());
for (S32 i = 0; i < drawablep->getNumFaces(); i++)
{
gGL.vertex3fv(drawablep->getFace(i)->mCenterLocal.mV);
@@ -3314,6 +3392,11 @@ LLDrawInfo::~LLDrawInfo()
{
mFace->setDrawInfo(NULL);
}
+
+ if (gDebugGL)
+ {
+ gPipeline.checkReferences(this);
+ }
}
LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage)
diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp
index de5234ae4..6e53ff1c1 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -60,7 +60,6 @@
#include "llcachename.h"
#include "llviewercontrol.h"
#include "lldir.h"
-#include "lleventpoll.h" // OGPX for Agent Domain event queue
#include "llerrorcontrol.h"
#include "llfiltersd2xmlrpc.h"
#include "llfocusmgr.h"
@@ -140,7 +139,6 @@
#include "llpreview.h"
#include "llpreviewscript.h"
#include "llproductinforequest.h"
-#include "llsdhttpserver.h" // OGPX might not need when EVENTHACK is sorted
#include "llsecondlifeurls.h"
#include "llselectmgr.h"
#include "llsky.h"
diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp
index 1e412de26..b68e19f19 100644
--- a/indra/newview/lltoolselect.cpp
+++ b/indra/newview/lltoolselect.cpp
@@ -56,9 +56,6 @@
#include "llfloatertools.h"
// [/RLVa:KB]
-// Globals
-extern BOOL gAllowSelectAvatar;
-
const F32 SELECTION_ROTATION_TRESHOLD = 0.1f;
LLToolSelect::LLToolSelect( LLToolComposite* composite )
@@ -137,7 +134,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi
BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly");
// *NOTE: These settings must be cleaned up at bottom of function.
- if (temp_select || gAllowSelectAvatar)
+ if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar)
{
gSavedSettings.setBOOL("SelectOwnedOnly", FALSE);
gSavedSettings.setBOOL("SelectMovableOnly", FALSE);
@@ -267,7 +264,7 @@ LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pi
} //if(!object)
// Cleanup temp select settings above.
- if (temp_select || gAllowSelectAvatar)
+ if (temp_select || LLSelectMgr::getInstance()->mAllowSelectAvatar)
{
gSavedSettings.setBOOL("SelectOwnedOnly", select_owned);
gSavedSettings.setBOOL("SelectMovableOnly", select_movable);
diff --git a/indra/newview/llurlhistory.cpp b/indra/newview/llurlhistory.cpp
index a93cc2ff7..5f17aef78 100644
--- a/indra/newview/llurlhistory.cpp
+++ b/indra/newview/llurlhistory.cpp
@@ -77,7 +77,7 @@ bool LLURLHistory::saveFile(const std::string& filename)
std::string temp_str = gDirUtilp->getLindenUserDir(true);
if( temp_str.empty() )
{
- llwarns << "Can't save. No user directory set." << llendl;
+ llinfos << "Can't save URL history - no user directory set yet." << llendl;
return false;
}
diff --git a/indra/newview/llurlwhitelist.cpp b/indra/newview/llurlwhitelist.cpp
index da69039cf..46bc9276c 100644
--- a/indra/newview/llurlwhitelist.cpp
+++ b/indra/newview/llurlwhitelist.cpp
@@ -121,6 +121,12 @@ bool LLUrlWhiteList::save ()
// build filename for each user
std::string resolvedFilename = gDirUtilp->getExpandedFilename ( LL_PATH_PER_SL_ACCOUNT, mFilename );
+ if (resolvedFilename.empty())
+ {
+ llinfos << "No per-user dir for saving URL whitelist - presumably not logged in yet. Skipping." << llendl;
+ return false;
+ }
+
// open a file for writing
llofstream file ( resolvedFilename );
if ( file.is_open () )
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index 29d201a22..8e62a5753 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -648,10 +648,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo
&& gSavedSettings.getBOOL("UseOcclusion")
&& gGLManager.mHasOcclusionQuery) ? 2 : 0;
- if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred)
+ /*if (LLPipeline::sUseOcclusion && LLPipeline::sRenderDeferred)
{ //force occlusion on for all render types if doing deferred render
LLPipeline::sUseOcclusion = 3;
- }
+ }*/
LLPipeline::sFastAlpha = gSavedSettings.getBOOL("RenderFastAlpha");
LLPipeline::sUseFarClip = gSavedSettings.getBOOL("RenderUseFarClip");
@@ -915,12 +915,29 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
gPipeline.mDeferredScreen.flush();
+ if(LLRenderTarget::sUseFBO)
+ {
+ LLRenderTarget::copyContentsToFramebuffer(gPipeline.mDeferredScreen, 0, 0, gPipeline.mDeferredScreen.getWidth(),
+ gPipeline.mDeferredScreen.getHeight(), 0, 0,
+ gPipeline.mDeferredScreen.getWidth(),
+ gPipeline.mDeferredScreen.getHeight(),
+ GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
}
else if(!tiling)
{
gPipeline.mScreen.flush();
+ if(LLRenderTarget::sUseFBO)
+ {
+ LLRenderTarget::copyContentsToFramebuffer(gPipeline.mScreen, 0, 0, gPipeline.mScreen.getWidth(),
+ gPipeline.mScreen.getHeight(), 0, 0,
+ gPipeline.mScreen.getWidth(),
+ gPipeline.mScreen.getHeight(),
+ GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
}
}
+ //gGL.flush();
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
@@ -936,9 +953,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot, boo
render_ui();
}
- gPipeline.rebuildGroups();
LLSpatialGroup::sNoDelete = FALSE;
+ gPipeline.clearReferences();
+
+ gPipeline.rebuildGroups();
}
LLAppViewer::instance()->pingMainloopTimeout("Display:FrameStats");
@@ -1061,7 +1080,7 @@ void render_hud_attachments()
glh_set_current_modelview(current_mod);
}
-BOOL setup_hud_matrices()
+LLRect get_whole_screen_region()
{
LLRect whole_screen = gViewerWindow->getVirtualWindowRect();
@@ -1078,11 +1097,10 @@ BOOL setup_hud_matrices()
whole_screen.setLeftTopAndSize(tile_x * tile_width, gViewerWindow->getWindowHeight() - (tile_y * tile_height), tile_width, tile_height);
}
-
- return setup_hud_matrices(whole_screen);
+ return whole_screen;
}
-BOOL setup_hud_matrices(const LLRect& screen_region)
+bool get_hud_matrices(const LLRect& screen_region, glh::matrix4f &proj, glh::matrix4f &model)
{
LLVOAvatar* my_avatarp = gAgent.getAvatarObject();
if (my_avatarp && my_avatarp->hasHUDAttachment())
@@ -1091,11 +1109,10 @@ BOOL setup_hud_matrices(const LLRect& screen_region)
LLBBox hud_bbox = my_avatarp->getHUDBBox();
// set up transform to keep HUD objects in front of camera
- glMatrixMode(GL_PROJECTION);
F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f);
- glh::matrix4f proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
+ proj = gl_ortho(-0.5f * LLViewerCamera::getInstance()->getAspect(), 0.5f * LLViewerCamera::getInstance()->getAspect(), -0.5f, 0.5f, 0.f, hud_depth);
proj.element(2,2) = -0.01f;
-
+
F32 aspect_ratio = LLViewerCamera::getInstance()->getAspect();
glh::matrix4f mat;
@@ -1105,22 +1122,16 @@ BOOL setup_hud_matrices(const LLRect& screen_region)
mat.set_translate(
glh::vec3f(clamp_rescale((F32)screen_region.getCenterX(), 0.f, (F32)gViewerWindow->getWindowWidth(), 0.5f * scale_x * aspect_ratio, -0.5f * scale_x * aspect_ratio),
clamp_rescale((F32)screen_region.getCenterY(), 0.f, (F32)gViewerWindow->getWindowHeight(), 0.5f * scale_y, -0.5f * scale_y),
- 0.f));
+ 0.f));
proj *= mat;
-
- glLoadMatrixf(proj.m);
- glh_set_current_projection(proj);
-
- glMatrixMode(GL_MODELVIEW);
- glh::matrix4f model((GLfloat*) OGL_TO_CFR_ROTATION);
+
+ glh::matrix4f tmp_model((GLfloat*) OGL_TO_CFR_ROTATION);
mat.set_scale(glh::vec3f(zoom_level, zoom_level, zoom_level));
mat.set_translate(glh::vec3f(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f));
-
- model *= mat;
- glLoadMatrixf(model.m);
- glh_set_current_modelview(model);
-
+
+ tmp_model *= mat;
+ model = tmp_model;
return TRUE;
}
else
@@ -1129,15 +1140,46 @@ BOOL setup_hud_matrices(const LLRect& screen_region)
}
}
+bool get_hud_matrices(glh::matrix4f &proj, glh::matrix4f &model)
+{
+ LLRect whole_screen = get_whole_screen_region();
+ return get_hud_matrices(whole_screen, proj, model);
+}
+BOOL setup_hud_matrices()
+{
+ LLRect whole_screen = get_whole_screen_region();
+ return setup_hud_matrices(whole_screen);
+}
+
+BOOL setup_hud_matrices(const LLRect& screen_region)
+{
+ glh::matrix4f proj, model;
+ bool result = get_hud_matrices(screen_region, proj, model);
+ if (!result) return result;
+
+ // set up transform to keep HUD objects in front of camera
+ glMatrixMode(GL_PROJECTION);
+ glLoadMatrixf(proj.m);
+ glh_set_current_projection(proj);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(model.m);
+ glh_set_current_modelview(model);
+ return TRUE;
+}
void render_ui(F32 zoom_factor, int subfield, bool tiling)
{
LLGLState::checkStates();
- glPushMatrix();
- glLoadMatrixd(gGLLastModelView);
glh::matrix4f saved_view = glh_get_current_modelview();
- glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
+
+ if (!gSnapshot)
+ {
+ glPushMatrix();
+ glLoadMatrixd(gGLLastModelView);
+ glh_set_current_modelview(glh_copy_matrix(gGLLastModelView));
+ }
{
BOOL to_texture = gPipeline.canUseVertexShaders() &&
@@ -1195,8 +1237,11 @@ void render_ui(F32 zoom_factor, int subfield, bool tiling)
LLVertexBuffer::unbind();
}
- glh_set_current_modelview(saved_view);
- glPopMatrix();
+ if (!gSnapshot)
+ {
+ glh_set_current_modelview(saved_view);
+ glPopMatrix();
+ }
if (gDisplaySwapBuffers)
{
diff --git a/indra/newview/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index fd779746e..e154234b1 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -273,7 +273,6 @@ void LLViewerInventoryItem::setTransactionID(const LLTransactionID& transaction_
// virtual
void LLViewerInventoryItem::packMessage(LLMessageSystem* msg) const
{
- LL_INFOS("Inventory") << " UDP Rez/UpdateObject of UUID " << mUUID << " parent = " << mParentUUID << " type= " << mType << " transaction= "<< mTransactionID << LL_ENDL; // OGPX
msg->addUUIDFast(_PREHASH_ItemID, mUUID);
msg->addUUIDFast(_PREHASH_FolderID, mParentUUID);
mPermissions.packMessage(msg);
@@ -503,11 +502,20 @@ bool LLViewerInventoryCategory::fetchDescendents()
// This comes from LLInventoryFilter from llfolderview.h
U32 sort_order = gSavedSettings.getU32("InventorySortOrder") & 0x1;
- std::string url = gAgent.getCapability("agent/inventory"); // OGPX : was WebFetchInventoryDescendents
- if (url.empty()) //OGPX : agent/inventory Capability not found on agent domain. See if the region has one.
+ // *NOTE: For bug EXT-2879, originally commented out
+ // gAgent.getRegion()->getCapability in order to use the old
+ // message-based system. This has been uncommented now that
+ // AIS folks are aware of the issue and have a fix in process.
+ // see ticket for details.
+
+ std::string url;
+ if (gAgent.getRegion())
{
- llinfos << " agent/inventory not on AD, checking fallback to region " << llendl; //OGPX
- url = gAgent.getRegion()->getCapability("WebFetchInventoryDescendents");
+ url = gAgent.getRegion()->getCapability("FetchInventoryDescendents");
+ }
+ else
+ {
+ llwarns << "agent region is null" << llendl;
}
if (!url.empty()) //Capability found. Build up LLSD and use it.
{
@@ -515,7 +523,7 @@ bool LLViewerInventoryCategory::fetchDescendents()
}
else
{ //Deprecated, but if we don't have a capability, use the old system.
- llinfos << "WebFetchInventoryDescendents or agent/inventory capability not found. Using deprecated UDP message." << llendl;
+ llinfos << "FetchInventoryDescendents capability not found. Using deprecated UDP message." << llendl;
LLMessageSystem* msg = gMessageSystem;
msg->newMessage("FetchInventoryDescendents");
msg->nextBlock("AgentData");
diff --git a/indra/newview/llviewerjointattachment.h b/indra/newview/llviewerjointattachment.h
index 269f7158b..7ca508a3c 100644
--- a/indra/newview/llviewerjointattachment.h
+++ b/indra/newview/llviewerjointattachment.h
@@ -71,7 +71,7 @@ public:
void setPieSlice(S32 pie_slice) { mPieSlice = pie_slice; }
void setVisibleInFirstPerson(BOOL visibility) { mVisibleInFirst = visibility; }
- BOOL getVisibleInFirstPerson() { return mVisibleInFirst; }
+ BOOL getVisibleInFirstPerson() const { return mVisibleInFirst; }
void setGroup(S32 group) { mGroup = group; }
void setOriginalPosition(LLVector3 &position);
void setAttachmentVisibility(BOOL visible);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index a92a46ddb..fda6dee8c 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -281,13 +281,15 @@ void handle_test_load_url(void*);
//
// Evil hackish imported globals
//
-extern BOOL gRenderLightGlows;
-extern BOOL gRenderAvatar;
-extern BOOL gHideSelectedObjects;
+//extern BOOL gHideSelectedObjects;
+//extern BOOL gAllowSelectAvatar;
+extern BOOL gDebugClicks;
+extern BOOL gDebugWindowProc;
+extern BOOL gDebugTextEditorTips;
+//extern BOOL gDebugSelectMgr;
+extern BOOL gDebugAvatarRotation;
extern BOOL gShowOverlayTitle;
extern BOOL gOcclusionCull;
-extern BOOL gAllowSelectAvatar;
-
//
// Globals
//
@@ -1257,11 +1259,6 @@ static void handle_export_menus_to_xml_continued(AIFilePicker* filepicker)
out.close();
}
-extern BOOL gDebugClicks;
-extern BOOL gDebugWindowProc;
-extern BOOL gDebugTextEditorTips;
-extern BOOL gDebugSelectMgr;
-
void init_debug_ui_menu(LLMenuGL* menu)
{
menu->append(new LLMenuItemCheckGL("Rotate Mini-Map", menu_toggle_control, NULL, menu_check_control, (void*)"MiniMapRotate"));
@@ -1287,7 +1284,7 @@ void init_debug_ui_menu(LLMenuGL* menu)
(void*)"DoubleClickTeleport"));
menu->appendSeparator();
// menu->append(new LLMenuItemCallGL( "Print Packets Lost", &print_packets_lost, NULL, NULL, 'L', MASK_SHIFT ));
- menu->append(new LLMenuItemToggleGL("Debug SelectMgr", &gDebugSelectMgr));
+ menu->append(new LLMenuItemCheckGL("Debug SelectMgr", menu_toggle_control, NULL, menu_check_control, (void*)"DebugSelectMgr"));
menu->append(new LLMenuItemToggleGL("Debug Clicks", &gDebugClicks));
menu->append(new LLMenuItemToggleGL("Debug Views", &LLView::sDebugRects));
menu->append(new LLMenuItemCheckGL("Show Name Tooltips", toggle_show_xui_names, NULL, check_show_xui_names, NULL));
@@ -1516,7 +1513,7 @@ void init_debug_rendering_menu(LLMenuGL* menu)
//menu->append(new LLMenuItemCheckGL("Cull Small Objects", toggle_cull_small, NULL, menu_check_control, (void*)"RenderCullBySize"));
menu->appendSeparator();
- menu->append(new LLMenuItemToggleGL("Hide Selected", &gHideSelectedObjects));
+ menu->append(new LLMenuItemCheckGL("Hide Selected", menu_toggle_control, NULL, menu_check_control, (void*)"HideSelectedObjects"));
menu->appendSeparator();
menu->append(new LLMenuItemCheckGL("Tangent Basis", menu_toggle_control, NULL, menu_check_control, (void*)"ShowTangentBasis"));
menu->append(new LLMenuItemCallGL("Selected Texture Info", handle_selected_texture_info, NULL, NULL, 'T', MASK_CONTROL|MASK_SHIFT|MASK_ALT));
@@ -1602,7 +1599,7 @@ void init_debug_avatar_menu(LLMenuGL* menu)
sub_menu->append(new LLMenuItemCallGL("Toggle PG", handle_toggle_pg));
- sub_menu->append(new LLMenuItemToggleGL("Allow Select Avatar", &gAllowSelectAvatar));
+ sub_menu->append(new LLMenuItemCheckGL("Allow Select Avatar", menu_toggle_control, NULL, menu_check_control, (void*)"AllowSelectAvatar"));
sub_menu->createJumpKeys();
menu->appendMenu(sub_menu);
@@ -5337,26 +5334,7 @@ class LLToolsEnableLink : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
- bool new_value = false;
- // check if there are at least 2 objects selected, and that the
- // user can modify at least one of the selected objects.
-
- // in component mode, can't link
- if (!gSavedSettings.getBOOL("EditLinkedParts"))
- {
- if(LLSelectMgr::getInstance()->selectGetAllRootsValid() && LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() >= 2)
- {
- struct f : public LLSelectedObjectFunctor
- {
- virtual bool apply(LLViewerObject* object)
- {
- return object->permModify();
- }
- } func;
- const bool firstonly = true;
- new_value = LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, firstonly);
- }
- }
+ bool new_value = LLSelectMgr::getInstance()->enableLinkObjects();
gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
return true;
}
@@ -5366,45 +5344,7 @@ class LLToolsLink : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
- if(!LLSelectMgr::getInstance()->selectGetAllRootsValid())
- {
- LLNotifications::instance().add("UnableToLinkWhileDownloading");
- return true;
- }
-
- S32 object_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
- if (object_count > MAX_CHILDREN_PER_TASK + 1)
- {
- LLSD args;
- args["COUNT"] = llformat("%d", object_count);
- int max = MAX_CHILDREN_PER_TASK+1;
- args["MAX"] = llformat("%d", max);
- LLNotifications::instance().add("UnableToLinkObjects", args);
- return true;
- }
-
- if(LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() < 2)
- {
- LLNotifications::instance().add("CannotLinkIncompleteSet");
- return true;
- }
- if(!LLSelectMgr::getInstance()->selectGetRootsModify())
- {
- LLNotifications::instance().add("CannotLinkModify");
- return true;
- }
- LLUUID owner_id;
- std::string owner_name;
- if(!LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name))
- {
- // we don't actually care if you're the owner, but novices are
- // the most likely to be stumped by this one, so offer the
- // easiest and most likely solution.
- LLNotifications::instance().add("CannotLinkDifferentOwners");
- return true;
- }
- LLSelectMgr::getInstance()->sendLink();
- return true;
+ return LLSelectMgr::getInstance()->linkObjects();
}
};
@@ -5412,19 +5352,7 @@ class LLToolsEnableUnlink : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
- bool new_value = LLSelectMgr::getInstance()->selectGetAllRootsValid() &&
- LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject() &&
- !LLSelectMgr::getInstance()->getSelection()->getFirstEditableObject()->isAttachment();
-// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.1.3b) | Modified: RLVa-0.2.0g | OK
- if ( (new_value) && (!gRlvHandler.canStand()) )
- {
- // Allow only if the avie isn't sitting on any of the selected objects
- LLObjectSelectionHandle handleSel = LLSelectMgr::getInstance()->getSelection();
- RlvSelectIsSittingOn f(gAgent.getAvatarObject()->getRoot());
- if (handleSel->getFirstRootNode(&f, TRUE) != NULL)
- new_value = false;
- }
-// [/RLVa:KB]
+ bool new_value = LLSelectMgr::getInstance()->enableUnlinkObjects();
gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value);
return true;
}
@@ -5434,18 +5362,7 @@ class LLToolsUnlink : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
-// [RLVa:KB] - Checked: 2010-04-01 (RLVa-1.1.3b) | Modified: RLVa-0.2.0g | OK
- if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canStand()) )
- {
- // Allow only if the avie isn't sitting on any of the selected objects
- LLObjectSelectionHandle hSel = LLSelectMgr::getInstance()->getSelection();
- RlvSelectIsSittingOn f(gAgent.getAvatarObject()->getRoot());
- if ( (hSel.notNull()) && (hSel->getFirstRootNode(&f, TRUE)) )
- return true;
- }
-// [/RLVa:KB]
-
- LLSelectMgr::getInstance()->sendDelink();
+ LLSelectMgr::getInstance()->unlinkObjects();
return true;
}
};
@@ -8298,9 +8215,8 @@ class LLToolsShowSelectionHighlights : public view_listener_t
{
bool handleEvent(LLPointer event, const LLSD& userdata)
{
- LLSelectMgr::sRenderSelectionHighlights = !LLSelectMgr::sRenderSelectionHighlights;
-
- gSavedSettings.setBOOL("RenderHighlightSelections", LLSelectMgr::sRenderSelectionHighlights);
+ LLControlVariable *ctrl = gSavedSettings.getControl("RenderHighlightSelections");
+ ctrl->setValue(!ctrl->getValue().asBoolean());
return true;
}
};
@@ -8961,7 +8877,7 @@ void force_error_bad_memory_access(void *)
void force_error_infinite_loop(void *)
{
- LLAppViewer::instance()->forceErrorInifiniteLoop();
+ LLAppViewer::instance()->forceErrorInfiniteLoop();
}
void force_error_software_exception(void *)
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index e341631a8..753f1ab42 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -3698,19 +3698,6 @@ void process_teleport_finish(LLMessageSystem* msg, void**)
effectp->setColor(LLColor4U(gAgent.getEffectColor()));
LLHUDManager::getInstance()->sendEffects();
- // OGPX : when using agent domain, we get tp finish with ip of 0.0.0.0 and port 0.
- // try bailing out early if tp state is PLACE_AVATAR (so legacy should still execute rest of this path)
- // not really wild about this, but it's a way to test if we can get TP working w/o receiving TP finish
- // TODO: can be removed *when* agent domain no longer sends tp finish
- //
- // OGPX TODO: see if we can nuke TELEPORT_PLACE_AVATAR state once TeleportFinish is
- // completely removed from all SL and OS region code
-
- if (gAgent.getTeleportState() == LLAgent::TELEPORT_PLACE_AVATAR )
- {
- llinfos << "Got teleport location message when doing agentd TP" << llendl;
- return;
- }
U32 location_id;
U32 sim_ip;
U16 sim_port;
@@ -3883,10 +3870,8 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
gCacheName->setUpstream(msg->getSender());
gViewerThrottle.sendToSim();
gViewerWindow->sendShapeToSim();
- // if this is an AgentMovementComplete message that happened as the result of a teleport,
- // then we need to do things like chat the URL and reset the camera.
- bool is_teleport = (gAgent.getTeleportState() & (LLAgent::TELEPORT_MOVING | LLAgent::TELEPORT_PLACE_AVATAR)); //OGPX
- llinfos << " is_teleport =" << is_teleport << llendl;
+
+ bool is_teleport = gAgent.getTeleportState() == LLAgent::TELEPORT_MOVING;
if( is_teleport )
{
@@ -3922,11 +3907,6 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
avatarp->clearChat();
avatarp->slamPosition();
}
- // OGPX TODO: remove all usage of TELEPORT_PLACE_AVATAR state once Teleport UDP sequence finalized
- if ( gAgent.getTeleportState() == LLAgent::TELEPORT_PLACE_AVATAR ) // unset TP state, agent domain is done. OGPX
- {
- gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
- }
// add teleport destination to the list of visited places
gFloaterTeleportHistory->addPendingEntry(regionp->getName(), (S16)agent_pos.mV[VX], (S16)agent_pos.mV[VY], (S16)agent_pos.mV[VZ]);
@@ -3935,6 +3915,17 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
{
// This is likely just the initial logging in phase.
gAgent.setTeleportState( LLAgent::TELEPORT_NONE );
+
+ if(LLStartUp::getStartupState() < STATE_STARTED)
+ { // This is initial log-in, not a region crossing:
+ // Set the camera looking ahead of the AV so send_agent_update() below
+ // will report the correct location to the server.
+ LLVector3 look_at_point = look_at;
+ look_at_point = agent_pos + look_at_point.rotVec(gAgent.getQuat());
+
+ static LLVector3 up_direction(0.0f, 0.0f, 1.0f);
+ LLViewerCamera::getInstance()->lookAt(agent_pos, look_at_point, up_direction);
+ }
}
if ( LLTracker::isTracking(NULL) )
@@ -4299,7 +4290,6 @@ void process_object_update(LLMessageSystem *mesgsys, void **user_data)
// Update the object...
gObjectList.processObjectUpdate(mesgsys, user_data, OUT_FULL);
- stop_glerror();
}
void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data)
@@ -4317,7 +4307,6 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data
// Update the object...
gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_FULL_COMPRESSED);
- stop_glerror();
}
void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
@@ -4335,7 +4324,6 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
// Update the object...
gObjectList.processCachedObjectUpdate(mesgsys, user_data, OUT_FULL_CACHED);
- stop_glerror();
}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index 74a84cd00..3a68d6133 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -4576,7 +4576,11 @@ LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 para
new_block = new LLSculptParams();
break;
}
-
+ case LLNetworkData::PARAMS_LIGHT_IMAGE:
+ {
+ new_block = new LLLightImageParams();
+ break;
+ }
default:
{
llinfos << "Unknown param type." << llendl;
diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp
index 6fe2e4b18..94e519604 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -957,7 +957,8 @@ void LLViewerObjectList::killAllObjects()
objectp = *iter;
killObject(objectp);
- llassert(objectp->isDead());
+ // Object must be dead, or it's the LLVOAvatarSelf which never dies.
+ llassert((objectp == gAgent.getAvatarObject()) || objectp->isDead());
}
cleanDeadObjects(FALSE);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index b3a123eed..3ab4390d7 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1452,9 +1452,13 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("DispatchRegionInfo");
capabilityNames.append("EstateChangeInfo");
capabilityNames.append("EventQueueGet");
- capabilityNames.append("FetchInventory");
- capabilityNames.append("FetchLib");
- capabilityNames.append("FetchLibDescendents");
+ if (false)//gSavedSettings.getBOOL("UseHTTPInventory")) //Caps suffixed with 2 by LL. Don't update until rest of fetch system is updated first.
+ {
+ capabilityNames.append("FetchLib");
+ capabilityNames.append("FetchLibDescendents");
+ capabilityNames.append("FetchInventory");
+ capabilityNames.append("FetchInventoryDescendents");
+ }
capabilityNames.append("GetTexture");
capabilityNames.append("GroupProposalBallot");
capabilityNames.append("GetDisplayNames");
@@ -1491,10 +1495,6 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("UploadBakedTexture");
capabilityNames.append("ViewerStartAuction");
capabilityNames.append("ViewerStats");
- capabilityNames.append("WebFetchInventoryDescendents"); // OGPX : since this is asking the region
- // leave the old naming in place, on agent domain
- // it is now called agent/inventory. Both
- // caps have the same LLSD returned.
// Please add new capabilities alphabetically to reduce
// merge conflicts.
diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp
index 50a57d827..0ab17f6d7 100644
--- a/indra/newview/llviewershadermgr.cpp
+++ b/indra/newview/llviewershadermgr.cpp
@@ -130,6 +130,7 @@ LLGLSLShader gDeferredGIProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredGIFinalProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredPostGIProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gDeferredPostProgram(LLViewerShaderMgr::SHADER_DEFERRED);
+LLGLSLShader gDeferredPostNoDoFProgram(LLViewerShaderMgr::SHADER_DEFERRED);
LLGLSLShader gLuminanceGatherProgram(LLViewerShaderMgr::SHADER_DEFERRED);
//current avatar shader parameter pointer
@@ -878,7 +879,7 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
{
gDeferredMultiLightProgram.mName = "Deferred MultiLight Shader";
gDeferredMultiLightProgram.mShaderFiles.clear();
- gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/pointLightV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightV.glsl", GL_VERTEX_SHADER_ARB));
gDeferredMultiLightProgram.mShaderFiles.push_back(make_pair("deferred/multiPointLightF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredMultiLightProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredMultiLightProgram.createShader(NULL, NULL);
@@ -980,10 +981,21 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
if (success)
{
+ std::string fragment;
+
+ if (mVertexShaderLevel[SHADER_DEFERRED] < 2 && !gSavedSettings.getBOOL("RenderDeferredSSAO"))
+ {
+ fragment = "deferred/softenLightNoSSAOF.glsl";
+ }
+ else
+ {
+ fragment = "deferred/softenLightF.glsl";
+ }
+
gDeferredSoftenProgram.mName = "Deferred Soften Shader";
gDeferredSoftenProgram.mShaderFiles.clear();
gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredSoftenProgram.mShaderFiles.push_back(make_pair("deferred/softenLightF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredSoftenProgram.mShaderFiles.push_back(make_pair(fragment, GL_FRAGMENT_SHADER_ARB));
gDeferredSoftenProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredSoftenProgram.createShader(NULL, NULL);
}
@@ -1041,11 +1053,31 @@ BOOL LLViewerShaderMgr::loadShadersDeferred()
gDeferredAvatarAlphaProgram.mFeatures.hasLighting = true;
gDeferredAvatarAlphaProgram.mShaderFiles.clear();
gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaV.glsl", GL_VERTEX_SHADER_ARB));
- gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/avatarAlphaF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredAvatarAlphaProgram.mShaderFiles.push_back(make_pair("deferred/alphaF.glsl", GL_FRAGMENT_SHADER_ARB));
gDeferredAvatarAlphaProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
success = gDeferredAvatarAlphaProgram.createShader(&mAvatarAttribs, &mAvatarUniforms);
}
+ if (success)
+ {
+ gDeferredPostProgram.mName = "Deferred Post Shader";
+ gDeferredPostProgram.mShaderFiles.clear();
+ gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredPostProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredPostProgram.createShader(NULL, NULL);
+ }
+
+ if (success)
+ {
+ gDeferredPostNoDoFProgram.mName = "Deferred Post Shader";
+ gDeferredPostNoDoFProgram.mShaderFiles.clear();
+ gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredV.glsl", GL_VERTEX_SHADER_ARB));
+ gDeferredPostNoDoFProgram.mShaderFiles.push_back(make_pair("deferred/postDeferredNoDoFF.glsl", GL_FRAGMENT_SHADER_ARB));
+ gDeferredPostNoDoFProgram.mShaderLevel = mVertexShaderLevel[SHADER_DEFERRED];
+ success = gDeferredPostNoDoFProgram.createShader(NULL, NULL);
+ }
+
if (mVertexShaderLevel[SHADER_DEFERRED] > 1)
{
if (success)
diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h
index 1c4e912a4..f952b1a6f 100644
--- a/indra/newview/llviewershadermgr.h
+++ b/indra/newview/llviewershadermgr.h
@@ -366,6 +366,7 @@ extern LLGLSLShader gDeferredSoftenProgram;
extern LLGLSLShader gDeferredShadowProgram;
extern LLGLSLShader gDeferredPostGIProgram;
extern LLGLSLShader gDeferredPostProgram;
+extern LLGLSLShader gDeferredPostNoDoFProgram;
extern LLGLSLShader gDeferredAvatarShadowProgram;
extern LLGLSLShader gDeferredAlphaProgram;
extern LLGLSLShader gDeferredFullbrightProgram;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index cf6f4bde6..6b633b523 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -4344,6 +4344,21 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
image_width *= internal_scale;
#endif //shy_mod
+ //Hack until hud ui works in high-res shots again (nameplates and hud attachments are buggered).
+ if ((image_width > window_width || image_height > window_height))
+ {
+ if(LLPipeline::sShowHUDAttachments)
+ {
+ hide_hud=true;
+ LLPipeline::sShowHUDAttachments = FALSE;
+ }
+ if(show_ui)
+ {
+ show_ui=false;
+ LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
+ }
+ }
+
if(!keep_window_aspect) //image cropping
{
F32 ratio = llmin( (F32)window_width / image_width , (F32)window_height / image_height) ;
@@ -4535,7 +4550,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei
gDepthDirty = TRUE;
// POST SNAPSHOT
- if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ if (prev_draw_ui != gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
{
LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
}
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index bddefa52b..a7c797f51 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -72,7 +72,7 @@ const F32 FORCE_SIMPLE_RENDER_AREA = 512.f;
const F32 FORCE_CULL_AREA = 8.f;
BOOL gAnimateTextures = TRUE;
-extern BOOL gHideSelectedObjects;
+//extern BOOL gHideSelectedObjects;
F32 LLVOVolume::sLODFactor = 1.f;
F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop
@@ -2204,7 +2204,7 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, const LLVector3& e
if (!mbCanSelect ||
// (gHideSelectedObjects && isSelected()) ||
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.1.3b
- ( (gHideSelectedObjects && isSelected()) &&
+ ( (LLSelectMgr::getInstance()->mHideSelectedObjects && isSelected()) &&
((!rlv_handler_t::isEnabled()) || (!isHUDAttachment()) || (!gRlvAttachmentLocks.isLockedAttachment(getRootEdit()))) ) ||
// [/RLVa:KB]
mDrawable->isDead() ||
@@ -2351,7 +2351,7 @@ void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep,
// if (facep->getViewerObject()->isSelected() && gHideSelectedObjects)
// [RLVa:KB] - Checked: 2010-09-28 (RLVa-1.1.3b) | Modified: RLVa-1.2.1f
const LLViewerObject* pObj = facep->getViewerObject();
- if ( (pObj->isSelected() && gHideSelectedObjects) &&
+ if ( (pObj->isSelected() && LLSelectMgr::getInstance()->mHideSelectedObjects) &&
((!rlv_handler_t::isEnabled()) || (!pObj->isHUDAttachment()) || (!gRlvAttachmentLocks.isLockedAttachment(pObj->getRootEdit()))) )
// [/RLVa:KB]
{
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index facce5332..cae557a60 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -106,6 +106,26 @@
#include "rlvhandler.h"
// [/RLVa:KB]
+void check_stack_depth(S32 stack_depth)
+{
+ if (gDebugGL || gDebugSession)
+ {
+ GLint depth;
+ glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
+ if (depth != stack_depth)
+ {
+ if (gDebugSession)
+ {
+ ll_fail("GL matrix stack corrupted.");
+ }
+ else
+ {
+ llerrs << "GL matrix stack corrupted!" << llendl;
+ }
+ }
+ }
+}
+
#ifdef _DEBUG
// Debug indices is disabled for now for debug performance - djs 4/24/02
//#define DEBUG_INDICES
@@ -126,7 +146,7 @@ const S32 MAX_OCCLUDER_COUNT = 2;
extern S32 gBoxFrame;
extern BOOL gRenderLightGlows;
-extern BOOL gHideSelectedObjects;
+//extern BOOL gHideSelectedObjects;
extern BOOL gDisplaySwapBuffers;
extern BOOL gDebugGL;
@@ -537,7 +557,13 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
addDeferredAttachments(mDeferredScreen);
mScreen.allocate(resX, resY, format, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+
+#if LL_DARWIN
+ // As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO
+ mEdgeMap.allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+#else
mEdgeMap.allocate(resX, resY, GL_ALPHA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE, FALSE);
+#endif
if (shadow_detail > 0 || ssao)
{ //only need mDeferredLight[0] for shadows OR ssao
@@ -548,8 +574,8 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
mDeferredLight[0].release();
}
- if (ssao)
- { //only need mDeferredLight[1] for ssao
+ if (ssao || gi)
+ { //only need mDeferredLight[1] for ssao... and GI
mDeferredLight[1].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
}
else
@@ -562,7 +588,12 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
mDeferredLight[2].allocate(resX, resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
for (U32 i = 0; i < 2; i++)
{
+#if LL_DARWIN
+ // As of OS X 10.6.7, Apple doesn't support multiple color formats in a single FBO
+ mGIMapPost[i].allocate(resX,resY, GL_RGBA, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+#else
mGIMapPost[i].allocate(resX,resY, GL_RGB, FALSE, FALSE, LLTexUnit::TT_RECT_TEXTURE);
+#endif
}
}
else
@@ -577,9 +608,13 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
F32 scale = gSavedSettings.getF32("RenderShadowResolutionScale");
+#if LL_DARWIN
+ U32 shadow_fmt = 0;
+#else
//HACK: make alpha masking work on ATI depth shadows (work around for ATI driver bug)
//TO-DO: Test if this is actually needed.
U32 shadow_fmt = gGLManager.mIsATI ? GL_ALPHA : 0;
+#endif
if (shadow_detail > 0)
{ //allocate 4 sun shadow maps
@@ -689,7 +724,6 @@ void LLPipeline::allocateScreenBuffer(U32 resX, U32 resY)
void LLPipeline::updateRenderDeferred()
{
sRenderDeferred = (gSavedSettings.getBOOL("RenderDeferred") &&
- LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
LLRenderTarget::sUseFBO &&
LLFeatureManager::getInstance()->isFeatureAvailable("RenderDeferred") &&
gSavedSettings.getBOOL("VertexShaderEnable") &&
@@ -1533,6 +1567,184 @@ void LLPipeline::grabReferences(LLCullResult& result)
sCull = &result;
}
+void LLPipeline::clearReferences()
+{
+ sCull = NULL;
+}
+
+void check_references(LLSpatialGroup* group, LLDrawable* drawable)
+{
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+ {
+ if (drawable == *i)
+ {
+ llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl;
+ }
+ }
+}
+
+void check_references(LLDrawable* drawable, LLFace* face)
+{
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+ {
+ if (drawable->getFace(i) == face)
+ {
+ llerrs << "LLFace deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+}
+
+void check_references(LLSpatialGroup* group, LLFace* face)
+{
+ for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i)
+ {
+ LLDrawable* drawable = *i;
+ check_references(drawable, face);
+ }
+}
+
+void LLPipeline::checkReferences(LLFace* face)
+{
+#if 0
+ if (sCull)
+ {
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, face);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, face);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, face);
+ }
+
+ for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter)
+ {
+ LLDrawable* drawable = *iter;
+ check_references(drawable, face);
+ }
+ }
+#endif
+}
+
+void LLPipeline::checkReferences(LLDrawable* drawable)
+{
+#if 0
+ if (sCull)
+ {
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, drawable);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, drawable);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, drawable);
+ }
+
+ for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList(); iter != sCull->endVisibleList(); ++iter)
+ {
+ if (drawable == *iter)
+ {
+ llerrs << "LLDrawable deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+ }
+#endif
+}
+
+void check_references(LLSpatialGroup* group, LLDrawInfo* draw_info)
+{
+ for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i)
+ {
+ LLSpatialGroup::drawmap_elem_t& draw_vec = i->second;
+ for (LLSpatialGroup::drawmap_elem_t::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j)
+ {
+ LLDrawInfo* params = *j;
+ if (params == draw_info)
+ {
+ llerrs << "LLDrawInfo deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+ }
+}
+
+
+void LLPipeline::checkReferences(LLDrawInfo* draw_info)
+{
+#if 0
+ if (sCull)
+ {
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, draw_info);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, draw_info);
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ {
+ LLSpatialGroup* group = *iter;
+ check_references(group, draw_info);
+ }
+ }
+#endif
+}
+
+void LLPipeline::checkReferences(LLSpatialGroup* group)
+{
+#if 0
+ if (sCull)
+ {
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
+ {
+ if (group == *iter)
+ {
+ llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginAlphaGroups(); iter != sCull->endAlphaGroups(); ++iter)
+ {
+ if (group == *iter)
+ {
+ llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+
+ for (LLCullResult::sg_list_t::iterator iter = sCull->beginDrawableGroups(); iter != sCull->endDrawableGroups(); ++iter)
+ {
+ if (group == *iter)
+ {
+ llerrs << "LLSpatialGroup deleted while actively referenced by LLPipeline." << llendl;
+ }
+ }
+ }
+#endif
+}
+
+
BOOL LLPipeline::visibleObjectsInFrustum(LLCamera& camera)
{
for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin();
@@ -2234,10 +2446,10 @@ void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority)
{
llassert_always(!mGroupQ2Locked);
//llerrs << "Non-priority updates not yet supported!" << llendl;
- if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end())
+ /*if (std::find(mGroupQ2.begin(), mGroupQ2.end(), group) != mGroupQ2.end())
{
llerrs << "WTF?" << llendl;
- }
+ }*/
mGroupQ2.push_back(group);
group->setState(LLSpatialGroup::IN_BUILD_Q2);
@@ -2315,6 +2527,42 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
}
}
}
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ {
+ LLSpatialGroup* last_group = NULL;
+ for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
+ {
+ LLCullResult::bridge_list_t::iterator cur_iter = i;
+ LLSpatialBridge* bridge = *cur_iter;
+ LLSpatialGroup* group = bridge->getSpatialGroup();
+
+ if (last_group == NULL)
+ {
+ last_group = group;
+ }
+
+ if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
+ {
+ stateSort(bridge, camera);
+ }
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
+ last_group != group && last_group->changeLOD())
+ {
+ last_group->mLastUpdateDistance = last_group->mDistance;
+ }
+
+ last_group = group;
+ }
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD &&
+ last_group && last_group->changeLOD())
+ {
+ last_group->mLastUpdateDistance = last_group->mDistance;
+ }
+ }
+
for (LLCullResult::sg_list_t::iterator iter = sCull->beginVisibleGroups(); iter != sCull->endVisibleGroups(); ++iter)
{
LLSpatialGroup* group = *iter;
@@ -2330,19 +2578,6 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result)
}
}
- if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
- {
- for (LLCullResult::bridge_list_t::iterator i = sCull->beginVisibleBridge(); i != sCull->endVisibleBridge(); ++i)
- {
- LLCullResult::bridge_list_t::iterator cur_iter = i;
- LLSpatialBridge* bridge = *cur_iter;
- LLSpatialGroup* group = bridge->getSpatialGroup();
- if (!bridge->isDead() && group && !group->isOcclusionState(LLSpatialGroup::OCCLUDED))
- {
- stateSort(bridge, camera);
- }
- }
- }
{
LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE);
for (LLCullResult::drawable_list_t::iterator iter = sCull->beginVisibleList();
@@ -2374,6 +2609,11 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
LLDrawable* drawablep = *i;
stateSort(drawablep, camera);
}
+
+ if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
+ { //avoid redundant stateSort calls
+ group->mLastUpdateDistance = group->mDistance;
+ }
}
}
@@ -2381,7 +2621,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera)
void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
- if (!sShadowRender && !sSkipUpdate && bridge->getSpatialGroup()->changeLOD())
+ if (/*!sShadowRender && */!sSkipUpdate && bridge->getSpatialGroup()->changeLOD())
{
bool force_update = false;
bridge->updateDistance(camera, force_update);
@@ -2399,7 +2639,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
return;
}
- if (gHideSelectedObjects)
+ if (LLSelectMgr::getInstance()->mHideSelectedObjects)
{
// if (drawablep->getVObj().notNull() &&
// drawablep->getVObj()->isSelected())
@@ -2445,10 +2685,11 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD)
{
- LLSpatialGroup* group = drawablep->getSpatialGroup();
+ /*LLSpatialGroup* group = drawablep->getSpatialGroup();
if (!group || group->changeLOD())
{
- if (drawablep->isVisible() && !sSkipUpdate)
+ if (drawablep->isVisible() && !sSkipUpdate)*/
+ if(!sSkipUpdate)
{
if (!drawablep->isActive())
{
@@ -2461,7 +2702,7 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera)
drawablep->updateDistance(camera, force_update); // calls vobj->updateLOD() which calls LLVOAvatar::updateVisibility()
}
}
- }
+ //}
}
if(!drawablep->getVOVolume())
@@ -2842,9 +3083,9 @@ void LLPipeline::postSort(LLCamera& camera)
else if (sourcep->isMuted())
color = LLColor4(0.f, 1.f, 1.f, 0.5f); // Cyan: Muted sound source.
gObjectList.addDebugBeacon(pos, "", color, LLColor4(1.f, 1.f, 1.f, 0.5f), width);
+ //
+ //gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), debug_beacon_line_width);
}
- //
- //gObjectList.addDebugBeacon(pos, "", LLColor4(1.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f), debug_beacon_line_width);
}
// now deal with highlights for all those seeable sound sources
forAllVisibleDrawables(renderSoundHighlights);
@@ -2995,6 +3236,8 @@ void LLPipeline::renderHighlights()
}
}
+//debug use
+U32 LLPipeline::sCurRenderPoolType = 0 ;
void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
{
LLMemType mt(LLMemType::MTYPE_PIPELINE);
@@ -3015,6 +3258,13 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
}
}
+ S32 stack_depth = 0;
+
+ if (gDebugGL)
+ {
+ glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &stack_depth);
+ }
+
///////////////////////////////////////////
//
// Sync and verify GL state
@@ -3121,6 +3371,9 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
cur_type = poolp->getType();
+ //debug use
+ sCurRenderPoolType = cur_type ;
+
if (occlude && cur_type >= LLDrawPool::POOL_GRASS)
{
occlude = FALSE;
@@ -3153,14 +3406,9 @@ void LLPipeline::renderGeom(LLCamera& camera, BOOL forceVBOUpdate)
}
poolp->endRenderPass(i);
LLVertexBuffer::unbind();
- if (gDebugGL || gDebugPipeline)
+ if (gDebugGL)
{
- GLint depth;
- glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth);
- if (depth > 3)
- {
- llerrs << "GL matrix stack corrupted!" << llendl;
- }
+ check_stack_depth(stack_depth);
std::string msg = llformat("%s pass %d", gPoolNames[cur_type].c_str(), i);
LLGLState::checkStates(msg);
LLGLState::checkTextureChannels(msg);
@@ -3604,6 +3852,8 @@ void LLPipeline::renderDebug()
if (hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SHADOW_FRUSTA))
{
+ LLVertexBuffer::unbind();
+
LLGLEnable blend(GL_BLEND);
LLGLDepthTest depth(TRUE, FALSE);
LLGLDisable cull(GL_CULL_FACE);
@@ -3909,7 +4159,7 @@ void LLPipeline::renderForSelect(std::set& objects, BOOL render
LLDrawable* drawable = vobj->mDrawable;
if (vobj->isDead() ||
vobj->isHUDAttachment() ||
- (gHideSelectedObjects && vobj->isSelected()) ||
+ (LLSelectMgr::getInstance()->mHideSelectedObjects && vobj->isSelected()) ||
drawable->isDead() ||
!hasRenderType(drawable->getRenderType()))
{
@@ -4847,6 +5097,7 @@ void LLPipeline::enableLightsFullbright(const LLColor4& color)
void LLPipeline::disableLights()
{
enableLights(0); // no lighting (full bright)
+ glColor4f(1.f, 1.f, 1.f, 1.f);
}
//============================================================================
@@ -5610,6 +5861,10 @@ void validate_framebuffer_object()
case GL_FRAMEBUFFER_COMPLETE_EXT:
//framebuffer OK, no error.
break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
+ // frame buffer not OK: probably means unsupported depth buffer format
+ llerrs << "Framebuffer Incomplete Missing Attachment." << llendl;
+ break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
// frame buffer not OK: probably means unsupported depth buffer format
llerrs << "Framebuffer Incomplete Dimensions." << llendl;
@@ -5866,16 +6121,152 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b
LLVertexBuffer::unbind();
- if (LLPipeline::sRenderDeferred && LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+ if (LLPipeline::sRenderDeferred && !LLViewerCamera::getInstance()->cameraUnderWater())
{
- LLGLDisable blend(GL_BLEND);
- bindDeferredShader(gDeferredGIFinalProgram);
+ bool dof_enabled = true;
- S32 channel = gDeferredGIFinalProgram.enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
+ LLGLSLShader* shader = &gDeferredPostProgram;
+ static const LLCachedControl render_dof("RenderDepthOfField",false);
+ if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_DEFERRED) > 2)
+ {
+ shader = &gDeferredGIFinalProgram;
+ dof_enabled = false;
+ }
+ else if (LLToolMgr::getInstance()->inBuildMode() || !render_dof)
+ { //squish focal length when in build mode (or if DoF is disabled) so DoF doesn't make editing objects difficult
+ shader = &gDeferredPostNoDoFProgram;
+ dof_enabled = false;
+ }
+
+
+ LLGLDisable blend(GL_BLEND);
+ bindDeferredShader(*shader);
+
+ if (dof_enabled)
+ {
+ //depth of field focal plane calculations
+
+ static F32 current_distance = 16.f;
+ static F32 start_distance = 16.f;
+ static F32 transition_time = 1.f;
+
+ LLVector3 focus_point;
+
+ /*LLViewerObject* obj = LLViewerMediaFocus::getInstance()->getFocusedObject();
+ if (obj && obj->mDrawable && obj->isSelected())
+ { //focus on selected media object
+ S32 face_idx = LLViewerMediaFocus::getInstance()->getFocusedFace();
+ if (obj && obj->mDrawable)
+ {
+ LLFace* face = obj->mDrawable->getFace(face_idx);
+ if (face)
+ {
+ focus_point = face->getPositionAgent();
+ }
+ }
+ }*/
+
+ if (focus_point.isExactlyZero())
+ {
+ if (LLViewerJoystick::getInstance()->getOverrideCamera())
+ { //focus on point under cursor
+ focus_point = gDebugRaycastIntersection;
+ }
+ else if (gAgent.cameraMouselook())
+ { //focus on point under mouselook crosshairs
+ gViewerWindow->cursorIntersect(-1, -1, 512.f, NULL, -1, FALSE,
+ NULL,
+ &focus_point);
+ }
+ else
+ {
+ LLViewerObject* obj = gAgent.getFocusObject();
+ if (obj)
+ { //focus on alt-zoom target
+ focus_point = LLVector3(gAgent.getFocusGlobal()-gAgent.getRegion()->getOriginGlobal());
+ }
+ else
+ { //focus on your avatar
+ focus_point = gAgent.getPositionAgent();
+ }
+ }
+ }
+
+ LLVector3 eye = LLViewerCamera::getInstance()->getOrigin();
+ F32 target_distance = 16.f;
+ if (!focus_point.isExactlyZero())
+ {
+ target_distance = LLViewerCamera::getInstance()->getAtAxis() * (focus_point-eye);
+ }
+
+ if (transition_time >= 1.f &&
+ fabsf(current_distance-target_distance)/current_distance > 0.01f)
+ { //large shift happened, interpolate smoothly to new target distance
+ transition_time = 0.f;
+ start_distance = current_distance;
+ }
+ else if (transition_time < 1.f)
+ { //currently in a transition, continue interpolating
+ static const LLCachedControl cam_focus_transition_time("CameraFocusTransitionTime",.5f);
+ transition_time += 1.f/cam_focus_transition_time*gFrameIntervalSeconds;
+ transition_time = llmin(transition_time, 1.f);
+
+ F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f;
+ current_distance = start_distance + (target_distance-start_distance)*t;
+ }
+ else
+ { //small or no change, just snap to target distance
+ current_distance = target_distance;
+ }
+
+ //convert to mm
+ F32 subject_distance = current_distance*1000.f;
+ static const LLCachedControl fnumber("CameraFNumber",9.f);
+ static const LLCachedControl default_focal_length("CameraFocalLength",50.f);
+ static const LLCachedControl cam_field_of_view("CameraFieldOfView",60.f);
+
+ F32 fov = LLViewerCamera::getInstance()->getView();
+
+ const F32 default_fov = cam_field_of_view * F_PI/180.f;
+ //const F32 default_aspect_ratio = gSavedSettings.getF32("CameraAspectRatio");
+
+ //F32 aspect_ratio = (F32) mScreen.getWidth()/(F32)mScreen.getHeight();
+
+ F32 dv = 2.f*default_focal_length * tanf(default_fov/2.f);
+ //F32 dh = 2.f*default_focal_length * tanf(default_fov*default_aspect_ratio/2.f);
+
+ F32 focal_length = dv/(2*tanf(fov/2.f));
+
+ //F32 tan_pixel_angle = tanf(LLDrawable::sCurPixelAngle);
+
+ // from wikipedia -- c = |s2-s1|/s2 * f^2/(N(S1-f))
+ // where N = fnumber
+ // s2 = dot distance
+ // s1 = subject distance
+ // f = focal length
+ //
+
+ F32 blur_constant = focal_length*focal_length/(fnumber*(subject_distance-focal_length));
+ blur_constant /= 1000.f; //convert to meters for shader
+ F32 magnification = focal_length/(subject_distance-focal_length);
+
+ shader->uniform1f("focal_distance", -subject_distance/1000.f);
+ shader->uniform1f("blur_constant", blur_constant);
+ shader->uniform1f("tan_pixel_angle", tanf(1.f/LLDrawable::sCurPixelAngle));
+ shader->uniform1f("magnification", magnification);
+ }
+
+ S32 channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DIFFUSE, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
mScreen.bindTexture(0, channel);
+ gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
}
+ //channel = shader->enableTexture(LLViewerShaderMgr::DEFERRED_DEPTH, LLTexUnit::TT_RECT_TEXTURE);
+ //if (channel > -1)
+ //{
+ //gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
+ //}
gGL.begin(LLRender::TRIANGLE_STRIP);
gGL.texCoord2f(tc1.mV[0], tc1.mV[1]);
@@ -5889,7 +6280,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b
gGL.end();
- unbindDeferredShader(gDeferredGIFinalProgram);
+ unbindDeferredShader(*shader);
}
else
{
@@ -5952,12 +6343,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+ }
- if (LLRenderTarget::sUseFBO)
- { //copy depth buffer from mScreen to framebuffer
- LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(),
- 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
- }
+ if (LLRenderTarget::sUseFBO)
+ { //copy depth buffer from mScreen to framebuffer
+ LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(),
+ 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
}
@@ -5976,7 +6367,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield, b
void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRenderTarget* gi_source, LLRenderTarget* last_gi_post, U32 noise_map)
{
- //LLFastTimer t(FTM_BIND_DEFERRED);
+ LLFastTimer t(LLFastTimer::FTM_BIND_DEFERRED);
if (noise_map == 0xFFFFFFFF)
{
@@ -6083,6 +6474,14 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen
gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
}
+ channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
+ if (channel > -1)
+ {
+ has_gi = TRUE;
+ gi_source->bindTexture(0, channel);
+ gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
+ }
+
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_DEPTH);
if (channel > -1)
{
@@ -6188,13 +6587,6 @@ void LLPipeline::bindDeferredShader(LLGLSLShader& shader, U32 light_index, LLRen
mGlow[1].bindTexture(0, channel);
}
- channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_GI_LIGHT, LLTexUnit::TT_RECT_TEXTURE);
- if (channel > -1)
- {
- gi_source->bindTexture(0, channel);
- gGL.getTexUnit(channel)->setTextureFilteringOption(LLTexUnit::TFO_POINT);
- }
-
channel = shader.enableTexture(LLViewerShaderMgr::DEFERRED_EDGE, LLTexUnit::TT_RECT_TEXTURE);
if (channel > -1)
{
@@ -6389,6 +6781,7 @@ void LLPipeline::renderDeferredLighting()
}
{
+ LLFastTimer ftm(LLFastTimer::FTM_RENDER_DEFERRED);
LLViewerCamera* camera = LLViewerCamera::getInstance();
{
@@ -6449,7 +6842,7 @@ void LLPipeline::renderDeferredLighting()
{
mDeferredLight[0].bindTarget();
{ //paint shadow/SSAO light map (direct lighting lightmap)
- //LLFastTimer ftm(FTM_SUN_SHADOW);
+ LLFastTimer ftm(LLFastTimer::FTM_SUN_SHADOW);
bindDeferredShader(gDeferredSunProgram, 0);
glClearColor(1,1,1,1);
@@ -6497,7 +6890,7 @@ void LLPipeline::renderDeferredLighting()
if (render_deferred_blur_light &&
render_shadow_gi)
{
- //LLFastTimer ftm(FTM_EDGE_DETECTION);
+ LLFastTimer ftm(LLFastTimer::FTM_EDGE_DETECTION);
//generate edge map
LLGLDisable blend(GL_BLEND);
LLGLDisable test(GL_ALPHA_TEST);
@@ -6540,7 +6933,7 @@ void LLPipeline::renderDeferredLighting()
}
{ //paint noisy GI map (bounce lighting lightmap)
- //LLFastTimer ftm(FTM_GI_TRACE);
+ LLFastTimer ftm(LLFastTimer::FTM_GI_TRACE);
LLGLDisable blend(GL_BLEND);
LLGLDepthTest depth(GL_FALSE);
LLGLDisable test(GL_ALPHA_TEST);
@@ -6565,7 +6958,7 @@ void LLPipeline::renderDeferredLighting()
static const LLCachedControl render_gui_blur_brightness("RenderGIBlurBrightness",1.025f);
for (U32 i = 0; i < pass_count; ++i)
{ //gather/soften indirect lighting map
- //LLFastTimer ftm(FTM_GI_GATHER);
+ LLFastTimer ftm(LLFastTimer::FTM_GI_GATHER);
bindDeferredShader(gDeferredPostGIProgram, 0, &mGIMapPost[0], NULL, mTrueNoiseMap);
F32 blur_size = render_gui_blur_size/((F32) i * render_gui_blur_increment+1.f);
gDeferredPostGIProgram.uniform2f("delta", 1.f, 0.f);
@@ -6601,66 +6994,81 @@ void LLPipeline::renderDeferredLighting()
}
}
- if(render_deferred_ssao)
- { //soften direct lighting lightmap
- //LLFastTimer ftm(FTM_SOFTEN_SHADOW);
- //blur lightmap
+ //if (gSavedSettings.getBOOL("RenderDeferredSSAO"))
+ //Make sure to blur normal shadows, even if ssao isn't enabled...
+ if(mDeferredLight[0].getTexture(0))
+ {
+ LLFastTimer ftm(LLFastTimer::FTM_SOFTEN_SHADOW);
+ //blur lightmap
+ if(mDeferredLight[1].getTexture(0))
+ {
mDeferredLight[1].bindTarget();
glClearColor(1,1,1,1);
mDeferredLight[1].clear(GL_COLOR_BUFFER_BIT);
- glClearColor(0,0,0,0);
+ glClearColor(0,0,0,0);
+ }
+ else
+ mDeferredLight[0].bindTarget();
- bindDeferredShader(gDeferredBlurLightProgram);
+ bindDeferredShader(gDeferredBlurLightProgram);
- static const LLCachedControl go("RenderShadowGaussian",LLVector3(3.f,2.f,0.f));
- const U32 kern_length = 4;
- static const LLCachedControl blur_size("RenderShadowBlurSize",1.4f);
- static const LLCachedControl shadow_blur_dist_factor("RenderShadowBlurDistFactor",.1f);
+ static const LLCachedControl go("RenderShadowGaussian",LLVector3(3.f,2.f,0.f));
+ const U32 kern_length = 4;
+ static const LLCachedControl blur_size("RenderShadowBlurSize",1.4f);
+ static const LLCachedControl shadow_blur_dist_factor("RenderShadowBlurDistFactor",.1f);
- // sample symmetrically with the middle sample falling exactly on 0.0
- F32 x = 0.f;
+ // sample symmetrically with the middle sample falling exactly on 0.0
+ F32 x = 0.f;
- LLVector3 gauss[32]; // xweight, yweight, offset
+ LLVector3 gauss[32]; // xweight, yweight, offset
- for (U32 i = 0; i < kern_length; i++)
- {
- gauss[i].mV[0] = llgaussian(x, go.get().mV[0]);
- gauss[i].mV[1] = llgaussian(x, go.get().mV[1]);
- gauss[i].mV[2] = x;
- x += 1.f;
- }
+ for (U32 i = 0; i < kern_length; i++)
+ {
+ gauss[i].mV[0] = llgaussian(x, go.get().mV[0]);
+ gauss[i].mV[1] = llgaussian(x, go.get().mV[1]);
+ gauss[i].mV[2] = x;
+ x += 1.f;
+ }
- gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
- gDeferredBlurLightProgram.uniform1f("dist_factor", shadow_blur_dist_factor);
- gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
- gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+ gDeferredBlurLightProgram.uniform2f("delta", 1.f, 0.f);
+ gDeferredBlurLightProgram.uniform1f("dist_factor", shadow_blur_dist_factor);
+ gDeferredBlurLightProgram.uniform3fv("kern", kern_length, gauss[0].mV);
+ gDeferredBlurLightProgram.uniform1f("kern_scale", blur_size * (kern_length/2.f - 0.5f));
+
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+
+ if(mDeferredLight[1].getTexture(0))
+ {
+ mDeferredLight[1].flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
- stop_glerror();
- }
-
- mDeferredLight[1].flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
+ bindDeferredShader(gDeferredBlurLightProgram, 1);
+ }
+ else
+ {
+ mDeferredLight[0].flush();
+ }
+
+ mDeferredLight[0].bindTarget();
- bindDeferredShader(gDeferredBlurLightProgram, 1);
- mDeferredLight[0].bindTarget();
+ gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
- gDeferredBlurLightProgram.uniform2f("delta", 0.f, 1.f);
-
- {
- LLGLDisable blend(GL_BLEND);
- LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
- stop_glerror();
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
- stop_glerror();
- }
- mDeferredLight[0].flush();
- unbindDeferredShader(gDeferredBlurLightProgram);
+ {
+ LLGLDisable blend(GL_BLEND);
+ LLGLDepthTest depth(GL_TRUE, GL_FALSE, GL_ALWAYS);
+ stop_glerror();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ stop_glerror();
+ }
+ mDeferredLight[0].flush();
+ unbindDeferredShader(gDeferredBlurLightProgram);
}
stop_glerror();
@@ -6693,30 +7101,30 @@ void LLPipeline::renderDeferredLighting()
static const LLCachedControl render_deferred_atmospheric("RenderDeferredAtmospheric",false);
if (render_deferred_atmospheric)
{ //apply sunlight contribution
- //LLFastTimer ftm(FTM_ATMOSPHERICS);
+ LLFastTimer ftm(LLFastTimer::FTM_ATMOSPHERICS);
bindDeferredShader(gDeferredSoftenProgram, 0, &mGIMapPost[0]);
- {
- LLGLDepthTest depth(GL_FALSE);
- LLGLDisable blend(GL_BLEND);
- LLGLDisable test(GL_ALPHA_TEST);
+ {
+ LLGLDepthTest depth(GL_FALSE);
+ LLGLDisable blend(GL_BLEND);
+ LLGLDisable test(GL_ALPHA_TEST);
- //full screen blit
- glPushMatrix();
- glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
+ //full screen blit
+ glPushMatrix();
+ glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glPushMatrix();
+ glLoadIdentity();
- glVertexPointer(2, GL_FLOAT, 0, vert);
+ glVertexPointer(2, GL_FLOAT, 0, vert);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
- glPopMatrix();
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- }
+ glPopMatrix();
+ glMatrixMode(GL_MODELVIEW);
+ glPopMatrix();
+ }
- unbindDeferredShader(gDeferredSoftenProgram);
+ unbindDeferredShader(gDeferredSoftenProgram);
}
{ //render sky
@@ -6843,6 +7251,7 @@ void LLPipeline::renderDeferredLighting()
continue;
}
+ LLFastTimer ftm(LLFastTimer::FTM_LOCAL_LIGHTS);
glTexCoord4f(tc.v[0], tc.v[1], tc.v[2], s*s);
glColor4f(col.mV[0], col.mV[1], col.mV[2], volume->getLightFalloff()*0.5f);
glDrawRangeElements(GL_TRIANGLE_FAN, 0, 7, 8,
@@ -6874,7 +7283,7 @@ void LLPipeline::renderDeferredLighting()
for (LLDrawable::drawable_list_t::iterator iter = spot_lights.begin(); iter != spot_lights.end(); ++iter)
{
- //LLFastTimer ftm(FTM_PROJECTORS);
+ LLFastTimer ftm(LLFastTimer::FTM_PROJECTORS);
LLDrawable* drawablep = *iter;
LLVOVolume* volume = drawablep->getVOVolume();
@@ -6940,6 +7349,7 @@ void LLPipeline::renderDeferredLighting()
while (!fullscreen_lights.empty())
{
+ LLFastTimer ftm(LLFastTimer::FTM_FULLSCREEN_LIGHTS);
light[count] = fullscreen_lights.front();
fullscreen_lights.pop_front();
col[count] = light_colors.front();
@@ -6959,6 +7369,7 @@ void LLPipeline::renderDeferredLighting()
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
}
}
+
unbindDeferredShader(gDeferredMultiLightProgram);
bindDeferredShader(gDeferredMultiSpotLightProgram);
@@ -6967,7 +7378,7 @@ void LLPipeline::renderDeferredLighting()
for (LLDrawable::drawable_list_t::iterator iter = fullscreen_spot_lights.begin(); iter != fullscreen_spot_lights.end(); ++iter)
{
- //LLFastTimer ftm(FTM_PROJECTORS);
+ LLFastTimer ftm(LLFastTimer::FTM_PROJECTORS);
LLDrawable* drawablep = *iter;
LLVOVolume* volume = drawablep->getVOVolume();
@@ -7012,7 +7423,7 @@ void LLPipeline::renderDeferredLighting()
gGL.setSceneBlendType(LLRender::BT_ALPHA);
{ //mix various light maps (local, sun, gi)
- //LLFastTimer ftm(FTM_POST);
+ LLFastTimer ftm(LLFastTimer::FTM_POST);
LLGLDisable blend(GL_BLEND);
LLGLDisable test(GL_ALPHA_TEST);
LLGLDepthTest depth(GL_FALSE);
@@ -7300,7 +7711,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
if (LLPipeline::sWaterReflections && assertInitialized() && LLDrawPoolWater::sNeedsReflectionUpdate)
{
LLVOAvatar* agent = gAgent.getAvatarObject();
- if (gAgent.getCameraAnimating() || gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK)
+ if (!isAgentAvatarValid() || gAgent.getCameraAnimating() || gAgent.getCameraMode() != CAMERA_MODE_MOUSELOOK)
{
agent = NULL;
}
@@ -7318,11 +7729,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
LLCamera camera = camera_in;
camera.setFar(camera.getFar()*0.87654321f);
LLPipeline::sReflectionRender = TRUE;
- S32 occlusion = LLPipeline::sUseOcclusion;
-
- LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
-
- LLPipeline::sUseOcclusion = llmin(occlusion, 1);
gPipeline.pushRenderTypeMask();
@@ -7358,9 +7764,14 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
if (!LLViewerCamera::getInstance()->cameraUnderWater())
{ //generate planar reflection map
+
+ //disable occlusion culling for reflection map for now
+ S32 occlusion = LLPipeline::sUseOcclusion;
+ LLPipeline::sUseOcclusion = 0;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
glClearColor(0,0,0,0);
mWaterRef.bindTarget();
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER0;
gGL.setColorMask(true, true);
mWaterRef.clear();
gGL.setColorMask(true, false);
@@ -7455,6 +7866,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
glPopMatrix();
mWaterRef.flush();
glh_set_current_modelview(current);
+ LLPipeline::sUseOcclusion = occlusion;
}
camera.setOrigin(camera_in.getOrigin());
@@ -7486,6 +7898,7 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
LLColor4& col = LLDrawPoolWater::sWaterFogColor;
glClearColor(col.mV[0], col.mV[1], col.mV[2], 0.f);
mWaterDis.bindTarget();
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WATER1;
mWaterDis.getViewport(gGLViewport);
if (!LLPipeline::sUnderWaterRender || LLDrawPoolWater::sNeedsReflectionUpdate)
@@ -7526,7 +7939,6 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
LLDrawPoolWater::sNeedsReflectionUpdate = FALSE;
LLDrawPoolWater::sNeedsDistortionUpdate = FALSE;
LLViewerCamera::getInstance()->setUserClipPlane(LLPlane(-pnorm, -pd));
- LLPipeline::sUseOcclusion = occlusion;
LLGLState::checkStates();
LLGLState::checkTextureChannels();
@@ -7536,6 +7948,8 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
{
agent->updateAttachmentVisibility(gAgent.getCameraMode());
}
+
+ LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD;
}
}
@@ -7635,14 +8049,14 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
glLoadMatrixf(proj.m);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
- glLoadMatrixf(view.m);
+ glLoadMatrixd(gGLModelView);
stop_glerror();
gGLLastMatrix = NULL;
{
- LLGLDepthTest depth(GL_TRUE);
- glClear(GL_DEPTH_BUFFER_BIT);
+ //LLGLDepthTest depth(GL_TRUE);
+ //glClear(GL_DEPTH_BUFFER_BIT);
}
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
@@ -7658,7 +8072,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
LLVertexBuffer::unbind();
{
- //LLFastTimer ftm(FTM_SHADOW_SIMPLE);
+ LLFastTimer ftm(LLFastTimer::FTM_SHADOW_SIMPLE);
LLGLDisable test(GL_ALPHA_TEST);
gGL.getTexUnit(0)->disable();
for (U32 i = 0; i < sizeof(types)/sizeof(U32); ++i)
@@ -7680,7 +8094,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
}
{
- //LLFastTimer ftm(FTM_SHADOW_ALPHA);
+ LLFastTimer ftm(LLFastTimer::FTM_SHADOW_ALPHA);
LLGLEnable test(GL_ALPHA_TEST);
gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.6f);
renderObjects(LLRenderPass::PASS_ALPHA_SHADOW, LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD0 | LLVertexBuffer::MAP_COLOR, TRUE);
@@ -7714,7 +8128,7 @@ void LLPipeline::renderShadow(glh::matrix4f& view, glh::matrix4f& proj, LLCamera
BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector3& max, std::vector& fp, LLVector3 light_dir)
{
- //LLFastTimer t(FTM_VISIBLE_CLOUD);
+ LLFastTimer t(LLFastTimer::FTM_VISIBLE_CLOUD);
//get point cloud of intersection of frust and min, max
if (getVisibleExtents(camera, min, max))
@@ -7800,7 +8214,7 @@ BOOL LLPipeline::getVisiblePointCloud(LLCamera& camera, LLVector3& min, LLVector
0,1,
1,2,
2,3,
- 3,1,
+ 3,0,
4,5,
5,6,
@@ -8128,6 +8542,14 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
//LLVector3 &n = shadow_near_dist.get();
//F32 nearDist[] = { n.mV[0], n.mV[1], n.mV[2], n.mV[2] };
+ //put together a universal "near clip" plane for shadow frusta
+ /*LLPlane shadow_near_clip;
+ {
+ LLVector3 p = gAgent.getCameraPositionAgent();//gAgent.getPositionAgent();
+ p += mSunDir * gSavedSettings.getF32("RenderFarClip")*2.f;
+ shadow_near_clip.setVec(p, mSunDir);
+ }*/
+
LLVector3 lightDir = -mSunDir;
lightDir.normVec();
@@ -8555,7 +8977,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
}
}
- shadow_cam.setFar(128.f);
+ //shadow_cam.setFar(128.f);
shadow_cam.setOriginAndLookAt(eye, up, center);
shadow_cam.setOrigin(0,0,0);
@@ -8566,6 +8988,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera)
LLViewerCamera::updateFrustumPlanes(shadow_cam, FALSE, FALSE, TRUE);
shadow_cam.ignoreAgentFrustumPlane(LLCamera::AGENT_PLANE_NEAR);
+ //shadow_cam.getAgentPlane(LLCamera::AGENT_PLANE_NEAR).set(shadow_near_clip);
//translate and scale to from [-1, 1] to [0, 1]
glh::matrix4f trans(0.5f, 0.f, 0.f, 0.5f,
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index af720625e..56720d027 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -207,6 +207,13 @@ public:
void renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL texture);
void grabReferences(LLCullResult& result);
+ void clearReferences();
+
+ //check references will assert that there are no references in sCullResult to the provided data
+ void checkReferences(LLFace* face);
+ void checkReferences(LLDrawable* drawable);
+ void checkReferences(LLDrawInfo* draw_info);
+ void checkReferences(LLSpatialGroup* group);
void renderGeom(LLCamera& camera, BOOL forceVBOUpdate = FALSE);
void renderGeomDeferred(LLCamera& camera);
@@ -657,6 +664,9 @@ protected:
public:
static BOOL sRenderBeacons;
static BOOL sRenderHighlight;
+
+ //debug use
+ static U32 sCurRenderPoolType ;
};
void render_bbox(const LLVector3 &min, const LLVector3 &max);
diff --git a/indra/newview/skins/default/xui/en-us/notifications.xml b/indra/newview/skins/default/xui/en-us/notifications.xml
index 6c2ff33a1..42adbe080 100644
--- a/indra/newview/skins/default/xui/en-us/notifications.xml
+++ b/indra/newview/skins/default/xui/en-us/notifications.xml
@@ -6821,6 +6821,14 @@ The URL you clicked cannot be opened from this web browser.
You do not appear to have the proper hardware requirements for [VIEWER_NAME]. The viewer requires an OpenGL graphics card that has multitexture support. If this is the case, you may want to make sure that you have the latest drivers for your graphics card, and service packs and patches for your operating system.
+
+ You do not appear to have the proper hardware requirements for [VIEWER_NAME]. The viewer requires a CPU that supports SSE2
+
+
+
+ You do not appear to have the proper hardware requirements for [VIEWER_NAME]. The viewer requires a CPU that supports SSE
+
+
796
diff --git a/indra/newview/statemachine/aistatemachine.cpp b/indra/newview/statemachine/aistatemachine.cpp
index b950fc236..e8a0d99de 100644
--- a/indra/newview/statemachine/aistatemachine.cpp
+++ b/indra/newview/statemachine/aistatemachine.cpp
@@ -311,9 +311,9 @@ void AIStateMachine::mainloop(void*)
AIStateMachine& statemachine(iter->statemachine());
if (!statemachine.mIdle)
{
- U64 start = get_cpu_clock_count();
+ U64 start = LLFastTimer::getCPUClockCount64();
iter->statemachine().multiplex(start);
- U64 delta = get_cpu_clock_count() - start;
+ U64 delta = LLFastTimer::getCPUClockCount64() - start;
iter->add(delta);
total_clocks += delta;
if (total_clocks >= max_count)
diff --git a/indra/newview/statemachine/aistatemachine.h b/indra/newview/statemachine/aistatemachine.h
index cc0b63ce1..42419cdb8 100644
--- a/indra/newview/statemachine/aistatemachine.h
+++ b/indra/newview/statemachine/aistatemachine.h
@@ -226,7 +226,7 @@ class AIStateMachine {
void yield_frame(unsigned int frames) { mSleep = -(S64)frames; }
//! Temporarily halt the state machine.
- void yield_ms(unsigned int ms) { mSleep = get_cpu_clock_count() + LLFastTimer::countsPerSecond() * ms / 1000; }
+ void yield_ms(unsigned int ms) { mSleep = LLFastTimer::getCPUClockCount64() + LLFastTimer::countsPerSecond() * ms / 1000; }
//! Continue running after calling idle.
void cont(void);