llcommon merge. Added LLUnits.
This commit is contained in:
@@ -230,9 +230,13 @@ set(llcommon_HEADER_FILES
|
||||
llthreadsafequeue.h
|
||||
lltimer.h
|
||||
lltreeiterators.h
|
||||
llunits.h
|
||||
llunittype.h
|
||||
lltypeinfolookup.h
|
||||
lluri.h
|
||||
lluuid.h
|
||||
llwin32headers.h
|
||||
llwin32headerslean.h
|
||||
llworkerthread.h
|
||||
metaclass.h
|
||||
metaclasst.h
|
||||
|
||||
@@ -64,7 +64,7 @@ LLAlignedArray<T, alignment>::LLAlignedArray()
|
||||
template <class T, U32 alignment>
|
||||
LLAlignedArray<T, alignment>::~LLAlignedArray()
|
||||
{
|
||||
ll_aligned_free(mArray);
|
||||
ll_aligned_free<alignment>(mArray);
|
||||
mArray = NULL;
|
||||
mElementCount = 0;
|
||||
mCapacity = 0;
|
||||
@@ -78,7 +78,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
|
||||
{
|
||||
mCapacity++;
|
||||
mCapacity *= 2;
|
||||
T* new_buf = (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment);
|
||||
T* new_buf = (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T));
|
||||
if (mArray)
|
||||
{
|
||||
ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount);
|
||||
@@ -90,7 +90,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
|
||||
mArray[mElementCount++] = elem;
|
||||
|
||||
//delete old array here to prevent error on a.push_back(a[0])
|
||||
ll_aligned_free(old_buf);
|
||||
ll_aligned_free<alignment>(old_buf);
|
||||
}
|
||||
|
||||
template <class T, U32 alignment>
|
||||
@@ -99,11 +99,11 @@ void LLAlignedArray<T, alignment>::resize(U32 size)
|
||||
if (mCapacity < size)
|
||||
{
|
||||
mCapacity = size+mCapacity*2;
|
||||
T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment) : NULL;
|
||||
T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T)) : NULL;
|
||||
if (mArray)
|
||||
{
|
||||
ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount);
|
||||
ll_aligned_free(mArray);
|
||||
ll_aligned_free<alignment>(mArray);
|
||||
}
|
||||
|
||||
/*for (U32 i = mElementCount; i < mCapacity; ++i)
|
||||
|
||||
@@ -30,13 +30,17 @@
|
||||
#include "llbase64.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "apr_base64.h"
|
||||
|
||||
|
||||
// static
|
||||
std::string LLBase64::encode(const U8* input, size_t input_size)
|
||||
{
|
||||
if (!(input && input_size > 0)) return LLStringUtil::null;
|
||||
|
||||
std::string output;
|
||||
if (input
|
||||
&& input_size > 0)
|
||||
{
|
||||
// Yes, it returns int.
|
||||
int b64_buffer_length = apr_base64_encode_len(input_size);
|
||||
char* b64_buffer = new char[b64_buffer_length];
|
||||
@@ -49,12 +53,12 @@ std::string LLBase64::encode(const U8* input, size_t input_size)
|
||||
b64_buffer,
|
||||
input,
|
||||
input_size);
|
||||
std::string result;
|
||||
result.assign(b64_buffer);
|
||||
output.assign(b64_buffer);
|
||||
delete[] b64_buffer;
|
||||
|
||||
return result;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
std::string LLBase64::encode(const std::string& in_str)
|
||||
|
||||
@@ -55,8 +55,8 @@ LLDate::LLDate(const LLDate& date) :
|
||||
mSecondsSinceEpoch(date.mSecondsSinceEpoch)
|
||||
{}
|
||||
|
||||
LLDate::LLDate(F64 seconds_since_epoch) :
|
||||
mSecondsSinceEpoch(seconds_since_epoch)
|
||||
LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) :
|
||||
mSecondsSinceEpoch(seconds_since_epoch.value())
|
||||
{}
|
||||
|
||||
LLDate::LLDate(const std::string& iso8601_date)
|
||||
@@ -83,7 +83,7 @@ std::string LLDate::asString() const
|
||||
// is one of the standards used and the prefered format
|
||||
std::string LLDate::asRFC1123() const
|
||||
{
|
||||
return toHTTPDateString(LLStringExplicit("%A, %d %b %Y %H:%M:%S GMT"));
|
||||
return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
|
||||
}
|
||||
|
||||
LLFastTimer::DeclareTimer FT_DATE_FORMAT("Date Format");
|
||||
|
||||
@@ -38,9 +38,8 @@
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include "llpreprocessor.h"
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include "llunits.h"
|
||||
|
||||
/**
|
||||
* @class LLDate
|
||||
@@ -64,9 +63,9 @@ public:
|
||||
/**
|
||||
* @brief Construct a date from a seconds since epoch value.
|
||||
*
|
||||
* @pararm seconds_since_epoch The number of seconds since UTC epoch.
|
||||
* @param seconds_since_epoch The number of seconds since UTC epoch.
|
||||
*/
|
||||
LLDate(F64 seconds_since_epoch);
|
||||
LLDate(F64SecondsImplicit seconds_since_epoch);
|
||||
|
||||
/**
|
||||
* @brief Construct a date from a string representation
|
||||
@@ -163,4 +162,6 @@ LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLDate& date);
|
||||
// Helper function to stream in a date
|
||||
LL_COMMON_API std::istream& operator>>(std::istream& s, LLDate& date);
|
||||
|
||||
|
||||
|
||||
#endif // LL_LLDATE_H
|
||||
|
||||
@@ -65,7 +65,7 @@ LLEventTimer::~LLEventTimer()
|
||||
void LLEventTimer::updateClass()
|
||||
{
|
||||
std::list<LLEventTimer*> completed_timers;
|
||||
for (instance_iter iter = beginInstances(), iter_end = endInstances(); iter != iter_end;)
|
||||
for (instance_iter iter = beginInstances(), end_iter = endInstances(); iter != end_iter;)
|
||||
{
|
||||
LLEventTimer& timer = *iter++;
|
||||
F32 et = timer.mEventTimer.getElapsedTimeF32();
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
*/
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include <windows.h>
|
||||
#include "llwin32headerslean.h"
|
||||
#include <stdlib.h> // Windows errno
|
||||
#else
|
||||
#include <errno.h>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include "llwin32headers.h"
|
||||
#include <winnt.h>
|
||||
#endif
|
||||
|
||||
@@ -183,7 +183,7 @@ canonise_fl(FL_Locale *l) {
|
||||
#define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn)
|
||||
struct IDToCode {
|
||||
LANGID id;
|
||||
char* code;
|
||||
const char* code;
|
||||
};
|
||||
static const IDToCode both_to_code[] = {
|
||||
{ML(ENGLISH,US), "en_US.ISO_8859-1"},
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
|
||||
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
|
||||
: LLLineBuffer(),
|
||||
mMaxLines(max_lines)
|
||||
mMaxLines(max_lines),
|
||||
mMutex()
|
||||
{
|
||||
mTimer.reset();
|
||||
}
|
||||
|
||||
@@ -194,13 +194,6 @@ public:
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef LLHandle<T> handle_type_t;
|
||||
LLHandleProvider()
|
||||
{
|
||||
// provided here to enforce T deriving from LLHandleProvider<T>
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
|
||||
{
|
||||
@@ -209,6 +202,12 @@ protected:
|
||||
return downcast_handle;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef LLHandle<T> handle_type_t;
|
||||
LLHandleProvider()
|
||||
{
|
||||
// provided here to enforce T deriving from LLHandleProvider<T>
|
||||
}
|
||||
|
||||
private:
|
||||
mutable LLRootHandle<T> mHandle;
|
||||
|
||||
@@ -88,46 +88,51 @@ LLLiveFile::~LLLiveFile()
|
||||
|
||||
bool LLLiveFile::Impl::check()
|
||||
{
|
||||
if (!mForceCheck && mRefreshTimer.getElapsedTimeF32() < mRefreshPeriod)
|
||||
{
|
||||
bool detected_change = false;
|
||||
// Skip the check if not enough time has elapsed and we're not
|
||||
// forcing a check of the file
|
||||
return false;
|
||||
}
|
||||
mForceCheck = false;
|
||||
mRefreshTimer.reset();
|
||||
if (mForceCheck || mRefreshTimer.getElapsedTimeF32() >= mRefreshPeriod)
|
||||
{
|
||||
mForceCheck = false; // force only forces one check
|
||||
mRefreshTimer.reset(); // don't check again until mRefreshPeriod has passed
|
||||
|
||||
// Stat the file to see if it exists and when it was last modified.
|
||||
llstat stat_data;
|
||||
int res = LLFile::stat(mFilename, &stat_data);
|
||||
|
||||
if (res)
|
||||
if (LLFile::stat(mFilename, &stat_data))
|
||||
{
|
||||
// Couldn't stat the file, that means it doesn't exist or is
|
||||
// broken somehow. Clear flags and return.
|
||||
// broken somehow.
|
||||
if (mLastExists)
|
||||
{
|
||||
mLastExists = false;
|
||||
return true; // no longer existing is a change!
|
||||
detected_change = true; // no longer existing is a change!
|
||||
LL_DEBUGS() << "detected deleted file '" << mFilename << "'" << LL_ENDL;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// The file exists, decide if we want to load it.
|
||||
if (mLastExists)
|
||||
else
|
||||
{
|
||||
// The file existed last time, don't read it if it hasn't changed since
|
||||
// last time.
|
||||
if (stat_data.st_mtime <= mLastModTime)
|
||||
// The file exists
|
||||
if ( ! mLastExists )
|
||||
{
|
||||
return false;
|
||||
// last check, it did not exist - that counts as a change
|
||||
LL_DEBUGS() << "detected created file '" << mFilename << "'" << LL_ENDL;
|
||||
detected_change = true;
|
||||
}
|
||||
else if ( stat_data.st_mtime > mLastModTime )
|
||||
{
|
||||
// file modification time is newer than last check
|
||||
LL_DEBUGS() << "detected updated file '" << mFilename << "'" << LL_ENDL;
|
||||
detected_change = true;
|
||||
}
|
||||
|
||||
// We want to read the file. Update status info for the file.
|
||||
mLastExists = true;
|
||||
mLastStatTime = stat_data.st_mtime;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (detected_change)
|
||||
{
|
||||
LL_INFOS() << "detected file change '" << mFilename << "'" << LL_ENDL;
|
||||
}
|
||||
return detected_change;
|
||||
}
|
||||
|
||||
void LLLiveFile::Impl::changed()
|
||||
|
||||
@@ -119,6 +119,12 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) {
|
||||
|
||||
buffer_space = 64 - buffer_index; // how much space is left in buffer
|
||||
|
||||
// now, transform each 64-byte piece of the input, bypassing the buffer
|
||||
if (input == NULL || input_length == 0){
|
||||
std::cerr << "LLMD5::update: Invalid input!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Transform as many times as possible.
|
||||
if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
|
||||
// fill the rest of the buffer and transform
|
||||
@@ -128,12 +134,6 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) {
|
||||
buffer_space);
|
||||
transform (buffer);
|
||||
|
||||
// now, transform each 64-byte piece of the input, bypassing the buffer
|
||||
if (input == NULL || input_length == 0){
|
||||
std::cerr << "LLMD5::update: Invalid input!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
for (input_index = buffer_space; input_index + 63 < input_length;
|
||||
input_index += 64)
|
||||
transform (input+input_index);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
//#endif
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
//# include <windows.h>
|
||||
#include "llwin32headerslean.h"
|
||||
# include <psapi.h>
|
||||
#elif defined(LL_DARWIN)
|
||||
# include <sys/types.h>
|
||||
@@ -50,11 +50,11 @@
|
||||
|
||||
//static
|
||||
char* LLMemory::reserveMem = 0;
|
||||
U32 LLMemory::sAvailPhysicalMemInKB = U32_MAX ;
|
||||
U32 LLMemory::sMaxPhysicalMemInKB = 0;
|
||||
U32 LLMemory::sAllocatedMemInKB = 0;
|
||||
U32 LLMemory::sAllocatedPageSizeInKB = 0 ;
|
||||
U32 LLMemory::sMaxHeapSizeInKB = U32_MAX ;
|
||||
U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
|
||||
U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0);
|
||||
U32Kilobytes LLMemory::sAllocatedMemInKB(0);
|
||||
U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
|
||||
U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
|
||||
BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
|
||||
|
||||
#if __DEBUG_PRIVATE_MEM__
|
||||
@@ -93,9 +93,9 @@ void LLMemory::freeReserve()
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMemory::initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure)
|
||||
void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure)
|
||||
{
|
||||
sMaxHeapSizeInKB = (U32)(max_heap_size_gb * 1024 * 1024) ;
|
||||
sMaxHeapSizeInKB = max_heap_size;
|
||||
sEnableMemoryFailurePrevention = prevent_heap_failure ;
|
||||
}
|
||||
|
||||
@@ -112,10 +112,10 @@ void LLMemory::updateMemoryInfo()
|
||||
return ;
|
||||
}
|
||||
|
||||
sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ;
|
||||
sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ;
|
||||
sAllocatedMemInKB = (U32Bytes)(counters.WorkingSetSize) ;
|
||||
sAllocatedPageSizeInKB = (U32Bytes)(counters.PagefileUsage) ;
|
||||
|
||||
U32 avail_phys, avail_virtual;
|
||||
U32Kilobytes avail_phys, avail_virtual;
|
||||
LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
|
||||
sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
|
||||
|
||||
@@ -125,14 +125,16 @@ void LLMemory::updateMemoryInfo()
|
||||
}
|
||||
else
|
||||
{
|
||||
sAvailPhysicalMemInKB = 0 ;
|
||||
sAvailPhysicalMemInKB = U32Kilobytes(0);
|
||||
}
|
||||
#else
|
||||
//not valid for other systems for now.
|
||||
sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ;
|
||||
sMaxPhysicalMemInKB = U32_MAX ;
|
||||
sAvailPhysicalMemInKB = U32_MAX ;
|
||||
sAllocatedMemInKB = (U32Bytes)LLMemory::getCurrentRSS();
|
||||
sMaxPhysicalMemInKB = (U32Bytes)U32_MAX ;
|
||||
sAvailPhysicalMemInKB = (U32Bytes)U32_MAX ;
|
||||
#endif
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -184,8 +186,8 @@ void LLMemory::logMemoryInfo(BOOL update)
|
||||
//static
|
||||
bool LLMemory::isMemoryPoolLow()
|
||||
{
|
||||
static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use
|
||||
const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
|
||||
static const U32Megabytes LOW_MEMORY_POOL_THRESHOLD(64);
|
||||
const static U32Megabytes MAX_SIZE_CHECKED_MEMORY_BLOCK(64);
|
||||
static void* last_reserved_address = NULL ;
|
||||
|
||||
if(!sEnableMemoryFailurePrevention)
|
||||
@@ -193,32 +195,32 @@ bool LLMemory::isMemoryPoolLow()
|
||||
return false ; //no memory failure prevention.
|
||||
}
|
||||
|
||||
if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory
|
||||
if(sAvailPhysicalMemInKB < (LOW_MEMORY_POOL_THRESHOLD / 4)) //out of physical memory
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space.
|
||||
if(sAllocatedPageSizeInKB + (LOW_MEMORY_POOL_THRESHOLD / 4) > sMaxHeapSizeInKB) //out of virtual address space.
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB ||
|
||||
sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ;
|
||||
bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD
|
||||
|| sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ;
|
||||
|
||||
//check the virtual address space fragmentation
|
||||
if(!is_low)
|
||||
{
|
||||
if(!last_reserved_address)
|
||||
{
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
|
||||
if(!last_reserved_address) //failed, try once more
|
||||
{
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,19 +231,19 @@ bool LLMemory::isMemoryPoolLow()
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLMemory::getAvailableMemKB()
|
||||
U32Kilobytes LLMemory::getAvailableMemKB()
|
||||
{
|
||||
return sAvailPhysicalMemInKB ;
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLMemory::getMaxMemKB()
|
||||
U32Kilobytes LLMemory::getMaxMemKB()
|
||||
{
|
||||
return sMaxPhysicalMemInKB ;
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLMemory::getAllocatedMemKB()
|
||||
U32Kilobytes LLMemory::getAllocatedMemKB()
|
||||
{
|
||||
return sAllocatedMemInKB ;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
#define LLMEMORY_H
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llunits.h"
|
||||
#include "stdtypes.h"
|
||||
#include <new>
|
||||
#include <cstdlib>
|
||||
#if !LL_WINDOWS
|
||||
@@ -42,6 +43,21 @@ class LLMutex ;
|
||||
#define LL_CHECK_MEMORY
|
||||
#endif
|
||||
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define LL_ALIGN_OF __alignof
|
||||
#else
|
||||
#define LL_ALIGN_OF __align_of__
|
||||
#endif
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define LL_DEFAULT_HEAP_ALIGN 8
|
||||
#elif LL_DARWIN
|
||||
#define LL_DEFAULT_HEAP_ALIGN 16
|
||||
#elif LL_LINUX
|
||||
#define LL_DEFAULT_HEAP_ALIGN 8
|
||||
#endif
|
||||
|
||||
//<singu>
|
||||
// ll_assert_aligned seems to only exist to set breakpoints in case an alignment check fails.
|
||||
// However, the implementation was horrible: the test was done using a integer modulo after
|
||||
@@ -102,7 +118,17 @@ template <typename T> T* LL_NEXT_ALIGNED_ADDRESS_64(T* address)
|
||||
|
||||
#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16)
|
||||
|
||||
inline void* ll_aligned_malloc( size_t size, int align )
|
||||
//------------------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library
|
||||
// change preprocessor code to: #if 1 && defined(LL_WINDOWS)
|
||||
|
||||
#if 0 && defined(LL_WINDOWS)
|
||||
void* ll_aligned_malloc_fallback( size_t size, int align );
|
||||
void ll_aligned_free_fallback( void* ptr );
|
||||
//------------------------------------------------------------------------------------------------
|
||||
#else
|
||||
inline void* ll_aligned_malloc_fallback( size_t size, int align )
|
||||
{
|
||||
#if defined(LL_WINDOWS)
|
||||
return _aligned_malloc(size, align);
|
||||
@@ -116,7 +142,7 @@ inline void* ll_aligned_malloc( size_t size, int align )
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void ll_aligned_free( void* ptr )
|
||||
inline void ll_aligned_free_fallback( void* ptr )
|
||||
{
|
||||
#if defined(LL_WINDOWS)
|
||||
_aligned_free(ptr);
|
||||
@@ -127,6 +153,8 @@ inline void ll_aligned_free( void* ptr )
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
//------------------------------------------------------------------------------------------------
|
||||
|
||||
#if !LL_USE_TCMALLOC
|
||||
inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16().
|
||||
@@ -189,7 +217,7 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi
|
||||
#if defined(LL_WINDOWS)
|
||||
return _aligned_malloc(size, 32);
|
||||
#elif defined(LL_DARWIN)
|
||||
return ll_aligned_malloc( size, 32 );
|
||||
return ll_aligned_malloc_fallback( size, 32 );
|
||||
#else
|
||||
void *rtn;
|
||||
if (LL_LIKELY(0 == posix_memalign(&rtn, 32, size)))
|
||||
@@ -204,12 +232,54 @@ inline void ll_aligned_free_32(void *p)
|
||||
#if defined(LL_WINDOWS)
|
||||
_aligned_free(p);
|
||||
#elif defined(LL_DARWIN)
|
||||
ll_aligned_free( p );
|
||||
ll_aligned_free_fallback( p );
|
||||
#else
|
||||
free(p); // posix_memalign() is compatible with heap deallocator
|
||||
#endif
|
||||
}
|
||||
|
||||
// general purpose dispatch functions that are forced inline so they can compile down to a single call
|
||||
template<size_t ALIGNMENT>
|
||||
LL_FORCE_INLINE void* ll_aligned_malloc(size_t size)
|
||||
{
|
||||
if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
else if (ALIGNMENT == 16)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
else if (ALIGNMENT == 32)
|
||||
{
|
||||
return ll_aligned_malloc_32(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ll_aligned_malloc_fallback(size, ALIGNMENT);
|
||||
}
|
||||
}
|
||||
|
||||
template<size_t ALIGNMENT>
|
||||
LL_FORCE_INLINE void ll_aligned_free(void* ptr)
|
||||
{
|
||||
if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
else if (ALIGNMENT == 16)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
else if (ALIGNMENT == 32)
|
||||
{
|
||||
return ll_aligned_free_32(ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ll_aligned_free_fallback(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP.
|
||||
// Source and dest must be 16-byte aligned and size must be multiple of 16.
|
||||
@@ -297,22 +367,22 @@ public:
|
||||
static U64 getCurrentRSS();
|
||||
static U32 getWorkingSetSize();
|
||||
static void* tryToAlloc(void* address, U32 size);
|
||||
static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure);
|
||||
static void initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure);
|
||||
static void updateMemoryInfo() ;
|
||||
static void logMemoryInfo(BOOL update = FALSE);
|
||||
static bool isMemoryPoolLow();
|
||||
|
||||
static U32 getAvailableMemKB() ;
|
||||
static U32 getMaxMemKB() ;
|
||||
static U32 getAllocatedMemKB() ;
|
||||
static U32Kilobytes getAvailableMemKB() ;
|
||||
static U32Kilobytes getMaxMemKB() ;
|
||||
static U32Kilobytes getAllocatedMemKB() ;
|
||||
private:
|
||||
static char* reserveMem;
|
||||
static U32 sAvailPhysicalMemInKB ;
|
||||
static U32 sMaxPhysicalMemInKB ;
|
||||
static U32 sAllocatedMemInKB;
|
||||
static U32 sAllocatedPageSizeInKB ;
|
||||
static U32Kilobytes sAvailPhysicalMemInKB ;
|
||||
static U32Kilobytes sMaxPhysicalMemInKB ;
|
||||
static U32Kilobytes sAllocatedMemInKB;
|
||||
static U32Kilobytes sAllocatedPageSizeInKB ;
|
||||
|
||||
static U32 sMaxHeapSizeInKB;
|
||||
static U32Kilobytes sMaxHeapSizeInKB;
|
||||
static BOOL sEnableMemoryFailurePrevention;
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define LLMORTICIAN_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include <list>
|
||||
|
||||
class LL_COMMON_API LLMortician
|
||||
{
|
||||
|
||||
@@ -32,9 +32,7 @@
|
||||
//#include <memory>
|
||||
|
||||
#if LL_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# include "llwin32headerslean.h"
|
||||
# define _interlockedbittestandset _renamed_interlockedbittestandset
|
||||
# define _interlockedbittestandreset _renamed_interlockedbittestandreset
|
||||
# include <intrin.h>
|
||||
@@ -881,7 +879,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
|
||||
|
||||
|
||||
LLProcessorInfo::~LLProcessorInfo() {}
|
||||
F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
|
||||
F64MegahertzImplicit 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(); }
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#ifndef LLPROCESSOR_H
|
||||
#define LLPROCESSOR_H
|
||||
#include "llunits.h"
|
||||
|
||||
class LLProcessorInfoImpl;
|
||||
|
||||
class LL_COMMON_API LLProcessorInfo
|
||||
@@ -41,7 +43,7 @@ public:
|
||||
LLProcessorInfo();
|
||||
~LLProcessorInfo();
|
||||
|
||||
F64 getCPUFrequency() const;
|
||||
F64MegahertzImplicit getCPUFrequency() const;
|
||||
bool hasSSE() const;
|
||||
bool hasSSE2() const;
|
||||
bool hasAltivec() const;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) :
|
||||
LLThread(name),
|
||||
mThreaded(threaded),
|
||||
mIdleThread(TRUE),
|
||||
mIdleThread(true),
|
||||
mNextHandle(0),
|
||||
mStarted(FALSE)
|
||||
{
|
||||
@@ -552,14 +552,15 @@ void LLQueuedThread::run()
|
||||
break;
|
||||
}
|
||||
|
||||
mIdleThread = FALSE;
|
||||
mIdleThread = false;
|
||||
|
||||
threadedUpdate();
|
||||
|
||||
int res = processNextRequest();
|
||||
if (res == 0)
|
||||
int pending_work = processNextRequest();
|
||||
|
||||
if (pending_work == 0)
|
||||
{
|
||||
mIdleThread = TRUE;
|
||||
mIdleThread = true;
|
||||
ms_sleep(1);
|
||||
}
|
||||
//LLThread::yield(); // thread should yield after each request
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "llapr.h"
|
||||
|
||||
#include "llthread.h"
|
||||
#include "llsimplehash.h"
|
||||
|
||||
@@ -204,7 +202,7 @@ public:
|
||||
protected:
|
||||
BOOL mThreaded; // if false, run on main thread and do updates during update()
|
||||
BOOL mStarted; // required when mThreaded is false to call startThread() from update()
|
||||
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
|
||||
LLAtomic32<bool> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
|
||||
|
||||
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
|
||||
request_queue_t mRequestQueue;
|
||||
|
||||
@@ -31,15 +31,15 @@
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
#include "llthread.h"
|
||||
#include "llapr.h"
|
||||
#endif
|
||||
|
||||
LLRefCount::LLRefCount(const LLRefCount& other)
|
||||
: mRef(0)
|
||||
{
|
||||
LLRefCount::LLRefCount(const LLRefCount& other) :
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
mCrashAtUnlock = FALSE ;
|
||||
mMutex(),
|
||||
mCrashAtUnlock(FALSE),
|
||||
#endif
|
||||
mRef(0)
|
||||
{
|
||||
}
|
||||
|
||||
LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
||||
@@ -49,11 +49,12 @@ LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
||||
}
|
||||
|
||||
LLRefCount::LLRefCount() :
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
mMutex(),
|
||||
mCrashAtUnlock(FALSE),
|
||||
#endif
|
||||
mRef(0)
|
||||
{
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
mCrashAtUnlock = FALSE ;
|
||||
#endif
|
||||
}
|
||||
|
||||
LLRefCount::~LLRefCount()
|
||||
|
||||
@@ -337,10 +337,9 @@ void clear_eol(std::istream& input)
|
||||
static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize)
|
||||
{
|
||||
unsigned count = 0;
|
||||
char c;
|
||||
while (count < bufsize && input.good())
|
||||
{
|
||||
input.get(c);
|
||||
char c = input.get();
|
||||
buf[count++] = c;
|
||||
if (is_eol(c))
|
||||
break;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "windows.h"
|
||||
#include "llwin32headerslean.h"
|
||||
#include "Dbghelp.h"
|
||||
|
||||
typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
|
||||
|
||||
@@ -508,6 +508,27 @@ llbind2nd(const _Operation& __oper, const _Tp& __x)
|
||||
return llbinder2nd<_Operation>(__oper, _Arg2_type(__x));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare std::type_info* pointers a la std::less. We break this out as a
|
||||
* separate function for use in two different std::less specializations.
|
||||
*/
|
||||
inline
|
||||
bool before(const std::type_info* lhs, const std::type_info* rhs)
|
||||
{
|
||||
#if LL_LINUX && defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4 && __GNUC_MINOR__ < 4))
|
||||
// If we're building on Linux with gcc, and it's either gcc 3.x or
|
||||
// 4.{0,1,2,3}, then we have to use a workaround. Note that we use gcc on
|
||||
// Mac too, and some people build with gcc on Windows (cygwin or mingw).
|
||||
// On Linux, different load modules may produce different type_info*
|
||||
// pointers for the same type. Have to compare name strings to get good
|
||||
// results.
|
||||
return strcmp(lhs->name(), rhs->name()) < 0;
|
||||
#else // not Linux, or gcc 4.4+
|
||||
// Just use before(), as we normally would
|
||||
return lhs->before(*rhs) ? true : false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Specialize std::less<std::type_info*> to use std::type_info::before().
|
||||
* See MAINT-1175. It is NEVER a good idea to directly compare std::type_info*
|
||||
@@ -522,7 +543,7 @@ namespace std
|
||||
{
|
||||
bool operator()(const std::type_info* lhs, const std::type_info* rhs) const
|
||||
{
|
||||
return lhs->before(*rhs);
|
||||
return before(lhs, rhs);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -532,7 +553,7 @@ namespace std
|
||||
{
|
||||
bool operator()(std::type_info* lhs, std::type_info* rhs) const
|
||||
{
|
||||
return lhs->before(*rhs);
|
||||
return before(lhs, rhs);
|
||||
}
|
||||
};
|
||||
} // std
|
||||
|
||||
@@ -30,9 +30,7 @@
|
||||
#include "llerror.h"
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include "llwin32headerslean.h"
|
||||
#include <winnls.h> // for WideCharToMultiByte
|
||||
#endif
|
||||
|
||||
|
||||
@@ -53,9 +53,7 @@
|
||||
using namespace llsd;
|
||||
|
||||
#if LL_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# include "llwin32headerslean.h"
|
||||
# include <psapi.h> // GetPerformanceInfo() et al.
|
||||
# include <VersionHelpers.h>
|
||||
#elif LL_DARWIN
|
||||
@@ -705,7 +703,7 @@ LLMemoryInfo::LLMemoryInfo()
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
static U32 LLMemoryAdjustKBResult(U32 inKB)
|
||||
static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)
|
||||
{
|
||||
// Moved this here from llfloaterabout.cpp
|
||||
|
||||
@@ -716,16 +714,16 @@ static U32 LLMemoryAdjustKBResult(U32 inKB)
|
||||
// returned from the GetMemoryStatusEx function. Here we keep the
|
||||
// original adjustment from llfoaterabout.cpp until this can be
|
||||
// fixed somehow.
|
||||
inKB += 1024;
|
||||
inKB += U32Megabytes(1);
|
||||
|
||||
return inKB;
|
||||
}
|
||||
#endif
|
||||
|
||||
U32 LLMemoryInfo::getPhysicalMemoryKB() const
|
||||
U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
return LLMemoryAdjustKBResult(mStatsMap["Total Physical KB"].asInteger());
|
||||
return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));
|
||||
|
||||
#elif LL_DARWIN
|
||||
// This might work on Linux as well. Someone check...
|
||||
@@ -735,17 +733,17 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
|
||||
size_t len = sizeof(phys);
|
||||
sysctl(mib, 2, &phys, &len, NULL, 0);
|
||||
|
||||
return (U32)(phys >> 10);
|
||||
return U64Bytes(phys);
|
||||
|
||||
#elif LL_LINUX
|
||||
U64 phys = 0;
|
||||
phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
|
||||
return (U32)(phys >> 10);
|
||||
return U64Bytes(phys);
|
||||
|
||||
#elif LL_SOLARIS
|
||||
U64 phys = 0;
|
||||
phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
|
||||
return (U32)(phys >> 10);
|
||||
return U64Bytes(phys);
|
||||
|
||||
#else
|
||||
return 0;
|
||||
@@ -753,32 +751,32 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
|
||||
#endif
|
||||
}
|
||||
|
||||
U32 LLMemoryInfo::getPhysicalMemoryClamped() const
|
||||
U32Bytes LLMemoryInfo::getPhysicalMemoryClamped() const
|
||||
{
|
||||
// Return the total physical memory in bytes, but clamp it
|
||||
// to no more than U32_MAX
|
||||
|
||||
U32 phys_kb = getPhysicalMemoryKB();
|
||||
if (phys_kb >= 4194304 /* 4GB in KB */)
|
||||
U32Kilobytes phys_kb = getPhysicalMemoryKB();
|
||||
if (phys_kb >= U32Gigabytes(4))
|
||||
{
|
||||
return U32_MAX;
|
||||
return U32Bytes(U32_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
return phys_kb << 10;
|
||||
return phys_kb;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
|
||||
void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
// Sigh, this shouldn't be a static method, then we wouldn't have to
|
||||
// reload this data separately from refresh()
|
||||
LLSD statsMap(loadStatsMap());
|
||||
|
||||
avail_physical_mem_kb = statsMap["Avail Physical KB"].asInteger();
|
||||
avail_virtual_mem_kb = statsMap["Avail Virtual KB"].asInteger();
|
||||
avail_physical_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger();
|
||||
avail_virtual_mem_kb = (U32Kilobytes)statsMap["Avail Virtual KB"].asInteger();
|
||||
|
||||
#elif LL_DARWIN
|
||||
// mStatsMap is derived from vm_stat, look for (e.g.) "kb free":
|
||||
@@ -795,8 +793,8 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v
|
||||
// Pageins: 2097212.
|
||||
// Pageouts: 41759.
|
||||
// Object cache: 841598 hits of 7629869 lookups (11% hit rate)
|
||||
avail_physical_mem_kb = -1 ;
|
||||
avail_virtual_mem_kb = -1 ;
|
||||
avail_physical_mem_kb = (U32Kilobytes)-1 ;
|
||||
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
|
||||
|
||||
#elif LL_LINUX
|
||||
// mStatsMap is derived from MEMINFO_FILE:
|
||||
@@ -847,15 +845,15 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v
|
||||
// DirectMap4k: 434168 kB
|
||||
// DirectMap2M: 477184 kB
|
||||
// (could also run 'free', but easier to read a file than run a program)
|
||||
avail_physical_mem_kb = -1 ;
|
||||
avail_virtual_mem_kb = -1 ;
|
||||
avail_physical_mem_kb = (U32Kilobytes)-1 ;
|
||||
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
|
||||
|
||||
#else
|
||||
//do not know how to collect available memory info for other systems.
|
||||
//leave it blank here for now.
|
||||
|
||||
avail_physical_mem_kb = -1 ;
|
||||
avail_virtual_mem_kb = -1 ;
|
||||
avail_physical_mem_kb = (U32Kilobytes)-1 ;
|
||||
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -112,15 +112,15 @@ public:
|
||||
LLMemoryInfo(); ///< Default constructor
|
||||
void stream(std::ostream& s) const; ///< output text info to s
|
||||
|
||||
U32 getPhysicalMemoryKB() const; ///< Memory size in KiloBytes
|
||||
U32Kilobytes getPhysicalMemoryKB() const;
|
||||
|
||||
/*! Memory size in bytes, if total memory is >= 4GB then U32_MAX will
|
||||
** be returned.
|
||||
*/
|
||||
U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
|
||||
U32Bytes getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
|
||||
|
||||
//get the available memory infomation in KiloBytes.
|
||||
static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb);
|
||||
static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb);
|
||||
|
||||
// Retrieve a map of memory statistics. The keys of the map are platform-
|
||||
// dependent. The values are in kilobytes to try to avoid integer overflow.
|
||||
|
||||
@@ -31,9 +31,7 @@
|
||||
#include "u64.h"
|
||||
|
||||
#if LL_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# include "llwin32headerslean.h"
|
||||
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
|
||||
# include <errno.h>
|
||||
# include <sys/time.h>
|
||||
@@ -83,7 +81,7 @@ U32 micro_sleep(U64 us, U32 max_yields)
|
||||
{
|
||||
// max_yields is unused; just fiddle with it to avoid warnings.
|
||||
max_yields = 0;
|
||||
ms_sleep(us / 1000);
|
||||
ms_sleep((U32)(us / 1000));
|
||||
return 0;
|
||||
}
|
||||
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
|
||||
@@ -216,56 +214,68 @@ U64 get_clock_count()
|
||||
#endif
|
||||
|
||||
|
||||
void update_clock_frequencies()
|
||||
TimerInfo::TimerInfo()
|
||||
: mClockFrequency(0.0),
|
||||
mTotalTimeClockCount(0),
|
||||
mLastTotalTimeClockCount(0)
|
||||
{}
|
||||
|
||||
void TimerInfo::update()
|
||||
{
|
||||
gClockFrequency = calc_clock_frequency();
|
||||
gClockFrequencyInv = 1.0/gClockFrequency;
|
||||
gClocksToMicroseconds = gClockFrequencyInv * SEC_TO_MICROSEC;
|
||||
mClockFrequency = calc_clock_frequency();
|
||||
mClockFrequencyInv = 1.0/mClockFrequency;
|
||||
mClocksToMicroseconds = mClockFrequencyInv;
|
||||
}
|
||||
|
||||
TimerInfo& get_timer_info()
|
||||
{
|
||||
static TimerInfo sTimerInfo;
|
||||
return sTimerInfo;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// returns a U64 number that represents the number of
|
||||
// microseconds since the Unix epoch - Jan 1, 1970
|
||||
U64 totalTime()
|
||||
U64MicrosecondsImplicit totalTime()
|
||||
{
|
||||
U64 current_clock_count = get_clock_count();
|
||||
if (!gTotalTimeClockCount)
|
||||
if (!get_timer_info().mTotalTimeClockCount || get_timer_info().mClocksToMicroseconds.value() == 0)
|
||||
{
|
||||
update_clock_frequencies();
|
||||
gTotalTimeClockCount = current_clock_count;
|
||||
get_timer_info().update();
|
||||
get_timer_info().mTotalTimeClockCount = current_clock_count;
|
||||
|
||||
#if LL_WINDOWS
|
||||
// Synch us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
|
||||
// Sync us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
|
||||
// Unix platforms use gettimeofday so they are synced, although this probably isn't a good assumption to
|
||||
// make in the future.
|
||||
|
||||
gTotalTimeClockCount = (U64)(time(NULL) * gClockFrequency);
|
||||
get_timer_info().mTotalTimeClockCount = (U64)(time(NULL) * get_timer_info().mClockFrequency);
|
||||
#endif
|
||||
|
||||
// Update the last clock count
|
||||
gLastTotalTimeClockCount = current_clock_count;
|
||||
get_timer_info().mLastTotalTimeClockCount = current_clock_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LL_LIKELY(current_clock_count >= gLastTotalTimeClockCount))
|
||||
if (current_clock_count >= get_timer_info().mLastTotalTimeClockCount)
|
||||
{
|
||||
// No wrapping, we're all okay.
|
||||
gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount;
|
||||
get_timer_info().mTotalTimeClockCount += current_clock_count - get_timer_info().mLastTotalTimeClockCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We've wrapped. Compensate correctly
|
||||
gTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - gLastTotalTimeClockCount) + current_clock_count;
|
||||
get_timer_info().mTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - get_timer_info().mLastTotalTimeClockCount) + current_clock_count;
|
||||
}
|
||||
|
||||
// Update the last clock count
|
||||
gLastTotalTimeClockCount = current_clock_count;
|
||||
get_timer_info().mLastTotalTimeClockCount = current_clock_count;
|
||||
}
|
||||
|
||||
// Return the total clock tick count in microseconds.
|
||||
return (U64)(gTotalTimeClockCount*gClocksToMicroseconds);
|
||||
U64Microseconds time(get_timer_info().mTotalTimeClockCount*get_timer_info().mClocksToMicroseconds);
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
@@ -273,9 +283,9 @@ U64 totalTime()
|
||||
|
||||
LLTimer::LLTimer()
|
||||
{
|
||||
if (!gClockFrequency)
|
||||
if (!get_timer_info().mClockFrequency)
|
||||
{
|
||||
update_clock_frequencies();
|
||||
get_timer_info().update();
|
||||
}
|
||||
|
||||
mStarted = TRUE;
|
||||
@@ -283,20 +293,32 @@ LLTimer::LLTimer()
|
||||
}
|
||||
|
||||
LLTimer::~LLTimer()
|
||||
{}
|
||||
|
||||
// static
|
||||
void LLTimer::initClass()
|
||||
{
|
||||
if (!sTimer) sTimer = new LLTimer;
|
||||
}
|
||||
|
||||
// static
|
||||
U64 LLTimer::getTotalTime()
|
||||
void LLTimer::cleanupClass()
|
||||
{
|
||||
delete sTimer; sTimer = NULL;
|
||||
}
|
||||
|
||||
// static
|
||||
U64MicrosecondsImplicit LLTimer::getTotalTime()
|
||||
{
|
||||
// simply call into the implementation function.
|
||||
return totalTime();
|
||||
U64MicrosecondsImplicit total_time = totalTime();
|
||||
return total_time;
|
||||
}
|
||||
|
||||
// static
|
||||
F64 LLTimer::getTotalSeconds()
|
||||
F64SecondsImplicit LLTimer::getTotalSeconds()
|
||||
{
|
||||
return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64;
|
||||
return F64Microseconds(U64_to_F64(getTotalTime()));
|
||||
}
|
||||
|
||||
void LLTimer::reset()
|
||||
@@ -343,43 +365,43 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
|
||||
}
|
||||
|
||||
|
||||
F64 LLTimer::getElapsedTimeF64() const
|
||||
F64SecondsImplicit LLTimer::getElapsedTimeF64() const
|
||||
{
|
||||
U64 last = mLastClockCount;
|
||||
return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv;
|
||||
return (F64)getElapsedTimeAndUpdate(last) * get_timer_info().mClockFrequencyInv;
|
||||
}
|
||||
|
||||
F32 LLTimer::getElapsedTimeF32() const
|
||||
F32SecondsImplicit LLTimer::getElapsedTimeF32() const
|
||||
{
|
||||
return (F32)getElapsedTimeF64();
|
||||
}
|
||||
|
||||
F64 LLTimer::getElapsedTimeAndResetF64()
|
||||
F64SecondsImplicit LLTimer::getElapsedTimeAndResetF64()
|
||||
{
|
||||
return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv;
|
||||
return (F64)getElapsedTimeAndUpdate(mLastClockCount) * get_timer_info().mClockFrequencyInv;
|
||||
}
|
||||
|
||||
F32 LLTimer::getElapsedTimeAndResetF32()
|
||||
F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()
|
||||
{
|
||||
return (F32)getElapsedTimeAndResetF64();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LLTimer::setTimerExpirySec(F32 expiration)
|
||||
void LLTimer::setTimerExpirySec(F32SecondsImplicit expiration)
|
||||
{
|
||||
mExpirationTicks = get_clock_count()
|
||||
+ (U64)((F32)(expiration * gClockFrequency));
|
||||
+ (U64)((F32)(expiration * get_timer_info().mClockFrequency.value()));
|
||||
}
|
||||
|
||||
F32 LLTimer::getRemainingTimeF32() const
|
||||
F32SecondsImplicit LLTimer::getRemainingTimeF32() const
|
||||
{
|
||||
U64 cur_ticks = get_clock_count();
|
||||
if (cur_ticks > mExpirationTicks)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return F32((mExpirationTicks - cur_ticks) * gClockFrequencyInv);
|
||||
return F32((mExpirationTicks - cur_ticks) * get_timer_info().mClockFrequencyInv);
|
||||
}
|
||||
|
||||
|
||||
@@ -392,7 +414,7 @@ BOOL LLTimer::checkExpirationAndReset(F32 expiration)
|
||||
}
|
||||
|
||||
mExpirationTicks = cur_ticks
|
||||
+ (U64)((F32)(expiration * gClockFrequency));
|
||||
+ (U64)((F32)(expiration * get_timer_info().mClockFrequency));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -491,20 +513,20 @@ BOOL is_daylight_savings()
|
||||
|
||||
struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
|
||||
{
|
||||
S32 pacific_offset_hours;
|
||||
S32Hours pacific_offset_hours;
|
||||
if (pacific_daylight_time)
|
||||
{
|
||||
pacific_offset_hours = 7;
|
||||
pacific_offset_hours = S32Hours(7);
|
||||
}
|
||||
else
|
||||
{
|
||||
pacific_offset_hours = 8;
|
||||
pacific_offset_hours = S32Hours(8);
|
||||
}
|
||||
|
||||
// We subtract off the PST/PDT offset _before_ getting
|
||||
// "UTC" time, because this will handle wrapping around
|
||||
// for 5 AM UTC -> 10 PM PDT of the previous day.
|
||||
utc_time -= pacific_offset_hours * MIN_PER_HOUR * SEC_PER_MIN;
|
||||
utc_time -= S32SecondsImplicit(pacific_offset_hours);
|
||||
|
||||
// Internal buffer to PST/PDT (see above)
|
||||
struct tm* internal_time = gmtime(&utc_time);
|
||||
@@ -521,7 +543,7 @@ struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
|
||||
}
|
||||
|
||||
|
||||
void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
|
||||
void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring)
|
||||
{
|
||||
U64 hours;
|
||||
U64 minutes;
|
||||
@@ -543,9 +565,9 @@ void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
|
||||
}
|
||||
|
||||
|
||||
void secondsToTimecodeString(F32 current_time, std::string& tcstring)
|
||||
void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring)
|
||||
{
|
||||
microsecondsToTimecodeString((U64)((F64)(SEC_TO_MICROSEC*current_time)), tcstring);
|
||||
microsecondsToTimecodeString(current_time, tcstring);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <string>
|
||||
#include <list>
|
||||
// units conversions
|
||||
#include "llunits.h"
|
||||
#ifndef USEC_PER_SEC
|
||||
const U32 USEC_PER_SEC = 1000000;
|
||||
#endif
|
||||
@@ -61,21 +62,28 @@ public:
|
||||
LLTimer();
|
||||
~LLTimer();
|
||||
|
||||
static void initClass() { if (!sTimer) sTimer = new LLTimer; }
|
||||
static void cleanupClass() { delete sTimer; sTimer = NULL; }
|
||||
static void initClass();
|
||||
static void cleanupClass();
|
||||
|
||||
// Return a high precision number of seconds since the start of
|
||||
// this application instance.
|
||||
static F64 getElapsedSeconds()
|
||||
static F64SecondsImplicit getElapsedSeconds()
|
||||
{
|
||||
if (sTimer)
|
||||
{
|
||||
return sTimer->getElapsedTimeF64();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Return a high precision usec since epoch
|
||||
static U64 getTotalTime();
|
||||
static U64MicrosecondsImplicit getTotalTime();
|
||||
|
||||
// Return a high precision seconds since epoch
|
||||
static F64 getTotalSeconds();
|
||||
static F64SecondsImplicit getTotalSeconds();
|
||||
|
||||
|
||||
// MANIPULATORS
|
||||
@@ -83,19 +91,19 @@ public:
|
||||
void stop() { mStarted = FALSE; }
|
||||
void reset(); // Resets the timer
|
||||
void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time
|
||||
void setTimerExpirySec(F32 expiration);
|
||||
void setTimerExpirySec(F32SecondsImplicit expiration);
|
||||
BOOL checkExpirationAndReset(F32 expiration);
|
||||
BOOL hasExpired() const;
|
||||
F32 getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
|
||||
F64 getElapsedTimeAndResetF64();
|
||||
F32SecondsImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
|
||||
F64SecondsImplicit getElapsedTimeAndResetF64();
|
||||
|
||||
F32 getRemainingTimeF32() const;
|
||||
F32SecondsImplicit getRemainingTimeF32() const;
|
||||
|
||||
static BOOL knownBadTimer();
|
||||
|
||||
// ACCESSORS
|
||||
F32 getElapsedTimeF32() const; // Returns elapsed time in seconds
|
||||
F64 getElapsedTimeF64() const; // Returns elapsed time in seconds
|
||||
F32SecondsImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds
|
||||
F64SecondsImplicit getElapsedTimeF64() const; // Returns elapsed time in seconds
|
||||
|
||||
bool getStarted() const { return mStarted; }
|
||||
|
||||
@@ -106,6 +114,20 @@ public:
|
||||
//
|
||||
// Various functions for initializing/accessing clock and timing stuff. Don't use these without REALLY knowing how they work.
|
||||
//
|
||||
struct TimerInfo
|
||||
{
|
||||
TimerInfo();
|
||||
void update();
|
||||
|
||||
F64HertzImplicit mClockFrequency;
|
||||
F64SecondsImplicit mClockFrequencyInv;
|
||||
F64MicrosecondsImplicit mClocksToMicroseconds;
|
||||
U64 mTotalTimeClockCount;
|
||||
U64 mLastTotalTimeClockCount;
|
||||
};
|
||||
|
||||
TimerInfo& get_timer_info();
|
||||
|
||||
LL_COMMON_API U64 get_clock_count();
|
||||
LL_COMMON_API F64 calc_clock_frequency();
|
||||
LL_COMMON_API void update_clock_frequencies();
|
||||
@@ -160,10 +182,10 @@ LL_COMMON_API BOOL is_daylight_savings();
|
||||
// struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight);
|
||||
LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
|
||||
|
||||
LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
|
||||
LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
|
||||
LL_COMMON_API void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring);
|
||||
LL_COMMON_API void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring);
|
||||
LL_COMMON_API void timeToFormattedString(time_t time, std::string format, std::string ×tr);
|
||||
LL_COMMON_API void timeStructToFormattedString(struct tm * time, std::string format, std::string ×tr);
|
||||
|
||||
U64 LL_COMMON_API totalTime(); // Returns current system time in microseconds
|
||||
U64MicrosecondsImplicit LL_COMMON_API totalTime(); // Returns current system time in microseconds
|
||||
#endif
|
||||
|
||||
129
indra/llcommon/llunits.h
Normal file
129
indra/llcommon/llunits.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* @file llunits.h
|
||||
* @brief Unit definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLUNITTYPE_H
|
||||
#define LL_LLUNITTYPE_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include "llunittype.h"
|
||||
|
||||
//
|
||||
// Unit declarations
|
||||
//
|
||||
|
||||
namespace LLUnits
|
||||
{
|
||||
LL_DECLARE_BASE_UNIT(Bytes, "B");
|
||||
// technically, these are kibibytes, mibibytes, etc. but we should stick with commonly accepted terminology
|
||||
LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, / 1024);
|
||||
LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Kilobytes, / 1024);
|
||||
LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, / 1024);
|
||||
}
|
||||
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bytes);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobytes);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabytes);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes);
|
||||
|
||||
namespace LLUnits
|
||||
{
|
||||
// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology
|
||||
LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, * 8 );
|
||||
LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bits, / 1024);
|
||||
LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Kilobits, / 1024);
|
||||
LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Megabits, / 1024);
|
||||
}
|
||||
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobits);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabits);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits);
|
||||
|
||||
namespace LLUnits
|
||||
{
|
||||
LL_DECLARE_BASE_UNIT(Seconds, "s");
|
||||
LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, / 60);
|
||||
LL_DECLARE_DERIVED_UNIT(Hours, "h", Minutes, / 60);
|
||||
LL_DECLARE_DERIVED_UNIT(Days, "d", Hours, / 24);
|
||||
LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, * 1000);
|
||||
LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Milliseconds, * 1000);
|
||||
LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, * 1000);
|
||||
}
|
||||
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Seconds);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Minutes);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hours);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Days);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milliseconds);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Microseconds);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds);
|
||||
|
||||
namespace LLUnits
|
||||
{
|
||||
LL_DECLARE_BASE_UNIT(Meters, "m");
|
||||
LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, / 1000);
|
||||
LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, * 100);
|
||||
LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, * 1000);
|
||||
}
|
||||
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Meters);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilometers);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Centimeters);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Millimeters);
|
||||
|
||||
namespace LLUnits
|
||||
{
|
||||
// rare units
|
||||
LL_DECLARE_BASE_UNIT(Hertz, "Hz");
|
||||
LL_DECLARE_DERIVED_UNIT(Kilohertz, "KHz", Hertz, / 1000);
|
||||
LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Kilohertz, / 1000);
|
||||
LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, / 1000);
|
||||
|
||||
LL_DECLARE_BASE_UNIT(Radians, "rad");
|
||||
LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 57.29578f);
|
||||
|
||||
LL_DECLARE_BASE_UNIT(Percent, "%");
|
||||
LL_DECLARE_DERIVED_UNIT(Ratio, "x", Percent, / 100);
|
||||
|
||||
LL_DECLARE_BASE_UNIT(Triangles, "tris");
|
||||
LL_DECLARE_DERIVED_UNIT(Kilotriangles, "ktris", Triangles, / 1000);
|
||||
|
||||
} // namespace LLUnits
|
||||
|
||||
// rare units
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hertz);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilohertz);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megahertz);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigahertz);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Radians);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Degrees);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Percent);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ratio);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Triangles);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilotriangles);
|
||||
|
||||
|
||||
#endif // LL_LLUNITTYPE_H
|
||||
838
indra/llcommon/llunittype.h
Normal file
838
indra/llcommon/llunittype.h
Normal file
@@ -0,0 +1,838 @@
|
||||
/**
|
||||
* @file llunit.h
|
||||
* @brief Unit conversion classes
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_UNITTYPE_H
|
||||
#define LL_UNITTYPE_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include "llpreprocessor.h"
|
||||
#include "llerror.h"
|
||||
|
||||
//lightweight replacement of type traits for simple type equality check
|
||||
template<typename S, typename T>
|
||||
struct LLIsSameType
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LLIsSameType<T, T>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
// workaround for decltype() not existing and typeof() not working inline in gcc 4.2
|
||||
template<typename S, typename T>
|
||||
struct LLResultTypeAdd
|
||||
{
|
||||
typedef LL_TYPEOF(S() + T()) type_t;
|
||||
};
|
||||
|
||||
template<typename S, typename T>
|
||||
struct LLResultTypeSubtract
|
||||
{
|
||||
typedef LL_TYPEOF(S() - T()) type_t;
|
||||
};
|
||||
|
||||
template<typename S, typename T>
|
||||
struct LLResultTypeMultiply
|
||||
{
|
||||
typedef LL_TYPEOF(S() * T()) type_t;
|
||||
};
|
||||
|
||||
template<typename S, typename T>
|
||||
struct LLResultTypeDivide
|
||||
{
|
||||
typedef LL_TYPEOF(S() / T(1)) type_t;
|
||||
};
|
||||
|
||||
template<typename S, typename T>
|
||||
struct LLResultTypePromote
|
||||
{
|
||||
typedef LL_TYPEOF((true) ? S() : T()) type_t;
|
||||
};
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
struct LLUnit
|
||||
{
|
||||
typedef LLUnit<STORAGE_TYPE, UNITS> self_t;
|
||||
typedef STORAGE_TYPE storage_t;
|
||||
typedef void is_unit_t;
|
||||
|
||||
// value initialization
|
||||
LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t())
|
||||
: mValue(value)
|
||||
{}
|
||||
|
||||
|
||||
LL_FORCE_INLINE static self_t convert(self_t v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename FROM_STORAGE_TYPE>
|
||||
LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, UNITS> v)
|
||||
{
|
||||
self_t result;
|
||||
result.mValue = (STORAGE_TYPE)v.value();
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename FROM_UNITS>
|
||||
LL_FORCE_INLINE static self_t convert(LLUnit<STORAGE_TYPE, FROM_UNITS> v)
|
||||
{
|
||||
self_t result;
|
||||
STORAGE_TYPE divisor = ll_convert_units(v, result);
|
||||
result.mValue /= divisor;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename FROM_STORAGE_TYPE, typename FROM_UNITS>
|
||||
LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, FROM_UNITS> v)
|
||||
{
|
||||
typedef typename LLResultTypePromote<FROM_STORAGE_TYPE, STORAGE_TYPE>::type_t result_storage_t;
|
||||
LLUnit<result_storage_t, UNITS> result;
|
||||
result_storage_t divisor = ll_convert_units(v, result);
|
||||
result.value(result.value() / divisor);
|
||||
return self_t(result.value());
|
||||
}
|
||||
|
||||
|
||||
// unit initialization and conversion
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
|
||||
: mValue(convert(other).mValue)
|
||||
{}
|
||||
|
||||
LL_FORCE_INLINE storage_t value() const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void value(storage_t value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
template<typename NEW_UNITS>
|
||||
storage_t valueInUnits()
|
||||
{
|
||||
return LLUnit<storage_t, NEW_UNITS>(*this).value();
|
||||
}
|
||||
|
||||
template<typename NEW_UNITS>
|
||||
void valueInUnits(storage_t value)
|
||||
{
|
||||
*this = LLUnit<storage_t, NEW_UNITS>(value);
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator += (self_t other)
|
||||
{
|
||||
mValue += convert(other).mValue;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator -= (self_t other)
|
||||
{
|
||||
mValue -= convert(other).mValue;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator *= (storage_t multiplicand)
|
||||
{
|
||||
mValue *= multiplicand;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator *= (self_t multiplicand)
|
||||
{
|
||||
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator /= (storage_t divisor)
|
||||
{
|
||||
mValue /= divisor;
|
||||
}
|
||||
|
||||
void operator /= (self_t divisor)
|
||||
{
|
||||
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue == convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue != convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue < convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue <= convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue > convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue >= convert(other).value();
|
||||
}
|
||||
|
||||
protected:
|
||||
storage_t mValue;
|
||||
};
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNITS>& unit)
|
||||
{
|
||||
s << unit.value() << UNITS::getUnitLabel();
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNITS>& unit)
|
||||
{
|
||||
STORAGE_TYPE val;
|
||||
s >> val;
|
||||
unit.value(val);
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
|
||||
{
|
||||
typedef LLUnitImplicit<STORAGE_TYPE, UNITS> self_t;
|
||||
typedef typename LLUnit<STORAGE_TYPE, UNITS>::storage_t storage_t;
|
||||
typedef LLUnit<STORAGE_TYPE, UNITS> base_t;
|
||||
|
||||
LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t())
|
||||
: base_t(value)
|
||||
{}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE LLUnitImplicit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
|
||||
: base_t(other)
|
||||
{}
|
||||
|
||||
// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
|
||||
// this allows for interoperability with legacy code
|
||||
LL_FORCE_INLINE operator storage_t() const
|
||||
{
|
||||
return base_t::value();
|
||||
}
|
||||
|
||||
using base_t::operator +=;
|
||||
LL_FORCE_INLINE void operator += (storage_t value)
|
||||
{
|
||||
base_t::mValue += value;
|
||||
}
|
||||
|
||||
// this overload exists to explicitly catch use of another implicit unit
|
||||
// without ambiguity between conversion to storage_t vs conversion to base_t
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE void operator += (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
|
||||
{
|
||||
base_t::mValue += base_t::convert(other).value();
|
||||
}
|
||||
|
||||
using base_t::operator -=;
|
||||
LL_FORCE_INLINE void operator -= (storage_t value)
|
||||
{
|
||||
base_t::mValue -= value;
|
||||
}
|
||||
|
||||
// this overload exists to explicitly catch use of another implicit unit
|
||||
// without ambiguity between conversion to storage_t vs conversion to base_t
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE void operator -= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
|
||||
{
|
||||
base_t::mValue -= base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue == base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue == base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator == (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue == other;
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue != convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue != base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator != (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue != other;
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue < base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue < base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator < (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue < other;
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue <= base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue <= base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator <= (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue <= other;
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue > base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue > base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator > (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue > other;
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue >= base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue >= base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator >= (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue >= other;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
|
||||
{
|
||||
s << unit.value() << UNITS::getUnitLabel();
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
|
||||
{
|
||||
STORAGE_TYPE val;
|
||||
s >> val;
|
||||
unit = val;
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename S1, typename T1, typename S2, typename T2>
|
||||
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out)
|
||||
{
|
||||
S2 divisor(1);
|
||||
|
||||
LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value
|
||||
|| !LLIsSameType<T1, typename T1::base_unit_t>::value
|
||||
|| !LLIsSameType<T2, typename T2::base_unit_t>::value),
|
||||
"conversion requires compatible units");
|
||||
|
||||
if (LLIsSameType<T1, T2>::value)
|
||||
{
|
||||
// T1 and T2 same type, just assign
|
||||
out.value((S2)in.value());
|
||||
}
|
||||
else if (T1::sLevel > T2::sLevel)
|
||||
{
|
||||
// reduce T1
|
||||
LLUnit<S2, typename T1::base_unit_t> new_in;
|
||||
divisor *= (S2)ll_convert_units(in, new_in);
|
||||
divisor *= (S2)ll_convert_units(new_in, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
// reduce T2
|
||||
LLUnit<S2, typename T2::base_unit_t> new_out;
|
||||
divisor *= (S2)ll_convert_units(in, new_out);
|
||||
divisor *= (S2)ll_convert_units(new_out, out);
|
||||
}
|
||||
return divisor;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct LLStorageType
|
||||
{
|
||||
typedef T type_t;
|
||||
};
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
struct LLStorageType<LLUnit<STORAGE_TYPE, UNITS> >
|
||||
{
|
||||
typedef STORAGE_TYPE type_t;
|
||||
};
|
||||
|
||||
// all of these operators need to perform type promotion on the storage type of the units, so they
|
||||
// cannot be expressed as operations on identical types with implicit unit conversion
|
||||
// e.g. typeof(S32Bytes(x) + F32Megabytes(y)) <==> F32Bytes
|
||||
|
||||
//
|
||||
// operator +
|
||||
//
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result += second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
|
||||
LLUnit<STORAGE_TYPE, UNITS> operator + (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
|
||||
{
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
|
||||
return LLUnit<STORAGE_TYPE, UNITS>(0);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
|
||||
LLUnit<STORAGE_TYPE, UNITS> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
|
||||
return LLUnit<STORAGE_TYPE, UNITS>(0);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result += second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result += second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result += LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator + (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
|
||||
result += second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
|
||||
type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
|
||||
result += second;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// operator -
|
||||
//
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result -= second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
|
||||
LLUnit<STORAGE_TYPE, UNITS> operator - (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
|
||||
{
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
|
||||
return LLUnit<STORAGE_TYPE, UNITS>(0);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
|
||||
LLUnit<STORAGE_TYPE, UNITS> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
|
||||
return LLUnit<STORAGE_TYPE, UNITS>(0);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result -= second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result -= second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result -= LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator - (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
|
||||
result -= second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
|
||||
result -= second;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// operator *
|
||||
//
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LLUnit<STORAGE_TYPE1, UNITS1> operator * (LLUnit<STORAGE_TYPE1, UNITS1>, LLUnit<STORAGE_TYPE2, UNITS2>)
|
||||
{
|
||||
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
|
||||
return LLUnit<STORAGE_TYPE1, UNITS1>();
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() * second);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LLUnitImplicit<STORAGE_TYPE1, UNITS1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNITS1>, LLUnitImplicit<STORAGE_TYPE2, UNITS2>)
|
||||
{
|
||||
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
|
||||
return LLUnitImplicit<STORAGE_TYPE1, UNITS1>();
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNITS>(first.value() * second);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// operator /
|
||||
//
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
return first.value() / first.convert(second).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct LLGetUnitLabel
|
||||
{
|
||||
static const char* getUnitLabel() { return ""; }
|
||||
};
|
||||
|
||||
template<typename T, typename STORAGE_T>
|
||||
struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
|
||||
{
|
||||
static const char* getUnitLabel() { return T::getUnitLabel(); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LLUnitLinearOps
|
||||
{
|
||||
typedef LLUnitLinearOps<T> self_t;
|
||||
|
||||
LLUnitLinearOps(T val)
|
||||
: mValue(val),
|
||||
mDivisor(1)
|
||||
{}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator * (OTHER_T other)
|
||||
{
|
||||
return mValue * other;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator / (OTHER_T other)
|
||||
{
|
||||
mDivisor *= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator + (OTHER_T other)
|
||||
{
|
||||
mValue += other * mDivisor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator - (OTHER_T other)
|
||||
{
|
||||
mValue -= other * mDivisor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T mValue;
|
||||
T mDivisor;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LLUnitInverseLinearOps
|
||||
{
|
||||
typedef LLUnitInverseLinearOps<T> self_t;
|
||||
|
||||
LLUnitInverseLinearOps(T val)
|
||||
: mValue(val),
|
||||
mDivisor(1),
|
||||
mMultiplicand(1)
|
||||
{}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator * (OTHER_T other)
|
||||
{
|
||||
mDivisor *= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator / (OTHER_T other)
|
||||
{
|
||||
mValue *= other;
|
||||
mMultiplicand *= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator + (OTHER_T other)
|
||||
{
|
||||
mValue -= other * mMultiplicand;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator - (OTHER_T other)
|
||||
{
|
||||
mValue += other * mMultiplicand;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T mValue;
|
||||
T mDivisor;
|
||||
T mMultiplicand;
|
||||
};
|
||||
|
||||
#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \
|
||||
struct base_unit_name \
|
||||
{ \
|
||||
static const int sLevel = 0; \
|
||||
typedef base_unit_name base_unit_t; \
|
||||
static const char* getUnitLabel() { return unit_label; } \
|
||||
template<typename T> \
|
||||
static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
|
||||
template<typename STORAGE_T, typename UNIT_T> \
|
||||
static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
|
||||
{ return LLUnit<STORAGE_T, base_unit_name>(value); } \
|
||||
}
|
||||
|
||||
|
||||
#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \
|
||||
struct unit_name \
|
||||
{ \
|
||||
static const int sLevel = base_unit_name::sLevel + 1; \
|
||||
typedef base_unit_name base_unit_t; \
|
||||
static const char* getUnitLabel() { return unit_label; } \
|
||||
template<typename T> \
|
||||
static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); } \
|
||||
template<typename STORAGE_T, typename UNIT_T> \
|
||||
static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
|
||||
{ return LLUnit<STORAGE_T, unit_name>(value); } \
|
||||
}; \
|
||||
\
|
||||
template<typename S1, typename S2> \
|
||||
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \
|
||||
{ \
|
||||
typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
|
||||
LLUnitInverseLinearOps<result_storage_t> result = \
|
||||
LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation; \
|
||||
out = LLUnit<S2, base_unit_name>((S2)result.mValue); \
|
||||
return result.mDivisor; \
|
||||
} \
|
||||
\
|
||||
template<typename S1, typename S2> \
|
||||
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \
|
||||
{ \
|
||||
typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
|
||||
LLUnitLinearOps<result_storage_t> result = \
|
||||
LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation; \
|
||||
out = LLUnit<S2, unit_name>((S2)result.mValue); \
|
||||
return result.mDivisor; \
|
||||
}
|
||||
|
||||
#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name) \
|
||||
typedef LLUnit<F32, ns::unit_name> F32##unit_name; \
|
||||
typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\
|
||||
typedef LLUnit<F64, ns::unit_name> F64##unit_name; \
|
||||
typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\
|
||||
typedef LLUnit<S32, ns::unit_name> S32##unit_name; \
|
||||
typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\
|
||||
typedef LLUnit<S64, ns::unit_name> S64##unit_name; \
|
||||
typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\
|
||||
typedef LLUnit<U32, ns::unit_name> U32##unit_name; \
|
||||
typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\
|
||||
typedef LLUnit<U64, ns::unit_name> U64##unit_name; \
|
||||
typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit
|
||||
|
||||
#endif //LL_UNITTYPE_H
|
||||
@@ -27,9 +27,7 @@
|
||||
|
||||
// We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
|
||||
#if LL_WINDOWS
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include "llwin32headers.h"
|
||||
#endif
|
||||
|
||||
#include "lldefs.h"
|
||||
|
||||
42
indra/llcommon/llwin32headers.h
Normal file
42
indra/llcommon/llwin32headers.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file llwin32headers.h
|
||||
* @brief sanitized include of windows header files
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLWINDOWS_H
|
||||
#define LL_LLWINDOWS_H
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
// reset to default, which is lean
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#undef NOMINMAX
|
||||
#endif
|
||||
|
||||
#endif
|
||||
40
indra/llcommon/llwin32headerslean.h
Normal file
40
indra/llcommon/llwin32headerslean.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file llwin32headerslean.h
|
||||
* @brief sanitized include of windows header files
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLWINDOWS_H
|
||||
#define LL_LLWINDOWS_H
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef NOMINMAX
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -37,7 +37,7 @@
|
||||
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) :
|
||||
LLQueuedThread(name, threaded, should_pause)
|
||||
{
|
||||
mDeleteMutex = new LLMutex;
|
||||
mDeleteMutex = new LLMutex();
|
||||
}
|
||||
|
||||
LLWorkerThread::~LLWorkerThread()
|
||||
@@ -199,6 +199,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
|
||||
mWorkerClassName(name),
|
||||
mRequestHandle(LLWorkerThread::nullHandle()),
|
||||
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
|
||||
mMutex(),
|
||||
mWorkFlags(0)
|
||||
{
|
||||
if (!mWorkerThread)
|
||||
@@ -345,10 +346,14 @@ bool LLWorkerClass::checkWork(bool aborting)
|
||||
}
|
||||
|
||||
LLQueuedThread::status_t status = workreq->getStatus();
|
||||
if (status == LLWorkerThread::STATUS_COMPLETE || status == LLWorkerThread::STATUS_ABORTED)
|
||||
if (status == LLWorkerThread::STATUS_ABORTED)
|
||||
{
|
||||
complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED);
|
||||
abort = true;
|
||||
}
|
||||
else if (status == LLWorkerThread::STATUS_COMPLETE)
|
||||
{
|
||||
complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED);
|
||||
abort = status == LLWorkerThread::STATUS_ABORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -4699,7 +4699,7 @@ LLVolumeFace::~LLVolumeFace()
|
||||
|
||||
void LLVolumeFace::freeData()
|
||||
{
|
||||
ll_aligned_free(mPositions);
|
||||
ll_aligned_free<64>(mPositions);
|
||||
mPositions = NULL;
|
||||
|
||||
//normals and texture coordinates are part of the same buffer as mPositions, do not free them separately
|
||||
@@ -5273,7 +5273,7 @@ void LLVolumeFace::cacheOptimize()
|
||||
//allocate space for new buffer
|
||||
S32 num_verts = mNumVertices;
|
||||
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
|
||||
LLVector4a* pos = (LLVector4a*) ll_aligned_malloc(sizeof(LLVector4a)*2*num_verts+size, 64);
|
||||
LLVector4a* pos = (LLVector4a*) ll_aligned_malloc<64>(sizeof(LLVector4a)*2*num_verts+size);
|
||||
LLVector4a* norm = pos + num_verts;
|
||||
LLVector2* tc = (LLVector2*) (norm + num_verts);
|
||||
|
||||
@@ -5323,7 +5323,7 @@ void LLVolumeFace::cacheOptimize()
|
||||
mIndices[i] = new_idx[mIndices[i]];
|
||||
}
|
||||
|
||||
ll_aligned_free(mPositions);
|
||||
ll_aligned_free<64>(mPositions);
|
||||
// DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
||||
ll_aligned_free_16(mWeights);
|
||||
ll_aligned_free_16(mTangents);
|
||||
@@ -6041,7 +6041,7 @@ void LLVolumeFace::createTangents()
|
||||
|
||||
void LLVolumeFace::resizeVertices(S32 num_verts)
|
||||
{
|
||||
ll_aligned_free(mPositions);
|
||||
ll_aligned_free<64>(mPositions);
|
||||
//DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
||||
ll_aligned_free_16(mTangents);
|
||||
|
||||
@@ -6052,7 +6052,7 @@ void LLVolumeFace::resizeVertices(S32 num_verts)
|
||||
//pad texture coordinate block end to allow for QWORD reads
|
||||
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
|
||||
|
||||
mPositions = (LLVector4a*) ll_aligned_malloc(sizeof(LLVector4a)*2*num_verts+size, 64);
|
||||
mPositions = (LLVector4a*) ll_aligned_malloc<64>(sizeof(LLVector4a)*2*num_verts+size);
|
||||
mNormals = mPositions+num_verts;
|
||||
mTexCoords = (LLVector2*) (mNormals+num_verts);
|
||||
|
||||
@@ -6092,7 +6092,7 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
|
||||
|
||||
LLVector4a* old_buf = mPositions;
|
||||
|
||||
mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64);
|
||||
mPositions = (LLVector4a*) ll_aligned_malloc<64>(new_size);
|
||||
mNormals = mPositions+new_verts;
|
||||
mTexCoords = (LLVector2*) (mNormals+new_verts);
|
||||
|
||||
@@ -6111,7 +6111,7 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
|
||||
//tex coords
|
||||
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tc_size);
|
||||
|
||||
ll_aligned_free(old_buf);
|
||||
ll_aligned_free<64>(old_buf);
|
||||
|
||||
//<singu>
|
||||
}
|
||||
@@ -6120,6 +6120,7 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
|
||||
//just clear tangents
|
||||
ll_aligned_free_16(mTangents);
|
||||
mTangents = NULL;
|
||||
ll_aligned_free<64>(old_buf);
|
||||
|
||||
mNumAllocatedVertices = new_verts;
|
||||
|
||||
@@ -6220,7 +6221,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
|
||||
|
||||
//allocate new buffer space
|
||||
LLVector4a* old_buf = mPositions;
|
||||
mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64);
|
||||
mPositions = (LLVector4a*) ll_aligned_malloc<64>(new_size);
|
||||
mNormals = mPositions + new_count;
|
||||
mTexCoords = (LLVector2*) (mNormals+new_count);
|
||||
|
||||
|
||||
@@ -298,7 +298,7 @@ LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const
|
||||
return mGLTexturep->getAddressMode() ;
|
||||
}
|
||||
|
||||
S32 LLGLTexture::getTextureMemory() const
|
||||
S32Bytes LLGLTexture::getTextureMemory() const
|
||||
{
|
||||
llassert(mGLTexturep.notNull()) ;
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ public:
|
||||
S32 getDiscardLevel() const;
|
||||
S8 getComponents() const;
|
||||
BOOL getBoundRecently() const;
|
||||
S32 getTextureMemory() const ;
|
||||
S32Bytes getTextureMemory() const ;
|
||||
LLGLenum getPrimaryFormat() const;
|
||||
BOOL getIsAlphaMask(const F32 max_rmse) const ;
|
||||
LLTexUnit::eTextureType getTarget(void) const ;
|
||||
|
||||
@@ -50,9 +50,9 @@ U32 wpo2(U32 i);
|
||||
|
||||
U32 LLImageGL::sUniqueCount = 0;
|
||||
U32 LLImageGL::sBindCount = 0;
|
||||
S32 LLImageGL::sGlobalTextureMemoryInBytes = 0;
|
||||
S32 LLImageGL::sBoundTextureMemoryInBytes = 0;
|
||||
S32 LLImageGL::sCurBoundTextureMemory = 0;
|
||||
S32Bytes LLImageGL::sGlobalTextureMemory(0);
|
||||
S32Bytes LLImageGL::sBoundTextureMemory(0);
|
||||
S32Bytes LLImageGL::sCurBoundTextureMemory(0);
|
||||
S32 LLImageGL::sCount = 0;
|
||||
|
||||
BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
|
||||
@@ -78,9 +78,9 @@ S32 LLImageGL::sCurTexPickSize = -1 ;
|
||||
LLPointer<LLImageGL> LLImageGL::sHighlightTexturep = NULL;
|
||||
S32 LLImageGL::sMaxCategories = 1 ;
|
||||
|
||||
std::vector<S32> LLImageGL::sTextureMemByCategory;
|
||||
std::vector<S32> LLImageGL::sTextureMemByCategoryBound ;
|
||||
std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ;
|
||||
std::vector<S32Bytes> LLImageGL::sTextureMemByCategory;
|
||||
std::vector<S32Bytes> LLImageGL::sTextureMemByCategoryBound ;
|
||||
std::vector<S32Bytes> LLImageGL::sTextureCurMemByCategoryBound ;
|
||||
//------------------------
|
||||
// ****************************************************************************************************
|
||||
//End for texture auditing use only
|
||||
@@ -292,8 +292,8 @@ void LLImageGL::updateStats(F32 current_time)
|
||||
{
|
||||
LLFastTimer t(FTM_IMAGE_UPDATE_STATS);
|
||||
sLastFrameTime = current_time;
|
||||
sBoundTextureMemoryInBytes = sCurBoundTextureMemory;
|
||||
sCurBoundTextureMemory = 0;
|
||||
sBoundTextureMemory = sCurBoundTextureMemory;
|
||||
sCurBoundTextureMemory = S32Bytes(0);
|
||||
|
||||
if(gAuditTexture)
|
||||
{
|
||||
@@ -305,22 +305,22 @@ void LLImageGL::updateStats(F32 current_time)
|
||||
for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++)
|
||||
{
|
||||
sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ;
|
||||
sTextureCurMemByCategoryBound[i] = 0 ;
|
||||
sTextureCurMemByCategoryBound[i] = (S32Bytes)0 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category)
|
||||
S32 LLImageGL::updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category)
|
||||
{
|
||||
if(gAuditTexture && ncomponents > 0 && category > -1)
|
||||
{
|
||||
sTextureCurBoundCounter[getTextureCounterIndex(mem / ncomponents)]++ ;
|
||||
sTextureCurBoundCounter[getTextureCounterIndex(mem.value() / ncomponents)]++ ;
|
||||
sTextureCurMemByCategoryBound[category] += mem ;
|
||||
}
|
||||
|
||||
LLImageGL::sCurBoundTextureMemory += mem ;
|
||||
return LLImageGL::sCurBoundTextureMemory;
|
||||
return LLImageGL::sCurBoundTextureMemory.value();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -480,7 +480,7 @@ void LLImageGL::init(BOOL usemipmaps)
|
||||
// so that it is obvious by visual inspection if we forgot to
|
||||
// init a field.
|
||||
|
||||
mTextureMemory = 0;
|
||||
mTextureMemory = (S32Bytes)0;
|
||||
mLastBindTime = 0.f;
|
||||
|
||||
mPickMask = NULL;
|
||||
@@ -644,7 +644,7 @@ void LLImageGL::forceUpdateBindStats(void) const
|
||||
mLastBindTime = sLastFrameTime;
|
||||
}
|
||||
|
||||
BOOL LLImageGL::updateBindStats(S32 tex_mem) const
|
||||
BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const
|
||||
{
|
||||
if (mTexName != 0)
|
||||
{
|
||||
@@ -1677,7 +1677,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
|
||||
|
||||
if (old_name != 0)
|
||||
{
|
||||
sGlobalTextureMemoryInBytes -= mTextureMemory;
|
||||
sGlobalTextureMemory -= mTextureMemory;
|
||||
|
||||
if(gAuditTexture)
|
||||
{
|
||||
@@ -1689,8 +1689,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
mTextureMemory = getMipBytes(discard_level);
|
||||
sGlobalTextureMemoryInBytes += mTextureMemory;
|
||||
mTextureMemory = (S32Bytes)getMipBytes(discard_level);
|
||||
sGlobalTextureMemory += mTextureMemory;
|
||||
|
||||
if(gAuditTexture)
|
||||
{
|
||||
@@ -1829,14 +1829,14 @@ void LLImageGL::destroyGLTexture()
|
||||
{
|
||||
if (mTexName != 0)
|
||||
{
|
||||
if(mTextureMemory)
|
||||
if(mTextureMemory != S32Bytes(0))
|
||||
{
|
||||
if(gAuditTexture)
|
||||
{
|
||||
decTextureCounter(mTextureMemory, mComponents, mCategory) ;
|
||||
}
|
||||
sGlobalTextureMemoryInBytes -= mTextureMemory;
|
||||
mTextureMemory = 0;
|
||||
sGlobalTextureMemory -= mTextureMemory;
|
||||
mTextureMemory = (S32Bytes)0;
|
||||
}
|
||||
|
||||
LLImageGL::deleteTextures(1, &mTexName);
|
||||
@@ -2356,19 +2356,19 @@ S32 LLImageGL::getTextureCounterIndex(U32 val)
|
||||
}
|
||||
|
||||
//static
|
||||
void LLImageGL::incTextureCounter(U32 val, S32 ncomponents, S32 category)
|
||||
void LLImageGL::incTextureCounter(S32Bytes val, S32 ncomponents, S32 category)
|
||||
{
|
||||
sTextureLoadedCounter[getTextureCounterIndex(val)]++ ;
|
||||
sTextureLoadedCounter[getTextureCounterIndex(val.value())]++ ;
|
||||
if(category > -1)
|
||||
sTextureMemByCategory[category] += (S32)val * ncomponents ;
|
||||
sTextureMemByCategory[category] += (S32Bytes)val * ncomponents ;
|
||||
}
|
||||
|
||||
//static
|
||||
void LLImageGL::decTextureCounter(U32 val, S32 ncomponents, S32 category)
|
||||
void LLImageGL::decTextureCounter(S32Bytes val, S32 ncomponents, S32 category)
|
||||
{
|
||||
sTextureLoadedCounter[getTextureCounterIndex(val)]-- ;
|
||||
sTextureLoadedCounter[getTextureCounterIndex(val.value())]-- ;
|
||||
if(category > -1)
|
||||
sTextureMemByCategory[category] -= (S32)val * ncomponents ;
|
||||
sTextureMemByCategory[category] -= (S32Bytes)val * ncomponents ;
|
||||
}
|
||||
|
||||
void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size)
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "llpointer.h"
|
||||
#include "llrefcount.h"
|
||||
#include "v2math.h"
|
||||
#include "llunits.h"
|
||||
|
||||
#include "llrender.h"
|
||||
|
||||
@@ -55,7 +56,7 @@ public:
|
||||
static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);
|
||||
static S32 dataFormatComponents(S32 dataformat);
|
||||
|
||||
BOOL updateBindStats(S32 tex_mem) const ;
|
||||
BOOL updateBindStats(S32Bytes tex_mem) const ;
|
||||
F32 getTimePassedSinceLastBound();
|
||||
void forceUpdateBindStats(void) const;
|
||||
|
||||
@@ -68,7 +69,7 @@ public:
|
||||
static void dirtyTexOptions();
|
||||
|
||||
// Sometimes called externally for textures not using LLImageGL (should go away...)
|
||||
static S32 updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) ;
|
||||
static S32 updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) ;
|
||||
|
||||
static bool checkSize(S32 width, S32 height);
|
||||
|
||||
@@ -172,7 +173,7 @@ public:
|
||||
void setNeedsAlphaAndPickMask(BOOL need_mask);
|
||||
public:
|
||||
// Various GL/Rendering options
|
||||
S32 mTextureMemory;
|
||||
S32Bytes mTextureMemory;
|
||||
mutable F32 mLastBindTime; // last time this was bound, by discard level
|
||||
|
||||
private:
|
||||
@@ -228,9 +229,9 @@ public:
|
||||
static F32 sLastFrameTime;
|
||||
|
||||
// Global memory statistics
|
||||
static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem
|
||||
static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame
|
||||
static S32 sCurBoundTextureMemory; // Tracks bound texmem for current frame
|
||||
static S32Bytes sGlobalTextureMemory; // Tracks main memory texmem
|
||||
static S32Bytes sBoundTextureMemory; // Tracks bound texmem for last completed frame
|
||||
static S32Bytes sCurBoundTextureMemory; // Tracks bound texmem for current frame
|
||||
static U32 sBindCount; // Tracks number of texture binds for current frame
|
||||
static U32 sUniqueCount; // Tracks number of unique texture binds for current frame
|
||||
static BOOL sGlobalUseAnisotropic;
|
||||
@@ -274,8 +275,8 @@ public:
|
||||
|
||||
static void setHighlightTexture(S32 category) ;
|
||||
static S32 getTextureCounterIndex(U32 val) ;
|
||||
static void incTextureCounter(U32 val, S32 ncomponents, S32 category) ;
|
||||
static void decTextureCounter(U32 val, S32 ncomponents, S32 category) ;
|
||||
static void incTextureCounter(S32Bytes val, S32 ncomponents, S32 category) ;
|
||||
static void decTextureCounter(S32Bytes val, S32 ncomponents, S32 category) ;
|
||||
static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ;
|
||||
static void resetCurTexSizebar();
|
||||
//----------------------------------------
|
||||
@@ -283,9 +284,9 @@ public:
|
||||
//for debug use: show texture category distribution
|
||||
//----------------------------------------
|
||||
|
||||
static std::vector<S32> sTextureMemByCategory;
|
||||
static std::vector<S32> sTextureMemByCategoryBound ;
|
||||
static std::vector<S32> sTextureCurMemByCategoryBound ;
|
||||
static std::vector<S32Bytes> sTextureMemByCategory;
|
||||
static std::vector<S32Bytes> sTextureMemByCategoryBound ;
|
||||
static std::vector<S32Bytes> sTextureCurMemByCategoryBound ;
|
||||
//----------------------------------------
|
||||
// ****************************************************************************************************
|
||||
//End of definitions for texture auditing use only
|
||||
|
||||
@@ -187,7 +187,7 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed)
|
||||
if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
|
||||
{
|
||||
glBufferDataARB(mType, size, 0, mUsage);
|
||||
ret = (U8*) ll_aligned_malloc(size, 64);
|
||||
ret = (U8*) ll_aligned_malloc<64>(size);
|
||||
}
|
||||
else
|
||||
{ //always use a true hint of static draw when allocating non-client-backed buffers
|
||||
@@ -240,7 +240,7 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size)
|
||||
llassert(vbo_block_size(size) == size);
|
||||
|
||||
deleteBuffer(name);
|
||||
ll_aligned_free((U8*) buffer);
|
||||
ll_aligned_free<64>((U8*) buffer);
|
||||
|
||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||
{
|
||||
@@ -294,7 +294,7 @@ void LLVBOPool::cleanup()
|
||||
|
||||
if (r.mClientData)
|
||||
{
|
||||
ll_aligned_free((void*) r.mClientData);
|
||||
ll_aligned_free<64>((void*) r.mClientData);
|
||||
}
|
||||
|
||||
l.pop_front();
|
||||
|
||||
@@ -415,7 +415,7 @@ LLNotification::LLNotification(const LLNotification::Params& p) :
|
||||
mTimestamp(p.timestamp),
|
||||
mSubstitutions(p.substitutions),
|
||||
mPayload(p.payload),
|
||||
mExpiresAt(0),
|
||||
mExpiresAt(F64SecondsImplicit()),
|
||||
mResponseFunctorName(p.functor_name),
|
||||
mTemporaryResponder(p.mTemporaryResponder),
|
||||
mRespondedTo(false),
|
||||
|
||||
@@ -279,7 +279,7 @@ BOOL gUseWireframe = FALSE;
|
||||
LLVFS* gStaticVFS = NULL;
|
||||
|
||||
LLMemoryInfo gSysMemory;
|
||||
U64 gMemoryAllocated = 0; // updated in display_stats() in llviewerdisplay.cpp
|
||||
U64Bytes gMemoryAllocated(0); // updated in display_stats() in llviewerdisplay.cpp
|
||||
|
||||
std::string gLastVersionChannel;
|
||||
|
||||
@@ -955,9 +955,8 @@ bool LLAppViewer::init()
|
||||
|
||||
// get RAM data from XML
|
||||
std::stringstream minRAMString(LLNotificationTemplates::instance().getGlobalString("UnsupportedRAMAmount"));
|
||||
U64 minRAM = 0;
|
||||
U64Bytes minRAM;
|
||||
minRAMString >> minRAM;
|
||||
minRAM = minRAM * 1024 * 1024;
|
||||
|
||||
if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
|
||||
{
|
||||
@@ -1037,7 +1036,7 @@ void LLAppViewer::initMaxHeapSize()
|
||||
|
||||
//F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ;
|
||||
|
||||
F32 max_heap_size_gb = gSavedSettings.getF32("MaxHeapSize") ;
|
||||
F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ;
|
||||
|
||||
//This is all a bunch of CRAP. We run LAA on windows. 64bit windows supports LAA out of the box. 32bit does not, unless PAE is on.
|
||||
#if LL_WINDOWS
|
||||
@@ -1051,7 +1050,7 @@ void LLAppViewer::initMaxHeapSize()
|
||||
|
||||
if(fnIsWow64Process && fnIsWow64Process(GetCurrentProcess(), &bWow64Process) && bWow64Process)
|
||||
{
|
||||
max_heap_size_gb = 3.7f;
|
||||
max_heap_size_gb = F32Gigabytes(3.7f);
|
||||
}
|
||||
else if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"), &hKey))
|
||||
{
|
||||
@@ -1060,7 +1059,7 @@ void LLAppViewer::initMaxHeapSize()
|
||||
if(ERROR_SUCCESS == RegQueryValueEx(hKey, TEXT("PhysicalAddressExtension"), NULL, NULL, (LPBYTE)&dwResult, &dwSize))
|
||||
{
|
||||
if(dwResult)
|
||||
max_heap_size_gb = 3.7f;
|
||||
max_heap_size_gb = F32Gigabytes(3.7f);
|
||||
}
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
@@ -2694,8 +2693,8 @@ void LLAppViewer::writeSystemInfo()
|
||||
gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
|
||||
gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
|
||||
|
||||
gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB());
|
||||
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated>>10); // MB -> KB
|
||||
gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB().value());
|
||||
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated.valueInUnits<LLUnits::Kilobytes>());
|
||||
gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple();
|
||||
|
||||
// The user is not logged on yet, but record the current grid choice login url
|
||||
|
||||
@@ -333,7 +333,7 @@ extern BOOL gUseWireframe;
|
||||
extern LLVFS *gStaticVFS;
|
||||
|
||||
extern LLMemoryInfo gSysMemory;
|
||||
extern U64 gMemoryAllocated;
|
||||
extern U64Bytes gMemoryAllocated;
|
||||
|
||||
extern std::string gLastVersionChannel;
|
||||
|
||||
|
||||
@@ -676,7 +676,7 @@ void LLFeatureManager::applyBaseMasks()
|
||||
maskFeatures(gpustr);
|
||||
|
||||
// now mask cpu type ones
|
||||
if (gSysMemory.getPhysicalMemoryClamped() <= 256*1024*1024)
|
||||
if (gSysMemory.getPhysicalMemoryClamped() <= U32Megabytes(256))
|
||||
{
|
||||
maskFeatures("RAM256MB");
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ LLFloaterAbout::LLFloaterAbout()
|
||||
else
|
||||
support.append(" None\n"); */
|
||||
|
||||
U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024;
|
||||
U32Megabytes memory = gSysMemory.getPhysicalMemoryKB();
|
||||
// Moved hack adjustment to Windows memory size into llsys.cpp
|
||||
|
||||
std::string mem_text = llformat("Memory: %u MB\n", memory );
|
||||
|
||||
@@ -472,9 +472,13 @@ void LLPanelDisplay::refreshEnabledState()
|
||||
mWindowSizeLabel->setVisible(!isFullScreen);
|
||||
mCtrlWindowSize->setVisible(!isFullScreen);
|
||||
|
||||
F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
|
||||
S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting();
|
||||
S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier);
|
||||
|
||||
// Hardware tab
|
||||
getChild<LLUICtrl>("GrapicsCardTextureMemory")->setMinValue(LLViewerTextureList::getMinVideoRamSetting());
|
||||
getChild<LLUICtrl>("GrapicsCardTextureMemory")->setMaxValue(LLViewerTextureList::getMaxVideoRamSetting());
|
||||
getChild<LLUICtrl>("GrapicsCardTextureMemory")->setMinValue(min_tex_mem.value());
|
||||
getChild<LLUICtrl>("GrapicsCardTextureMemory")->setMaxValue(max_tex_mem.value());
|
||||
|
||||
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
|
||||
!gGLManager.mHasVertexBufferObject)
|
||||
|
||||
@@ -619,11 +619,25 @@ class LLVolumeGeometryManager: public LLGeometryManager
|
||||
DISTANCE_SORT
|
||||
} eSortType;
|
||||
|
||||
LLVolumeGeometryManager();
|
||||
virtual ~LLVolumeGeometryManager();
|
||||
virtual void rebuildGeom(LLSpatialGroup* group);
|
||||
virtual void rebuildMesh(LLSpatialGroup* group);
|
||||
virtual void getGeometry(LLSpatialGroup* group);
|
||||
void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE);
|
||||
void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type);
|
||||
private:
|
||||
void allocateFaces(U32 pMaxFaceCount);
|
||||
void freeFaces();
|
||||
|
||||
static int32_t sInstanceCount;
|
||||
static LLFace** sFullbrightFaces;
|
||||
static LLFace** sBumpFaces;
|
||||
static LLFace** sSimpleFaces;
|
||||
static LLFace** sNormFaces;
|
||||
static LLFace** sSpecFaces;
|
||||
static LLFace** sNormSpecFaces;
|
||||
static LLFace** sAlphaFaces;
|
||||
};
|
||||
|
||||
//spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp)
|
||||
|
||||
@@ -129,8 +129,8 @@ public:
|
||||
// debug
|
||||
S32 getNumReads() { return mReaders.size(); }
|
||||
S32 getNumWrites() { return mWriters.size(); }
|
||||
S64 getUsage() { return mTexturesSizeTotal; }
|
||||
S64 getMaxUsage() { return sCacheMaxTexturesSize; }
|
||||
S64Bytes getUsage() { return S64Bytes(mTexturesSizeTotal); }
|
||||
S64Bytes getMaxUsage() { return S64Bytes(sCacheMaxTexturesSize); }
|
||||
U32 getEntries() { return mHeaderEntriesInfo.mEntries; }
|
||||
U32 getMaxEntries() { return sCacheMaxEntries; };
|
||||
BOOL isInCache(const LLUUID& id) ;
|
||||
@@ -202,7 +202,7 @@ private:
|
||||
typedef std::map<LLUUID,S32> size_map_t;
|
||||
size_map_t mTexturesSizeMap;
|
||||
S64 mTexturesSizeTotal;
|
||||
LLAtomic32<BOOL> mDoPurge;
|
||||
LLAtomic32<bool> mDoPurge;
|
||||
|
||||
typedef std::map<S32, Entry> idx_entry_map_t;
|
||||
idx_entry_map_t mUpdatedEntryMap;
|
||||
|
||||
@@ -316,11 +316,11 @@ private:
|
||||
U8 mImageCodec;
|
||||
|
||||
LLViewerAssetStats::duration_t mMetricsStartTime;
|
||||
unsigned int mHttpReplySize; // Actual received data size
|
||||
unsigned int mHttpReplyOffset; // Actual received data offset
|
||||
U32 mHttpReplySize, // Actual received data size
|
||||
mHttpReplyOffset; // Actual received data offset
|
||||
// State history
|
||||
U32 mCacheReadCount;
|
||||
U32 mCacheWriteCount;
|
||||
U32 mCacheReadCount,
|
||||
mCacheWriteCount;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -425,7 +425,7 @@ public:
|
||||
worker->setGetStatus(mStatus, mReason);
|
||||
LL_WARNS() << "CURL GET FAILED, status:" << mStatus << " reason:" << mReason << LL_ENDL;
|
||||
}
|
||||
S32 data_size = worker->callbackHttpGet(mReplyOffset, mReplyLength, channels, buffer, partial, success);
|
||||
S32BytesImplicit data_size = worker->callbackHttpGet(mReplyOffset, mReplyLength, channels, buffer, partial, success);
|
||||
|
||||
if(log_texture_traffic && data_size > 0)
|
||||
{
|
||||
|
||||
@@ -407,7 +407,7 @@ void LLTextureBar::draw()
|
||||
default:;
|
||||
};
|
||||
std::string num_str = llformat("%4dx%4d (%+d) %7d %s", mImagep->getWidth(), mImagep->getHeight(),
|
||||
mImagep->getDiscardLevel(), mImagep->hasGLTexture() ? mImagep->getTextureMemory() : 0, boost_lvl.c_str());
|
||||
mImagep->getDiscardLevel(), mImagep->hasGLTexture() ? mImagep->getTextureMemory().value() : 0, boost_lvl.c_str());
|
||||
LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, title_x4, getRect().getHeight(), color,
|
||||
LLFontGL::LEFT, LLFontGL::TOP);
|
||||
}
|
||||
@@ -564,17 +564,17 @@ private:
|
||||
|
||||
void LLGLTexMemBar::draw()
|
||||
{
|
||||
S32 bound_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sBoundTextureMemoryInBytes);
|
||||
S32 max_bound_mem = LLViewerTexture::sMaxBoundTextureMemInMegaBytes;
|
||||
S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sTotalTextureMemoryInBytes);
|
||||
S32 max_total_mem = LLViewerTexture::sMaxTotalTextureMemInMegaBytes;
|
||||
S32Megabytes bound_mem = LLViewerTexture::sBoundTextureMemory;
|
||||
S32Megabytes max_bound_mem = LLViewerTexture::sMaxBoundTextureMemory;
|
||||
S32Megabytes total_mem = LLViewerTexture::sTotalTextureMemory;
|
||||
S32Megabytes max_total_mem = LLViewerTexture::sMaxTotalTextureMem;
|
||||
F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;
|
||||
F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ;
|
||||
F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ;
|
||||
S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
|
||||
S32 v_offset = 0;
|
||||
F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024);
|
||||
F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024);
|
||||
F32 cache_usage = LLAppViewer::getTextureCache()->getUsage().valueInUnits<LLUnits::Megabytes>();
|
||||
F32 cache_max_usage = LLAppViewer::getTextureCache()->getMaxUsage().valueInUnits<LLUnits::Megabytes>();
|
||||
S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
|
||||
S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f);
|
||||
F32Bytes total_texture_downloaded = gTotalTextureData;
|
||||
F32Bytes total_object_downloaded = gTotalObjectData;
|
||||
U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests();
|
||||
//----------------------------------------------------------------------------
|
||||
LLGLSUIDefault gls_ui;
|
||||
@@ -588,10 +588,10 @@ void LLGLTexMemBar::draw()
|
||||
global_raw_memory = *AIAccess<S32>(LLImageRaw::sGlobalRawMemory);
|
||||
}
|
||||
text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d",
|
||||
total_mem,
|
||||
max_total_mem,
|
||||
bound_mem,
|
||||
max_bound_mem,
|
||||
total_mem.value(),
|
||||
max_total_mem.value(),
|
||||
bound_mem.value(),
|
||||
max_bound_mem.value(),
|
||||
LLRenderTarget::sBytesAllocated/(1024*1024),
|
||||
global_raw_memory >> 20, discard_bias,
|
||||
cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded, total_http_requests);
|
||||
@@ -890,7 +890,7 @@ void LLTextureView::draw()
|
||||
|
||||
if (mPrintList)
|
||||
{
|
||||
S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory() : 0 ;
|
||||
S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory().value() : 0 ;
|
||||
LL_INFOS() << imagep->getID()
|
||||
<< "\t" << tex_mem
|
||||
<< "\t" << imagep->getBoostLevel()
|
||||
@@ -1317,7 +1317,7 @@ void LLTextureSizeView::drawTextureCategoryGraph()
|
||||
for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
|
||||
{
|
||||
U32 k = LLViewerTexture::getIndexFromCategory(i) ;
|
||||
mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k] >> 20, LLImageGL::sTextureMemByCategoryBound[k] >> 20, size_bar_scale) ;
|
||||
mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k].value() >> 20, LLImageGL::sTextureMemByCategoryBound[k].value() >> 20, size_bar_scale) ;
|
||||
mTextureSizeBar[i]->draw() ;
|
||||
}
|
||||
LLImageGL::resetCurTexSizebar();
|
||||
@@ -1335,7 +1335,7 @@ F32 LLTextureSizeView::drawTextureCategoryDistributionGraph()
|
||||
S32 count = 0 ;
|
||||
for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++)
|
||||
{
|
||||
S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ;
|
||||
S32 tmp = LLImageGL::sTextureMemByCategory[i].value() >> 20 ;
|
||||
if(tmp > count)
|
||||
{
|
||||
count = tmp ;
|
||||
|
||||
@@ -325,7 +325,7 @@ static bool handleMaxPartCountChanged(const LLSD& newvalue)
|
||||
|
||||
static bool handleVideoMemoryChanged(const LLSD& newvalue)
|
||||
{
|
||||
gTextureList.updateMaxResidentTexMem(newvalue.asInteger());
|
||||
gTextureList.updateMaxResidentTexMem(S32Megabytes(newvalue.asInteger()));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -236,9 +236,9 @@ void display_stats()
|
||||
F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
|
||||
if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
|
||||
{
|
||||
gMemoryAllocated = LLMemory::getCurrentRSS();
|
||||
U32 memory = (U32)(gMemoryAllocated / (1024*1024));
|
||||
LL_INFOS() << llformat("MEMORY: %d MB", memory) << LL_ENDL;
|
||||
gMemoryAllocated = (U64Bytes)LLMemory::getCurrentRSS();
|
||||
U32Megabytes memory = gMemoryAllocated;
|
||||
LL_INFOS() << llformat("MEMORY: %d MB", memory.value()) << LL_ENDL;
|
||||
LL_INFOS() << "THREADS: "<< LLThread::getCount() << LL_ENDL;
|
||||
LL_INFOS() << "MALLOC: " << SGMemStat::getPrintableStat() <<LL_ENDL;
|
||||
LLMemory::logMemoryInfo(TRUE) ;
|
||||
|
||||
@@ -2809,7 +2809,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
|
||||
LLSD args;
|
||||
args["SUBJECT"] = subj;
|
||||
args["MESSAGE"] = mes;
|
||||
LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).timestamp(timestamp));
|
||||
LLDate notice_date = LLDate(timestamp).notNull() ? LLDate(timestamp) : LLDate::now();
|
||||
LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).timestamp(notice_date));
|
||||
}
|
||||
|
||||
// Also send down the old path for now.
|
||||
@@ -5162,18 +5163,18 @@ void send_agent_update(BOOL force_send, BOOL send_reliable)
|
||||
|
||||
// *TODO: Remove this dependency, or figure out a better way to handle
|
||||
// this hack.
|
||||
extern U32 gObjectBits;
|
||||
extern U32Bits gObjectData;
|
||||
|
||||
void process_object_update(LLMessageSystem *mesgsys, void **user_data)
|
||||
{
|
||||
// Update the data counters
|
||||
if (mesgsys->getReceiveCompressedSize())
|
||||
{
|
||||
gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
|
||||
gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
gObjectBits += mesgsys->getReceiveSize() * 8;
|
||||
gObjectData += (U32Bytes)mesgsys->getReceiveSize();
|
||||
}
|
||||
|
||||
// Update the object...
|
||||
@@ -5185,11 +5186,11 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data
|
||||
// Update the data counters
|
||||
if (mesgsys->getReceiveCompressedSize())
|
||||
{
|
||||
gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
|
||||
gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
gObjectBits += mesgsys->getReceiveSize() * 8;
|
||||
gObjectData += (U32Bytes)mesgsys->getReceiveSize();
|
||||
}
|
||||
|
||||
// Update the object...
|
||||
@@ -5201,11 +5202,11 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
|
||||
// Update the data counters
|
||||
if (mesgsys->getReceiveCompressedSize())
|
||||
{
|
||||
gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
|
||||
gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
gObjectBits += mesgsys->getReceiveSize() * 8;
|
||||
gObjectData += (U32Bytes)mesgsys->getReceiveSize();
|
||||
}
|
||||
|
||||
// Update the object...
|
||||
@@ -5217,11 +5218,11 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_
|
||||
{
|
||||
if (mesgsys->getReceiveCompressedSize())
|
||||
{
|
||||
gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
|
||||
gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
gObjectBits += mesgsys->getReceiveSize() * 8;
|
||||
gObjectData += (U32Bytes)mesgsys->getReceiveSize();
|
||||
}
|
||||
|
||||
gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED);
|
||||
|
||||
@@ -451,8 +451,8 @@ void output_statistics(void*)
|
||||
LL_INFOS() << "Number of orphans: " << gObjectList.getOrphanCount() << LL_ENDL;
|
||||
LL_INFOS() << "Number of dead objects: " << gObjectList.mNumDeadObjects << LL_ENDL;
|
||||
LL_INFOS() << "Num images: " << gTextureList.getNumImages() << LL_ENDL;
|
||||
LL_INFOS() << "Texture usage: " << LLImageGL::sGlobalTextureMemoryInBytes << LL_ENDL;
|
||||
LL_INFOS() << "Texture working set: " << LLImageGL::sBoundTextureMemoryInBytes << LL_ENDL;
|
||||
LL_INFOS() << "Texture usage: " << LLImageGL::sGlobalTextureMemory.value() << LL_ENDL;
|
||||
LL_INFOS() << "Texture working set: " << LLImageGL::sBoundTextureMemory.value() << LL_ENDL;
|
||||
LL_INFOS() << "Raw usage: " << global_raw_memory << LL_ENDL;
|
||||
LL_INFOS() << "Formatted usage: " << LLImageFormatted::sGlobalFormattedMemory << LL_ENDL;
|
||||
LL_INFOS() << "Zombie Viewer Objects: " << LLViewerObject::getNumZombieObjects() << LL_ENDL;
|
||||
@@ -570,19 +570,25 @@ void output_statistics(void*)
|
||||
}
|
||||
|
||||
|
||||
U32 gTotalLandIn = 0, gTotalLandOut = 0;
|
||||
U32 gTotalWaterIn = 0, gTotalWaterOut = 0;
|
||||
U32 gTotalLandIn = 0,
|
||||
gTotalLandOut = 0,
|
||||
gTotalWaterIn = 0,
|
||||
gTotalWaterOut = 0;
|
||||
|
||||
F32 gAveLandCompression = 0.f, gAveWaterCompression = 0.f;
|
||||
F32 gBestLandCompression = 1.f, gBestWaterCompression = 1.f;
|
||||
F32 gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f;
|
||||
F32 gAveLandCompression = 0.f,
|
||||
gAveWaterCompression = 0.f,
|
||||
gBestLandCompression = 1.f,
|
||||
gBestWaterCompression = 1.f,
|
||||
gWorstLandCompression = 0.f,
|
||||
gWorstWaterCompression = 0.f;
|
||||
|
||||
|
||||
|
||||
U32 gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0;
|
||||
U32 gObjectBits = 0;
|
||||
F32 gAvgSimPing = 0.f;
|
||||
U32 gTotalTextureBytesPerBoostLevel[LLGLTexture::MAX_GL_IMAGE_CATEGORY] = {0};
|
||||
U32Bytes gTotalWorldData,
|
||||
gTotalObjectData,
|
||||
gTotalTextureData;
|
||||
U32 gSimPingCount = 0;
|
||||
U32Bits gObjectData;
|
||||
F32Milliseconds gAvgSimPing(0.f);
|
||||
U32Bytes gTotalTextureBytesPerBoostLevel[LLGLTexture::MAX_GL_IMAGE_CATEGORY] = {U32Bytes(0)};
|
||||
|
||||
extern U32 gVisCompared;
|
||||
extern U32 gVisTested;
|
||||
@@ -591,8 +597,8 @@ LLFrameTimer gTextureTimer;
|
||||
|
||||
void update_statistics()
|
||||
{
|
||||
gTotalWorldBytes += gVLManager.getTotalBytes();
|
||||
gTotalObjectBytes += gObjectBits / 8;
|
||||
gTotalWorldData += U32Bytes(gVLManager.getTotalBytes());
|
||||
gTotalObjectData += gObjectData;
|
||||
|
||||
LLViewerStats& stats = LLViewerStats::instance();
|
||||
|
||||
@@ -634,7 +640,7 @@ void update_statistics()
|
||||
if (cdp)
|
||||
{
|
||||
stats.mSimPingStat.addValue(cdp->getPingDelay());
|
||||
gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1);
|
||||
gAvgSimPing = F32Milliseconds(((gAvgSimPing.value() * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1));
|
||||
gSimPingCount++;
|
||||
}
|
||||
else
|
||||
@@ -643,11 +649,11 @@ void update_statistics()
|
||||
}
|
||||
|
||||
stats.mFPSStat.addValue(1);
|
||||
F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
|
||||
stats.mLayersKBitStat.addValue(layer_bits/1024.f);
|
||||
stats.mObjectKBitStat.addValue(gObjectBits/1024.f);
|
||||
F64Bits layer_bits = F64Bits(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
|
||||
stats.mLayersKBitStat.addValue((F32)layer_bits.valueInUnits<LLUnits::Kilobits>());
|
||||
stats.mObjectKBitStat.addValue(gObjectData.valueInUnits<LLUnits::Kilobits>());
|
||||
stats.mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending());
|
||||
stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f);
|
||||
stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET) / 1024);
|
||||
gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
|
||||
|
||||
if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
|
||||
@@ -675,7 +681,7 @@ void update_statistics()
|
||||
|
||||
// Reset all of these values.
|
||||
gVLManager.resetBitCounts();
|
||||
gObjectBits = 0;
|
||||
gObjectData = (U32Bytes)0;
|
||||
// gDecodedBits = 0;
|
||||
|
||||
// Only update texture stats periodically so that they are less noisy
|
||||
@@ -685,10 +691,10 @@ void update_statistics()
|
||||
if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
|
||||
{
|
||||
stats.mHTTPTextureKBitStat.addValue(AICurlInterface::getHTTPBandwidth()/125.f);
|
||||
stats.mUDPTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f);
|
||||
stats.mUDPTextureKBitStat.addValue(LLViewerTextureList::sTextureBits.valueInUnits<LLUnits::Kilobits>());
|
||||
stats.mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets);
|
||||
gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8;
|
||||
LLViewerTextureList::sTextureBits = 0;
|
||||
gTotalTextureData += U32Bits(LLViewerTextureList::sTextureBits);
|
||||
LLViewerTextureList::sTextureBits = U32Bits(0);
|
||||
LLViewerTextureList::sTexturePackets = 0;
|
||||
texture_stats_timer.reset();
|
||||
}
|
||||
@@ -792,14 +798,14 @@ void send_stats()
|
||||
gSimFrames = (F32) gFrameCount;
|
||||
|
||||
agent["agents_in_view"] = LLVOAvatar::sNumVisibleAvatars;
|
||||
agent["ping"] = gAvgSimPing;
|
||||
agent["ping"] = gAvgSimPing.value();
|
||||
agent["meters_traveled"] = gAgent.getDistanceTraveled();
|
||||
agent["regions_visited"] = gAgent.getRegionsVisited();
|
||||
agent["mem_use"] = LLMemory::getCurrentRSS() / 1024.0;
|
||||
|
||||
LLSD &system = body["system"];
|
||||
|
||||
system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB();
|
||||
system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB().value();
|
||||
system["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
|
||||
system["cpu"] = gSysCPU.getCPUString();
|
||||
unsigned char MACAddress[MAC_ADDRESS_BYTES];
|
||||
@@ -823,9 +829,9 @@ void send_stats()
|
||||
|
||||
LLSD &download = body["downloads"];
|
||||
|
||||
download["world_kbytes"] = gTotalWorldBytes / 1024.0;
|
||||
download["object_kbytes"] = gTotalObjectBytes / 1024.0;
|
||||
download["texture_kbytes"] = gTotalTextureBytes / 1024.0;
|
||||
download["world_kbytes"] = F64Kilobytes(gTotalWorldData).value();
|
||||
download["object_kbytes"] = F64Kilobytes(gTotalObjectData).value();
|
||||
download["texture_kbytes"] = F64Kilobytes(gTotalTextureData).value();
|
||||
download["mesh_kbytes"] = LLMeshRepository::sBytesReceived/1024.0;
|
||||
|
||||
LLSD &in = body["stats"]["net"]["in"];
|
||||
@@ -886,7 +892,10 @@ void send_stats()
|
||||
body["MinimalSkin"] = false;
|
||||
|
||||
LLViewerStats::getInstance()->addToMessage(body);
|
||||
LLHTTPClient::post(url, body, new ViewerStatsResponder);
|
||||
|
||||
LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL;
|
||||
LLHTTPClient::post(url, body, new ViewerStatsResponder());
|
||||
|
||||
}
|
||||
|
||||
LLViewerStats::PhaseMap::PhaseMap()
|
||||
|
||||
@@ -321,7 +321,7 @@ void update_statistics();
|
||||
void send_stats();
|
||||
|
||||
extern LLFrameTimer gTextureTimer;
|
||||
extern U32 gTotalTextureBytes;
|
||||
extern U32 gTotalObjectBytes;
|
||||
extern U32 gTotalTextureBytesPerBoostLevel[] ;
|
||||
extern U32Bytes gTotalTextureData;
|
||||
extern U32Bytes gTotalObjectData;
|
||||
extern U32Bytes gTotalTextureBytesPerBoostLevel[] ;
|
||||
#endif // LL_LLVIEWERSTATS_H
|
||||
|
||||
@@ -63,6 +63,11 @@
|
||||
#include "lltexturecache.h"
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// extern
|
||||
const S32Megabytes gMinVideoRam(32);
|
||||
const S32Megabytes gMaxVideoRam(1024);
|
||||
|
||||
|
||||
// statics
|
||||
LLPointer<LLViewerTexture> LLViewerTexture::sNullImagep = NULL;
|
||||
LLPointer<LLViewerTexture> LLViewerTexture::sBlackImagep = NULL;
|
||||
@@ -83,11 +88,11 @@ S32 LLViewerTexture::sAuxCount = 0;
|
||||
LLFrameTimer LLViewerTexture::sEvaluationTimer;
|
||||
F32 LLViewerTexture::sDesiredDiscardBias = 0.f;
|
||||
F32 LLViewerTexture::sDesiredDiscardScale = 1.1f;
|
||||
S32 LLViewerTexture::sBoundTextureMemoryInBytes = 0;
|
||||
S32 LLViewerTexture::sTotalTextureMemoryInBytes = 0;
|
||||
S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0;
|
||||
S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0;
|
||||
S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ;
|
||||
S32Bytes LLViewerTexture::sBoundTextureMemory;
|
||||
S32Bytes LLViewerTexture::sTotalTextureMemory;
|
||||
S32Megabytes LLViewerTexture::sMaxBoundTextureMemory;
|
||||
S32Megabytes LLViewerTexture::sMaxTotalTextureMem;
|
||||
S32Bytes LLViewerTexture::sMaxDesiredTextureMem;
|
||||
S8 LLViewerTexture::sCameraMovingDiscardBias = 0;
|
||||
F32 LLViewerTexture::sCameraMovingBias = 0.0f ;
|
||||
S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size
|
||||
@@ -450,8 +455,9 @@ bool LLViewerTexture::isMemoryForTextureLow()
|
||||
timer.reset() ;
|
||||
|
||||
LLFastTimer t(FTM_TEXTURE_MEMORY_CHECK);
|
||||
const static S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB
|
||||
const static S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB
|
||||
|
||||
static const S32Megabytes MIN_FREE_TEXTURE_MEMORY(5); //MB
|
||||
static const S32Megabytes MIN_FREE_MAIN_MEMORY(100); //MB
|
||||
|
||||
bool low_mem = false ;
|
||||
if (gGLManager.mHasATIMemInfo)
|
||||
@@ -459,7 +465,7 @@ bool LLViewerTexture::isMemoryForTextureLow()
|
||||
S32 meminfo[4];
|
||||
glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
|
||||
|
||||
if(meminfo[0] / 1024 < MIN_FREE_TEXTURE_MEMORY)
|
||||
if((S32Megabytes)meminfo[0] < MIN_FREE_TEXTURE_MEMORY)
|
||||
{
|
||||
low_mem = true ;
|
||||
}
|
||||
@@ -467,7 +473,7 @@ bool LLViewerTexture::isMemoryForTextureLow()
|
||||
if(!low_mem) //check main memory, only works for windows.
|
||||
{
|
||||
LLMemory::updateMemoryInfo() ;
|
||||
if(LLMemory::getAvailableMemKB() / 1024 < MIN_FREE_MAIN_MEMORy)
|
||||
if(LLMemory::getAvailableMemKB() < MIN_FREE_TEXTURE_MEMORY)
|
||||
{
|
||||
low_mem = true ;
|
||||
}
|
||||
@@ -511,17 +517,17 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
|
||||
LLViewerMediaTexture::updateClass() ;
|
||||
}
|
||||
|
||||
sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes
|
||||
sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes
|
||||
sMaxBoundTextureMemInMegaBytes = gTextureList.getMaxResidentTexMem();//in MB
|
||||
sMaxTotalTextureMemInMegaBytes = gTextureList.getMaxTotalTextureMem() ;//in MB
|
||||
sMaxDesiredTextureMemInBytes = MEGA_BYTES_TO_BYTES(sMaxTotalTextureMemInMegaBytes) ; //in Bytes, by default and when total used texture memory is small.
|
||||
sBoundTextureMemory = LLImageGL::sBoundTextureMemory;
|
||||
sTotalTextureMemory = LLImageGL::sGlobalTextureMemory;
|
||||
sMaxBoundTextureMemory = S32Megabytes(gTextureList.getMaxResidentTexMem());
|
||||
sMaxTotalTextureMem = S32Megabytes(gTextureList.getMaxTotalTextureMem());
|
||||
sMaxDesiredTextureMem = sMaxTotalTextureMem; //in Bytes, by default and when total used texture memory is small.
|
||||
|
||||
if (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) >= sMaxBoundTextureMemInMegaBytes ||
|
||||
BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) >= sMaxTotalTextureMemInMegaBytes)
|
||||
if (sBoundTextureMemory >= sMaxBoundTextureMemory ||
|
||||
sTotalTextureMemory >= sMaxTotalTextureMem)
|
||||
{
|
||||
//when texture memory overflows, lower down the threashold to release the textures more aggressively.
|
||||
sMaxDesiredTextureMemInBytes = llmin((S32)(sMaxDesiredTextureMemInBytes * 0.75f) , MEGA_BYTES_TO_BYTES(MAX_VIDEO_RAM_IN_MEGA_BYTES)) ;//512 MB
|
||||
//when texture memory overflows, lower down the threshold to release the textures more aggressively.
|
||||
sMaxDesiredTextureMem = llmin(sMaxDesiredTextureMem * 0.75f, F32Bytes(gMaxVideoRam));
|
||||
|
||||
// If we are using more texture memory than we should,
|
||||
// scale up the desired discard level
|
||||
@@ -537,8 +543,8 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
|
||||
sEvaluationTimer.reset();
|
||||
}
|
||||
else if (sDesiredDiscardBias > 0.0f &&
|
||||
BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < sMaxBoundTextureMemInMegaBytes * texmem_lower_bound_scale &&
|
||||
BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < sMaxTotalTextureMemInMegaBytes * texmem_lower_bound_scale)
|
||||
sBoundTextureMemory < sMaxBoundTextureMemory * texmem_lower_bound_scale &&
|
||||
sTotalTextureMemory < sMaxTotalTextureMem * texmem_lower_bound_scale)
|
||||
{
|
||||
// If we are using less texture memory than we should,
|
||||
// scale down the desired discard level
|
||||
@@ -549,15 +555,14 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
|
||||
}
|
||||
}
|
||||
sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max);
|
||||
//LLViewerTexture::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ;
|
||||
|
||||
F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed();
|
||||
F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
|
||||
sCameraMovingBias = llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1);
|
||||
sCameraMovingDiscardBias = (S8)(sCameraMovingBias);
|
||||
|
||||
LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) &&
|
||||
(BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ;
|
||||
LLViewerTexture::sFreezeImageScalingDown = (sBoundTextureMemory < 0.75f * sMaxBoundTextureMemory * texmem_middle_bound_scale) &&
|
||||
(sTotalTextureMemory < 0.75f * sMaxTotalTextureMem * texmem_middle_bound_scale);
|
||||
}
|
||||
|
||||
//end of static functions
|
||||
@@ -1156,7 +1161,7 @@ void LLViewerFetchedTexture::dump()
|
||||
// ONLY called from LLViewerFetchedTextureList
|
||||
void LLViewerFetchedTexture::destroyTexture()
|
||||
{
|
||||
if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes * 0.95f)//not ready to release unused memory.
|
||||
if(LLImageGL::sGlobalTextureMemory < sMaxDesiredTextureMem * 0.95f)//not ready to release unused memory.
|
||||
{
|
||||
return ;
|
||||
}
|
||||
@@ -3049,13 +3054,13 @@ void LLViewerLODTexture::processTextureStats()
|
||||
scaleDown() ;
|
||||
}
|
||||
// Limit the amount of GL memory bound each frame
|
||||
else if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale &&
|
||||
else if ( sBoundTextureMemory > sMaxBoundTextureMemory * texmem_middle_bound_scale &&
|
||||
(!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
|
||||
{
|
||||
scaleDown() ;
|
||||
}
|
||||
// Only allow GL to have 2x the video card memory
|
||||
else if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale &&
|
||||
else if ( sTotalTextureMemory > sMaxTotalTextureMem * texmem_middle_bound_scale &&
|
||||
(!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
|
||||
{
|
||||
scaleDown() ;
|
||||
@@ -3639,10 +3644,10 @@ LLTexturePipelineTester::LLTexturePipelineTester() : LLMetricPerformanceTesterWi
|
||||
addMetric("TotalBytesBoundForLargeImage") ;
|
||||
addMetric("PercentageBytesBound") ;
|
||||
|
||||
mTotalBytesLoaded = 0 ;
|
||||
mTotalBytesLoadedFromCache = 0 ;
|
||||
mTotalBytesLoadedForLargeImage = 0 ;
|
||||
mTotalBytesLoadedForSculpties = 0 ;
|
||||
mTotalBytesLoaded = (S32Bytes)0;
|
||||
mTotalBytesLoadedFromCache = (S32Bytes)0;
|
||||
mTotalBytesLoadedForLargeImage = (S32Bytes)0;
|
||||
mTotalBytesLoadedForSculpties = (S32Bytes)0;
|
||||
|
||||
reset() ;
|
||||
}
|
||||
@@ -3656,8 +3661,8 @@ void LLTexturePipelineTester::update()
|
||||
{
|
||||
mLastTotalBytesUsed = mTotalBytesUsed ;
|
||||
mLastTotalBytesUsedForLargeImage = mTotalBytesUsedForLargeImage ;
|
||||
mTotalBytesUsed = 0 ;
|
||||
mTotalBytesUsedForLargeImage = 0 ;
|
||||
mTotalBytesUsed = (S32Bytes)0;
|
||||
mTotalBytesUsedForLargeImage = (S32Bytes)0;
|
||||
|
||||
if(LLAppViewer::getTextureFetch()->getNumRequests() > 0) //fetching list is not empty
|
||||
{
|
||||
@@ -3698,10 +3703,10 @@ void LLTexturePipelineTester::reset()
|
||||
mStartStablizingTime = 0.0f ;
|
||||
mEndStablizingTime = 0.0f ;
|
||||
|
||||
mTotalBytesUsed = 0 ;
|
||||
mTotalBytesUsedForLargeImage = 0 ;
|
||||
mLastTotalBytesUsed = 0 ;
|
||||
mLastTotalBytesUsedForLargeImage = 0 ;
|
||||
mTotalBytesUsed = (S32Bytes)0;
|
||||
mTotalBytesUsedForLargeImage = (S32Bytes)0;
|
||||
mLastTotalBytesUsed = (S32Bytes)0;
|
||||
mLastTotalBytesUsedForLargeImage = (S32Bytes)0;
|
||||
|
||||
mStartFetchingTime = 0.0f ;
|
||||
|
||||
@@ -3716,10 +3721,10 @@ void LLTexturePipelineTester::reset()
|
||||
void LLTexturePipelineTester::outputTestRecord(LLSD *sd)
|
||||
{
|
||||
std::string currentLabel = getCurrentLabelName();
|
||||
(*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ;
|
||||
(*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ;
|
||||
(*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ;
|
||||
(*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ;
|
||||
(*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded.value();
|
||||
(*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache.value();
|
||||
(*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage.value();
|
||||
(*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties.value();
|
||||
|
||||
(*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime;
|
||||
(*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime;
|
||||
@@ -3729,17 +3734,17 @@ void LLTexturePipelineTester::outputTestRecord(LLSD *sd)
|
||||
(*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties;
|
||||
|
||||
(*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime;
|
||||
(*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ;
|
||||
(*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ;
|
||||
(*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed.value();
|
||||
(*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage.value();
|
||||
(*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded);
|
||||
}
|
||||
|
||||
void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep)
|
||||
{
|
||||
U32 mem_size = (U32)imagep->getTextureMemory() ;
|
||||
U32Bytes mem_size = imagep->getTextureMemory();
|
||||
mTotalBytesUsed += mem_size;
|
||||
|
||||
if(MIN_LARGE_IMAGE_AREA <= (U32)(mem_size / (U32)imagep->getComponents()))
|
||||
if(MIN_LARGE_IMAGE_AREA <= (U32)(mem_size.value() / (U32)imagep->getComponents()))
|
||||
{
|
||||
mTotalBytesUsedForLargeImage += mem_size;
|
||||
}
|
||||
@@ -3747,7 +3752,7 @@ void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* i
|
||||
|
||||
void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache)
|
||||
{
|
||||
U32 data_size = (U32)raw_imagep->getDataSize() ;
|
||||
U32Bytes data_size = (U32Bytes)raw_imagep->getDataSize();
|
||||
mTotalBytesLoaded += data_size;
|
||||
|
||||
if(from_cache)
|
||||
@@ -3755,7 +3760,7 @@ void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTex
|
||||
mTotalBytesLoadedFromCache += data_size;
|
||||
}
|
||||
|
||||
if(MIN_LARGE_IMAGE_AREA <= (U32)(data_size / (U32)raw_imagep->getComponents()))
|
||||
if(MIN_LARGE_IMAGE_AREA <= (U32)(data_size.value() / (U32)raw_imagep->getComponents()))
|
||||
{
|
||||
mTotalBytesLoadedForLargeImage += data_size;
|
||||
}
|
||||
|
||||
@@ -41,8 +41,9 @@
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#define MIN_VIDEO_RAM_IN_MEGA_BYTES 32
|
||||
#define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons.
|
||||
extern const S32Megabytes gMinVideoRam;
|
||||
extern const S32Megabytes gMaxVideoRam;
|
||||
|
||||
|
||||
class LLImageGL ;
|
||||
class LLImageRaw;
|
||||
@@ -210,11 +211,11 @@ public:
|
||||
static LLFrameTimer sEvaluationTimer;
|
||||
static F32 sDesiredDiscardBias;
|
||||
static F32 sDesiredDiscardScale;
|
||||
static S32 sBoundTextureMemoryInBytes;
|
||||
static S32 sTotalTextureMemoryInBytes;
|
||||
static S32 sMaxBoundTextureMemInMegaBytes;
|
||||
static S32 sMaxTotalTextureMemInMegaBytes;
|
||||
static S32 sMaxDesiredTextureMemInBytes ;
|
||||
static S32Bytes sBoundTextureMemory;
|
||||
static S32Bytes sTotalTextureMemory;
|
||||
static S32Megabytes sMaxBoundTextureMemory;
|
||||
static S32Megabytes sMaxTotalTextureMem;
|
||||
static S32Bytes sMaxDesiredTextureMem ;
|
||||
static S8 sCameraMovingDiscardBias;
|
||||
static F32 sCameraMovingBias;
|
||||
static S32 sMaxSculptRez ;
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL;
|
||||
|
||||
U32 LLViewerTextureList::sTextureBits = 0;
|
||||
U32Bits LLViewerTextureList::sTextureBits(0);
|
||||
U32 LLViewerTextureList::sTexturePackets = 0;
|
||||
S32 LLViewerTextureList::sNumImages = 0;
|
||||
|
||||
@@ -95,8 +95,8 @@ void LLViewerTextureList::init()
|
||||
mInitialized = TRUE ;
|
||||
sNumImages = 0;
|
||||
mUpdateStats = TRUE;
|
||||
mMaxResidentTexMemInMegaBytes = 0;
|
||||
mMaxTotalTextureMemInMegaBytes = 0 ;
|
||||
mMaxResidentTexMemInMegaBytes = (U32Bytes)0;
|
||||
mMaxTotalTextureMemInMegaBytes = (U32Bytes)0;
|
||||
if (gNoRender)
|
||||
{
|
||||
// Don't initialize GL stuff if we're not rendering.
|
||||
@@ -104,7 +104,7 @@ void LLViewerTextureList::init()
|
||||
}
|
||||
|
||||
// Update how much texture RAM we're allowed to use.
|
||||
updateMaxResidentTexMem(0); // 0 = use current
|
||||
updateMaxResidentTexMem(S32Megabytes(0)); // 0 = use current
|
||||
|
||||
doPreloadImages();
|
||||
}
|
||||
@@ -706,8 +706,8 @@ void LLViewerTextureList::updateImages(F32 max_time)
|
||||
}
|
||||
LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages);
|
||||
LLViewerStats::getInstance()->mNumRawImagesStat.addValue(LLImageRaw::sRawImageCount);
|
||||
LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes));
|
||||
LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes));
|
||||
LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)LLImageGL::sGlobalTextureMemory.valueInUnits<LLUnits::Megabytes>());
|
||||
LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)LLImageGL::sBoundTextureMemory.valueInUnits<LLUnits::Megabytes>());
|
||||
LLViewerStats::getInstance()->mRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(global_raw_memory));
|
||||
LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory));
|
||||
|
||||
@@ -960,12 +960,10 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
|
||||
static const bool SKIP_LOW_PRIO = gSavedSettings.getBOOL("TextureFetchUpdateSkipLowPriority"); // default: false
|
||||
|
||||
size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*MAX_HIGH_PRIO_COUNT*gFrameIntervalSeconds)+1, MAX_HIGH_PRIO_COUNT);
|
||||
//Old: size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*40.f*gFrameIntervalSeconds)+1, MAX_HIGH_PRIO_COUNT);
|
||||
max_priority_count = llmin(max_priority_count, mImageList.size());
|
||||
|
||||
size_t total_update_count = mUUIDMap.size();
|
||||
size_t max_update_count = llmin((S32) (MAX_UPDATE_COUNT*MAX_UPDATE_COUNT*gFrameIntervalSeconds)+1, MAX_UPDATE_COUNT);
|
||||
//Old: size_t max_priority_count = llmin((S32) (MAX_UPDATE_COUNT*40.f*gFrameIntervalSeconds)+1, MAX_UPDATE_COUNT);
|
||||
max_update_count = llmin(max_update_count, total_update_count);
|
||||
|
||||
// MAX_HIGH_PRIO_COUNT high priority entries
|
||||
@@ -1218,20 +1216,16 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage
|
||||
}
|
||||
|
||||
// Returns min setting for TextureMemory (in MB)
|
||||
S32 LLViewerTextureList::getMinVideoRamSetting()
|
||||
S32Megabytes LLViewerTextureList::getMinVideoRamSetting()
|
||||
{
|
||||
S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped());
|
||||
if (system_ram > 2000)
|
||||
return 128;
|
||||
else if (system_ram > 1000)
|
||||
return 64;
|
||||
else
|
||||
return MIN_VIDEO_RAM_IN_MEGA_BYTES;
|
||||
S32Megabytes system_ram = gSysMemory.getPhysicalMemoryClamped();
|
||||
//min texture mem sets to 64M if total physical mem is more than 1.5GB
|
||||
return (system_ram > S32Megabytes(1500)) ? S32Megabytes(64) : gMinVideoRam ;
|
||||
}
|
||||
|
||||
//static
|
||||
// Returns max setting for TextureMemory (in MB)
|
||||
S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
|
||||
S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier)
|
||||
{
|
||||
#if LL_LINUX
|
||||
if (gGLManager.mIsIntel && gGLManager.mGLVersion >= 3.f && !gGLManager.mVRAM)
|
||||
@@ -1239,12 +1233,12 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
|
||||
gGLManager.mVRAM = 512;
|
||||
}
|
||||
#endif
|
||||
S32 max_texmem;
|
||||
S32Megabytes max_texmem;
|
||||
if (gGLManager.mVRAM != 0)
|
||||
{
|
||||
// Treat any card with < 32 MB (shudder) as having 32 MB
|
||||
// - it's going to be swapping constantly regardless
|
||||
S32 max_vram = gGLManager.mVRAM;
|
||||
S32Megabytes max_vram(gGLManager.mVRAM);
|
||||
max_vram = llmax(max_vram, getMinVideoRamSetting());
|
||||
max_texmem = max_vram;
|
||||
if (!get_recommended)
|
||||
@@ -1252,72 +1246,81 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (get_recommended)
|
||||
max_texmem = 128;
|
||||
if (!get_recommended)
|
||||
{
|
||||
max_texmem = (S32Megabytes)512;
|
||||
}
|
||||
else if (gSavedSettings.getBOOL("NoHardwareProbe")) //did not do hardware detection at startup
|
||||
{
|
||||
max_texmem = (S32Megabytes)512;
|
||||
}
|
||||
else
|
||||
max_texmem = 512;
|
||||
{
|
||||
max_texmem = (S32Megabytes)128;
|
||||
}
|
||||
|
||||
LL_WARNS() << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << LL_ENDL;
|
||||
}
|
||||
|
||||
S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB
|
||||
S32Megabytes system_ram = gSysMemory.getPhysicalMemoryClamped(); // In MB
|
||||
//LL_INFOS() << "*** DETECTED " << system_ram << " MB of system memory." << LL_ENDL;
|
||||
if (get_recommended)
|
||||
max_texmem = llmin(max_texmem, (S32)(system_ram/2));
|
||||
max_texmem = llmin(max_texmem, system_ram/2);
|
||||
else
|
||||
max_texmem = llmin(max_texmem, (S32)(system_ram));
|
||||
max_texmem = llmin(max_texmem, system_ram);
|
||||
|
||||
max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES);
|
||||
// limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise
|
||||
max_texmem = llmin(max_texmem, (S32Megabytes) (mem_multiplier * max_texmem));
|
||||
|
||||
max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), gMaxVideoRam);
|
||||
|
||||
return max_texmem;
|
||||
}
|
||||
|
||||
const S32 VIDEO_CARD_FRAMEBUFFER_MEM = 12; // MB
|
||||
const S32 MIN_MEM_FOR_NON_TEXTURE = 512 ; //MB
|
||||
void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)
|
||||
const S32Megabytes VIDEO_CARD_FRAMEBUFFER_MEM(12);
|
||||
const S32Megabytes MIN_MEM_FOR_NON_TEXTURE(512);
|
||||
void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem)
|
||||
{
|
||||
// Initialize the image pipeline VRAM settings
|
||||
S32 cur_mem = gSavedSettings.getS32("TextureMemory");
|
||||
S32Megabytes cur_mem(gSavedSettings.getS32("TextureMemory"));
|
||||
F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
|
||||
S32 default_mem = getMaxVideoRamSetting(true); // recommended default
|
||||
if (mem == 0)
|
||||
S32Megabytes default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default
|
||||
if (mem == (S32Bytes)0)
|
||||
{
|
||||
mem = cur_mem > 0 ? cur_mem : default_mem;
|
||||
mem = cur_mem > (S32Bytes)0 ? cur_mem : default_mem;
|
||||
}
|
||||
else if (mem < 0)
|
||||
else if (mem < (S32Bytes)0)
|
||||
{
|
||||
mem = default_mem;
|
||||
}
|
||||
|
||||
// limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise
|
||||
mem = llmin(mem, (S32) (mem_multiplier * (F32) default_mem));
|
||||
|
||||
mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting());
|
||||
mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier));
|
||||
if (mem != cur_mem)
|
||||
{
|
||||
gSavedSettings.setS32("TextureMemory", mem);
|
||||
gSavedSettings.setS32("TextureMemory", mem.value());
|
||||
return; //listener will re-enter this function
|
||||
}
|
||||
|
||||
// TODO: set available resident texture mem based on use by other subsystems
|
||||
// currently max(12MB, VRAM/4) assumed...
|
||||
|
||||
S32 vb_mem = mem;
|
||||
S32 fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4);
|
||||
S32Megabytes vb_mem = mem;
|
||||
S32Megabytes fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4);
|
||||
mMaxResidentTexMemInMegaBytes = (vb_mem - fb_mem) ; //in MB
|
||||
|
||||
mMaxTotalTextureMemInMegaBytes = mMaxResidentTexMemInMegaBytes * 2;
|
||||
if (mMaxResidentTexMemInMegaBytes > 640)
|
||||
if (mMaxResidentTexMemInMegaBytes > (S32Megabytes)640)
|
||||
{
|
||||
mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes >> 2);
|
||||
mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes / 4);
|
||||
}
|
||||
|
||||
//system mem
|
||||
S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB
|
||||
S32Megabytes system_ram = gSysMemory.getPhysicalMemoryClamped();
|
||||
|
||||
//minimum memory reserved for non-texture use.
|
||||
//if system_raw >= 1GB, reserve at least 512MB for non-texture use;
|
||||
//otherwise reserve half of the system_ram for non-texture use.
|
||||
S32 min_non_texture_mem = llmin(system_ram / 2, MIN_MEM_FOR_NON_TEXTURE) ;
|
||||
S32Megabytes min_non_texture_mem = llmin(system_ram / 2, MIN_MEM_FOR_NON_TEXTURE) ;
|
||||
|
||||
if (mMaxTotalTextureMemInMegaBytes > system_ram - min_non_texture_mem)
|
||||
{
|
||||
@@ -1345,17 +1348,17 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d
|
||||
char ip_string[256];
|
||||
u32_to_ip_string(msg->getSenderIP(),ip_string);
|
||||
|
||||
U32 received_size ;
|
||||
U32Bytes received_size ;
|
||||
if (msg->getReceiveCompressedSize())
|
||||
{
|
||||
received_size = msg->getReceiveCompressedSize() ;
|
||||
received_size = (U32Bytes)msg->getReceiveCompressedSize() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
received_size = msg->getReceiveSize() ;
|
||||
received_size = (U32Bytes)msg->getReceiveSize() ;
|
||||
}
|
||||
// Only used for statistics and texture console.
|
||||
gTextureList.sTextureBits += received_size * 8;
|
||||
gTextureList.sTextureBits += received_size;
|
||||
gTextureList.sTexturePackets++;
|
||||
|
||||
U8 codec;
|
||||
@@ -1419,16 +1422,16 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d
|
||||
char ip_string[256];
|
||||
u32_to_ip_string(msg->getSenderIP(),ip_string);
|
||||
|
||||
U32 received_size ;
|
||||
U32Bytes received_size ;
|
||||
if (msg->getReceiveCompressedSize())
|
||||
{
|
||||
received_size = msg->getReceiveCompressedSize() ;
|
||||
received_size = (U32Bytes)msg->getReceiveCompressedSize() ;
|
||||
}
|
||||
else
|
||||
{
|
||||
received_size = msg->getReceiveSize() ;
|
||||
received_size = (U32Bytes)msg->getReceiveSize() ;
|
||||
}
|
||||
gTextureList.sTextureBits += received_size * 8;
|
||||
gTextureList.sTextureBits += received_size;
|
||||
gTextureList.sTexturePackets++;
|
||||
|
||||
//llprintline("Start decode, image header...");
|
||||
@@ -1494,24 +1497,6 @@ void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void **
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//static
|
||||
const U32 SIXTEEN_MEG = 0x1000000;
|
||||
S32 LLViewerTextureList::calcMaxTextureRAM()
|
||||
{
|
||||
// Decide the maximum amount of RAM we should allow the user to allocate to texture cache
|
||||
LLMemoryInfo memory_info;
|
||||
U32 available_memory = memory_info.getPhysicalMemoryClamped();
|
||||
|
||||
clamp_rescale((F32)available_memory,
|
||||
(F32)(SIXTEEN_MEG * 16),
|
||||
(F32)U32_MAX,
|
||||
(F32)(SIXTEEN_MEG * 4),
|
||||
(F32)(U32_MAX >> 1));
|
||||
return available_memory;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// explicitly cleanup resources, as this is a singleton class with process
|
||||
// lifetime so ability to perform std::map operations in destructor is not
|
||||
// guaranteed.
|
||||
|
||||
@@ -71,7 +71,6 @@ public:
|
||||
static BOOL verifyUploadFile(const std::string& out_filename, const U8 codec);
|
||||
static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image);
|
||||
static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data );
|
||||
static S32 calcMaxTextureRAM();
|
||||
static void receiveImageHeader(LLMessageSystem *msg, void **user_data);
|
||||
static void receiveImagePacket(LLMessageSystem *msg, void **user_data);
|
||||
|
||||
@@ -101,19 +100,19 @@ public:
|
||||
|
||||
void setUpdateStats(BOOL b) { mUpdateStats = b; }
|
||||
|
||||
S32 getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; }
|
||||
S32 getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;}
|
||||
S32Megabytes getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; }
|
||||
S32Megabytes getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;}
|
||||
S32 getNumImages() { return mImageList.size(); }
|
||||
|
||||
void updateMaxResidentTexMem(S32 mem);
|
||||
void updateMaxResidentTexMem(S32Megabytes mem);
|
||||
|
||||
void doPreloadImages();
|
||||
void doPrefetchImages();
|
||||
|
||||
void clearFetchingRequests();
|
||||
|
||||
static S32 getMinVideoRamSetting();
|
||||
static S32 getMaxVideoRamSetting(bool get_recommended = false);
|
||||
static S32Megabytes getMinVideoRamSetting();
|
||||
static S32Megabytes getMaxVideoRamSetting(bool get_recommended, float mem_multiplier);
|
||||
|
||||
private:
|
||||
void updateImagesDecodePriorities();
|
||||
@@ -195,12 +194,12 @@ private:
|
||||
|
||||
BOOL mInitialized ;
|
||||
BOOL mUpdateStats;
|
||||
S32 mMaxResidentTexMemInMegaBytes;
|
||||
S32 mMaxTotalTextureMemInMegaBytes;
|
||||
S32Megabytes mMaxResidentTexMemInMegaBytes;
|
||||
S32Megabytes mMaxTotalTextureMemInMegaBytes;
|
||||
LLFrameTimer mForceDecodeTimer;
|
||||
|
||||
public:
|
||||
static U32 sTextureBits;
|
||||
static U32Bits sTextureBits;
|
||||
static U32 sTexturePackets;
|
||||
|
||||
private:
|
||||
|
||||
@@ -5356,7 +5356,7 @@ void LLViewerWindow::stopGL(BOOL save_state)
|
||||
|
||||
gGL.resetVertexBuffers();
|
||||
|
||||
LL_INFOS() << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << LL_ENDL;
|
||||
LL_INFOS() << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemory << " bytes" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5169,9 +5169,9 @@ std::string LLVOAvatar::bakedTextureOriginInfo()
|
||||
return result;
|
||||
}
|
||||
|
||||
S32 LLVOAvatar::totalTextureMemForUUIDS(std::set<LLUUID>& ids)
|
||||
S32Bytes LLVOAvatar::totalTextureMemForUUIDS(std::set<LLUUID>& ids)
|
||||
{
|
||||
S32 result = 0;
|
||||
S32Bytes result(0);
|
||||
for (std::set<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it)
|
||||
{
|
||||
LLViewerFetchedTexture *imagep = gTextureList.findImage(*it);
|
||||
@@ -5236,12 +5236,12 @@ void LLVOAvatar::collectTextureUUIDs(std::set<LLUUID>& ids)
|
||||
|
||||
void LLVOAvatar::releaseOldTextures()
|
||||
{
|
||||
S32 current_texture_mem = 0;
|
||||
S32Bytes current_texture_mem;
|
||||
|
||||
// Any textures that we used to be using but are no longer using should no longer be flagged as "NO_DELETE"
|
||||
std::set<LLUUID> baked_texture_ids;
|
||||
collectBakedTextureUUIDs(baked_texture_ids);
|
||||
S32 new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids);
|
||||
S32Bytes new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids);
|
||||
|
||||
std::set<LLUUID> local_texture_ids;
|
||||
collectLocalTextureUUIDs(local_texture_ids);
|
||||
@@ -5250,7 +5250,7 @@ void LLVOAvatar::releaseOldTextures()
|
||||
std::set<LLUUID> new_texture_ids;
|
||||
new_texture_ids.insert(baked_texture_ids.begin(),baked_texture_ids.end());
|
||||
new_texture_ids.insert(local_texture_ids.begin(),local_texture_ids.end());
|
||||
S32 new_total_mem = totalTextureMemForUUIDS(new_texture_ids);
|
||||
S32Bytes new_total_mem = totalTextureMemForUUIDS(new_texture_ids);
|
||||
|
||||
//S32 old_total_mem = totalTextureMemForUUIDS(mTextureIDs);
|
||||
//LL_DEBUGS("Avatar") << getFullname() << " old_total_mem: " << old_total_mem << " new_total_mem (L/B): " << new_total_mem << " (" << new_local_mem <<", " << new_baked_mem << ")" << LL_ENDL;
|
||||
|
||||
@@ -184,7 +184,7 @@ public:
|
||||
void updateLODRiggedAttachments( void );
|
||||
void updateSoftwareSkinnedVertices(const LLMeshSkinInfo* skin, const LLVector4a* weight, const LLVolumeFace& vol_face, LLVertexBuffer *buffer);
|
||||
/*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate.
|
||||
S32 totalTextureMemForUUIDS(std::set<LLUUID>& ids);
|
||||
S32Bytes totalTextureMemForUUIDS(std::set<LLUUID>& ids);
|
||||
bool allTexturesCompletelyDownloaded(std::set<LLUUID>& ids) const;
|
||||
bool allLocalTexturesCompletelyDownloaded() const;
|
||||
bool allBakedTexturesCompletelyDownloaded() const;
|
||||
|
||||
@@ -157,7 +157,7 @@ typedef LLHTTPClient::ResponderIgnore LLHoverHeightResponder;
|
||||
//-----------------------------------------------------------------------------
|
||||
// Static Data
|
||||
//-----------------------------------------------------------------------------
|
||||
S32 LLVOAvatarSelf::sScratchTexBytes = 0;
|
||||
S32Bytes LLVOAvatarSelf::sScratchTexBytes(0);
|
||||
LLMap< LLGLenum, LLGLuint*> LLVOAvatarSelf::sScratchTexNames;
|
||||
LLMap< LLGLenum, F32*> LLVOAvatarSelf::sScratchTexLastBindTime;
|
||||
|
||||
@@ -3215,8 +3215,8 @@ void LLVOAvatarSelf::deleteScratchTextures()
|
||||
{
|
||||
if(gAuditTexture)
|
||||
{
|
||||
S32 total_tex_size = sScratchTexBytes ;
|
||||
S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ;
|
||||
S32Bytes total_tex_size = sScratchTexBytes ;
|
||||
S32Bytes tex_size(SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT) ;
|
||||
|
||||
if( sScratchTexNames.checkData( GL_LUMINANCE ) )
|
||||
{
|
||||
@@ -3249,7 +3249,7 @@ void LLVOAvatarSelf::deleteScratchTextures()
|
||||
total_tex_size -= 4 * tex_size ;
|
||||
}
|
||||
//others
|
||||
while(total_tex_size > 0)
|
||||
while(total_tex_size > S32Bytes(0))
|
||||
{
|
||||
LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
||||
total_tex_size -= 4 * tex_size ;
|
||||
@@ -3264,14 +3264,14 @@ void LLVOAvatarSelf::deleteScratchTextures()
|
||||
stop_glerror();
|
||||
}
|
||||
|
||||
if( sScratchTexBytes )
|
||||
if( sScratchTexBytes.value() )
|
||||
{
|
||||
LL_DEBUGS() << "Clearing Scratch Textures " << (sScratchTexBytes/1024) << "KB" << LL_ENDL;
|
||||
LL_DEBUGS() << "Clearing Scratch Textures " << (S32Kilobytes)sScratchTexBytes << "KB" << LL_ENDL;
|
||||
|
||||
sScratchTexNames.deleteAllData();
|
||||
sScratchTexLastBindTime.deleteAllData();
|
||||
LLImageGL::sGlobalTextureMemoryInBytes -= sScratchTexBytes;
|
||||
sScratchTexBytes = 0;
|
||||
LLImageGL::sGlobalTextureMemory -= sScratchTexBytes;
|
||||
sScratchTexBytes = S32Bytes(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@ public:
|
||||
public:
|
||||
static void deleteScratchTextures();
|
||||
private:
|
||||
static S32 sScratchTexBytes;
|
||||
static S32Bytes sScratchTexBytes;
|
||||
static LLMap< LLGLenum, LLGLuint*> sScratchTexNames;
|
||||
static LLMap< LLGLenum, F32*> sScratchTexLastBindTime;
|
||||
|
||||
|
||||
@@ -4001,7 +4001,8 @@ U32 LLVOVolume::getPartitionType() const
|
||||
}
|
||||
|
||||
LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp)
|
||||
: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp)
|
||||
: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp),
|
||||
LLVolumeGeometryManager()
|
||||
{
|
||||
mLODPeriod = 32;
|
||||
mDepthMask = FALSE;
|
||||
@@ -4012,7 +4013,8 @@ LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp)
|
||||
}
|
||||
|
||||
LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp)
|
||||
: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp)
|
||||
: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp),
|
||||
LLVolumeGeometryManager()
|
||||
{
|
||||
mDepthMask = FALSE;
|
||||
mLODPeriod = 32;
|
||||
@@ -4073,6 +4075,70 @@ bool can_batch_texture(const LLFace* facep)
|
||||
return true;
|
||||
}
|
||||
|
||||
const static U32 MAX_FACE_COUNT = 4096U;
|
||||
int32_t LLVolumeGeometryManager::sInstanceCount = 0;
|
||||
LLFace** LLVolumeGeometryManager::sFullbrightFaces = NULL;
|
||||
LLFace** LLVolumeGeometryManager::sBumpFaces = NULL;
|
||||
LLFace** LLVolumeGeometryManager::sSimpleFaces = NULL;
|
||||
LLFace** LLVolumeGeometryManager::sNormFaces = NULL;
|
||||
LLFace** LLVolumeGeometryManager::sSpecFaces = NULL;
|
||||
LLFace** LLVolumeGeometryManager::sNormSpecFaces = NULL;
|
||||
LLFace** LLVolumeGeometryManager::sAlphaFaces = NULL;
|
||||
|
||||
LLVolumeGeometryManager::LLVolumeGeometryManager()
|
||||
: LLGeometryManager()
|
||||
{
|
||||
llassert(sInstanceCount >= 0);
|
||||
if (sInstanceCount == 0)
|
||||
{
|
||||
allocateFaces(MAX_FACE_COUNT);
|
||||
}
|
||||
|
||||
++sInstanceCount;
|
||||
}
|
||||
|
||||
LLVolumeGeometryManager::~LLVolumeGeometryManager()
|
||||
{
|
||||
llassert(sInstanceCount > 0);
|
||||
--sInstanceCount;
|
||||
|
||||
if (sInstanceCount <= 0)
|
||||
{
|
||||
freeFaces();
|
||||
sInstanceCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount)
|
||||
{
|
||||
sFullbrightFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
|
||||
sBumpFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
|
||||
sSimpleFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
|
||||
sNormFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
|
||||
sSpecFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
|
||||
sNormSpecFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
|
||||
sAlphaFaces = static_cast<LLFace**>(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*)));
|
||||
}
|
||||
|
||||
void LLVolumeGeometryManager::freeFaces()
|
||||
{
|
||||
ll_aligned_free<64>(sFullbrightFaces);
|
||||
ll_aligned_free<64>(sBumpFaces);
|
||||
ll_aligned_free<64>(sSimpleFaces);
|
||||
ll_aligned_free<64>(sNormFaces);
|
||||
ll_aligned_free<64>(sSpecFaces);
|
||||
ll_aligned_free<64>(sNormSpecFaces);
|
||||
ll_aligned_free<64>(sAlphaFaces);
|
||||
|
||||
sFullbrightFaces = NULL;
|
||||
sBumpFaces = NULL;
|
||||
sSimpleFaces = NULL;
|
||||
sNormFaces = NULL;
|
||||
sSpecFaces = NULL;
|
||||
sNormSpecFaces = NULL;
|
||||
sAlphaFaces = NULL;
|
||||
}
|
||||
|
||||
static LLFastTimer::DeclareTimer FTM_REGISTER_FACE("Register Face");
|
||||
|
||||
void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
|
||||
@@ -4428,16 +4494,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
|
||||
mFaceList.clear();
|
||||
|
||||
const U32 MAX_FACE_COUNT = 4096;
|
||||
|
||||
static LLFace** fullbright_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64);
|
||||
static LLFace** bump_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64);
|
||||
static LLFace** simple_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64);
|
||||
static LLFace** norm_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64);
|
||||
static LLFace** spec_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64);
|
||||
static LLFace** normspec_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64);
|
||||
static LLFace** alpha_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64);
|
||||
|
||||
U32 fullbright_count = 0;
|
||||
U32 bump_count = 0;
|
||||
U32 simple_count = 0;
|
||||
@@ -4931,7 +4987,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
{ //can be treated as alpha mask
|
||||
if (simple_count < MAX_FACE_COUNT)
|
||||
{
|
||||
simple_faces[simple_count++] = facep;
|
||||
sSimpleFaces[simple_count++] = facep;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -4942,7 +4998,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
}
|
||||
if (alpha_count < MAX_FACE_COUNT)
|
||||
{
|
||||
alpha_faces[alpha_count++] = facep;
|
||||
sAlphaFaces[alpha_count++] = facep;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4967,14 +5023,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
{ //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
|
||||
if (normspec_count < MAX_FACE_COUNT)
|
||||
{
|
||||
normspec_faces[normspec_count++] = facep;
|
||||
sNormSpecFaces[normspec_count++] = facep;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //has normal map (needs texcoord1 and tangent)
|
||||
if (norm_count < MAX_FACE_COUNT)
|
||||
{
|
||||
norm_faces[norm_count++] = facep;
|
||||
sNormFaces[norm_count++] = facep;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4982,14 +5038,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
{ //has specular map but no normal map, needs texcoord2
|
||||
if (spec_count < MAX_FACE_COUNT)
|
||||
{
|
||||
spec_faces[spec_count++] = facep;
|
||||
sSpecFaces[spec_count++] = facep;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //has neither specular map nor normal map, only needs texcoord0
|
||||
if (simple_count < MAX_FACE_COUNT)
|
||||
{
|
||||
simple_faces[simple_count++] = facep;
|
||||
sSimpleFaces[simple_count++] = facep;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4997,14 +5053,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
{ //needs normal + tangent
|
||||
if (bump_count < MAX_FACE_COUNT)
|
||||
{
|
||||
bump_faces[bump_count++] = facep;
|
||||
sBumpFaces[bump_count++] = facep;
|
||||
}
|
||||
}
|
||||
else if (te->getShiny() || !te->getFullbright())
|
||||
{ //needs normal
|
||||
if (simple_count < MAX_FACE_COUNT)
|
||||
{
|
||||
simple_faces[simple_count++] = facep;
|
||||
sSimpleFaces[simple_count++] = facep;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -5012,7 +5068,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
facep->setState(LLFace::FULLBRIGHT);
|
||||
if (fullbright_count < MAX_FACE_COUNT)
|
||||
{
|
||||
fullbright_faces[fullbright_count++] = facep;
|
||||
sFullbrightFaces[fullbright_count++] = facep;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5022,7 +5078,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
{ //needs normal + tangent
|
||||
if (bump_count < MAX_FACE_COUNT)
|
||||
{
|
||||
bump_faces[bump_count++] = facep;
|
||||
sBumpFaces[bump_count++] = facep;
|
||||
}
|
||||
}
|
||||
else if ((te->getShiny() && LLPipeline::sRenderBump) ||
|
||||
@@ -5030,7 +5086,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
{ //needs normal
|
||||
if (simple_count < MAX_FACE_COUNT)
|
||||
{
|
||||
simple_faces[simple_count++] = facep;
|
||||
sSimpleFaces[simple_count++] = facep;
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -5038,7 +5094,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
facep->setState(LLFace::FULLBRIGHT);
|
||||
if (fullbright_count < MAX_FACE_COUNT)
|
||||
{
|
||||
fullbright_faces[fullbright_count++] = facep;
|
||||
sFullbrightFaces[fullbright_count++] = facep;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5051,7 +5107,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
|
||||
if (type == LLDrawPool::POOL_ALPHA)
|
||||
{
|
||||
cur_type = &alpha_faces;
|
||||
cur_type = &sAlphaFaces;
|
||||
cur_count = &alpha_count;
|
||||
|
||||
if (te->getColor().mV[3] > 0.f)
|
||||
@@ -5066,30 +5122,30 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
{
|
||||
if (mat->getSpecularID().notNull())
|
||||
{ //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
|
||||
cur_type = &normspec_faces;
|
||||
cur_type = &sNormSpecFaces;
|
||||
cur_count = &normspec_count;
|
||||
}
|
||||
else
|
||||
{ //has normal map (needs texcoord1 and tangent)
|
||||
cur_type = &norm_faces;
|
||||
cur_type = &sNormFaces;
|
||||
cur_count = &norm_count;
|
||||
}
|
||||
}
|
||||
else if (mat->getSpecularID().notNull())
|
||||
{ //has specular map but no normal map, needs texcoord2
|
||||
cur_type = &spec_faces;
|
||||
cur_type = &sSpecFaces;
|
||||
cur_count = &spec_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(type == LLDrawPool::POOL_ALPHA_MASK)
|
||||
{
|
||||
cur_type = &simple_faces;
|
||||
cur_type = &sSimpleFaces;
|
||||
cur_count = &simple_count;
|
||||
}
|
||||
else if(type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK)
|
||||
{
|
||||
cur_type = &fullbright_faces;
|
||||
cur_type = &sFullbrightFaces;
|
||||
cur_count = &fullbright_count;
|
||||
}
|
||||
else
|
||||
@@ -5103,30 +5159,30 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
{ //needs normal + tangent
|
||||
if(te->getBumpmap() > 0 && te->getBumpmap() < 18)
|
||||
{
|
||||
cur_type = &bump_faces;
|
||||
cur_type = &sBumpFaces;
|
||||
cur_count = &bump_count;
|
||||
}
|
||||
else if(te->getShiny())
|
||||
{
|
||||
cur_type = &simple_faces;
|
||||
cur_type = &sSimpleFaces;
|
||||
cur_count = &simple_count;
|
||||
}
|
||||
}
|
||||
else if (type == LLDrawPool::POOL_SIMPLE)
|
||||
{ //needs normal + tangent
|
||||
cur_type = &simple_faces;
|
||||
cur_type = &sSimpleFaces;
|
||||
cur_count = &simple_count;
|
||||
}
|
||||
else if (type == LLDrawPool::POOL_FULLBRIGHT)
|
||||
{ //doesn't need normal...
|
||||
if(LLPipeline::sRenderBump && te->getShiny()) //unless it's shiny..
|
||||
{
|
||||
cur_type = &simple_faces;
|
||||
cur_type = &sSimpleFaces;
|
||||
cur_count = &simple_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
cur_type = &fullbright_faces;
|
||||
cur_type = &sFullbrightFaces;
|
||||
cur_count = &fullbright_count;
|
||||
}
|
||||
}
|
||||
@@ -5140,23 +5196,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
{
|
||||
if (mat->getSpecularID().notNull())
|
||||
{ //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
|
||||
cur_type = &normspec_faces;
|
||||
cur_type = &sNormSpecFaces;
|
||||
cur_count = &normspec_count;
|
||||
}
|
||||
else
|
||||
{ //has normal map (needs texcoord1 and tangent)
|
||||
cur_type = &norm_faces;
|
||||
cur_type = &sNormFaces;
|
||||
cur_count = &norm_count;
|
||||
}
|
||||
}
|
||||
else if (mat->getSpecularID().notNull())
|
||||
{ //has specular map but no normal map, needs texcoord2
|
||||
cur_type = &spec_faces;
|
||||
cur_type = &sSpecFaces;
|
||||
cur_count = &spec_count;
|
||||
}
|
||||
else
|
||||
{ //has neither specular map nor normal map, only needs texcoord0
|
||||
cur_type = &simple_faces;
|
||||
cur_type = &sSimpleFaces;
|
||||
cur_count = &simple_count;
|
||||
}
|
||||
}
|
||||
@@ -5218,13 +5274,13 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
||||
if(emissive)
|
||||
additional_flags |= LLVertexBuffer::MAP_EMISSIVE;
|
||||
|
||||
genDrawInfo(group, simple_mask | additional_flags, simple_faces, simple_count, FALSE, batch_textures);
|
||||
genDrawInfo(group, fullbright_mask | additional_flags, fullbright_faces, fullbright_count, FALSE, batch_textures);
|
||||
genDrawInfo(group, alpha_mask | additional_flags, alpha_faces, alpha_count, TRUE, batch_textures);
|
||||
genDrawInfo(group, bump_mask | additional_flags, bump_faces, bump_count, FALSE);
|
||||
genDrawInfo(group, norm_mask | additional_flags, norm_faces, norm_count, FALSE);
|
||||
genDrawInfo(group, spec_mask | additional_flags, spec_faces, spec_count, FALSE);
|
||||
genDrawInfo(group, normspec_mask | additional_flags, normspec_faces, normspec_count, FALSE);
|
||||
genDrawInfo(group, simple_mask | additional_flags, sSimpleFaces, simple_count, FALSE, batch_textures);
|
||||
genDrawInfo(group, fullbright_mask | additional_flags, sFullbrightFaces, fullbright_count, FALSE, batch_textures);
|
||||
genDrawInfo(group, alpha_mask | additional_flags, sAlphaFaces, alpha_count, TRUE, batch_textures);
|
||||
genDrawInfo(group, bump_mask | additional_flags, sBumpFaces, bump_count, FALSE);
|
||||
genDrawInfo(group, norm_mask | additional_flags, sNormFaces, norm_count, FALSE);
|
||||
genDrawInfo(group, spec_mask | additional_flags, sSpecFaces, spec_count, FALSE);
|
||||
genDrawInfo(group, normspec_mask | additional_flags, sNormSpecFaces, normspec_count, FALSE);
|
||||
|
||||
if (!LLPipeline::sDelayVBUpdate)
|
||||
{
|
||||
|
||||
@@ -2830,7 +2830,7 @@ void LLPipeline::updateGeom(F32 max_dtime)
|
||||
|
||||
S32 count = 0;
|
||||
|
||||
max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime);
|
||||
max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, F32SecondsImplicit(max_dtime));
|
||||
LLSpatialGroup* last_group = NULL;
|
||||
LLSpatialBridge* last_bridge = NULL;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user