llcommon merge. Added LLUnits.
This commit is contained in:
@@ -230,9 +230,13 @@ set(llcommon_HEADER_FILES
|
|||||||
llthreadsafequeue.h
|
llthreadsafequeue.h
|
||||||
lltimer.h
|
lltimer.h
|
||||||
lltreeiterators.h
|
lltreeiterators.h
|
||||||
|
llunits.h
|
||||||
|
llunittype.h
|
||||||
lltypeinfolookup.h
|
lltypeinfolookup.h
|
||||||
lluri.h
|
lluri.h
|
||||||
lluuid.h
|
lluuid.h
|
||||||
|
llwin32headers.h
|
||||||
|
llwin32headerslean.h
|
||||||
llworkerthread.h
|
llworkerthread.h
|
||||||
metaclass.h
|
metaclass.h
|
||||||
metaclasst.h
|
metaclasst.h
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ LLAlignedArray<T, alignment>::LLAlignedArray()
|
|||||||
template <class T, U32 alignment>
|
template <class T, U32 alignment>
|
||||||
LLAlignedArray<T, alignment>::~LLAlignedArray()
|
LLAlignedArray<T, alignment>::~LLAlignedArray()
|
||||||
{
|
{
|
||||||
ll_aligned_free(mArray);
|
ll_aligned_free<alignment>(mArray);
|
||||||
mArray = NULL;
|
mArray = NULL;
|
||||||
mElementCount = 0;
|
mElementCount = 0;
|
||||||
mCapacity = 0;
|
mCapacity = 0;
|
||||||
@@ -78,7 +78,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
|
|||||||
{
|
{
|
||||||
mCapacity++;
|
mCapacity++;
|
||||||
mCapacity *= 2;
|
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)
|
if (mArray)
|
||||||
{
|
{
|
||||||
ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount);
|
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;
|
mArray[mElementCount++] = elem;
|
||||||
|
|
||||||
//delete old array here to prevent error on a.push_back(a[0])
|
//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>
|
template <class T, U32 alignment>
|
||||||
@@ -99,11 +99,11 @@ void LLAlignedArray<T, alignment>::resize(U32 size)
|
|||||||
if (mCapacity < size)
|
if (mCapacity < size)
|
||||||
{
|
{
|
||||||
mCapacity = size+mCapacity*2;
|
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)
|
if (mArray)
|
||||||
{
|
{
|
||||||
ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount);
|
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)
|
/*for (U32 i = mElementCount; i < mCapacity; ++i)
|
||||||
|
|||||||
@@ -30,32 +30,36 @@
|
|||||||
#include "llbase64.h"
|
#include "llbase64.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "apr_base64.h"
|
#include "apr_base64.h"
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
std::string LLBase64::encode(const U8* input, size_t input_size)
|
std::string LLBase64::encode(const U8* input, size_t input_size)
|
||||||
{
|
{
|
||||||
if (!(input && input_size > 0)) return LLStringUtil::null;
|
std::string output;
|
||||||
|
if (input
|
||||||
// Yes, it returns int.
|
&& input_size > 0)
|
||||||
int b64_buffer_length = apr_base64_encode_len(input_size);
|
{
|
||||||
char* b64_buffer = new char[b64_buffer_length];
|
// Yes, it returns int.
|
||||||
|
int b64_buffer_length = apr_base64_encode_len(input_size);
|
||||||
// This is faster than apr_base64_encode() if you know
|
char* b64_buffer = new char[b64_buffer_length];
|
||||||
// you're not on an EBCDIC machine. Also, the output is
|
|
||||||
// null terminated, even though the documentation doesn't
|
// This is faster than apr_base64_encode() if you know
|
||||||
// specify. See apr_base64.c for details. JC
|
// you're not on an EBCDIC machine. Also, the output is
|
||||||
b64_buffer_length = apr_base64_encode_binary(
|
// null terminated, even though the documentation doesn't
|
||||||
b64_buffer,
|
// specify. See apr_base64.c for details. JC
|
||||||
input,
|
b64_buffer_length = apr_base64_encode_binary(
|
||||||
input_size);
|
b64_buffer,
|
||||||
std::string result;
|
input,
|
||||||
result.assign(b64_buffer);
|
input_size);
|
||||||
delete[] b64_buffer;
|
output.assign(b64_buffer);
|
||||||
|
delete[] b64_buffer;
|
||||||
return result;
|
}
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
std::string LLBase64::encode(const std::string& in_str)
|
std::string LLBase64::encode(const std::string& in_str)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ LLDate::LLDate(const LLDate& date) :
|
|||||||
mSecondsSinceEpoch(date.mSecondsSinceEpoch)
|
mSecondsSinceEpoch(date.mSecondsSinceEpoch)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
LLDate::LLDate(F64 seconds_since_epoch) :
|
LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) :
|
||||||
mSecondsSinceEpoch(seconds_since_epoch)
|
mSecondsSinceEpoch(seconds_since_epoch.value())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
LLDate::LLDate(const std::string& iso8601_date)
|
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
|
// is one of the standards used and the prefered format
|
||||||
std::string LLDate::asRFC1123() const
|
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");
|
LLFastTimer::DeclareTimer FT_DATE_FORMAT("Date Format");
|
||||||
|
|||||||
@@ -38,9 +38,8 @@
|
|||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "llpreprocessor.h"
|
|
||||||
|
|
||||||
#include "stdtypes.h"
|
#include "stdtypes.h"
|
||||||
|
#include "llunits.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class LLDate
|
* @class LLDate
|
||||||
@@ -64,9 +63,9 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Construct a date from a seconds since epoch value.
|
* @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
|
* @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
|
// Helper function to stream in a date
|
||||||
LL_COMMON_API std::istream& operator>>(std::istream& s, LLDate& date);
|
LL_COMMON_API std::istream& operator>>(std::istream& s, LLDate& date);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // LL_LLDATE_H
|
#endif // LL_LLDATE_H
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ LLEventTimer::~LLEventTimer()
|
|||||||
void LLEventTimer::updateClass()
|
void LLEventTimer::updateClass()
|
||||||
{
|
{
|
||||||
std::list<LLEventTimer*> completed_timers;
|
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++;
|
LLEventTimer& timer = *iter++;
|
||||||
F32 et = timer.mEventTimer.getElapsedTimeF32();
|
F32 et = timer.mEventTimer.getElapsedTimeF32();
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
#include <windows.h>
|
#include "llwin32headerslean.h"
|
||||||
#include <stdlib.h> // Windows errno
|
#include <stdlib.h> // Windows errno
|
||||||
#else
|
#else
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#include <windows.h>
|
#include "llwin32headers.h"
|
||||||
#include <winnt.h>
|
#include <winnt.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -183,7 +183,7 @@ canonise_fl(FL_Locale *l) {
|
|||||||
#define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn)
|
#define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn)
|
||||||
struct IDToCode {
|
struct IDToCode {
|
||||||
LANGID id;
|
LANGID id;
|
||||||
char* code;
|
const char* code;
|
||||||
};
|
};
|
||||||
static const IDToCode both_to_code[] = {
|
static const IDToCode both_to_code[] = {
|
||||||
{ML(ENGLISH,US), "en_US.ISO_8859-1"},
|
{ML(ENGLISH,US), "en_US.ISO_8859-1"},
|
||||||
|
|||||||
@@ -30,7 +30,8 @@
|
|||||||
|
|
||||||
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
|
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
|
||||||
: LLLineBuffer(),
|
: LLLineBuffer(),
|
||||||
mMaxLines(max_lines)
|
mMaxLines(max_lines),
|
||||||
|
mMutex()
|
||||||
{
|
{
|
||||||
mTimer.reset();
|
mTimer.reset();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,13 +194,6 @@ public:
|
|||||||
return mHandle;
|
return mHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
|
||||||
typedef LLHandle<T> handle_type_t;
|
|
||||||
LLHandleProvider()
|
|
||||||
{
|
|
||||||
// provided here to enforce T deriving from LLHandleProvider<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
|
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;
|
return downcast_handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef LLHandle<T> handle_type_t;
|
||||||
|
LLHandleProvider()
|
||||||
|
{
|
||||||
|
// provided here to enforce T deriving from LLHandleProvider<T>
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable LLRootHandle<T> mHandle;
|
mutable LLRootHandle<T> mHandle;
|
||||||
|
|||||||
@@ -88,46 +88,51 @@ LLLiveFile::~LLLiveFile()
|
|||||||
|
|
||||||
bool LLLiveFile::Impl::check()
|
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
|
||||||
|
if (mForceCheck || mRefreshTimer.getElapsedTimeF32() >= mRefreshPeriod)
|
||||||
{
|
{
|
||||||
// Skip the check if not enough time has elapsed and we're not
|
mForceCheck = false; // force only forces one check
|
||||||
// forcing a check of the file
|
mRefreshTimer.reset(); // don't check again until mRefreshPeriod has passed
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mForceCheck = false;
|
|
||||||
mRefreshTimer.reset();
|
|
||||||
|
|
||||||
// Stat the file to see if it exists and when it was last modified.
|
// Stat the file to see if it exists and when it was last modified.
|
||||||
llstat stat_data;
|
llstat stat_data;
|
||||||
int res = LLFile::stat(mFilename, &stat_data);
|
if (LLFile::stat(mFilename, &stat_data))
|
||||||
|
{
|
||||||
if (res)
|
// Couldn't stat the file, that means it doesn't exist or is
|
||||||
{
|
// broken somehow.
|
||||||
// Couldn't stat the file, that means it doesn't exist or is
|
if (mLastExists)
|
||||||
// broken somehow. Clear flags and return.
|
{
|
||||||
if (mLastExists)
|
mLastExists = false;
|
||||||
{
|
detected_change = true; // no longer existing is a change!
|
||||||
mLastExists = false;
|
LL_DEBUGS() << "detected deleted file '" << mFilename << "'" << LL_ENDL;
|
||||||
return true; // no longer existing is a change!
|
}
|
||||||
}
|
}
|
||||||
return false;
|
else
|
||||||
}
|
{
|
||||||
|
// The file exists
|
||||||
// The file exists, decide if we want to load it.
|
if ( ! mLastExists )
|
||||||
if (mLastExists)
|
{
|
||||||
{
|
// last check, it did not exist - that counts as a change
|
||||||
// The file existed last time, don't read it if it hasn't changed since
|
LL_DEBUGS() << "detected created file '" << mFilename << "'" << LL_ENDL;
|
||||||
// last time.
|
detected_change = true;
|
||||||
if (stat_data.st_mtime <= mLastModTime)
|
}
|
||||||
{
|
else if ( stat_data.st_mtime > mLastModTime )
|
||||||
return false;
|
{
|
||||||
}
|
// 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;
|
mLastExists = true;
|
||||||
mLastStatTime = stat_data.st_mtime;
|
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()
|
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
|
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.
|
// Transform as many times as possible.
|
||||||
if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
|
if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
|
||||||
// fill the rest of the buffer and transform
|
// fill the rest of the buffer and transform
|
||||||
@@ -128,12 +134,6 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) {
|
|||||||
buffer_space);
|
buffer_space);
|
||||||
transform (buffer);
|
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;
|
for (input_index = buffer_space; input_index + 63 < input_length;
|
||||||
input_index += 64)
|
input_index += 64)
|
||||||
transform (input+input_index);
|
transform (input+input_index);
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
#if defined(LL_WINDOWS)
|
#if defined(LL_WINDOWS)
|
||||||
//# include <windows.h>
|
#include "llwin32headerslean.h"
|
||||||
# include <psapi.h>
|
# include <psapi.h>
|
||||||
#elif defined(LL_DARWIN)
|
#elif defined(LL_DARWIN)
|
||||||
# include <sys/types.h>
|
# include <sys/types.h>
|
||||||
@@ -50,11 +50,11 @@
|
|||||||
|
|
||||||
//static
|
//static
|
||||||
char* LLMemory::reserveMem = 0;
|
char* LLMemory::reserveMem = 0;
|
||||||
U32 LLMemory::sAvailPhysicalMemInKB = U32_MAX ;
|
U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
|
||||||
U32 LLMemory::sMaxPhysicalMemInKB = 0;
|
U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0);
|
||||||
U32 LLMemory::sAllocatedMemInKB = 0;
|
U32Kilobytes LLMemory::sAllocatedMemInKB(0);
|
||||||
U32 LLMemory::sAllocatedPageSizeInKB = 0 ;
|
U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
|
||||||
U32 LLMemory::sMaxHeapSizeInKB = U32_MAX ;
|
U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
|
||||||
BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
|
BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
|
||||||
|
|
||||||
#if __DEBUG_PRIVATE_MEM__
|
#if __DEBUG_PRIVATE_MEM__
|
||||||
@@ -93,9 +93,9 @@ void LLMemory::freeReserve()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//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 ;
|
sEnableMemoryFailurePrevention = prevent_heap_failure ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,10 +112,10 @@ void LLMemory::updateMemoryInfo()
|
|||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ;
|
sAllocatedMemInKB = (U32Bytes)(counters.WorkingSetSize) ;
|
||||||
sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ;
|
sAllocatedPageSizeInKB = (U32Bytes)(counters.PagefileUsage) ;
|
||||||
|
|
||||||
U32 avail_phys, avail_virtual;
|
U32Kilobytes avail_phys, avail_virtual;
|
||||||
LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
|
LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
|
||||||
sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
|
sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
|
||||||
|
|
||||||
@@ -125,14 +125,16 @@ void LLMemory::updateMemoryInfo()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sAvailPhysicalMemInKB = 0 ;
|
sAvailPhysicalMemInKB = U32Kilobytes(0);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
//not valid for other systems for now.
|
//not valid for other systems for now.
|
||||||
sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ;
|
sAllocatedMemInKB = (U32Bytes)LLMemory::getCurrentRSS();
|
||||||
sMaxPhysicalMemInKB = U32_MAX ;
|
sMaxPhysicalMemInKB = (U32Bytes)U32_MAX ;
|
||||||
sAvailPhysicalMemInKB = U32_MAX ;
|
sAvailPhysicalMemInKB = (U32Bytes)U32_MAX ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
return ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -184,8 +186,8 @@ void LLMemory::logMemoryInfo(BOOL update)
|
|||||||
//static
|
//static
|
||||||
bool LLMemory::isMemoryPoolLow()
|
bool LLMemory::isMemoryPoolLow()
|
||||||
{
|
{
|
||||||
static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use
|
static const U32Megabytes LOW_MEMORY_POOL_THRESHOLD(64);
|
||||||
const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
|
const static U32Megabytes MAX_SIZE_CHECKED_MEMORY_BLOCK(64);
|
||||||
static void* last_reserved_address = NULL ;
|
static void* last_reserved_address = NULL ;
|
||||||
|
|
||||||
if(!sEnableMemoryFailurePrevention)
|
if(!sEnableMemoryFailurePrevention)
|
||||||
@@ -193,32 +195,32 @@ bool LLMemory::isMemoryPoolLow()
|
|||||||
return false ; //no memory failure prevention.
|
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 ;
|
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 ;
|
return true ;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB ||
|
bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD
|
||||||
sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ;
|
|| sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ;
|
||||||
|
|
||||||
//check the virtual address space fragmentation
|
//check the virtual address space fragmentation
|
||||||
if(!is_low)
|
if(!is_low)
|
||||||
{
|
{
|
||||||
if(!last_reserved_address)
|
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
|
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
|
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
|
//static
|
||||||
U32 LLMemory::getAvailableMemKB()
|
U32Kilobytes LLMemory::getAvailableMemKB()
|
||||||
{
|
{
|
||||||
return sAvailPhysicalMemInKB ;
|
return sAvailPhysicalMemInKB ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
U32 LLMemory::getMaxMemKB()
|
U32Kilobytes LLMemory::getMaxMemKB()
|
||||||
{
|
{
|
||||||
return sMaxPhysicalMemInKB ;
|
return sMaxPhysicalMemInKB ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
U32 LLMemory::getAllocatedMemKB()
|
U32Kilobytes LLMemory::getAllocatedMemKB()
|
||||||
{
|
{
|
||||||
return sAllocatedMemInKB ;
|
return sAllocatedMemInKB ;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,8 @@
|
|||||||
#define LLMEMORY_H
|
#define LLMEMORY_H
|
||||||
|
|
||||||
#include "linden_common.h"
|
#include "linden_common.h"
|
||||||
|
#include "llunits.h"
|
||||||
|
#include "stdtypes.h"
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#if !LL_WINDOWS
|
#if !LL_WINDOWS
|
||||||
@@ -42,6 +43,21 @@ class LLMutex ;
|
|||||||
#define LL_CHECK_MEMORY
|
#define LL_CHECK_MEMORY
|
||||||
#endif
|
#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>
|
//<singu>
|
||||||
// ll_assert_aligned seems to only exist to set breakpoints in case an alignment check fails.
|
// 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
|
// However, the implementation was horrible: the test was done using a integer modulo after
|
||||||
@@ -102,31 +118,43 @@ 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)
|
#define LL_ALIGN_16(var) LL_ALIGN_PREFIX(16) var LL_ALIGN_POSTFIX(16)
|
||||||
|
|
||||||
inline void* ll_aligned_malloc( size_t size, int align )
|
//------------------------------------------------------------------------------------------------
|
||||||
{
|
//------------------------------------------------------------------------------------------------
|
||||||
#if defined(LL_WINDOWS)
|
// for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library
|
||||||
return _aligned_malloc(size, align);
|
// change preprocessor code to: #if 1 && defined(LL_WINDOWS)
|
||||||
#else
|
|
||||||
void* mem = malloc( size + (align - 1) + sizeof(void*) );
|
|
||||||
char* aligned = ((char*)mem) + sizeof(void*);
|
|
||||||
aligned += align - ((uintptr_t)aligned & (align - 1));
|
|
||||||
|
|
||||||
((void**)aligned)[-1] = mem;
|
#if 0 && defined(LL_WINDOWS)
|
||||||
return aligned;
|
void* ll_aligned_malloc_fallback( size_t size, int align );
|
||||||
#endif
|
void ll_aligned_free_fallback( void* ptr );
|
||||||
}
|
//------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
inline void ll_aligned_free( void* ptr )
|
|
||||||
{
|
|
||||||
#if defined(LL_WINDOWS)
|
|
||||||
_aligned_free(ptr);
|
|
||||||
#else
|
#else
|
||||||
if (ptr)
|
inline void* ll_aligned_malloc_fallback( size_t size, int align )
|
||||||
{
|
{
|
||||||
free( ((void**)ptr)[-1] );
|
#if defined(LL_WINDOWS)
|
||||||
|
return _aligned_malloc(size, align);
|
||||||
|
#else
|
||||||
|
void* mem = malloc( size + (align - 1) + sizeof(void*) );
|
||||||
|
char* aligned = ((char*)mem) + sizeof(void*);
|
||||||
|
aligned += align - ((uintptr_t)aligned & (align - 1));
|
||||||
|
|
||||||
|
((void**)aligned)[-1] = mem;
|
||||||
|
return aligned;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ll_aligned_free_fallback( void* ptr )
|
||||||
|
{
|
||||||
|
#if defined(LL_WINDOWS)
|
||||||
|
_aligned_free(ptr);
|
||||||
|
#else
|
||||||
|
if (ptr)
|
||||||
|
{
|
||||||
|
free( ((void**)ptr)[-1] );
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
//------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if !LL_USE_TCMALLOC
|
#if !LL_USE_TCMALLOC
|
||||||
inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16().
|
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)
|
#if defined(LL_WINDOWS)
|
||||||
return _aligned_malloc(size, 32);
|
return _aligned_malloc(size, 32);
|
||||||
#elif defined(LL_DARWIN)
|
#elif defined(LL_DARWIN)
|
||||||
return ll_aligned_malloc( size, 32 );
|
return ll_aligned_malloc_fallback( size, 32 );
|
||||||
#else
|
#else
|
||||||
void *rtn;
|
void *rtn;
|
||||||
if (LL_LIKELY(0 == posix_memalign(&rtn, 32, size)))
|
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)
|
#if defined(LL_WINDOWS)
|
||||||
_aligned_free(p);
|
_aligned_free(p);
|
||||||
#elif defined(LL_DARWIN)
|
#elif defined(LL_DARWIN)
|
||||||
ll_aligned_free( p );
|
ll_aligned_free_fallback( p );
|
||||||
#else
|
#else
|
||||||
free(p); // posix_memalign() is compatible with heap deallocator
|
free(p); // posix_memalign() is compatible with heap deallocator
|
||||||
#endif
|
#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.
|
// 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.
|
// Source and dest must be 16-byte aligned and size must be multiple of 16.
|
||||||
@@ -297,22 +367,22 @@ public:
|
|||||||
static U64 getCurrentRSS();
|
static U64 getCurrentRSS();
|
||||||
static U32 getWorkingSetSize();
|
static U32 getWorkingSetSize();
|
||||||
static void* tryToAlloc(void* address, U32 size);
|
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 updateMemoryInfo() ;
|
||||||
static void logMemoryInfo(BOOL update = FALSE);
|
static void logMemoryInfo(BOOL update = FALSE);
|
||||||
static bool isMemoryPoolLow();
|
static bool isMemoryPoolLow();
|
||||||
|
|
||||||
static U32 getAvailableMemKB() ;
|
static U32Kilobytes getAvailableMemKB() ;
|
||||||
static U32 getMaxMemKB() ;
|
static U32Kilobytes getMaxMemKB() ;
|
||||||
static U32 getAllocatedMemKB() ;
|
static U32Kilobytes getAllocatedMemKB() ;
|
||||||
private:
|
private:
|
||||||
static char* reserveMem;
|
static char* reserveMem;
|
||||||
static U32 sAvailPhysicalMemInKB ;
|
static U32Kilobytes sAvailPhysicalMemInKB ;
|
||||||
static U32 sMaxPhysicalMemInKB ;
|
static U32Kilobytes sMaxPhysicalMemInKB ;
|
||||||
static U32 sAllocatedMemInKB;
|
static U32Kilobytes sAllocatedMemInKB;
|
||||||
static U32 sAllocatedPageSizeInKB ;
|
static U32Kilobytes sAllocatedPageSizeInKB ;
|
||||||
|
|
||||||
static U32 sMaxHeapSizeInKB;
|
static U32Kilobytes sMaxHeapSizeInKB;
|
||||||
static BOOL sEnableMemoryFailurePrevention;
|
static BOOL sEnableMemoryFailurePrevention;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#define LLMORTICIAN_H
|
#define LLMORTICIAN_H
|
||||||
|
|
||||||
#include "stdtypes.h"
|
#include "stdtypes.h"
|
||||||
|
#include <list>
|
||||||
|
|
||||||
class LL_COMMON_API LLMortician
|
class LL_COMMON_API LLMortician
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -32,9 +32,7 @@
|
|||||||
//#include <memory>
|
//#include <memory>
|
||||||
|
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
# define WIN32_LEAN_AND_MEAN
|
# include "llwin32headerslean.h"
|
||||||
# include <winsock2.h>
|
|
||||||
# include <windows.h>
|
|
||||||
# define _interlockedbittestandset _renamed_interlockedbittestandset
|
# define _interlockedbittestandset _renamed_interlockedbittestandset
|
||||||
# define _interlockedbittestandreset _renamed_interlockedbittestandreset
|
# define _interlockedbittestandreset _renamed_interlockedbittestandreset
|
||||||
# include <intrin.h>
|
# include <intrin.h>
|
||||||
@@ -881,7 +879,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
|
|||||||
|
|
||||||
|
|
||||||
LLProcessorInfo::~LLProcessorInfo() {}
|
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::hasSSE() const { return mImpl->hasSSE(); }
|
||||||
bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); }
|
bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); }
|
||||||
bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); }
|
bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); }
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
#ifndef LLPROCESSOR_H
|
#ifndef LLPROCESSOR_H
|
||||||
#define LLPROCESSOR_H
|
#define LLPROCESSOR_H
|
||||||
|
#include "llunits.h"
|
||||||
|
|
||||||
class LLProcessorInfoImpl;
|
class LLProcessorInfoImpl;
|
||||||
|
|
||||||
class LL_COMMON_API LLProcessorInfo
|
class LL_COMMON_API LLProcessorInfo
|
||||||
@@ -41,7 +43,7 @@ public:
|
|||||||
LLProcessorInfo();
|
LLProcessorInfo();
|
||||||
~LLProcessorInfo();
|
~LLProcessorInfo();
|
||||||
|
|
||||||
F64 getCPUFrequency() const;
|
F64MegahertzImplicit getCPUFrequency() const;
|
||||||
bool hasSSE() const;
|
bool hasSSE() const;
|
||||||
bool hasSSE2() const;
|
bool hasSSE2() const;
|
||||||
bool hasAltivec() const;
|
bool hasAltivec() const;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) :
|
LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) :
|
||||||
LLThread(name),
|
LLThread(name),
|
||||||
mThreaded(threaded),
|
mThreaded(threaded),
|
||||||
mIdleThread(TRUE),
|
mIdleThread(true),
|
||||||
mNextHandle(0),
|
mNextHandle(0),
|
||||||
mStarted(FALSE)
|
mStarted(FALSE)
|
||||||
{
|
{
|
||||||
@@ -552,14 +552,15 @@ void LLQueuedThread::run()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
mIdleThread = FALSE;
|
mIdleThread = false;
|
||||||
|
|
||||||
threadedUpdate();
|
threadedUpdate();
|
||||||
|
|
||||||
int res = processNextRequest();
|
int pending_work = processNextRequest();
|
||||||
if (res == 0)
|
|
||||||
|
if (pending_work == 0)
|
||||||
{
|
{
|
||||||
mIdleThread = TRUE;
|
mIdleThread = true;
|
||||||
ms_sleep(1);
|
ms_sleep(1);
|
||||||
}
|
}
|
||||||
//LLThread::yield(); // thread should yield after each request
|
//LLThread::yield(); // thread should yield after each request
|
||||||
|
|||||||
@@ -32,8 +32,6 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include "llapr.h"
|
|
||||||
|
|
||||||
#include "llthread.h"
|
#include "llthread.h"
|
||||||
#include "llsimplehash.h"
|
#include "llsimplehash.h"
|
||||||
|
|
||||||
@@ -204,7 +202,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
BOOL mThreaded; // if false, run on main thread and do updates during update()
|
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()
|
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;
|
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
|
||||||
request_queue_t mRequestQueue;
|
request_queue_t mRequestQueue;
|
||||||
|
|||||||
@@ -31,15 +31,15 @@
|
|||||||
|
|
||||||
#if LL_REF_COUNT_DEBUG
|
#if LL_REF_COUNT_DEBUG
|
||||||
#include "llthread.h"
|
#include "llthread.h"
|
||||||
#include "llapr.h"
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
LLRefCount::LLRefCount(const LLRefCount& other)
|
LLRefCount::LLRefCount(const LLRefCount& other) :
|
||||||
: mRef(0)
|
|
||||||
{
|
|
||||||
#if LL_REF_COUNT_DEBUG
|
#if LL_REF_COUNT_DEBUG
|
||||||
mCrashAtUnlock = FALSE ;
|
mMutex(),
|
||||||
|
mCrashAtUnlock(FALSE),
|
||||||
#endif
|
#endif
|
||||||
|
mRef(0)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
||||||
@@ -49,11 +49,12 @@ LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LLRefCount::LLRefCount() :
|
LLRefCount::LLRefCount() :
|
||||||
|
#if LL_REF_COUNT_DEBUG
|
||||||
|
mMutex(),
|
||||||
|
mCrashAtUnlock(FALSE),
|
||||||
|
#endif
|
||||||
mRef(0)
|
mRef(0)
|
||||||
{
|
{
|
||||||
#if LL_REF_COUNT_DEBUG
|
|
||||||
mCrashAtUnlock = FALSE ;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LLRefCount::~LLRefCount()
|
LLRefCount::~LLRefCount()
|
||||||
|
|||||||
@@ -337,10 +337,9 @@ void clear_eol(std::istream& input)
|
|||||||
static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize)
|
static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize)
|
||||||
{
|
{
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
char c;
|
|
||||||
while (count < bufsize && input.good())
|
while (count < bufsize && input.good())
|
||||||
{
|
{
|
||||||
input.get(c);
|
char c = input.get();
|
||||||
buf[count++] = c;
|
buf[count++] = c;
|
||||||
if (is_eol(c))
|
if (is_eol(c))
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "windows.h"
|
#include "llwin32headerslean.h"
|
||||||
#include "Dbghelp.h"
|
#include "Dbghelp.h"
|
||||||
|
|
||||||
typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
|
typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
|
||||||
|
|||||||
@@ -508,6 +508,27 @@ llbind2nd(const _Operation& __oper, const _Tp& __x)
|
|||||||
return llbinder2nd<_Operation>(__oper, _Arg2_type(__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().
|
* 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*
|
* 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
|
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
|
bool operator()(std::type_info* lhs, std::type_info* rhs) const
|
||||||
{
|
{
|
||||||
return lhs->before(*rhs);
|
return before(lhs, rhs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // std
|
} // std
|
||||||
|
|||||||
@@ -30,9 +30,7 @@
|
|||||||
#include "llerror.h"
|
#include "llerror.h"
|
||||||
|
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
#define WIN32_LEAN_AND_MEAN
|
#include "llwin32headerslean.h"
|
||||||
#include <winsock2.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#include <winnls.h> // for WideCharToMultiByte
|
#include <winnls.h> // for WideCharToMultiByte
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -53,9 +53,7 @@
|
|||||||
using namespace llsd;
|
using namespace llsd;
|
||||||
|
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
# define WIN32_LEAN_AND_MEAN
|
# include "llwin32headerslean.h"
|
||||||
# include <winsock2.h>
|
|
||||||
# include <windows.h>
|
|
||||||
# include <psapi.h> // GetPerformanceInfo() et al.
|
# include <psapi.h> // GetPerformanceInfo() et al.
|
||||||
# include <VersionHelpers.h>
|
# include <VersionHelpers.h>
|
||||||
#elif LL_DARWIN
|
#elif LL_DARWIN
|
||||||
@@ -705,7 +703,7 @@ LLMemoryInfo::LLMemoryInfo()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
static U32 LLMemoryAdjustKBResult(U32 inKB)
|
static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)
|
||||||
{
|
{
|
||||||
// Moved this here from llfloaterabout.cpp
|
// Moved this here from llfloaterabout.cpp
|
||||||
|
|
||||||
@@ -716,16 +714,16 @@ static U32 LLMemoryAdjustKBResult(U32 inKB)
|
|||||||
// returned from the GetMemoryStatusEx function. Here we keep the
|
// returned from the GetMemoryStatusEx function. Here we keep the
|
||||||
// original adjustment from llfoaterabout.cpp until this can be
|
// original adjustment from llfoaterabout.cpp until this can be
|
||||||
// fixed somehow.
|
// fixed somehow.
|
||||||
inKB += 1024;
|
inKB += U32Megabytes(1);
|
||||||
|
|
||||||
return inKB;
|
return inKB;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
U32 LLMemoryInfo::getPhysicalMemoryKB() const
|
U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
|
||||||
{
|
{
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
return LLMemoryAdjustKBResult(mStatsMap["Total Physical KB"].asInteger());
|
return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));
|
||||||
|
|
||||||
#elif LL_DARWIN
|
#elif LL_DARWIN
|
||||||
// This might work on Linux as well. Someone check...
|
// This might work on Linux as well. Someone check...
|
||||||
@@ -735,17 +733,17 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
|
|||||||
size_t len = sizeof(phys);
|
size_t len = sizeof(phys);
|
||||||
sysctl(mib, 2, &phys, &len, NULL, 0);
|
sysctl(mib, 2, &phys, &len, NULL, 0);
|
||||||
|
|
||||||
return (U32)(phys >> 10);
|
return U64Bytes(phys);
|
||||||
|
|
||||||
#elif LL_LINUX
|
#elif LL_LINUX
|
||||||
U64 phys = 0;
|
U64 phys = 0;
|
||||||
phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
|
phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
|
||||||
return (U32)(phys >> 10);
|
return U64Bytes(phys);
|
||||||
|
|
||||||
#elif LL_SOLARIS
|
#elif LL_SOLARIS
|
||||||
U64 phys = 0;
|
U64 phys = 0;
|
||||||
phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
|
phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
|
||||||
return (U32)(phys >> 10);
|
return U64Bytes(phys);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
@@ -753,32 +751,32 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
U32 LLMemoryInfo::getPhysicalMemoryClamped() const
|
U32Bytes LLMemoryInfo::getPhysicalMemoryClamped() const
|
||||||
{
|
{
|
||||||
// Return the total physical memory in bytes, but clamp it
|
// Return the total physical memory in bytes, but clamp it
|
||||||
// to no more than U32_MAX
|
// to no more than U32_MAX
|
||||||
|
|
||||||
U32 phys_kb = getPhysicalMemoryKB();
|
U32Kilobytes phys_kb = getPhysicalMemoryKB();
|
||||||
if (phys_kb >= 4194304 /* 4GB in KB */)
|
if (phys_kb >= U32Gigabytes(4))
|
||||||
{
|
{
|
||||||
return U32_MAX;
|
return U32Bytes(U32_MAX);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return phys_kb << 10;
|
return phys_kb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//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
|
#if LL_WINDOWS
|
||||||
// Sigh, this shouldn't be a static method, then we wouldn't have to
|
// Sigh, this shouldn't be a static method, then we wouldn't have to
|
||||||
// reload this data separately from refresh()
|
// reload this data separately from refresh()
|
||||||
LLSD statsMap(loadStatsMap());
|
LLSD statsMap(loadStatsMap());
|
||||||
|
|
||||||
avail_physical_mem_kb = statsMap["Avail Physical KB"].asInteger();
|
avail_physical_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger();
|
||||||
avail_virtual_mem_kb = statsMap["Avail Virtual KB"].asInteger();
|
avail_virtual_mem_kb = (U32Kilobytes)statsMap["Avail Virtual KB"].asInteger();
|
||||||
|
|
||||||
#elif LL_DARWIN
|
#elif LL_DARWIN
|
||||||
// mStatsMap is derived from vm_stat, look for (e.g.) "kb free":
|
// 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.
|
// Pageins: 2097212.
|
||||||
// Pageouts: 41759.
|
// Pageouts: 41759.
|
||||||
// Object cache: 841598 hits of 7629869 lookups (11% hit rate)
|
// Object cache: 841598 hits of 7629869 lookups (11% hit rate)
|
||||||
avail_physical_mem_kb = -1 ;
|
avail_physical_mem_kb = (U32Kilobytes)-1 ;
|
||||||
avail_virtual_mem_kb = -1 ;
|
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
|
||||||
|
|
||||||
#elif LL_LINUX
|
#elif LL_LINUX
|
||||||
// mStatsMap is derived from MEMINFO_FILE:
|
// mStatsMap is derived from MEMINFO_FILE:
|
||||||
@@ -847,15 +845,15 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v
|
|||||||
// DirectMap4k: 434168 kB
|
// DirectMap4k: 434168 kB
|
||||||
// DirectMap2M: 477184 kB
|
// DirectMap2M: 477184 kB
|
||||||
// (could also run 'free', but easier to read a file than run a program)
|
// (could also run 'free', but easier to read a file than run a program)
|
||||||
avail_physical_mem_kb = -1 ;
|
avail_physical_mem_kb = (U32Kilobytes)-1 ;
|
||||||
avail_virtual_mem_kb = -1 ;
|
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
//do not know how to collect available memory info for other systems.
|
//do not know how to collect available memory info for other systems.
|
||||||
//leave it blank here for now.
|
//leave it blank here for now.
|
||||||
|
|
||||||
avail_physical_mem_kb = -1 ;
|
avail_physical_mem_kb = (U32Kilobytes)-1 ;
|
||||||
avail_virtual_mem_kb = -1 ;
|
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -112,15 +112,15 @@ public:
|
|||||||
LLMemoryInfo(); ///< Default constructor
|
LLMemoryInfo(); ///< Default constructor
|
||||||
void stream(std::ostream& s) const; ///< output text info to s
|
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
|
/*! Memory size in bytes, if total memory is >= 4GB then U32_MAX will
|
||||||
** be returned.
|
** 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.
|
//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-
|
// 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.
|
// dependent. The values are in kilobytes to try to avoid integer overflow.
|
||||||
|
|||||||
@@ -31,11 +31,9 @@
|
|||||||
#include "u64.h"
|
#include "u64.h"
|
||||||
|
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
# define WIN32_LEAN_AND_MEAN
|
# include "llwin32headerslean.h"
|
||||||
# include <winsock2.h>
|
|
||||||
# include <windows.h>
|
|
||||||
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
|
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
|
||||||
# include <errno.h>
|
# include <errno.h>
|
||||||
# include <sys/time.h>
|
# include <sys/time.h>
|
||||||
#else
|
#else
|
||||||
# error "architecture not supported"
|
# error "architecture not supported"
|
||||||
@@ -81,10 +79,10 @@ void ms_sleep(U32 ms)
|
|||||||
|
|
||||||
U32 micro_sleep(U64 us, U32 max_yields)
|
U32 micro_sleep(U64 us, U32 max_yields)
|
||||||
{
|
{
|
||||||
// max_yields is unused; just fiddle with it to avoid warnings.
|
// max_yields is unused; just fiddle with it to avoid warnings.
|
||||||
max_yields = 0;
|
max_yields = 0;
|
||||||
ms_sleep(us / 1000);
|
ms_sleep((U32)(us / 1000));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
|
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
|
||||||
static void _sleep_loop(struct timespec& thiswait)
|
static void _sleep_loop(struct timespec& thiswait)
|
||||||
@@ -216,56 +214,68 @@ U64 get_clock_count()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void update_clock_frequencies()
|
TimerInfo::TimerInfo()
|
||||||
|
: mClockFrequency(0.0),
|
||||||
|
mTotalTimeClockCount(0),
|
||||||
|
mLastTotalTimeClockCount(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void TimerInfo::update()
|
||||||
{
|
{
|
||||||
gClockFrequency = calc_clock_frequency();
|
mClockFrequency = calc_clock_frequency();
|
||||||
gClockFrequencyInv = 1.0/gClockFrequency;
|
mClockFrequencyInv = 1.0/mClockFrequency;
|
||||||
gClocksToMicroseconds = gClockFrequencyInv * SEC_TO_MICROSEC;
|
mClocksToMicroseconds = mClockFrequencyInv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimerInfo& get_timer_info()
|
||||||
|
{
|
||||||
|
static TimerInfo sTimerInfo;
|
||||||
|
return sTimerInfo;
|
||||||
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// returns a U64 number that represents the number of
|
// returns a U64 number that represents the number of
|
||||||
// microseconds since the Unix epoch - Jan 1, 1970
|
// microseconds since the Unix epoch - Jan 1, 1970
|
||||||
U64 totalTime()
|
U64MicrosecondsImplicit totalTime()
|
||||||
{
|
{
|
||||||
U64 current_clock_count = get_clock_count();
|
U64 current_clock_count = get_clock_count();
|
||||||
if (!gTotalTimeClockCount)
|
if (!get_timer_info().mTotalTimeClockCount || get_timer_info().mClocksToMicroseconds.value() == 0)
|
||||||
{
|
{
|
||||||
update_clock_frequencies();
|
get_timer_info().update();
|
||||||
gTotalTimeClockCount = current_clock_count;
|
get_timer_info().mTotalTimeClockCount = current_clock_count;
|
||||||
|
|
||||||
#if LL_WINDOWS
|
#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
|
// Unix platforms use gettimeofday so they are synced, although this probably isn't a good assumption to
|
||||||
// make in the future.
|
// make in the future.
|
||||||
|
|
||||||
gTotalTimeClockCount = (U64)(time(NULL) * gClockFrequency);
|
get_timer_info().mTotalTimeClockCount = (U64)(time(NULL) * get_timer_info().mClockFrequency);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Update the last clock count
|
// Update the last clock count
|
||||||
gLastTotalTimeClockCount = current_clock_count;
|
get_timer_info().mLastTotalTimeClockCount = current_clock_count;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (LL_LIKELY(current_clock_count >= gLastTotalTimeClockCount))
|
if (current_clock_count >= get_timer_info().mLastTotalTimeClockCount)
|
||||||
{
|
{
|
||||||
// No wrapping, we're all okay.
|
// No wrapping, we're all okay.
|
||||||
gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount;
|
get_timer_info().mTotalTimeClockCount += current_clock_count - get_timer_info().mLastTotalTimeClockCount;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// We've wrapped. Compensate correctly
|
// 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
|
// 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 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()
|
LLTimer::LLTimer()
|
||||||
{
|
{
|
||||||
if (!gClockFrequency)
|
if (!get_timer_info().mClockFrequency)
|
||||||
{
|
{
|
||||||
update_clock_frequencies();
|
get_timer_info().update();
|
||||||
}
|
}
|
||||||
|
|
||||||
mStarted = TRUE;
|
mStarted = TRUE;
|
||||||
@@ -283,20 +293,32 @@ LLTimer::LLTimer()
|
|||||||
}
|
}
|
||||||
|
|
||||||
LLTimer::~LLTimer()
|
LLTimer::~LLTimer()
|
||||||
|
{}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void LLTimer::initClass()
|
||||||
{
|
{
|
||||||
|
if (!sTimer) sTimer = new LLTimer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
U64 LLTimer::getTotalTime()
|
void LLTimer::cleanupClass()
|
||||||
|
{
|
||||||
|
delete sTimer; sTimer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
U64MicrosecondsImplicit LLTimer::getTotalTime()
|
||||||
{
|
{
|
||||||
// simply call into the implementation function.
|
// simply call into the implementation function.
|
||||||
return totalTime();
|
U64MicrosecondsImplicit total_time = totalTime();
|
||||||
|
return total_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// 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()
|
void LLTimer::reset()
|
||||||
@@ -343,43 +365,43 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
F64 LLTimer::getElapsedTimeF64() const
|
F64SecondsImplicit LLTimer::getElapsedTimeF64() const
|
||||||
{
|
{
|
||||||
U64 last = mLastClockCount;
|
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();
|
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();
|
return (F32)getElapsedTimeAndResetF64();
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void LLTimer::setTimerExpirySec(F32 expiration)
|
void LLTimer::setTimerExpirySec(F32SecondsImplicit expiration)
|
||||||
{
|
{
|
||||||
mExpirationTicks = get_clock_count()
|
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();
|
U64 cur_ticks = get_clock_count();
|
||||||
if (cur_ticks > mExpirationTicks)
|
if (cur_ticks > mExpirationTicks)
|
||||||
{
|
{
|
||||||
return 0.0f;
|
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
|
mExpirationTicks = cur_ticks
|
||||||
+ (U64)((F32)(expiration * gClockFrequency));
|
+ (U64)((F32)(expiration * get_timer_info().mClockFrequency));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -491,20 +513,20 @@ BOOL is_daylight_savings()
|
|||||||
|
|
||||||
struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
|
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)
|
if (pacific_daylight_time)
|
||||||
{
|
{
|
||||||
pacific_offset_hours = 7;
|
pacific_offset_hours = S32Hours(7);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pacific_offset_hours = 8;
|
pacific_offset_hours = S32Hours(8);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We subtract off the PST/PDT offset _before_ getting
|
// We subtract off the PST/PDT offset _before_ getting
|
||||||
// "UTC" time, because this will handle wrapping around
|
// "UTC" time, because this will handle wrapping around
|
||||||
// for 5 AM UTC -> 10 PM PDT of the previous day.
|
// 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)
|
// Internal buffer to PST/PDT (see above)
|
||||||
struct tm* internal_time = gmtime(&utc_time);
|
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 hours;
|
||||||
U64 minutes;
|
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 <string>
|
||||||
#include <list>
|
#include <list>
|
||||||
// units conversions
|
// units conversions
|
||||||
|
#include "llunits.h"
|
||||||
#ifndef USEC_PER_SEC
|
#ifndef USEC_PER_SEC
|
||||||
const U32 USEC_PER_SEC = 1000000;
|
const U32 USEC_PER_SEC = 1000000;
|
||||||
#endif
|
#endif
|
||||||
@@ -61,21 +62,28 @@ public:
|
|||||||
LLTimer();
|
LLTimer();
|
||||||
~LLTimer();
|
~LLTimer();
|
||||||
|
|
||||||
static void initClass() { if (!sTimer) sTimer = new LLTimer; }
|
static void initClass();
|
||||||
static void cleanupClass() { delete sTimer; sTimer = NULL; }
|
static void cleanupClass();
|
||||||
|
|
||||||
// Return a high precision number of seconds since the start of
|
// Return a high precision number of seconds since the start of
|
||||||
// this application instance.
|
// this application instance.
|
||||||
static F64 getElapsedSeconds()
|
static F64SecondsImplicit getElapsedSeconds()
|
||||||
|
{
|
||||||
|
if (sTimer)
|
||||||
{
|
{
|
||||||
return sTimer->getElapsedTimeF64();
|
return sTimer->getElapsedTimeF64();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Return a high precision usec since epoch
|
// Return a high precision usec since epoch
|
||||||
static U64 getTotalTime();
|
static U64MicrosecondsImplicit getTotalTime();
|
||||||
|
|
||||||
// Return a high precision seconds since epoch
|
// Return a high precision seconds since epoch
|
||||||
static F64 getTotalSeconds();
|
static F64SecondsImplicit getTotalSeconds();
|
||||||
|
|
||||||
|
|
||||||
// MANIPULATORS
|
// MANIPULATORS
|
||||||
@@ -83,19 +91,19 @@ public:
|
|||||||
void stop() { mStarted = FALSE; }
|
void stop() { mStarted = FALSE; }
|
||||||
void reset(); // Resets the timer
|
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 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 checkExpirationAndReset(F32 expiration);
|
||||||
BOOL hasExpired() const;
|
BOOL hasExpired() const;
|
||||||
F32 getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
|
F32SecondsImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
|
||||||
F64 getElapsedTimeAndResetF64();
|
F64SecondsImplicit getElapsedTimeAndResetF64();
|
||||||
|
|
||||||
F32 getRemainingTimeF32() const;
|
F32SecondsImplicit getRemainingTimeF32() const;
|
||||||
|
|
||||||
static BOOL knownBadTimer();
|
static BOOL knownBadTimer();
|
||||||
|
|
||||||
// ACCESSORS
|
// ACCESSORS
|
||||||
F32 getElapsedTimeF32() const; // Returns elapsed time in seconds
|
F32SecondsImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds
|
||||||
F64 getElapsedTimeF64() const; // Returns elapsed time in seconds
|
F64SecondsImplicit getElapsedTimeF64() const; // Returns elapsed time in seconds
|
||||||
|
|
||||||
bool getStarted() const { return mStarted; }
|
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.
|
// 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 U64 get_clock_count();
|
||||||
LL_COMMON_API F64 calc_clock_frequency();
|
LL_COMMON_API F64 calc_clock_frequency();
|
||||||
LL_COMMON_API void update_clock_frequencies();
|
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);
|
// 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 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 microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring);
|
||||||
LL_COMMON_API void secondsToTimecodeString(F32 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 timeToFormattedString(time_t time, std::string format, std::string ×tr);
|
||||||
LL_COMMON_API void timeStructToFormattedString(struct tm * 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
|
#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.
|
// We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
|
||||||
#if LL_WINDOWS
|
#if LL_WINDOWS
|
||||||
#undef WIN32_LEAN_AND_MEAN
|
#include "llwin32headers.h"
|
||||||
#include <winsock2.h>
|
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "lldefs.h"
|
#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) :
|
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) :
|
||||||
LLQueuedThread(name, threaded, should_pause)
|
LLQueuedThread(name, threaded, should_pause)
|
||||||
{
|
{
|
||||||
mDeleteMutex = new LLMutex;
|
mDeleteMutex = new LLMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
LLWorkerThread::~LLWorkerThread()
|
LLWorkerThread::~LLWorkerThread()
|
||||||
@@ -199,6 +199,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
|
|||||||
mWorkerClassName(name),
|
mWorkerClassName(name),
|
||||||
mRequestHandle(LLWorkerThread::nullHandle()),
|
mRequestHandle(LLWorkerThread::nullHandle()),
|
||||||
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
|
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
|
||||||
|
mMutex(),
|
||||||
mWorkFlags(0)
|
mWorkFlags(0)
|
||||||
{
|
{
|
||||||
if (!mWorkerThread)
|
if (!mWorkerThread)
|
||||||
@@ -345,10 +346,14 @@ bool LLWorkerClass::checkWork(bool aborting)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LLQueuedThread::status_t status = workreq->getStatus();
|
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);
|
complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED);
|
||||||
abort = status == LLWorkerThread::STATUS_ABORTED;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4699,7 +4699,7 @@ LLVolumeFace::~LLVolumeFace()
|
|||||||
|
|
||||||
void LLVolumeFace::freeData()
|
void LLVolumeFace::freeData()
|
||||||
{
|
{
|
||||||
ll_aligned_free(mPositions);
|
ll_aligned_free<64>(mPositions);
|
||||||
mPositions = NULL;
|
mPositions = NULL;
|
||||||
|
|
||||||
//normals and texture coordinates are part of the same buffer as mPositions, do not free them separately
|
//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
|
//allocate space for new buffer
|
||||||
S32 num_verts = mNumVertices;
|
S32 num_verts = mNumVertices;
|
||||||
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
|
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;
|
LLVector4a* norm = pos + num_verts;
|
||||||
LLVector2* tc = (LLVector2*) (norm + num_verts);
|
LLVector2* tc = (LLVector2*) (norm + num_verts);
|
||||||
|
|
||||||
@@ -5323,7 +5323,7 @@ void LLVolumeFace::cacheOptimize()
|
|||||||
mIndices[i] = new_idx[mIndices[i]];
|
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
|
// DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
||||||
ll_aligned_free_16(mWeights);
|
ll_aligned_free_16(mWeights);
|
||||||
ll_aligned_free_16(mTangents);
|
ll_aligned_free_16(mTangents);
|
||||||
@@ -6041,7 +6041,7 @@ void LLVolumeFace::createTangents()
|
|||||||
|
|
||||||
void LLVolumeFace::resizeVertices(S32 num_verts)
|
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
|
//DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
||||||
ll_aligned_free_16(mTangents);
|
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
|
//pad texture coordinate block end to allow for QWORD reads
|
||||||
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
|
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;
|
mNormals = mPositions+num_verts;
|
||||||
mTexCoords = (LLVector2*) (mNormals+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;
|
LLVector4a* old_buf = mPositions;
|
||||||
|
|
||||||
mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64);
|
mPositions = (LLVector4a*) ll_aligned_malloc<64>(new_size);
|
||||||
mNormals = mPositions+new_verts;
|
mNormals = mPositions+new_verts;
|
||||||
mTexCoords = (LLVector2*) (mNormals+new_verts);
|
mTexCoords = (LLVector2*) (mNormals+new_verts);
|
||||||
|
|
||||||
@@ -6111,7 +6111,7 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
|
|||||||
//tex coords
|
//tex coords
|
||||||
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tc_size);
|
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tc_size);
|
||||||
|
|
||||||
ll_aligned_free(old_buf);
|
ll_aligned_free<64>(old_buf);
|
||||||
|
|
||||||
//<singu>
|
//<singu>
|
||||||
}
|
}
|
||||||
@@ -6120,6 +6120,7 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
|
|||||||
//just clear tangents
|
//just clear tangents
|
||||||
ll_aligned_free_16(mTangents);
|
ll_aligned_free_16(mTangents);
|
||||||
mTangents = NULL;
|
mTangents = NULL;
|
||||||
|
ll_aligned_free<64>(old_buf);
|
||||||
|
|
||||||
mNumAllocatedVertices = new_verts;
|
mNumAllocatedVertices = new_verts;
|
||||||
|
|
||||||
@@ -6220,7 +6221,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
|
|||||||
|
|
||||||
//allocate new buffer space
|
//allocate new buffer space
|
||||||
LLVector4a* old_buf = mPositions;
|
LLVector4a* old_buf = mPositions;
|
||||||
mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64);
|
mPositions = (LLVector4a*) ll_aligned_malloc<64>(new_size);
|
||||||
mNormals = mPositions + new_count;
|
mNormals = mPositions + new_count;
|
||||||
mTexCoords = (LLVector2*) (mNormals+new_count);
|
mTexCoords = (LLVector2*) (mNormals+new_count);
|
||||||
|
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const
|
|||||||
return mGLTexturep->getAddressMode() ;
|
return mGLTexturep->getAddressMode() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
S32 LLGLTexture::getTextureMemory() const
|
S32Bytes LLGLTexture::getTextureMemory() const
|
||||||
{
|
{
|
||||||
llassert(mGLTexturep.notNull()) ;
|
llassert(mGLTexturep.notNull()) ;
|
||||||
|
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ public:
|
|||||||
S32 getDiscardLevel() const;
|
S32 getDiscardLevel() const;
|
||||||
S8 getComponents() const;
|
S8 getComponents() const;
|
||||||
BOOL getBoundRecently() const;
|
BOOL getBoundRecently() const;
|
||||||
S32 getTextureMemory() const ;
|
S32Bytes getTextureMemory() const ;
|
||||||
LLGLenum getPrimaryFormat() const;
|
LLGLenum getPrimaryFormat() const;
|
||||||
BOOL getIsAlphaMask(const F32 max_rmse) const ;
|
BOOL getIsAlphaMask(const F32 max_rmse) const ;
|
||||||
LLTexUnit::eTextureType getTarget(void) const ;
|
LLTexUnit::eTextureType getTarget(void) const ;
|
||||||
|
|||||||
@@ -50,9 +50,9 @@ U32 wpo2(U32 i);
|
|||||||
|
|
||||||
U32 LLImageGL::sUniqueCount = 0;
|
U32 LLImageGL::sUniqueCount = 0;
|
||||||
U32 LLImageGL::sBindCount = 0;
|
U32 LLImageGL::sBindCount = 0;
|
||||||
S32 LLImageGL::sGlobalTextureMemoryInBytes = 0;
|
S32Bytes LLImageGL::sGlobalTextureMemory(0);
|
||||||
S32 LLImageGL::sBoundTextureMemoryInBytes = 0;
|
S32Bytes LLImageGL::sBoundTextureMemory(0);
|
||||||
S32 LLImageGL::sCurBoundTextureMemory = 0;
|
S32Bytes LLImageGL::sCurBoundTextureMemory(0);
|
||||||
S32 LLImageGL::sCount = 0;
|
S32 LLImageGL::sCount = 0;
|
||||||
|
|
||||||
BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
|
BOOL LLImageGL::sGlobalUseAnisotropic = FALSE;
|
||||||
@@ -78,9 +78,9 @@ S32 LLImageGL::sCurTexPickSize = -1 ;
|
|||||||
LLPointer<LLImageGL> LLImageGL::sHighlightTexturep = NULL;
|
LLPointer<LLImageGL> LLImageGL::sHighlightTexturep = NULL;
|
||||||
S32 LLImageGL::sMaxCategories = 1 ;
|
S32 LLImageGL::sMaxCategories = 1 ;
|
||||||
|
|
||||||
std::vector<S32> LLImageGL::sTextureMemByCategory;
|
std::vector<S32Bytes> LLImageGL::sTextureMemByCategory;
|
||||||
std::vector<S32> LLImageGL::sTextureMemByCategoryBound ;
|
std::vector<S32Bytes> LLImageGL::sTextureMemByCategoryBound ;
|
||||||
std::vector<S32> LLImageGL::sTextureCurMemByCategoryBound ;
|
std::vector<S32Bytes> LLImageGL::sTextureCurMemByCategoryBound ;
|
||||||
//------------------------
|
//------------------------
|
||||||
// ****************************************************************************************************
|
// ****************************************************************************************************
|
||||||
//End for texture auditing use only
|
//End for texture auditing use only
|
||||||
@@ -292,8 +292,8 @@ void LLImageGL::updateStats(F32 current_time)
|
|||||||
{
|
{
|
||||||
LLFastTimer t(FTM_IMAGE_UPDATE_STATS);
|
LLFastTimer t(FTM_IMAGE_UPDATE_STATS);
|
||||||
sLastFrameTime = current_time;
|
sLastFrameTime = current_time;
|
||||||
sBoundTextureMemoryInBytes = sCurBoundTextureMemory;
|
sBoundTextureMemory = sCurBoundTextureMemory;
|
||||||
sCurBoundTextureMemory = 0;
|
sCurBoundTextureMemory = S32Bytes(0);
|
||||||
|
|
||||||
if(gAuditTexture)
|
if(gAuditTexture)
|
||||||
{
|
{
|
||||||
@@ -305,22 +305,22 @@ void LLImageGL::updateStats(F32 current_time)
|
|||||||
for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++)
|
for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++)
|
||||||
{
|
{
|
||||||
sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ;
|
sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ;
|
||||||
sTextureCurMemByCategoryBound[i] = 0 ;
|
sTextureCurMemByCategoryBound[i] = (S32Bytes)0 ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//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)
|
if(gAuditTexture && ncomponents > 0 && category > -1)
|
||||||
{
|
{
|
||||||
sTextureCurBoundCounter[getTextureCounterIndex(mem / ncomponents)]++ ;
|
sTextureCurBoundCounter[getTextureCounterIndex(mem.value() / ncomponents)]++ ;
|
||||||
sTextureCurMemByCategoryBound[category] += mem ;
|
sTextureCurMemByCategoryBound[category] += mem ;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLImageGL::sCurBoundTextureMemory += 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
|
// so that it is obvious by visual inspection if we forgot to
|
||||||
// init a field.
|
// init a field.
|
||||||
|
|
||||||
mTextureMemory = 0;
|
mTextureMemory = (S32Bytes)0;
|
||||||
mLastBindTime = 0.f;
|
mLastBindTime = 0.f;
|
||||||
|
|
||||||
mPickMask = NULL;
|
mPickMask = NULL;
|
||||||
@@ -644,7 +644,7 @@ void LLImageGL::forceUpdateBindStats(void) const
|
|||||||
mLastBindTime = sLastFrameTime;
|
mLastBindTime = sLastFrameTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL LLImageGL::updateBindStats(S32 tex_mem) const
|
BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const
|
||||||
{
|
{
|
||||||
if (mTexName != 0)
|
if (mTexName != 0)
|
||||||
{
|
{
|
||||||
@@ -1677,7 +1677,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
|
|||||||
|
|
||||||
if (old_name != 0)
|
if (old_name != 0)
|
||||||
{
|
{
|
||||||
sGlobalTextureMemoryInBytes -= mTextureMemory;
|
sGlobalTextureMemory -= mTextureMemory;
|
||||||
|
|
||||||
if(gAuditTexture)
|
if(gAuditTexture)
|
||||||
{
|
{
|
||||||
@@ -1689,8 +1689,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_
|
|||||||
stop_glerror();
|
stop_glerror();
|
||||||
}
|
}
|
||||||
|
|
||||||
mTextureMemory = getMipBytes(discard_level);
|
mTextureMemory = (S32Bytes)getMipBytes(discard_level);
|
||||||
sGlobalTextureMemoryInBytes += mTextureMemory;
|
sGlobalTextureMemory += mTextureMemory;
|
||||||
|
|
||||||
if(gAuditTexture)
|
if(gAuditTexture)
|
||||||
{
|
{
|
||||||
@@ -1829,14 +1829,14 @@ void LLImageGL::destroyGLTexture()
|
|||||||
{
|
{
|
||||||
if (mTexName != 0)
|
if (mTexName != 0)
|
||||||
{
|
{
|
||||||
if(mTextureMemory)
|
if(mTextureMemory != S32Bytes(0))
|
||||||
{
|
{
|
||||||
if(gAuditTexture)
|
if(gAuditTexture)
|
||||||
{
|
{
|
||||||
decTextureCounter(mTextureMemory, mComponents, mCategory) ;
|
decTextureCounter(mTextureMemory, mComponents, mCategory) ;
|
||||||
}
|
}
|
||||||
sGlobalTextureMemoryInBytes -= mTextureMemory;
|
sGlobalTextureMemory -= mTextureMemory;
|
||||||
mTextureMemory = 0;
|
mTextureMemory = (S32Bytes)0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LLImageGL::deleteTextures(1, &mTexName);
|
LLImageGL::deleteTextures(1, &mTexName);
|
||||||
@@ -2356,19 +2356,19 @@ S32 LLImageGL::getTextureCounterIndex(U32 val)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//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)
|
if(category > -1)
|
||||||
sTextureMemByCategory[category] += (S32)val * ncomponents ;
|
sTextureMemByCategory[category] += (S32Bytes)val * ncomponents ;
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//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)
|
if(category > -1)
|
||||||
sTextureMemByCategory[category] -= (S32)val * ncomponents ;
|
sTextureMemByCategory[category] -= (S32Bytes)val * ncomponents ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size)
|
void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size)
|
||||||
|
|||||||
@@ -34,6 +34,7 @@
|
|||||||
#include "llpointer.h"
|
#include "llpointer.h"
|
||||||
#include "llrefcount.h"
|
#include "llrefcount.h"
|
||||||
#include "v2math.h"
|
#include "v2math.h"
|
||||||
|
#include "llunits.h"
|
||||||
|
|
||||||
#include "llrender.h"
|
#include "llrender.h"
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ public:
|
|||||||
static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);
|
static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height);
|
||||||
static S32 dataFormatComponents(S32 dataformat);
|
static S32 dataFormatComponents(S32 dataformat);
|
||||||
|
|
||||||
BOOL updateBindStats(S32 tex_mem) const ;
|
BOOL updateBindStats(S32Bytes tex_mem) const ;
|
||||||
F32 getTimePassedSinceLastBound();
|
F32 getTimePassedSinceLastBound();
|
||||||
void forceUpdateBindStats(void) const;
|
void forceUpdateBindStats(void) const;
|
||||||
|
|
||||||
@@ -68,7 +69,7 @@ public:
|
|||||||
static void dirtyTexOptions();
|
static void dirtyTexOptions();
|
||||||
|
|
||||||
// Sometimes called externally for textures not using LLImageGL (should go away...)
|
// 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);
|
static bool checkSize(S32 width, S32 height);
|
||||||
|
|
||||||
@@ -172,7 +173,7 @@ public:
|
|||||||
void setNeedsAlphaAndPickMask(BOOL need_mask);
|
void setNeedsAlphaAndPickMask(BOOL need_mask);
|
||||||
public:
|
public:
|
||||||
// Various GL/Rendering options
|
// Various GL/Rendering options
|
||||||
S32 mTextureMemory;
|
S32Bytes mTextureMemory;
|
||||||
mutable F32 mLastBindTime; // last time this was bound, by discard level
|
mutable F32 mLastBindTime; // last time this was bound, by discard level
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -228,9 +229,9 @@ public:
|
|||||||
static F32 sLastFrameTime;
|
static F32 sLastFrameTime;
|
||||||
|
|
||||||
// Global memory statistics
|
// Global memory statistics
|
||||||
static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem
|
static S32Bytes sGlobalTextureMemory; // Tracks main memory texmem
|
||||||
static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame
|
static S32Bytes sBoundTextureMemory; // Tracks bound texmem for last completed frame
|
||||||
static S32 sCurBoundTextureMemory; // Tracks bound texmem for current frame
|
static S32Bytes sCurBoundTextureMemory; // Tracks bound texmem for current frame
|
||||||
static U32 sBindCount; // Tracks number of texture binds 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 U32 sUniqueCount; // Tracks number of unique texture binds for current frame
|
||||||
static BOOL sGlobalUseAnisotropic;
|
static BOOL sGlobalUseAnisotropic;
|
||||||
@@ -274,8 +275,8 @@ public:
|
|||||||
|
|
||||||
static void setHighlightTexture(S32 category) ;
|
static void setHighlightTexture(S32 category) ;
|
||||||
static S32 getTextureCounterIndex(U32 val) ;
|
static S32 getTextureCounterIndex(U32 val) ;
|
||||||
static void incTextureCounter(U32 val, S32 ncomponents, S32 category) ;
|
static void incTextureCounter(S32Bytes val, S32 ncomponents, S32 category) ;
|
||||||
static void decTextureCounter(U32 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 setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ;
|
||||||
static void resetCurTexSizebar();
|
static void resetCurTexSizebar();
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
@@ -283,9 +284,9 @@ public:
|
|||||||
//for debug use: show texture category distribution
|
//for debug use: show texture category distribution
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
|
|
||||||
static std::vector<S32> sTextureMemByCategory;
|
static std::vector<S32Bytes> sTextureMemByCategory;
|
||||||
static std::vector<S32> sTextureMemByCategoryBound ;
|
static std::vector<S32Bytes> sTextureMemByCategoryBound ;
|
||||||
static std::vector<S32> sTextureCurMemByCategoryBound ;
|
static std::vector<S32Bytes> sTextureCurMemByCategoryBound ;
|
||||||
//----------------------------------------
|
//----------------------------------------
|
||||||
// ****************************************************************************************************
|
// ****************************************************************************************************
|
||||||
//End of definitions for texture auditing use only
|
//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)
|
if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB)
|
||||||
{
|
{
|
||||||
glBufferDataARB(mType, size, 0, mUsage);
|
glBufferDataARB(mType, size, 0, mUsage);
|
||||||
ret = (U8*) ll_aligned_malloc(size, 64);
|
ret = (U8*) ll_aligned_malloc<64>(size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //always use a true hint of static draw when allocating non-client-backed buffers
|
{ //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);
|
llassert(vbo_block_size(size) == size);
|
||||||
|
|
||||||
deleteBuffer(name);
|
deleteBuffer(name);
|
||||||
ll_aligned_free((U8*) buffer);
|
ll_aligned_free<64>((U8*) buffer);
|
||||||
|
|
||||||
if (mType == GL_ARRAY_BUFFER_ARB)
|
if (mType == GL_ARRAY_BUFFER_ARB)
|
||||||
{
|
{
|
||||||
@@ -294,7 +294,7 @@ void LLVBOPool::cleanup()
|
|||||||
|
|
||||||
if (r.mClientData)
|
if (r.mClientData)
|
||||||
{
|
{
|
||||||
ll_aligned_free((void*) r.mClientData);
|
ll_aligned_free<64>((void*) r.mClientData);
|
||||||
}
|
}
|
||||||
|
|
||||||
l.pop_front();
|
l.pop_front();
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ LLNotification::LLNotification(const LLNotification::Params& p) :
|
|||||||
mTimestamp(p.timestamp),
|
mTimestamp(p.timestamp),
|
||||||
mSubstitutions(p.substitutions),
|
mSubstitutions(p.substitutions),
|
||||||
mPayload(p.payload),
|
mPayload(p.payload),
|
||||||
mExpiresAt(0),
|
mExpiresAt(F64SecondsImplicit()),
|
||||||
mResponseFunctorName(p.functor_name),
|
mResponseFunctorName(p.functor_name),
|
||||||
mTemporaryResponder(p.mTemporaryResponder),
|
mTemporaryResponder(p.mTemporaryResponder),
|
||||||
mRespondedTo(false),
|
mRespondedTo(false),
|
||||||
|
|||||||
@@ -279,7 +279,7 @@ BOOL gUseWireframe = FALSE;
|
|||||||
LLVFS* gStaticVFS = NULL;
|
LLVFS* gStaticVFS = NULL;
|
||||||
|
|
||||||
LLMemoryInfo gSysMemory;
|
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;
|
std::string gLastVersionChannel;
|
||||||
|
|
||||||
@@ -955,9 +955,8 @@ bool LLAppViewer::init()
|
|||||||
|
|
||||||
// get RAM data from XML
|
// get RAM data from XML
|
||||||
std::stringstream minRAMString(LLNotificationTemplates::instance().getGlobalString("UnsupportedRAMAmount"));
|
std::stringstream minRAMString(LLNotificationTemplates::instance().getGlobalString("UnsupportedRAMAmount"));
|
||||||
U64 minRAM = 0;
|
U64Bytes minRAM;
|
||||||
minRAMString >> minRAM;
|
minRAMString >> minRAM;
|
||||||
minRAM = minRAM * 1024 * 1024;
|
|
||||||
|
|
||||||
if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN)
|
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 = 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.
|
//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
|
#if LL_WINDOWS
|
||||||
@@ -1051,7 +1050,7 @@ void LLAppViewer::initMaxHeapSize()
|
|||||||
|
|
||||||
if(fnIsWow64Process && fnIsWow64Process(GetCurrentProcess(), &bWow64Process) && bWow64Process)
|
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))
|
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(ERROR_SUCCESS == RegQueryValueEx(hKey, TEXT("PhysicalAddressExtension"), NULL, NULL, (LPBYTE)&dwResult, &dwSize))
|
||||||
{
|
{
|
||||||
if(dwResult)
|
if(dwResult)
|
||||||
max_heap_size_gb = 3.7f;
|
max_heap_size_gb = F32Gigabytes(3.7f);
|
||||||
}
|
}
|
||||||
RegCloseKey(hKey);
|
RegCloseKey(hKey);
|
||||||
}
|
}
|
||||||
@@ -2694,8 +2693,8 @@ void LLAppViewer::writeSystemInfo()
|
|||||||
gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
|
gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE();
|
||||||
gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
|
gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2();
|
||||||
|
|
||||||
gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB());
|
gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB().value());
|
||||||
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated>>10); // MB -> KB
|
gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated.valueInUnits<LLUnits::Kilobytes>());
|
||||||
gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple();
|
gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple();
|
||||||
|
|
||||||
// The user is not logged on yet, but record the current grid choice login url
|
// 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 LLVFS *gStaticVFS;
|
||||||
|
|
||||||
extern LLMemoryInfo gSysMemory;
|
extern LLMemoryInfo gSysMemory;
|
||||||
extern U64 gMemoryAllocated;
|
extern U64Bytes gMemoryAllocated;
|
||||||
|
|
||||||
extern std::string gLastVersionChannel;
|
extern std::string gLastVersionChannel;
|
||||||
|
|
||||||
|
|||||||
@@ -676,7 +676,7 @@ void LLFeatureManager::applyBaseMasks()
|
|||||||
maskFeatures(gpustr);
|
maskFeatures(gpustr);
|
||||||
|
|
||||||
// now mask cpu type ones
|
// now mask cpu type ones
|
||||||
if (gSysMemory.getPhysicalMemoryClamped() <= 256*1024*1024)
|
if (gSysMemory.getPhysicalMemoryClamped() <= U32Megabytes(256))
|
||||||
{
|
{
|
||||||
maskFeatures("RAM256MB");
|
maskFeatures("RAM256MB");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,7 +233,7 @@ LLFloaterAbout::LLFloaterAbout()
|
|||||||
else
|
else
|
||||||
support.append(" None\n"); */
|
support.append(" None\n"); */
|
||||||
|
|
||||||
U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024;
|
U32Megabytes memory = gSysMemory.getPhysicalMemoryKB();
|
||||||
// Moved hack adjustment to Windows memory size into llsys.cpp
|
// Moved hack adjustment to Windows memory size into llsys.cpp
|
||||||
|
|
||||||
std::string mem_text = llformat("Memory: %u MB\n", memory );
|
std::string mem_text = llformat("Memory: %u MB\n", memory );
|
||||||
|
|||||||
@@ -472,9 +472,13 @@ void LLPanelDisplay::refreshEnabledState()
|
|||||||
mWindowSizeLabel->setVisible(!isFullScreen);
|
mWindowSizeLabel->setVisible(!isFullScreen);
|
||||||
mCtrlWindowSize->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
|
// Hardware tab
|
||||||
getChild<LLUICtrl>("GrapicsCardTextureMemory")->setMinValue(LLViewerTextureList::getMinVideoRamSetting());
|
getChild<LLUICtrl>("GrapicsCardTextureMemory")->setMinValue(min_tex_mem.value());
|
||||||
getChild<LLUICtrl>("GrapicsCardTextureMemory")->setMaxValue(LLViewerTextureList::getMaxVideoRamSetting());
|
getChild<LLUICtrl>("GrapicsCardTextureMemory")->setMaxValue(max_tex_mem.value());
|
||||||
|
|
||||||
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
|
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
|
||||||
!gGLManager.mHasVertexBufferObject)
|
!gGLManager.mHasVertexBufferObject)
|
||||||
|
|||||||
@@ -619,11 +619,25 @@ class LLVolumeGeometryManager: public LLGeometryManager
|
|||||||
DISTANCE_SORT
|
DISTANCE_SORT
|
||||||
} eSortType;
|
} eSortType;
|
||||||
|
|
||||||
|
LLVolumeGeometryManager();
|
||||||
|
virtual ~LLVolumeGeometryManager();
|
||||||
virtual void rebuildGeom(LLSpatialGroup* group);
|
virtual void rebuildGeom(LLSpatialGroup* group);
|
||||||
virtual void rebuildMesh(LLSpatialGroup* group);
|
virtual void rebuildMesh(LLSpatialGroup* group);
|
||||||
virtual void getGeometry(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 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);
|
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)
|
//spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp)
|
||||||
|
|||||||
@@ -129,8 +129,8 @@ public:
|
|||||||
// debug
|
// debug
|
||||||
S32 getNumReads() { return mReaders.size(); }
|
S32 getNumReads() { return mReaders.size(); }
|
||||||
S32 getNumWrites() { return mWriters.size(); }
|
S32 getNumWrites() { return mWriters.size(); }
|
||||||
S64 getUsage() { return mTexturesSizeTotal; }
|
S64Bytes getUsage() { return S64Bytes(mTexturesSizeTotal); }
|
||||||
S64 getMaxUsage() { return sCacheMaxTexturesSize; }
|
S64Bytes getMaxUsage() { return S64Bytes(sCacheMaxTexturesSize); }
|
||||||
U32 getEntries() { return mHeaderEntriesInfo.mEntries; }
|
U32 getEntries() { return mHeaderEntriesInfo.mEntries; }
|
||||||
U32 getMaxEntries() { return sCacheMaxEntries; };
|
U32 getMaxEntries() { return sCacheMaxEntries; };
|
||||||
BOOL isInCache(const LLUUID& id) ;
|
BOOL isInCache(const LLUUID& id) ;
|
||||||
@@ -202,7 +202,7 @@ private:
|
|||||||
typedef std::map<LLUUID,S32> size_map_t;
|
typedef std::map<LLUUID,S32> size_map_t;
|
||||||
size_map_t mTexturesSizeMap;
|
size_map_t mTexturesSizeMap;
|
||||||
S64 mTexturesSizeTotal;
|
S64 mTexturesSizeTotal;
|
||||||
LLAtomic32<BOOL> mDoPurge;
|
LLAtomic32<bool> mDoPurge;
|
||||||
|
|
||||||
typedef std::map<S32, Entry> idx_entry_map_t;
|
typedef std::map<S32, Entry> idx_entry_map_t;
|
||||||
idx_entry_map_t mUpdatedEntryMap;
|
idx_entry_map_t mUpdatedEntryMap;
|
||||||
|
|||||||
@@ -316,11 +316,11 @@ private:
|
|||||||
U8 mImageCodec;
|
U8 mImageCodec;
|
||||||
|
|
||||||
LLViewerAssetStats::duration_t mMetricsStartTime;
|
LLViewerAssetStats::duration_t mMetricsStartTime;
|
||||||
unsigned int mHttpReplySize; // Actual received data size
|
U32 mHttpReplySize, // Actual received data size
|
||||||
unsigned int mHttpReplyOffset; // Actual received data offset
|
mHttpReplyOffset; // Actual received data offset
|
||||||
// State history
|
// State history
|
||||||
U32 mCacheReadCount;
|
U32 mCacheReadCount,
|
||||||
U32 mCacheWriteCount;
|
mCacheWriteCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -425,7 +425,7 @@ public:
|
|||||||
worker->setGetStatus(mStatus, mReason);
|
worker->setGetStatus(mStatus, mReason);
|
||||||
LL_WARNS() << "CURL GET FAILED, status:" << mStatus << " reason:" << mReason << LL_ENDL;
|
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)
|
if(log_texture_traffic && data_size > 0)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -407,7 +407,7 @@ void LLTextureBar::draw()
|
|||||||
default:;
|
default:;
|
||||||
};
|
};
|
||||||
std::string num_str = llformat("%4dx%4d (%+d) %7d %s", mImagep->getWidth(), mImagep->getHeight(),
|
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::getFontMonospace()->renderUTF8(num_str, 0, title_x4, getRect().getHeight(), color,
|
||||||
LLFontGL::LEFT, LLFontGL::TOP);
|
LLFontGL::LEFT, LLFontGL::TOP);
|
||||||
}
|
}
|
||||||
@@ -564,18 +564,18 @@ private:
|
|||||||
|
|
||||||
void LLGLTexMemBar::draw()
|
void LLGLTexMemBar::draw()
|
||||||
{
|
{
|
||||||
S32 bound_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sBoundTextureMemoryInBytes);
|
S32Megabytes bound_mem = LLViewerTexture::sBoundTextureMemory;
|
||||||
S32 max_bound_mem = LLViewerTexture::sMaxBoundTextureMemInMegaBytes;
|
S32Megabytes max_bound_mem = LLViewerTexture::sMaxBoundTextureMemory;
|
||||||
S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sTotalTextureMemoryInBytes);
|
S32Megabytes total_mem = LLViewerTexture::sTotalTextureMemory;
|
||||||
S32 max_total_mem = LLViewerTexture::sMaxTotalTextureMemInMegaBytes;
|
S32Megabytes max_total_mem = LLViewerTexture::sMaxTotalTextureMem;
|
||||||
F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;
|
F32 discard_bias = LLViewerTexture::sDesiredDiscardBias;
|
||||||
F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ;
|
F32 cache_usage = LLAppViewer::getTextureCache()->getUsage().valueInUnits<LLUnits::Megabytes>();
|
||||||
F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ;
|
F32 cache_max_usage = LLAppViewer::getTextureCache()->getMaxUsage().valueInUnits<LLUnits::Megabytes>();
|
||||||
S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f);
|
S32 line_height = LLFontGL::getFontMonospace()->getLineHeight();
|
||||||
S32 v_offset = 0;
|
S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f);
|
||||||
F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024);
|
F32Bytes total_texture_downloaded = gTotalTextureData;
|
||||||
F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024);
|
F32Bytes total_object_downloaded = gTotalObjectData;
|
||||||
U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ;
|
U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests();
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
LLGLSUIDefault gls_ui;
|
LLGLSUIDefault gls_ui;
|
||||||
LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
|
LLColor4 text_color(1.f, 1.f, 1.f, 0.75f);
|
||||||
@@ -588,10 +588,10 @@ void LLGLTexMemBar::draw()
|
|||||||
global_raw_memory = *AIAccess<S32>(LLImageRaw::sGlobalRawMemory);
|
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",
|
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,
|
total_mem.value(),
|
||||||
max_total_mem,
|
max_total_mem.value(),
|
||||||
bound_mem,
|
bound_mem.value(),
|
||||||
max_bound_mem,
|
max_bound_mem.value(),
|
||||||
LLRenderTarget::sBytesAllocated/(1024*1024),
|
LLRenderTarget::sBytesAllocated/(1024*1024),
|
||||||
global_raw_memory >> 20, discard_bias,
|
global_raw_memory >> 20, discard_bias,
|
||||||
cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded, total_http_requests);
|
cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded, total_http_requests);
|
||||||
@@ -890,7 +890,7 @@ void LLTextureView::draw()
|
|||||||
|
|
||||||
if (mPrintList)
|
if (mPrintList)
|
||||||
{
|
{
|
||||||
S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory() : 0 ;
|
S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory().value() : 0 ;
|
||||||
LL_INFOS() << imagep->getID()
|
LL_INFOS() << imagep->getID()
|
||||||
<< "\t" << tex_mem
|
<< "\t" << tex_mem
|
||||||
<< "\t" << imagep->getBoostLevel()
|
<< "\t" << imagep->getBoostLevel()
|
||||||
@@ -1317,7 +1317,7 @@ void LLTextureSizeView::drawTextureCategoryGraph()
|
|||||||
for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
|
for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++)
|
||||||
{
|
{
|
||||||
U32 k = LLViewerTexture::getIndexFromCategory(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() ;
|
mTextureSizeBar[i]->draw() ;
|
||||||
}
|
}
|
||||||
LLImageGL::resetCurTexSizebar();
|
LLImageGL::resetCurTexSizebar();
|
||||||
@@ -1335,7 +1335,7 @@ F32 LLTextureSizeView::drawTextureCategoryDistributionGraph()
|
|||||||
S32 count = 0 ;
|
S32 count = 0 ;
|
||||||
for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++)
|
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)
|
if(tmp > count)
|
||||||
{
|
{
|
||||||
count = tmp ;
|
count = tmp ;
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ static bool handleMaxPartCountChanged(const LLSD& newvalue)
|
|||||||
|
|
||||||
static bool handleVideoMemoryChanged(const LLSD& newvalue)
|
static bool handleVideoMemoryChanged(const LLSD& newvalue)
|
||||||
{
|
{
|
||||||
gTextureList.updateMaxResidentTexMem(newvalue.asInteger());
|
gTextureList.updateMaxResidentTexMem(S32Megabytes(newvalue.asInteger()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -236,9 +236,9 @@ void display_stats()
|
|||||||
F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
|
F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency");
|
||||||
if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
|
if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq)
|
||||||
{
|
{
|
||||||
gMemoryAllocated = LLMemory::getCurrentRSS();
|
gMemoryAllocated = (U64Bytes)LLMemory::getCurrentRSS();
|
||||||
U32 memory = (U32)(gMemoryAllocated / (1024*1024));
|
U32Megabytes memory = gMemoryAllocated;
|
||||||
LL_INFOS() << llformat("MEMORY: %d MB", memory) << LL_ENDL;
|
LL_INFOS() << llformat("MEMORY: %d MB", memory.value()) << LL_ENDL;
|
||||||
LL_INFOS() << "THREADS: "<< LLThread::getCount() << LL_ENDL;
|
LL_INFOS() << "THREADS: "<< LLThread::getCount() << LL_ENDL;
|
||||||
LL_INFOS() << "MALLOC: " << SGMemStat::getPrintableStat() <<LL_ENDL;
|
LL_INFOS() << "MALLOC: " << SGMemStat::getPrintableStat() <<LL_ENDL;
|
||||||
LLMemory::logMemoryInfo(TRUE) ;
|
LLMemory::logMemoryInfo(TRUE) ;
|
||||||
|
|||||||
@@ -2809,7 +2809,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
|
|||||||
LLSD args;
|
LLSD args;
|
||||||
args["SUBJECT"] = subj;
|
args["SUBJECT"] = subj;
|
||||||
args["MESSAGE"] = mes;
|
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.
|
// 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
|
// *TODO: Remove this dependency, or figure out a better way to handle
|
||||||
// this hack.
|
// this hack.
|
||||||
extern U32 gObjectBits;
|
extern U32Bits gObjectData;
|
||||||
|
|
||||||
void process_object_update(LLMessageSystem *mesgsys, void **user_data)
|
void process_object_update(LLMessageSystem *mesgsys, void **user_data)
|
||||||
{
|
{
|
||||||
// Update the data counters
|
// Update the data counters
|
||||||
if (mesgsys->getReceiveCompressedSize())
|
if (mesgsys->getReceiveCompressedSize())
|
||||||
{
|
{
|
||||||
gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
|
gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gObjectBits += mesgsys->getReceiveSize() * 8;
|
gObjectData += (U32Bytes)mesgsys->getReceiveSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the object...
|
// Update the object...
|
||||||
@@ -5185,11 +5186,11 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data
|
|||||||
// Update the data counters
|
// Update the data counters
|
||||||
if (mesgsys->getReceiveCompressedSize())
|
if (mesgsys->getReceiveCompressedSize())
|
||||||
{
|
{
|
||||||
gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
|
gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gObjectBits += mesgsys->getReceiveSize() * 8;
|
gObjectData += (U32Bytes)mesgsys->getReceiveSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the object...
|
// Update the object...
|
||||||
@@ -5201,11 +5202,11 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data)
|
|||||||
// Update the data counters
|
// Update the data counters
|
||||||
if (mesgsys->getReceiveCompressedSize())
|
if (mesgsys->getReceiveCompressedSize())
|
||||||
{
|
{
|
||||||
gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
|
gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gObjectBits += mesgsys->getReceiveSize() * 8;
|
gObjectData += (U32Bytes)mesgsys->getReceiveSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the object...
|
// Update the object...
|
||||||
@@ -5217,11 +5218,11 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_
|
|||||||
{
|
{
|
||||||
if (mesgsys->getReceiveCompressedSize())
|
if (mesgsys->getReceiveCompressedSize())
|
||||||
{
|
{
|
||||||
gObjectBits += mesgsys->getReceiveCompressedSize() * 8;
|
gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
gObjectBits += mesgsys->getReceiveSize() * 8;
|
gObjectData += (U32Bytes)mesgsys->getReceiveSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED);
|
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 orphans: " << gObjectList.getOrphanCount() << LL_ENDL;
|
||||||
LL_INFOS() << "Number of dead objects: " << gObjectList.mNumDeadObjects << LL_ENDL;
|
LL_INFOS() << "Number of dead objects: " << gObjectList.mNumDeadObjects << LL_ENDL;
|
||||||
LL_INFOS() << "Num images: " << gTextureList.getNumImages() << LL_ENDL;
|
LL_INFOS() << "Num images: " << gTextureList.getNumImages() << LL_ENDL;
|
||||||
LL_INFOS() << "Texture usage: " << LLImageGL::sGlobalTextureMemoryInBytes << LL_ENDL;
|
LL_INFOS() << "Texture usage: " << LLImageGL::sGlobalTextureMemory.value() << LL_ENDL;
|
||||||
LL_INFOS() << "Texture working set: " << LLImageGL::sBoundTextureMemoryInBytes << LL_ENDL;
|
LL_INFOS() << "Texture working set: " << LLImageGL::sBoundTextureMemory.value() << LL_ENDL;
|
||||||
LL_INFOS() << "Raw usage: " << global_raw_memory << LL_ENDL;
|
LL_INFOS() << "Raw usage: " << global_raw_memory << LL_ENDL;
|
||||||
LL_INFOS() << "Formatted usage: " << LLImageFormatted::sGlobalFormattedMemory << LL_ENDL;
|
LL_INFOS() << "Formatted usage: " << LLImageFormatted::sGlobalFormattedMemory << LL_ENDL;
|
||||||
LL_INFOS() << "Zombie Viewer Objects: " << LLViewerObject::getNumZombieObjects() << 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 gTotalLandIn = 0,
|
||||||
U32 gTotalWaterIn = 0, gTotalWaterOut = 0;
|
gTotalLandOut = 0,
|
||||||
|
gTotalWaterIn = 0,
|
||||||
|
gTotalWaterOut = 0;
|
||||||
|
|
||||||
F32 gAveLandCompression = 0.f, gAveWaterCompression = 0.f;
|
F32 gAveLandCompression = 0.f,
|
||||||
F32 gBestLandCompression = 1.f, gBestWaterCompression = 1.f;
|
gAveWaterCompression = 0.f,
|
||||||
F32 gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f;
|
gBestLandCompression = 1.f,
|
||||||
|
gBestWaterCompression = 1.f,
|
||||||
|
gWorstLandCompression = 0.f,
|
||||||
|
gWorstWaterCompression = 0.f;
|
||||||
|
|
||||||
|
U32Bytes gTotalWorldData,
|
||||||
|
gTotalObjectData,
|
||||||
U32 gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0;
|
gTotalTextureData;
|
||||||
U32 gObjectBits = 0;
|
U32 gSimPingCount = 0;
|
||||||
F32 gAvgSimPing = 0.f;
|
U32Bits gObjectData;
|
||||||
U32 gTotalTextureBytesPerBoostLevel[LLGLTexture::MAX_GL_IMAGE_CATEGORY] = {0};
|
F32Milliseconds gAvgSimPing(0.f);
|
||||||
|
U32Bytes gTotalTextureBytesPerBoostLevel[LLGLTexture::MAX_GL_IMAGE_CATEGORY] = {U32Bytes(0)};
|
||||||
|
|
||||||
extern U32 gVisCompared;
|
extern U32 gVisCompared;
|
||||||
extern U32 gVisTested;
|
extern U32 gVisTested;
|
||||||
@@ -591,8 +597,8 @@ LLFrameTimer gTextureTimer;
|
|||||||
|
|
||||||
void update_statistics()
|
void update_statistics()
|
||||||
{
|
{
|
||||||
gTotalWorldBytes += gVLManager.getTotalBytes();
|
gTotalWorldData += U32Bytes(gVLManager.getTotalBytes());
|
||||||
gTotalObjectBytes += gObjectBits / 8;
|
gTotalObjectData += gObjectData;
|
||||||
|
|
||||||
LLViewerStats& stats = LLViewerStats::instance();
|
LLViewerStats& stats = LLViewerStats::instance();
|
||||||
|
|
||||||
@@ -634,7 +640,7 @@ void update_statistics()
|
|||||||
if (cdp)
|
if (cdp)
|
||||||
{
|
{
|
||||||
stats.mSimPingStat.addValue(cdp->getPingDelay());
|
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++;
|
gSimPingCount++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -643,11 +649,11 @@ void update_statistics()
|
|||||||
}
|
}
|
||||||
|
|
||||||
stats.mFPSStat.addValue(1);
|
stats.mFPSStat.addValue(1);
|
||||||
F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
|
F64Bits layer_bits = F64Bits(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
|
||||||
stats.mLayersKBitStat.addValue(layer_bits/1024.f);
|
stats.mLayersKBitStat.addValue((F32)layer_bits.valueInUnits<LLUnits::Kilobits>());
|
||||||
stats.mObjectKBitStat.addValue(gObjectBits/1024.f);
|
stats.mObjectKBitStat.addValue(gObjectData.valueInUnits<LLUnits::Kilobits>());
|
||||||
stats.mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending());
|
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);
|
gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
|
||||||
|
|
||||||
if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
|
if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
|
||||||
@@ -675,7 +681,7 @@ void update_statistics()
|
|||||||
|
|
||||||
// Reset all of these values.
|
// Reset all of these values.
|
||||||
gVLManager.resetBitCounts();
|
gVLManager.resetBitCounts();
|
||||||
gObjectBits = 0;
|
gObjectData = (U32Bytes)0;
|
||||||
// gDecodedBits = 0;
|
// gDecodedBits = 0;
|
||||||
|
|
||||||
// Only update texture stats periodically so that they are less noisy
|
// 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)
|
if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
|
||||||
{
|
{
|
||||||
stats.mHTTPTextureKBitStat.addValue(AICurlInterface::getHTTPBandwidth()/125.f);
|
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);
|
stats.mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets);
|
||||||
gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8;
|
gTotalTextureData += U32Bits(LLViewerTextureList::sTextureBits);
|
||||||
LLViewerTextureList::sTextureBits = 0;
|
LLViewerTextureList::sTextureBits = U32Bits(0);
|
||||||
LLViewerTextureList::sTexturePackets = 0;
|
LLViewerTextureList::sTexturePackets = 0;
|
||||||
texture_stats_timer.reset();
|
texture_stats_timer.reset();
|
||||||
}
|
}
|
||||||
@@ -792,14 +798,14 @@ void send_stats()
|
|||||||
gSimFrames = (F32) gFrameCount;
|
gSimFrames = (F32) gFrameCount;
|
||||||
|
|
||||||
agent["agents_in_view"] = LLVOAvatar::sNumVisibleAvatars;
|
agent["agents_in_view"] = LLVOAvatar::sNumVisibleAvatars;
|
||||||
agent["ping"] = gAvgSimPing;
|
agent["ping"] = gAvgSimPing.value();
|
||||||
agent["meters_traveled"] = gAgent.getDistanceTraveled();
|
agent["meters_traveled"] = gAgent.getDistanceTraveled();
|
||||||
agent["regions_visited"] = gAgent.getRegionsVisited();
|
agent["regions_visited"] = gAgent.getRegionsVisited();
|
||||||
agent["mem_use"] = LLMemory::getCurrentRSS() / 1024.0;
|
agent["mem_use"] = LLMemory::getCurrentRSS() / 1024.0;
|
||||||
|
|
||||||
LLSD &system = body["system"];
|
LLSD &system = body["system"];
|
||||||
|
|
||||||
system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB();
|
system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB().value();
|
||||||
system["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
|
system["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
|
||||||
system["cpu"] = gSysCPU.getCPUString();
|
system["cpu"] = gSysCPU.getCPUString();
|
||||||
unsigned char MACAddress[MAC_ADDRESS_BYTES];
|
unsigned char MACAddress[MAC_ADDRESS_BYTES];
|
||||||
@@ -823,9 +829,9 @@ void send_stats()
|
|||||||
|
|
||||||
LLSD &download = body["downloads"];
|
LLSD &download = body["downloads"];
|
||||||
|
|
||||||
download["world_kbytes"] = gTotalWorldBytes / 1024.0;
|
download["world_kbytes"] = F64Kilobytes(gTotalWorldData).value();
|
||||||
download["object_kbytes"] = gTotalObjectBytes / 1024.0;
|
download["object_kbytes"] = F64Kilobytes(gTotalObjectData).value();
|
||||||
download["texture_kbytes"] = gTotalTextureBytes / 1024.0;
|
download["texture_kbytes"] = F64Kilobytes(gTotalTextureData).value();
|
||||||
download["mesh_kbytes"] = LLMeshRepository::sBytesReceived/1024.0;
|
download["mesh_kbytes"] = LLMeshRepository::sBytesReceived/1024.0;
|
||||||
|
|
||||||
LLSD &in = body["stats"]["net"]["in"];
|
LLSD &in = body["stats"]["net"]["in"];
|
||||||
@@ -886,7 +892,10 @@ void send_stats()
|
|||||||
body["MinimalSkin"] = false;
|
body["MinimalSkin"] = false;
|
||||||
|
|
||||||
LLViewerStats::getInstance()->addToMessage(body);
|
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()
|
LLViewerStats::PhaseMap::PhaseMap()
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ void update_statistics();
|
|||||||
void send_stats();
|
void send_stats();
|
||||||
|
|
||||||
extern LLFrameTimer gTextureTimer;
|
extern LLFrameTimer gTextureTimer;
|
||||||
extern U32 gTotalTextureBytes;
|
extern U32Bytes gTotalTextureData;
|
||||||
extern U32 gTotalObjectBytes;
|
extern U32Bytes gTotalObjectData;
|
||||||
extern U32 gTotalTextureBytesPerBoostLevel[] ;
|
extern U32Bytes gTotalTextureBytesPerBoostLevel[] ;
|
||||||
#endif // LL_LLVIEWERSTATS_H
|
#endif // LL_LLVIEWERSTATS_H
|
||||||
|
|||||||
@@ -63,6 +63,11 @@
|
|||||||
#include "lltexturecache.h"
|
#include "lltexturecache.h"
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// extern
|
||||||
|
const S32Megabytes gMinVideoRam(32);
|
||||||
|
const S32Megabytes gMaxVideoRam(1024);
|
||||||
|
|
||||||
|
|
||||||
// statics
|
// statics
|
||||||
LLPointer<LLViewerTexture> LLViewerTexture::sNullImagep = NULL;
|
LLPointer<LLViewerTexture> LLViewerTexture::sNullImagep = NULL;
|
||||||
LLPointer<LLViewerTexture> LLViewerTexture::sBlackImagep = NULL;
|
LLPointer<LLViewerTexture> LLViewerTexture::sBlackImagep = NULL;
|
||||||
@@ -83,12 +88,12 @@ S32 LLViewerTexture::sAuxCount = 0;
|
|||||||
LLFrameTimer LLViewerTexture::sEvaluationTimer;
|
LLFrameTimer LLViewerTexture::sEvaluationTimer;
|
||||||
F32 LLViewerTexture::sDesiredDiscardBias = 0.f;
|
F32 LLViewerTexture::sDesiredDiscardBias = 0.f;
|
||||||
F32 LLViewerTexture::sDesiredDiscardScale = 1.1f;
|
F32 LLViewerTexture::sDesiredDiscardScale = 1.1f;
|
||||||
S32 LLViewerTexture::sBoundTextureMemoryInBytes = 0;
|
S32Bytes LLViewerTexture::sBoundTextureMemory;
|
||||||
S32 LLViewerTexture::sTotalTextureMemoryInBytes = 0;
|
S32Bytes LLViewerTexture::sTotalTextureMemory;
|
||||||
S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0;
|
S32Megabytes LLViewerTexture::sMaxBoundTextureMemory;
|
||||||
S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0;
|
S32Megabytes LLViewerTexture::sMaxTotalTextureMem;
|
||||||
S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ;
|
S32Bytes LLViewerTexture::sMaxDesiredTextureMem;
|
||||||
S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ;
|
S8 LLViewerTexture::sCameraMovingDiscardBias = 0;
|
||||||
F32 LLViewerTexture::sCameraMovingBias = 0.0f ;
|
F32 LLViewerTexture::sCameraMovingBias = 0.0f ;
|
||||||
S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size
|
S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size
|
||||||
const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ;
|
const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ;
|
||||||
@@ -450,8 +455,9 @@ bool LLViewerTexture::isMemoryForTextureLow()
|
|||||||
timer.reset() ;
|
timer.reset() ;
|
||||||
|
|
||||||
LLFastTimer t(FTM_TEXTURE_MEMORY_CHECK);
|
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 ;
|
bool low_mem = false ;
|
||||||
if (gGLManager.mHasATIMemInfo)
|
if (gGLManager.mHasATIMemInfo)
|
||||||
@@ -459,7 +465,7 @@ bool LLViewerTexture::isMemoryForTextureLow()
|
|||||||
S32 meminfo[4];
|
S32 meminfo[4];
|
||||||
glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo);
|
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 ;
|
low_mem = true ;
|
||||||
}
|
}
|
||||||
@@ -467,7 +473,7 @@ bool LLViewerTexture::isMemoryForTextureLow()
|
|||||||
if(!low_mem) //check main memory, only works for windows.
|
if(!low_mem) //check main memory, only works for windows.
|
||||||
{
|
{
|
||||||
LLMemory::updateMemoryInfo() ;
|
LLMemory::updateMemoryInfo() ;
|
||||||
if(LLMemory::getAvailableMemKB() / 1024 < MIN_FREE_MAIN_MEMORy)
|
if(LLMemory::getAvailableMemKB() < MIN_FREE_TEXTURE_MEMORY)
|
||||||
{
|
{
|
||||||
low_mem = true ;
|
low_mem = true ;
|
||||||
}
|
}
|
||||||
@@ -511,17 +517,17 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
|
|||||||
LLViewerMediaTexture::updateClass() ;
|
LLViewerMediaTexture::updateClass() ;
|
||||||
}
|
}
|
||||||
|
|
||||||
sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes
|
sBoundTextureMemory = LLImageGL::sBoundTextureMemory;
|
||||||
sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes
|
sTotalTextureMemory = LLImageGL::sGlobalTextureMemory;
|
||||||
sMaxBoundTextureMemInMegaBytes = gTextureList.getMaxResidentTexMem();//in MB
|
sMaxBoundTextureMemory = S32Megabytes(gTextureList.getMaxResidentTexMem());
|
||||||
sMaxTotalTextureMemInMegaBytes = gTextureList.getMaxTotalTextureMem() ;//in MB
|
sMaxTotalTextureMem = S32Megabytes(gTextureList.getMaxTotalTextureMem());
|
||||||
sMaxDesiredTextureMemInBytes = MEGA_BYTES_TO_BYTES(sMaxTotalTextureMemInMegaBytes) ; //in Bytes, by default and when total used texture memory is small.
|
sMaxDesiredTextureMem = sMaxTotalTextureMem; //in Bytes, by default and when total used texture memory is small.
|
||||||
|
|
||||||
if (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) >= sMaxBoundTextureMemInMegaBytes ||
|
if (sBoundTextureMemory >= sMaxBoundTextureMemory ||
|
||||||
BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) >= sMaxTotalTextureMemInMegaBytes)
|
sTotalTextureMemory >= sMaxTotalTextureMem)
|
||||||
{
|
{
|
||||||
//when texture memory overflows, lower down the threashold to release the textures more aggressively.
|
//when texture memory overflows, lower down the threshold to release the textures more aggressively.
|
||||||
sMaxDesiredTextureMemInBytes = llmin((S32)(sMaxDesiredTextureMemInBytes * 0.75f) , MEGA_BYTES_TO_BYTES(MAX_VIDEO_RAM_IN_MEGA_BYTES)) ;//512 MB
|
sMaxDesiredTextureMem = llmin(sMaxDesiredTextureMem * 0.75f, F32Bytes(gMaxVideoRam));
|
||||||
|
|
||||||
// If we are using more texture memory than we should,
|
// If we are using more texture memory than we should,
|
||||||
// scale up the desired discard level
|
// scale up the desired discard level
|
||||||
@@ -537,8 +543,8 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity
|
|||||||
sEvaluationTimer.reset();
|
sEvaluationTimer.reset();
|
||||||
}
|
}
|
||||||
else if (sDesiredDiscardBias > 0.0f &&
|
else if (sDesiredDiscardBias > 0.0f &&
|
||||||
BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < sMaxBoundTextureMemInMegaBytes * texmem_lower_bound_scale &&
|
sBoundTextureMemory < sMaxBoundTextureMemory * texmem_lower_bound_scale &&
|
||||||
BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < sMaxTotalTextureMemInMegaBytes * texmem_lower_bound_scale)
|
sTotalTextureMemory < sMaxTotalTextureMem * texmem_lower_bound_scale)
|
||||||
{
|
{
|
||||||
// If we are using less texture memory than we should,
|
// If we are using less texture memory than we should,
|
||||||
// scale down the desired discard level
|
// 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);
|
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_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed();
|
||||||
F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
|
F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed();
|
||||||
sCameraMovingBias = llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1);
|
sCameraMovingBias = llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1);
|
||||||
sCameraMovingDiscardBias = (S8)(sCameraMovingBias);
|
sCameraMovingDiscardBias = (S8)(sCameraMovingBias);
|
||||||
|
|
||||||
LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) &&
|
LLViewerTexture::sFreezeImageScalingDown = (sBoundTextureMemory < 0.75f * sMaxBoundTextureMemory * texmem_middle_bound_scale) &&
|
||||||
(BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ;
|
(sTotalTextureMemory < 0.75f * sMaxTotalTextureMem * texmem_middle_bound_scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
//end of static functions
|
//end of static functions
|
||||||
@@ -1156,7 +1161,7 @@ void LLViewerFetchedTexture::dump()
|
|||||||
// ONLY called from LLViewerFetchedTextureList
|
// ONLY called from LLViewerFetchedTextureList
|
||||||
void LLViewerFetchedTexture::destroyTexture()
|
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 ;
|
return ;
|
||||||
}
|
}
|
||||||
@@ -3049,13 +3054,13 @@ void LLViewerLODTexture::processTextureStats()
|
|||||||
scaleDown() ;
|
scaleDown() ;
|
||||||
}
|
}
|
||||||
// Limit the amount of GL memory bound each frame
|
// 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))
|
(!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
|
||||||
{
|
{
|
||||||
scaleDown() ;
|
scaleDown() ;
|
||||||
}
|
}
|
||||||
// Only allow GL to have 2x the video card memory
|
// 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))
|
(!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel))
|
||||||
{
|
{
|
||||||
scaleDown() ;
|
scaleDown() ;
|
||||||
@@ -3639,10 +3644,10 @@ LLTexturePipelineTester::LLTexturePipelineTester() : LLMetricPerformanceTesterWi
|
|||||||
addMetric("TotalBytesBoundForLargeImage") ;
|
addMetric("TotalBytesBoundForLargeImage") ;
|
||||||
addMetric("PercentageBytesBound") ;
|
addMetric("PercentageBytesBound") ;
|
||||||
|
|
||||||
mTotalBytesLoaded = 0 ;
|
mTotalBytesLoaded = (S32Bytes)0;
|
||||||
mTotalBytesLoadedFromCache = 0 ;
|
mTotalBytesLoadedFromCache = (S32Bytes)0;
|
||||||
mTotalBytesLoadedForLargeImage = 0 ;
|
mTotalBytesLoadedForLargeImage = (S32Bytes)0;
|
||||||
mTotalBytesLoadedForSculpties = 0 ;
|
mTotalBytesLoadedForSculpties = (S32Bytes)0;
|
||||||
|
|
||||||
reset() ;
|
reset() ;
|
||||||
}
|
}
|
||||||
@@ -3656,8 +3661,8 @@ void LLTexturePipelineTester::update()
|
|||||||
{
|
{
|
||||||
mLastTotalBytesUsed = mTotalBytesUsed ;
|
mLastTotalBytesUsed = mTotalBytesUsed ;
|
||||||
mLastTotalBytesUsedForLargeImage = mTotalBytesUsedForLargeImage ;
|
mLastTotalBytesUsedForLargeImage = mTotalBytesUsedForLargeImage ;
|
||||||
mTotalBytesUsed = 0 ;
|
mTotalBytesUsed = (S32Bytes)0;
|
||||||
mTotalBytesUsedForLargeImage = 0 ;
|
mTotalBytesUsedForLargeImage = (S32Bytes)0;
|
||||||
|
|
||||||
if(LLAppViewer::getTextureFetch()->getNumRequests() > 0) //fetching list is not empty
|
if(LLAppViewer::getTextureFetch()->getNumRequests() > 0) //fetching list is not empty
|
||||||
{
|
{
|
||||||
@@ -3698,10 +3703,10 @@ void LLTexturePipelineTester::reset()
|
|||||||
mStartStablizingTime = 0.0f ;
|
mStartStablizingTime = 0.0f ;
|
||||||
mEndStablizingTime = 0.0f ;
|
mEndStablizingTime = 0.0f ;
|
||||||
|
|
||||||
mTotalBytesUsed = 0 ;
|
mTotalBytesUsed = (S32Bytes)0;
|
||||||
mTotalBytesUsedForLargeImage = 0 ;
|
mTotalBytesUsedForLargeImage = (S32Bytes)0;
|
||||||
mLastTotalBytesUsed = 0 ;
|
mLastTotalBytesUsed = (S32Bytes)0;
|
||||||
mLastTotalBytesUsedForLargeImage = 0 ;
|
mLastTotalBytesUsedForLargeImage = (S32Bytes)0;
|
||||||
|
|
||||||
mStartFetchingTime = 0.0f ;
|
mStartFetchingTime = 0.0f ;
|
||||||
|
|
||||||
@@ -3716,59 +3721,59 @@ void LLTexturePipelineTester::reset()
|
|||||||
void LLTexturePipelineTester::outputTestRecord(LLSD *sd)
|
void LLTexturePipelineTester::outputTestRecord(LLSD *sd)
|
||||||
{
|
{
|
||||||
std::string currentLabel = getCurrentLabelName();
|
std::string currentLabel = getCurrentLabelName();
|
||||||
(*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ;
|
(*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded.value();
|
||||||
(*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ;
|
(*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache.value();
|
||||||
(*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ;
|
(*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage.value();
|
||||||
(*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ;
|
(*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties.value();
|
||||||
|
|
||||||
(*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime ;
|
(*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime;
|
||||||
(*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime ;
|
(*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime;
|
||||||
(*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime ;
|
(*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime;
|
||||||
|
|
||||||
(*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties ;
|
(*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties;
|
||||||
(*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties ;
|
(*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties;
|
||||||
|
|
||||||
(*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime ;
|
(*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime;
|
||||||
(*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ;
|
(*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed.value();
|
||||||
(*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ;
|
(*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage.value();
|
||||||
(*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ;
|
(*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep)
|
void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep)
|
||||||
{
|
{
|
||||||
U32 mem_size = (U32)imagep->getTextureMemory() ;
|
U32Bytes mem_size = imagep->getTextureMemory();
|
||||||
mTotalBytesUsed += mem_size ;
|
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 ;
|
mTotalBytesUsedForLargeImage += mem_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache)
|
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 ;
|
mTotalBytesLoaded += data_size;
|
||||||
|
|
||||||
if(from_cache)
|
if(from_cache)
|
||||||
{
|
{
|
||||||
mTotalBytesLoadedFromCache += data_size ;
|
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 ;
|
mTotalBytesLoadedForLargeImage += data_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(imagep->forSculpt())
|
if(imagep->forSculpt())
|
||||||
{
|
{
|
||||||
mTotalBytesLoadedForSculpties += data_size ;
|
mTotalBytesLoadedForSculpties += data_size;
|
||||||
|
|
||||||
if(mStartTimeLoadingSculpties > mEndTimeLoadingSculpties)
|
if(mStartTimeLoadingSculpties > mEndTimeLoadingSculpties)
|
||||||
{
|
{
|
||||||
mStartTimeLoadingSculpties = LLImageGL::sLastFrameTime ;
|
mStartTimeLoadingSculpties = LLImageGL::sLastFrameTime;
|
||||||
}
|
}
|
||||||
mEndTimeLoadingSculpties = LLImageGL::sLastFrameTime ;
|
mEndTimeLoadingSculpties = LLImageGL::sLastFrameTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,9 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
|
||||||
#define MIN_VIDEO_RAM_IN_MEGA_BYTES 32
|
extern const S32Megabytes gMinVideoRam;
|
||||||
#define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons.
|
extern const S32Megabytes gMaxVideoRam;
|
||||||
|
|
||||||
|
|
||||||
class LLImageGL ;
|
class LLImageGL ;
|
||||||
class LLImageRaw;
|
class LLImageRaw;
|
||||||
@@ -210,11 +211,11 @@ public:
|
|||||||
static LLFrameTimer sEvaluationTimer;
|
static LLFrameTimer sEvaluationTimer;
|
||||||
static F32 sDesiredDiscardBias;
|
static F32 sDesiredDiscardBias;
|
||||||
static F32 sDesiredDiscardScale;
|
static F32 sDesiredDiscardScale;
|
||||||
static S32 sBoundTextureMemoryInBytes;
|
static S32Bytes sBoundTextureMemory;
|
||||||
static S32 sTotalTextureMemoryInBytes;
|
static S32Bytes sTotalTextureMemory;
|
||||||
static S32 sMaxBoundTextureMemInMegaBytes;
|
static S32Megabytes sMaxBoundTextureMemory;
|
||||||
static S32 sMaxTotalTextureMemInMegaBytes;
|
static S32Megabytes sMaxTotalTextureMem;
|
||||||
static S32 sMaxDesiredTextureMemInBytes ;
|
static S32Bytes sMaxDesiredTextureMem ;
|
||||||
static S8 sCameraMovingDiscardBias;
|
static S8 sCameraMovingDiscardBias;
|
||||||
static F32 sCameraMovingBias;
|
static F32 sCameraMovingBias;
|
||||||
static S32 sMaxSculptRez ;
|
static S32 sMaxSculptRez ;
|
||||||
|
|||||||
@@ -72,7 +72,7 @@
|
|||||||
|
|
||||||
void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL;
|
void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL;
|
||||||
|
|
||||||
U32 LLViewerTextureList::sTextureBits = 0;
|
U32Bits LLViewerTextureList::sTextureBits(0);
|
||||||
U32 LLViewerTextureList::sTexturePackets = 0;
|
U32 LLViewerTextureList::sTexturePackets = 0;
|
||||||
S32 LLViewerTextureList::sNumImages = 0;
|
S32 LLViewerTextureList::sNumImages = 0;
|
||||||
|
|
||||||
@@ -95,8 +95,8 @@ void LLViewerTextureList::init()
|
|||||||
mInitialized = TRUE ;
|
mInitialized = TRUE ;
|
||||||
sNumImages = 0;
|
sNumImages = 0;
|
||||||
mUpdateStats = TRUE;
|
mUpdateStats = TRUE;
|
||||||
mMaxResidentTexMemInMegaBytes = 0;
|
mMaxResidentTexMemInMegaBytes = (U32Bytes)0;
|
||||||
mMaxTotalTextureMemInMegaBytes = 0 ;
|
mMaxTotalTextureMemInMegaBytes = (U32Bytes)0;
|
||||||
if (gNoRender)
|
if (gNoRender)
|
||||||
{
|
{
|
||||||
// Don't initialize GL stuff if we're not rendering.
|
// 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.
|
// Update how much texture RAM we're allowed to use.
|
||||||
updateMaxResidentTexMem(0); // 0 = use current
|
updateMaxResidentTexMem(S32Megabytes(0)); // 0 = use current
|
||||||
|
|
||||||
doPreloadImages();
|
doPreloadImages();
|
||||||
}
|
}
|
||||||
@@ -706,8 +706,8 @@ void LLViewerTextureList::updateImages(F32 max_time)
|
|||||||
}
|
}
|
||||||
LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages);
|
LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages);
|
||||||
LLViewerStats::getInstance()->mNumRawImagesStat.addValue(LLImageRaw::sRawImageCount);
|
LLViewerStats::getInstance()->mNumRawImagesStat.addValue(LLImageRaw::sRawImageCount);
|
||||||
LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes));
|
LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)LLImageGL::sGlobalTextureMemory.valueInUnits<LLUnits::Megabytes>());
|
||||||
LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes));
|
LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)LLImageGL::sBoundTextureMemory.valueInUnits<LLUnits::Megabytes>());
|
||||||
LLViewerStats::getInstance()->mRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(global_raw_memory));
|
LLViewerStats::getInstance()->mRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(global_raw_memory));
|
||||||
LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory));
|
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
|
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);
|
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());
|
max_priority_count = llmin(max_priority_count, mImageList.size());
|
||||||
|
|
||||||
size_t total_update_count = mUUIDMap.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);
|
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_update_count = llmin(max_update_count, total_update_count);
|
||||||
|
|
||||||
// MAX_HIGH_PRIO_COUNT high priority entries
|
// MAX_HIGH_PRIO_COUNT high priority entries
|
||||||
@@ -1218,20 +1216,16 @@ LLPointer<LLImageJ2C> LLViewerTextureList::convertToUploadFile(LLPointer<LLImage
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns min setting for TextureMemory (in MB)
|
// Returns min setting for TextureMemory (in MB)
|
||||||
S32 LLViewerTextureList::getMinVideoRamSetting()
|
S32Megabytes LLViewerTextureList::getMinVideoRamSetting()
|
||||||
{
|
{
|
||||||
S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped());
|
S32Megabytes system_ram = gSysMemory.getPhysicalMemoryClamped();
|
||||||
if (system_ram > 2000)
|
//min texture mem sets to 64M if total physical mem is more than 1.5GB
|
||||||
return 128;
|
return (system_ram > S32Megabytes(1500)) ? S32Megabytes(64) : gMinVideoRam ;
|
||||||
else if (system_ram > 1000)
|
|
||||||
return 64;
|
|
||||||
else
|
|
||||||
return MIN_VIDEO_RAM_IN_MEGA_BYTES;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//static
|
//static
|
||||||
// Returns max setting for TextureMemory (in MB)
|
// 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 LL_LINUX
|
||||||
if (gGLManager.mIsIntel && gGLManager.mGLVersion >= 3.f && !gGLManager.mVRAM)
|
if (gGLManager.mIsIntel && gGLManager.mGLVersion >= 3.f && !gGLManager.mVRAM)
|
||||||
@@ -1239,12 +1233,12 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
|
|||||||
gGLManager.mVRAM = 512;
|
gGLManager.mVRAM = 512;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
S32 max_texmem;
|
S32Megabytes max_texmem;
|
||||||
if (gGLManager.mVRAM != 0)
|
if (gGLManager.mVRAM != 0)
|
||||||
{
|
{
|
||||||
// Treat any card with < 32 MB (shudder) as having 32 MB
|
// Treat any card with < 32 MB (shudder) as having 32 MB
|
||||||
// - it's going to be swapping constantly regardless
|
// - 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_vram = llmax(max_vram, getMinVideoRamSetting());
|
||||||
max_texmem = max_vram;
|
max_texmem = max_vram;
|
||||||
if (!get_recommended)
|
if (!get_recommended)
|
||||||
@@ -1252,72 +1246,81 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (get_recommended)
|
if (!get_recommended)
|
||||||
max_texmem = 128;
|
{
|
||||||
|
max_texmem = (S32Megabytes)512;
|
||||||
|
}
|
||||||
|
else if (gSavedSettings.getBOOL("NoHardwareProbe")) //did not do hardware detection at startup
|
||||||
|
{
|
||||||
|
max_texmem = (S32Megabytes)512;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
max_texmem = 512;
|
{
|
||||||
|
max_texmem = (S32Megabytes)128;
|
||||||
|
}
|
||||||
|
|
||||||
LL_WARNS() << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << LL_ENDL;
|
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;
|
//LL_INFOS() << "*** DETECTED " << system_ram << " MB of system memory." << LL_ENDL;
|
||||||
if (get_recommended)
|
if (get_recommended)
|
||||||
max_texmem = llmin(max_texmem, (S32)(system_ram/2));
|
max_texmem = llmin(max_texmem, system_ram/2);
|
||||||
else
|
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;
|
return max_texmem;
|
||||||
}
|
}
|
||||||
|
|
||||||
const S32 VIDEO_CARD_FRAMEBUFFER_MEM = 12; // MB
|
const S32Megabytes VIDEO_CARD_FRAMEBUFFER_MEM(12);
|
||||||
const S32 MIN_MEM_FOR_NON_TEXTURE = 512 ; //MB
|
const S32Megabytes MIN_MEM_FOR_NON_TEXTURE(512);
|
||||||
void LLViewerTextureList::updateMaxResidentTexMem(S32 mem)
|
void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem)
|
||||||
{
|
{
|
||||||
// Initialize the image pipeline VRAM settings
|
// Initialize the image pipeline VRAM settings
|
||||||
S32 cur_mem = gSavedSettings.getS32("TextureMemory");
|
S32Megabytes cur_mem(gSavedSettings.getS32("TextureMemory"));
|
||||||
F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
|
F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple");
|
||||||
S32 default_mem = getMaxVideoRamSetting(true); // recommended default
|
S32Megabytes default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default
|
||||||
if (mem == 0)
|
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;
|
mem = default_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
// limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise
|
mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier));
|
||||||
mem = llmin(mem, (S32) (mem_multiplier * (F32) default_mem));
|
|
||||||
|
|
||||||
mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting());
|
|
||||||
if (mem != cur_mem)
|
if (mem != cur_mem)
|
||||||
{
|
{
|
||||||
gSavedSettings.setS32("TextureMemory", mem);
|
gSavedSettings.setS32("TextureMemory", mem.value());
|
||||||
return; //listener will re-enter this function
|
return; //listener will re-enter this function
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: set available resident texture mem based on use by other subsystems
|
// TODO: set available resident texture mem based on use by other subsystems
|
||||||
// currently max(12MB, VRAM/4) assumed...
|
// currently max(12MB, VRAM/4) assumed...
|
||||||
|
|
||||||
S32 vb_mem = mem;
|
S32Megabytes vb_mem = mem;
|
||||||
S32 fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4);
|
S32Megabytes fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4);
|
||||||
mMaxResidentTexMemInMegaBytes = (vb_mem - fb_mem) ; //in MB
|
mMaxResidentTexMemInMegaBytes = (vb_mem - fb_mem) ; //in MB
|
||||||
|
|
||||||
mMaxTotalTextureMemInMegaBytes = mMaxResidentTexMemInMegaBytes * 2;
|
mMaxTotalTextureMemInMegaBytes = mMaxResidentTexMemInMegaBytes * 2;
|
||||||
if (mMaxResidentTexMemInMegaBytes > 640)
|
if (mMaxResidentTexMemInMegaBytes > (S32Megabytes)640)
|
||||||
{
|
{
|
||||||
mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes >> 2);
|
mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes / 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
//system mem
|
//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.
|
//minimum memory reserved for non-texture use.
|
||||||
//if system_raw >= 1GB, reserve at least 512MB 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.
|
//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)
|
if (mMaxTotalTextureMemInMegaBytes > system_ram - min_non_texture_mem)
|
||||||
{
|
{
|
||||||
@@ -1345,17 +1348,17 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d
|
|||||||
char ip_string[256];
|
char ip_string[256];
|
||||||
u32_to_ip_string(msg->getSenderIP(),ip_string);
|
u32_to_ip_string(msg->getSenderIP(),ip_string);
|
||||||
|
|
||||||
U32 received_size ;
|
U32Bytes received_size ;
|
||||||
if (msg->getReceiveCompressedSize())
|
if (msg->getReceiveCompressedSize())
|
||||||
{
|
{
|
||||||
received_size = msg->getReceiveCompressedSize() ;
|
received_size = (U32Bytes)msg->getReceiveCompressedSize() ;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
received_size = msg->getReceiveSize() ;
|
received_size = (U32Bytes)msg->getReceiveSize() ;
|
||||||
}
|
}
|
||||||
// Only used for statistics and texture console.
|
// Only used for statistics and texture console.
|
||||||
gTextureList.sTextureBits += received_size * 8;
|
gTextureList.sTextureBits += received_size;
|
||||||
gTextureList.sTexturePackets++;
|
gTextureList.sTexturePackets++;
|
||||||
|
|
||||||
U8 codec;
|
U8 codec;
|
||||||
@@ -1419,16 +1422,16 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d
|
|||||||
char ip_string[256];
|
char ip_string[256];
|
||||||
u32_to_ip_string(msg->getSenderIP(),ip_string);
|
u32_to_ip_string(msg->getSenderIP(),ip_string);
|
||||||
|
|
||||||
U32 received_size ;
|
U32Bytes received_size ;
|
||||||
if (msg->getReceiveCompressedSize())
|
if (msg->getReceiveCompressedSize())
|
||||||
{
|
{
|
||||||
received_size = msg->getReceiveCompressedSize() ;
|
received_size = (U32Bytes)msg->getReceiveCompressedSize() ;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
received_size = msg->getReceiveSize() ;
|
received_size = (U32Bytes)msg->getReceiveSize() ;
|
||||||
}
|
}
|
||||||
gTextureList.sTextureBits += received_size * 8;
|
gTextureList.sTextureBits += received_size;
|
||||||
gTextureList.sTexturePackets++;
|
gTextureList.sTexturePackets++;
|
||||||
|
|
||||||
//llprintline("Start decode, image header...");
|
//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
|
// explicitly cleanup resources, as this is a singleton class with process
|
||||||
// lifetime so ability to perform std::map operations in destructor is not
|
// lifetime so ability to perform std::map operations in destructor is not
|
||||||
// guaranteed.
|
// guaranteed.
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ public:
|
|||||||
static BOOL verifyUploadFile(const std::string& out_filename, const U8 codec);
|
static BOOL verifyUploadFile(const std::string& out_filename, const U8 codec);
|
||||||
static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image);
|
static LLPointer<LLImageJ2C> convertToUploadFile(LLPointer<LLImageRaw> raw_image);
|
||||||
static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data );
|
static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data );
|
||||||
static S32 calcMaxTextureRAM();
|
|
||||||
static void receiveImageHeader(LLMessageSystem *msg, void **user_data);
|
static void receiveImageHeader(LLMessageSystem *msg, void **user_data);
|
||||||
static void receiveImagePacket(LLMessageSystem *msg, void **user_data);
|
static void receiveImagePacket(LLMessageSystem *msg, void **user_data);
|
||||||
|
|
||||||
@@ -101,19 +100,19 @@ public:
|
|||||||
|
|
||||||
void setUpdateStats(BOOL b) { mUpdateStats = b; }
|
void setUpdateStats(BOOL b) { mUpdateStats = b; }
|
||||||
|
|
||||||
S32 getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; }
|
S32Megabytes getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; }
|
||||||
S32 getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;}
|
S32Megabytes getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;}
|
||||||
S32 getNumImages() { return mImageList.size(); }
|
S32 getNumImages() { return mImageList.size(); }
|
||||||
|
|
||||||
void updateMaxResidentTexMem(S32 mem);
|
void updateMaxResidentTexMem(S32Megabytes mem);
|
||||||
|
|
||||||
void doPreloadImages();
|
void doPreloadImages();
|
||||||
void doPrefetchImages();
|
void doPrefetchImages();
|
||||||
|
|
||||||
void clearFetchingRequests();
|
void clearFetchingRequests();
|
||||||
|
|
||||||
static S32 getMinVideoRamSetting();
|
static S32Megabytes getMinVideoRamSetting();
|
||||||
static S32 getMaxVideoRamSetting(bool get_recommended = false);
|
static S32Megabytes getMaxVideoRamSetting(bool get_recommended, float mem_multiplier);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateImagesDecodePriorities();
|
void updateImagesDecodePriorities();
|
||||||
@@ -195,12 +194,12 @@ private:
|
|||||||
|
|
||||||
BOOL mInitialized ;
|
BOOL mInitialized ;
|
||||||
BOOL mUpdateStats;
|
BOOL mUpdateStats;
|
||||||
S32 mMaxResidentTexMemInMegaBytes;
|
S32Megabytes mMaxResidentTexMemInMegaBytes;
|
||||||
S32 mMaxTotalTextureMemInMegaBytes;
|
S32Megabytes mMaxTotalTextureMemInMegaBytes;
|
||||||
LLFrameTimer mForceDecodeTimer;
|
LLFrameTimer mForceDecodeTimer;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static U32 sTextureBits;
|
static U32Bits sTextureBits;
|
||||||
static U32 sTexturePackets;
|
static U32 sTexturePackets;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -5356,7 +5356,7 @@ void LLViewerWindow::stopGL(BOOL save_state)
|
|||||||
|
|
||||||
gGL.resetVertexBuffers();
|
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;
|
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)
|
for (std::set<LLUUID>::const_iterator it = ids.begin(); it != ids.end(); ++it)
|
||||||
{
|
{
|
||||||
LLViewerFetchedTexture *imagep = gTextureList.findImage(*it);
|
LLViewerFetchedTexture *imagep = gTextureList.findImage(*it);
|
||||||
@@ -5236,12 +5236,12 @@ void LLVOAvatar::collectTextureUUIDs(std::set<LLUUID>& ids)
|
|||||||
|
|
||||||
void LLVOAvatar::releaseOldTextures()
|
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"
|
// 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;
|
std::set<LLUUID> baked_texture_ids;
|
||||||
collectBakedTextureUUIDs(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;
|
std::set<LLUUID> local_texture_ids;
|
||||||
collectLocalTextureUUIDs(local_texture_ids);
|
collectLocalTextureUUIDs(local_texture_ids);
|
||||||
@@ -5250,7 +5250,7 @@ void LLVOAvatar::releaseOldTextures()
|
|||||||
std::set<LLUUID> new_texture_ids;
|
std::set<LLUUID> new_texture_ids;
|
||||||
new_texture_ids.insert(baked_texture_ids.begin(),baked_texture_ids.end());
|
new_texture_ids.insert(baked_texture_ids.begin(),baked_texture_ids.end());
|
||||||
new_texture_ids.insert(local_texture_ids.begin(),local_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);
|
//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;
|
//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 updateLODRiggedAttachments( void );
|
||||||
void updateSoftwareSkinnedVertices(const LLMeshSkinInfo* skin, const LLVector4a* weight, const LLVolumeFace& vol_face, LLVertexBuffer *buffer);
|
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.
|
/*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 allTexturesCompletelyDownloaded(std::set<LLUUID>& ids) const;
|
||||||
bool allLocalTexturesCompletelyDownloaded() const;
|
bool allLocalTexturesCompletelyDownloaded() const;
|
||||||
bool allBakedTexturesCompletelyDownloaded() const;
|
bool allBakedTexturesCompletelyDownloaded() const;
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ typedef LLHTTPClient::ResponderIgnore LLHoverHeightResponder;
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Static Data
|
// Static Data
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
S32 LLVOAvatarSelf::sScratchTexBytes = 0;
|
S32Bytes LLVOAvatarSelf::sScratchTexBytes(0);
|
||||||
LLMap< LLGLenum, LLGLuint*> LLVOAvatarSelf::sScratchTexNames;
|
LLMap< LLGLenum, LLGLuint*> LLVOAvatarSelf::sScratchTexNames;
|
||||||
LLMap< LLGLenum, F32*> LLVOAvatarSelf::sScratchTexLastBindTime;
|
LLMap< LLGLenum, F32*> LLVOAvatarSelf::sScratchTexLastBindTime;
|
||||||
|
|
||||||
@@ -3215,8 +3215,8 @@ void LLVOAvatarSelf::deleteScratchTextures()
|
|||||||
{
|
{
|
||||||
if(gAuditTexture)
|
if(gAuditTexture)
|
||||||
{
|
{
|
||||||
S32 total_tex_size = sScratchTexBytes ;
|
S32Bytes total_tex_size = sScratchTexBytes ;
|
||||||
S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ;
|
S32Bytes tex_size(SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT) ;
|
||||||
|
|
||||||
if( sScratchTexNames.checkData( GL_LUMINANCE ) )
|
if( sScratchTexNames.checkData( GL_LUMINANCE ) )
|
||||||
{
|
{
|
||||||
@@ -3249,7 +3249,7 @@ void LLVOAvatarSelf::deleteScratchTextures()
|
|||||||
total_tex_size -= 4 * tex_size ;
|
total_tex_size -= 4 * tex_size ;
|
||||||
}
|
}
|
||||||
//others
|
//others
|
||||||
while(total_tex_size > 0)
|
while(total_tex_size > S32Bytes(0))
|
||||||
{
|
{
|
||||||
LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ;
|
||||||
total_tex_size -= 4 * tex_size ;
|
total_tex_size -= 4 * tex_size ;
|
||||||
@@ -3264,14 +3264,14 @@ void LLVOAvatarSelf::deleteScratchTextures()
|
|||||||
stop_glerror();
|
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();
|
sScratchTexNames.deleteAllData();
|
||||||
sScratchTexLastBindTime.deleteAllData();
|
sScratchTexLastBindTime.deleteAllData();
|
||||||
LLImageGL::sGlobalTextureMemoryInBytes -= sScratchTexBytes;
|
LLImageGL::sGlobalTextureMemory -= sScratchTexBytes;
|
||||||
sScratchTexBytes = 0;
|
sScratchTexBytes = S32Bytes(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -273,7 +273,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
static void deleteScratchTextures();
|
static void deleteScratchTextures();
|
||||||
private:
|
private:
|
||||||
static S32 sScratchTexBytes;
|
static S32Bytes sScratchTexBytes;
|
||||||
static LLMap< LLGLenum, LLGLuint*> sScratchTexNames;
|
static LLMap< LLGLenum, LLGLuint*> sScratchTexNames;
|
||||||
static LLMap< LLGLenum, F32*> sScratchTexLastBindTime;
|
static LLMap< LLGLenum, F32*> sScratchTexLastBindTime;
|
||||||
|
|
||||||
|
|||||||
@@ -4001,7 +4001,8 @@ U32 LLVOVolume::getPartitionType() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp)
|
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;
|
mLODPeriod = 32;
|
||||||
mDepthMask = FALSE;
|
mDepthMask = FALSE;
|
||||||
@@ -4012,7 +4013,8 @@ LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, 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;
|
mDepthMask = FALSE;
|
||||||
mLODPeriod = 32;
|
mLODPeriod = 32;
|
||||||
@@ -4073,6 +4075,70 @@ bool can_batch_texture(const LLFace* facep)
|
|||||||
return true;
|
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");
|
static LLFastTimer::DeclareTimer FTM_REGISTER_FACE("Register Face");
|
||||||
|
|
||||||
void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
|
void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type)
|
||||||
@@ -4427,16 +4493,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
group->clearDrawMap();
|
group->clearDrawMap();
|
||||||
|
|
||||||
mFaceList.clear();
|
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 fullbright_count = 0;
|
||||||
U32 bump_count = 0;
|
U32 bump_count = 0;
|
||||||
@@ -4931,7 +4987,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
{ //can be treated as alpha mask
|
{ //can be treated as alpha mask
|
||||||
if (simple_count < MAX_FACE_COUNT)
|
if (simple_count < MAX_FACE_COUNT)
|
||||||
{
|
{
|
||||||
simple_faces[simple_count++] = facep;
|
sSimpleFaces[simple_count++] = facep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -4942,7 +4998,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
}
|
}
|
||||||
if (alpha_count < MAX_FACE_COUNT)
|
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)
|
{ //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
|
||||||
if (normspec_count < MAX_FACE_COUNT)
|
if (normspec_count < MAX_FACE_COUNT)
|
||||||
{
|
{
|
||||||
normspec_faces[normspec_count++] = facep;
|
sNormSpecFaces[normspec_count++] = facep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //has normal map (needs texcoord1 and tangent)
|
{ //has normal map (needs texcoord1 and tangent)
|
||||||
if (norm_count < MAX_FACE_COUNT)
|
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
|
{ //has specular map but no normal map, needs texcoord2
|
||||||
if (spec_count < MAX_FACE_COUNT)
|
if (spec_count < MAX_FACE_COUNT)
|
||||||
{
|
{
|
||||||
spec_faces[spec_count++] = facep;
|
sSpecFaces[spec_count++] = facep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //has neither specular map nor normal map, only needs texcoord0
|
{ //has neither specular map nor normal map, only needs texcoord0
|
||||||
if (simple_count < MAX_FACE_COUNT)
|
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
|
{ //needs normal + tangent
|
||||||
if (bump_count < MAX_FACE_COUNT)
|
if (bump_count < MAX_FACE_COUNT)
|
||||||
{
|
{
|
||||||
bump_faces[bump_count++] = facep;
|
sBumpFaces[bump_count++] = facep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (te->getShiny() || !te->getFullbright())
|
else if (te->getShiny() || !te->getFullbright())
|
||||||
{ //needs normal
|
{ //needs normal
|
||||||
if (simple_count < MAX_FACE_COUNT)
|
if (simple_count < MAX_FACE_COUNT)
|
||||||
{
|
{
|
||||||
simple_faces[simple_count++] = facep;
|
sSimpleFaces[simple_count++] = facep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -5012,7 +5068,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
facep->setState(LLFace::FULLBRIGHT);
|
facep->setState(LLFace::FULLBRIGHT);
|
||||||
if (fullbright_count < MAX_FACE_COUNT)
|
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
|
{ //needs normal + tangent
|
||||||
if (bump_count < MAX_FACE_COUNT)
|
if (bump_count < MAX_FACE_COUNT)
|
||||||
{
|
{
|
||||||
bump_faces[bump_count++] = facep;
|
sBumpFaces[bump_count++] = facep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((te->getShiny() && LLPipeline::sRenderBump) ||
|
else if ((te->getShiny() && LLPipeline::sRenderBump) ||
|
||||||
@@ -5030,7 +5086,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
{ //needs normal
|
{ //needs normal
|
||||||
if (simple_count < MAX_FACE_COUNT)
|
if (simple_count < MAX_FACE_COUNT)
|
||||||
{
|
{
|
||||||
simple_faces[simple_count++] = facep;
|
sSimpleFaces[simple_count++] = facep;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -5038,7 +5094,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
facep->setState(LLFace::FULLBRIGHT);
|
facep->setState(LLFace::FULLBRIGHT);
|
||||||
if (fullbright_count < MAX_FACE_COUNT)
|
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)
|
if (type == LLDrawPool::POOL_ALPHA)
|
||||||
{
|
{
|
||||||
cur_type = &alpha_faces;
|
cur_type = &sAlphaFaces;
|
||||||
cur_count = &alpha_count;
|
cur_count = &alpha_count;
|
||||||
|
|
||||||
if (te->getColor().mV[3] > 0.f)
|
if (te->getColor().mV[3] > 0.f)
|
||||||
@@ -5066,30 +5122,30 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
{
|
{
|
||||||
if (mat->getSpecularID().notNull())
|
if (mat->getSpecularID().notNull())
|
||||||
{ //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
|
{ //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
|
||||||
cur_type = &normspec_faces;
|
cur_type = &sNormSpecFaces;
|
||||||
cur_count = &normspec_count;
|
cur_count = &normspec_count;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //has normal map (needs texcoord1 and tangent)
|
{ //has normal map (needs texcoord1 and tangent)
|
||||||
cur_type = &norm_faces;
|
cur_type = &sNormFaces;
|
||||||
cur_count = &norm_count;
|
cur_count = &norm_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mat->getSpecularID().notNull())
|
else if (mat->getSpecularID().notNull())
|
||||||
{ //has specular map but no normal map, needs texcoord2
|
{ //has specular map but no normal map, needs texcoord2
|
||||||
cur_type = &spec_faces;
|
cur_type = &sSpecFaces;
|
||||||
cur_count = &spec_count;
|
cur_count = &spec_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(type == LLDrawPool::POOL_ALPHA_MASK)
|
else if(type == LLDrawPool::POOL_ALPHA_MASK)
|
||||||
{
|
{
|
||||||
cur_type = &simple_faces;
|
cur_type = &sSimpleFaces;
|
||||||
cur_count = &simple_count;
|
cur_count = &simple_count;
|
||||||
}
|
}
|
||||||
else if(type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK)
|
else if(type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK)
|
||||||
{
|
{
|
||||||
cur_type = &fullbright_faces;
|
cur_type = &sFullbrightFaces;
|
||||||
cur_count = &fullbright_count;
|
cur_count = &fullbright_count;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -5103,30 +5159,30 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
{ //needs normal + tangent
|
{ //needs normal + tangent
|
||||||
if(te->getBumpmap() > 0 && te->getBumpmap() < 18)
|
if(te->getBumpmap() > 0 && te->getBumpmap() < 18)
|
||||||
{
|
{
|
||||||
cur_type = &bump_faces;
|
cur_type = &sBumpFaces;
|
||||||
cur_count = &bump_count;
|
cur_count = &bump_count;
|
||||||
}
|
}
|
||||||
else if(te->getShiny())
|
else if(te->getShiny())
|
||||||
{
|
{
|
||||||
cur_type = &simple_faces;
|
cur_type = &sSimpleFaces;
|
||||||
cur_count = &simple_count;
|
cur_count = &simple_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (type == LLDrawPool::POOL_SIMPLE)
|
else if (type == LLDrawPool::POOL_SIMPLE)
|
||||||
{ //needs normal + tangent
|
{ //needs normal + tangent
|
||||||
cur_type = &simple_faces;
|
cur_type = &sSimpleFaces;
|
||||||
cur_count = &simple_count;
|
cur_count = &simple_count;
|
||||||
}
|
}
|
||||||
else if (type == LLDrawPool::POOL_FULLBRIGHT)
|
else if (type == LLDrawPool::POOL_FULLBRIGHT)
|
||||||
{ //doesn't need normal...
|
{ //doesn't need normal...
|
||||||
if(LLPipeline::sRenderBump && te->getShiny()) //unless it's shiny..
|
if(LLPipeline::sRenderBump && te->getShiny()) //unless it's shiny..
|
||||||
{
|
{
|
||||||
cur_type = &simple_faces;
|
cur_type = &sSimpleFaces;
|
||||||
cur_count = &simple_count;
|
cur_count = &simple_count;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cur_type = &fullbright_faces;
|
cur_type = &sFullbrightFaces;
|
||||||
cur_count = &fullbright_count;
|
cur_count = &fullbright_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5140,23 +5196,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
{
|
{
|
||||||
if (mat->getSpecularID().notNull())
|
if (mat->getSpecularID().notNull())
|
||||||
{ //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
|
{ //has normal and specular maps (needs texcoord1, texcoord2, and tangent)
|
||||||
cur_type = &normspec_faces;
|
cur_type = &sNormSpecFaces;
|
||||||
cur_count = &normspec_count;
|
cur_count = &normspec_count;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //has normal map (needs texcoord1 and tangent)
|
{ //has normal map (needs texcoord1 and tangent)
|
||||||
cur_type = &norm_faces;
|
cur_type = &sNormFaces;
|
||||||
cur_count = &norm_count;
|
cur_count = &norm_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mat->getSpecularID().notNull())
|
else if (mat->getSpecularID().notNull())
|
||||||
{ //has specular map but no normal map, needs texcoord2
|
{ //has specular map but no normal map, needs texcoord2
|
||||||
cur_type = &spec_faces;
|
cur_type = &sSpecFaces;
|
||||||
cur_count = &spec_count;
|
cur_count = &spec_count;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ //has neither specular map nor normal map, only needs texcoord0
|
{ //has neither specular map nor normal map, only needs texcoord0
|
||||||
cur_type = &simple_faces;
|
cur_type = &sSimpleFaces;
|
||||||
cur_count = &simple_count;
|
cur_count = &simple_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5218,13 +5274,13 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
|
|||||||
if(emissive)
|
if(emissive)
|
||||||
additional_flags |= LLVertexBuffer::MAP_EMISSIVE;
|
additional_flags |= LLVertexBuffer::MAP_EMISSIVE;
|
||||||
|
|
||||||
genDrawInfo(group, simple_mask | additional_flags, simple_faces, simple_count, FALSE, batch_textures);
|
genDrawInfo(group, simple_mask | additional_flags, sSimpleFaces, simple_count, FALSE, batch_textures);
|
||||||
genDrawInfo(group, fullbright_mask | additional_flags, fullbright_faces, fullbright_count, FALSE, batch_textures);
|
genDrawInfo(group, fullbright_mask | additional_flags, sFullbrightFaces, fullbright_count, FALSE, batch_textures);
|
||||||
genDrawInfo(group, alpha_mask | additional_flags, alpha_faces, alpha_count, TRUE, batch_textures);
|
genDrawInfo(group, alpha_mask | additional_flags, sAlphaFaces, alpha_count, TRUE, batch_textures);
|
||||||
genDrawInfo(group, bump_mask | additional_flags, bump_faces, bump_count, FALSE);
|
genDrawInfo(group, bump_mask | additional_flags, sBumpFaces, bump_count, FALSE);
|
||||||
genDrawInfo(group, norm_mask | additional_flags, norm_faces, norm_count, FALSE);
|
genDrawInfo(group, norm_mask | additional_flags, sNormFaces, norm_count, FALSE);
|
||||||
genDrawInfo(group, spec_mask | additional_flags, spec_faces, spec_count, FALSE);
|
genDrawInfo(group, spec_mask | additional_flags, sSpecFaces, spec_count, FALSE);
|
||||||
genDrawInfo(group, normspec_mask | additional_flags, normspec_faces, normspec_count, FALSE);
|
genDrawInfo(group, normspec_mask | additional_flags, sNormSpecFaces, normspec_count, FALSE);
|
||||||
|
|
||||||
if (!LLPipeline::sDelayVBUpdate)
|
if (!LLPipeline::sDelayVBUpdate)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2830,7 +2830,7 @@ void LLPipeline::updateGeom(F32 max_dtime)
|
|||||||
|
|
||||||
S32 count = 0;
|
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;
|
LLSpatialGroup* last_group = NULL;
|
||||||
LLSpatialBridge* last_bridge = NULL;
|
LLSpatialBridge* last_bridge = NULL;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user