Merge branch 'master' of https://github.com/singularity-viewer/SingularityViewer
# Conflicts: # indra/newview/llvoavatar.cpp Also Reverted reversion of removal of before() wrapper in llstl.h
This commit is contained in:
@@ -2658,11 +2658,11 @@
|
||||
<key>archive</key>
|
||||
<map>
|
||||
<key>hash</key>
|
||||
<string>b41376a689fb4c9e9846d838283fdc5d</string>
|
||||
<string>7a619778a2ea5c3113549529dd4f7288</string>
|
||||
<key>hash_algorithm</key>
|
||||
<string>md5</string>
|
||||
<key>url</key>
|
||||
<string>http://depot.alchemyviewer.org/pub/windows/lib-vc14/xmlrpc_epi-0.54.2-windows-201601151034.tar.bz2</string>
|
||||
<string>http://depot.alchemyviewer.org/pub/windows/lib-vc14/xmlrpc_epi-0.54.2-windows-201603261505.tar.bz2</string>
|
||||
</map>
|
||||
<key>name</key>
|
||||
<string>windows</string>
|
||||
|
||||
@@ -14,6 +14,9 @@ set(ROOT_PROJECT_NAME "Singularity" CACHE STRING
|
||||
"The root project/makefile/solution name. Defaults to Singularity.")
|
||||
project(${ROOT_PROJECT_NAME})
|
||||
|
||||
string(REPLACE " " "" VIEWER_CHANNEL_NOSPACE ${VIEWER_CHANNEL})
|
||||
set(VIEWER_CHANNEL_NOSPACE ${VIEWER_CHANNEL_NOSPACE} CACHE STRING "Prefix used for resulting artifacts.")
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
|
||||
include(Variables)
|
||||
|
||||
@@ -36,6 +36,9 @@ else (STANDALONE)
|
||||
set(Boost_THREAD_LIBRARY
|
||||
optimized libboost_thread-mt
|
||||
debug libboost_thread-mt-gd)
|
||||
set(Boost_CHRONO_LIBRARY
|
||||
optimized libboost_chrono-mt
|
||||
debug libboost_chrono-mt-gd)
|
||||
elseif (LINUX)
|
||||
set(Boost_CONTEXT_LIBRARY
|
||||
optimized boost_context-mt
|
||||
@@ -58,6 +61,9 @@ else (STANDALONE)
|
||||
set(Boost_THREAD_LIBRARY
|
||||
optimized boost_thread-mt
|
||||
debug boost_thread-mt-d)
|
||||
set(Boost_CHRONO_LIBRARY
|
||||
optimized libboost_chrono-mt
|
||||
debug libboost_chrono-mt-d)
|
||||
elseif (DARWIN)
|
||||
set(Boost_CONTEXT_LIBRARY
|
||||
optimized boost_context-mt
|
||||
@@ -80,5 +86,8 @@ else (STANDALONE)
|
||||
set(Boost_THREAD_LIBRARY
|
||||
optimized boost_thread-mt
|
||||
debug boost_thread-mt-d)
|
||||
set(Boost_CHRONO_LIBRARY
|
||||
optimized libboost_chrono-mt
|
||||
debug libboost_chrono-mt-d)
|
||||
endif (WINDOWS)
|
||||
endif (STANDALONE)
|
||||
|
||||
@@ -172,6 +172,7 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
set(CMAKE_OSX_ARCHITECTURES i386)
|
||||
set(ARCH i386)
|
||||
set(WORD_SIZE 32)
|
||||
set(AUTOBUILD_PLATFORM_NAME "darwin")
|
||||
|
||||
set(LL_ARCH ${ARCH}_darwin)
|
||||
set(LL_ARCH_DIR universal-darwin)
|
||||
|
||||
@@ -489,25 +489,6 @@ void LLAvatarAppearance::computeBodySize()
|
||||
mAvatarOffset.mV[VX] = 0.0f;
|
||||
mAvatarOffset.mV[VY] = 0.0f;
|
||||
|
||||
// Certain configurations of avatars can force the overall height (with offset) to go negative.
|
||||
// Enforce a constraint to make sure we don't go below 0.1 meters.
|
||||
// Camera positioning and other things start to break down when your avatar is "walking" while being fully underground
|
||||
if (new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] < 0.1f)
|
||||
{
|
||||
mAvatarOffset.mV[VZ] = -(new_body_size.mV[VZ] - 0.11f); // avoid floating point rounding making the above check continue to fail.
|
||||
|
||||
llassert(new_body_size.mV[VZ] + mAvatarOffset.mV[VZ] >= 0.1f);
|
||||
|
||||
if (mWearableData && isSelf())
|
||||
{
|
||||
LLWearable* shape = mWearableData->getWearable(LLWearableType::WT_SHAPE, 0);
|
||||
if (shape)
|
||||
{
|
||||
shape->setVisualParamWeight(AVATAR_HOVER, mAvatarOffset.mV[VZ], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (new_body_size != mBodySize || old_offset != mAvatarOffset)
|
||||
{
|
||||
mBodySize = new_body_size;
|
||||
@@ -595,8 +576,6 @@ BOOL LLAvatarAppearance::setupBone(const LLAvatarBoneInfo* info, LLJoint* parent
|
||||
info->mRot.mV[VZ], LLQuaternion::XYZ));
|
||||
joint->setScale(info->mScale);
|
||||
|
||||
joint->setDefaultFromCurrentXform();
|
||||
|
||||
if (info->mIsJoint)
|
||||
{
|
||||
joint->setSkinOffset( info->mPivot );
|
||||
@@ -696,6 +675,42 @@ void LLAvatarAppearance::clearSkeleton()
|
||||
mSkeleton.clear();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// addPelvisFixup
|
||||
//------------------------------------------------------------------------
|
||||
void LLAvatarAppearance::addPelvisFixup( F32 fixup, const LLUUID& mesh_id )
|
||||
{
|
||||
LLVector3 pos(0.0,0.0,fixup);
|
||||
mPelvisFixups.add(mesh_id,pos);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// addPelvisFixup
|
||||
//------------------------------------------------------------------------
|
||||
void LLAvatarAppearance::removePelvisFixup( const LLUUID& mesh_id )
|
||||
{
|
||||
mPelvisFixups.remove(mesh_id);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// hasPelvisFixup
|
||||
//------------------------------------------------------------------------
|
||||
bool LLAvatarAppearance::hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const
|
||||
{
|
||||
LLVector3 pos;
|
||||
if (mPelvisFixups.findActiveOverride(mesh_id,pos))
|
||||
{
|
||||
fixup = pos[2];
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool LLAvatarAppearance::hasPelvisFixup( F32& fixup ) const
|
||||
{
|
||||
LLUUID mesh_id;
|
||||
return hasPelvisFixup( fixup, mesh_id );
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLAvatarAppearance::buildCharacter()
|
||||
// Deferred initialization and rebuild of the avatar.
|
||||
|
||||
@@ -159,11 +159,17 @@ protected:
|
||||
BOOL mIsBuilt; // state of deferred character building
|
||||
typedef std::vector<LLAvatarJoint*> avatar_joint_list_t;
|
||||
avatar_joint_list_t mSkeleton;
|
||||
|
||||
LLPosOverrideMap mPelvisFixups;
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// Pelvis height adjustment members.
|
||||
//--------------------------------------------------------------------
|
||||
public:
|
||||
void addPelvisFixup( F32 fixup, const LLUUID& mesh_id );
|
||||
void removePelvisFixup( const LLUUID& mesh_id );
|
||||
bool hasPelvisFixup( F32& fixup, LLUUID& mesh_id ) const;
|
||||
bool hasPelvisFixup( F32& fixup ) const;
|
||||
|
||||
LLVector3 mBodySize;
|
||||
LLVector3 mAvatarOffset;
|
||||
protected:
|
||||
|
||||
@@ -212,6 +212,7 @@ LLAvatarAppearanceDictionary::BakedEntry::BakedEntry(ETextureIndex tex_index,
|
||||
LLWearableType::EType t = (LLWearableType::EType)va_arg(argp,int);
|
||||
mWearables.push_back(t);
|
||||
}
|
||||
va_end(argp);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -85,8 +85,6 @@ LLSkinJoint::~LLSkinJoint()
|
||||
//-----------------------------------------------------------------------------
|
||||
void LLSkinJoint::setupSkinJoint( LLJoint *joint)
|
||||
{
|
||||
mRootToJointSkinOffset.clearVec();
|
||||
mRootToParentJointSkinOffset.clearVec();
|
||||
|
||||
// find the named joint
|
||||
if (!(mJoint = joint))
|
||||
@@ -96,6 +94,9 @@ void LLSkinJoint::setupSkinJoint( LLJoint *joint)
|
||||
}
|
||||
|
||||
// compute the inverse root skin matrix
|
||||
mRootToJointSkinOffset.clearVec();
|
||||
mRootToParentJointSkinOffset.clearVec();
|
||||
|
||||
do
|
||||
{
|
||||
mRootToJointSkinOffset -= joint->getSkinOffset();
|
||||
|
||||
@@ -680,8 +680,8 @@ BOOL LLPolyMorphTarget::setInfo(LLPolyMorphTargetInfo* info)
|
||||
if (!mMorphData)
|
||||
{
|
||||
const std::string driven_tag = "_Driven";
|
||||
U32 pos = morph_param_name.find(driven_tag);
|
||||
if (pos > 0)
|
||||
size_t pos = morph_param_name.find(driven_tag);
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
morph_param_name = morph_param_name.substr(0,pos);
|
||||
mMorphData = mMesh->getMorphData(morph_param_name);
|
||||
|
||||
@@ -1557,13 +1557,13 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
|
||||
}
|
||||
|
||||
U32 cache_index = alpha_mask_crc.getCRC();
|
||||
U8* alpha_data = NULL;//get_if_there(mAlphaCache,cache_index,(U8*)NULL);
|
||||
U8* alpha_data = NULL;
|
||||
// We believe we need to generate morph masks, do not assume that the cached version is accurate.
|
||||
// We can get bad morph masks during login, on minimize, and occasional gl errors.
|
||||
// We should only be doing this when we believe something has changed with respect to the user's appearance.
|
||||
//if (!alpha_data)
|
||||
{
|
||||
// clear out a slot if we have filled our cache
|
||||
LL_DEBUGS("Avatar") << "gl alpha cache of morph mask not found, doing readback: " << getName() << LL_ENDL;
|
||||
// clear out a slot if we have filled our cache
|
||||
S32 max_cache_entries = getTexLayerSet()->getAvatarAppearance()->isSelf() ? 4 : 1;
|
||||
while ((S32)mAlphaCache.size() >= max_cache_entries)
|
||||
{
|
||||
@@ -1573,8 +1573,12 @@ void LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
|
||||
mAlphaCache.erase(iter2);
|
||||
}
|
||||
alpha_data = new U8[width * height];
|
||||
U8* pixels_tmp = new U8[width * height * 4];
|
||||
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels_tmp);
|
||||
for (int i = 0; i < width * height; ++i)
|
||||
alpha_data[i] = pixels_tmp[i * 4 + 3];
|
||||
delete[] pixels_tmp;
|
||||
mAlphaCache[cache_index] = alpha_data;
|
||||
glReadPixels(x, y, width, height, GL_ALPHA, GL_UNSIGNED_BYTE, alpha_data);
|
||||
}
|
||||
|
||||
getTexLayerSet()->getAvatarAppearance()->dirtyMesh();
|
||||
@@ -1783,13 +1787,11 @@ LLTexLayer* LLTexLayerTemplate::getLayer(U32 i) const
|
||||
/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
|
||||
{
|
||||
U32 num_wearables = updateWearableCache();
|
||||
for (U32 i = 0; i < num_wearables; i++)
|
||||
U32 i = num_wearables - 1; // For rendering morph masks, we only want to use the top wearable
|
||||
LLTexLayer *layer = getLayer(i);
|
||||
if (layer)
|
||||
{
|
||||
LLTexLayer *layer = getLayer(i);
|
||||
if (layer)
|
||||
{
|
||||
layer->addAlphaMask(data, originX, originY, width, height);
|
||||
}
|
||||
layer->addAlphaMask(data, originX, originY, width, height);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -178,8 +178,9 @@ bool LLWearableData::swapWearables(const LLWearableType::EType type, U32 index_a
|
||||
}
|
||||
|
||||
wearableentry_vec_t& wearable_vec = wearable_iter->second;
|
||||
if (0 > index_a || index_a >= wearable_vec.size()) return false;
|
||||
if (0 > index_b || index_b >= wearable_vec.size()) return false;
|
||||
// removed 0 > index_a and index_b comparisions - can never be true
|
||||
if (index_a >= wearable_vec.size()) return false;
|
||||
if (index_b >= wearable_vec.size()) return false;
|
||||
|
||||
LLWearable* wearable = wearable_vec[index_a];
|
||||
wearable_vec[index_a] = wearable_vec[index_b];
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
|
||||
#include "llaudiodecodemgr.h"
|
||||
|
||||
#include "llvorbisdecode.h"
|
||||
#include "llaudioengine.h"
|
||||
#include "lllfsthread.h"
|
||||
#include "llvfile.h"
|
||||
@@ -43,10 +42,12 @@
|
||||
#include "llassetstorage.h"
|
||||
#include "llrefcount.h"
|
||||
|
||||
#include "llvorbisencode.h"
|
||||
|
||||
#include "vorbis/codec.h"
|
||||
#include "vorbis/vorbisfile.h"
|
||||
#include "llvorbisencode.h"
|
||||
#include <iterator> //VS2010
|
||||
#include <iterator>
|
||||
#include <deque>
|
||||
|
||||
extern LLAudioEngine *gAudiop;
|
||||
|
||||
@@ -120,7 +121,7 @@ size_t vfs_read(void *ptr, size_t size, size_t nmemb, void *datasource)
|
||||
}
|
||||
}
|
||||
|
||||
int vfs_seek(void *datasource, ogg_int64_t offset, int whence)
|
||||
S32 vfs_seek(void *datasource, ogg_int64_t offset, S32 whence)
|
||||
{
|
||||
LLVFile *file = (LLVFile *)datasource;
|
||||
|
||||
@@ -142,7 +143,7 @@ int vfs_seek(void *datasource, ogg_int64_t offset, int whence)
|
||||
origin = -1;
|
||||
break;
|
||||
default:
|
||||
LL_ERRS() << "Invalid whence argument to vfs_seek" << LL_ENDL;
|
||||
LL_ERRS("AudioEngine") << "Invalid whence argument to vfs_seek" << LL_ENDL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -156,7 +157,7 @@ int vfs_seek(void *datasource, ogg_int64_t offset, int whence)
|
||||
}
|
||||
}
|
||||
|
||||
int vfs_close (void *datasource)
|
||||
S32 vfs_close (void *datasource)
|
||||
{
|
||||
LLVFile *file = (LLVFile *)datasource;
|
||||
delete file;
|
||||
@@ -196,25 +197,25 @@ BOOL LLVorbisDecodeState::initDecode()
|
||||
vfs_callbacks.close_func = vfs_close;
|
||||
vfs_callbacks.tell_func = vfs_tell;
|
||||
|
||||
//LL_INFOS() << "Initing decode from vfile: " << mUUID << LL_ENDL;
|
||||
LL_DEBUGS("AudioEngine") << "Initing decode from vfile: " << mUUID << LL_ENDL;
|
||||
|
||||
mInFilep = new LLVFile(gVFS, mUUID, LLAssetType::AT_SOUND);
|
||||
if (!mInFilep || !mInFilep->getSize())
|
||||
{
|
||||
LL_WARNS() << "unable to open vorbis source vfile for reading" << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "unable to open vorbis source vfile for reading" << LL_ENDL;
|
||||
delete mInFilep;
|
||||
mInFilep = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int r = ov_open_callbacks(mInFilep, &mVF, NULL, 0, vfs_callbacks);
|
||||
S32 r = ov_open_callbacks(mInFilep, &mVF, NULL, 0, vfs_callbacks);
|
||||
if(r < 0)
|
||||
{
|
||||
LL_WARNS() << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << mUUID << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << r << " Input to vorbis decode does not appear to be an Ogg bitstream: " << mUUID << LL_ENDL;
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
S32 sample_count = ov_pcm_total(&mVF, -1);
|
||||
S32 sample_count = (S32)ov_pcm_total(&mVF, -1);
|
||||
size_t size_guess = (size_t)sample_count;
|
||||
vorbis_info* vi = ov_info(&mVF, -1);
|
||||
size_guess *= (vi? vi->channels : 1);
|
||||
@@ -228,13 +229,13 @@ BOOL LLVorbisDecodeState::initDecode()
|
||||
if( vi->channels < 1 || vi->channels > LLVORBIS_CLIP_MAX_CHANNELS )
|
||||
{
|
||||
abort_decode = true;
|
||||
LL_WARNS() << "Bad channel count: " << vi->channels << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "Bad channel count: " << vi->channels << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else // !vi
|
||||
{
|
||||
abort_decode = true;
|
||||
LL_WARNS() << "No default bitstream found" << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "No default bitstream found" << LL_ENDL;
|
||||
}
|
||||
// <edit>
|
||||
// This magic value is equivalent to 150MiB of data.
|
||||
@@ -252,25 +253,25 @@ BOOL LLVorbisDecodeState::initDecode()
|
||||
(size_t)sample_count <= 0)
|
||||
{
|
||||
abort_decode = true;
|
||||
LL_WARNS() << "Illegal sample count: " << sample_count << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "Illegal sample count: " << sample_count << LL_ENDL;
|
||||
}
|
||||
|
||||
if( size_guess > LLVORBIS_CLIP_REJECT_SIZE ||
|
||||
size_guess < 0)
|
||||
{
|
||||
abort_decode = true;
|
||||
LL_WARNS() << "Illegal sample size: " << size_guess << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "Illegal sample size: " << size_guess << LL_ENDL;
|
||||
}
|
||||
// <edit>
|
||||
}
|
||||
// </edit>
|
||||
if( abort_decode )
|
||||
{
|
||||
LL_WARNS() << "Canceling initDecode. Bad asset: " << mUUID << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "Canceling initDecode. Bad asset: " << mUUID << LL_ENDL;
|
||||
vorbis_comment* comment = ov_comment(&mVF,-1);
|
||||
if (comment && comment->vendor)
|
||||
{
|
||||
LL_WARNS() << "Bad asset encoded by: " << comment->vendor << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "Bad asset encoded by: " << comment->vendor << LL_ENDL;
|
||||
}
|
||||
delete mInFilep;
|
||||
mInFilep = NULL;
|
||||
@@ -388,7 +389,7 @@ BOOL LLVorbisDecodeState::decodeSection()
|
||||
{
|
||||
if (!mInFilep)
|
||||
{
|
||||
LL_WARNS() << "No VFS file to decode in vorbis!" << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "No VFS file to decode in vorbis!" << LL_ENDL;
|
||||
return TRUE;
|
||||
}
|
||||
if (mDone)
|
||||
@@ -413,7 +414,7 @@ BOOL LLVorbisDecodeState::decodeSection()
|
||||
/* error in the stream. Not a problem, just reporting it in
|
||||
case we (the app) cares. In this case, we don't. */
|
||||
|
||||
LL_WARNS() << "BAD vorbis decode in decodeSection." << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "BAD vorbis decode in decodeSection." << LL_ENDL;
|
||||
|
||||
mValid = FALSE;
|
||||
mDone = TRUE;
|
||||
@@ -434,7 +435,7 @@ BOOL LLVorbisDecodeState::finishDecode()
|
||||
{
|
||||
if (!isValid())
|
||||
{
|
||||
LL_WARNS() << "Bogus vorbis decode state for " << getUUID() << ", aborting!" << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "Bogus vorbis decode state for " << getUUID() << ", aborting!" << LL_ENDL;
|
||||
return TRUE; // We've finished
|
||||
}
|
||||
|
||||
@@ -515,7 +516,7 @@ BOOL LLVorbisDecodeState::finishDecode()
|
||||
|
||||
if (36 == data_length)
|
||||
{
|
||||
LL_WARNS() << "BAD Vorbis decode in finishDecode!" << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "BAD Vorbis decode in finishDecode!" << LL_ENDL;
|
||||
mValid = FALSE;
|
||||
return TRUE; // we've finished
|
||||
}
|
||||
@@ -532,7 +533,7 @@ BOOL LLVorbisDecodeState::finishDecode()
|
||||
{
|
||||
if (mBytesRead == 0)
|
||||
{
|
||||
LL_WARNS() << "Unable to write file in LLVorbisDecodeState::finishDecode" << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "Unable to write file in LLVorbisDecodeState::finishDecode" << LL_ENDL;
|
||||
mValid = FALSE;
|
||||
return TRUE; // we've finished
|
||||
}
|
||||
@@ -550,7 +551,7 @@ BOOL LLVorbisDecodeState::finishDecode()
|
||||
LLVFile output(gVFS, mUUID, LLAssetType::AT_SOUND_WAV);
|
||||
output.write(&mWAVBuffer[0], mWAVBuffer.size());
|
||||
#endif
|
||||
//LL_INFOS() << "Finished decode for " << getUUID() << LL_ENDL;
|
||||
LL_DEBUGS("AudioEngine") << "Finished decode for " << getUUID() << LL_ENDL;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -559,7 +560,7 @@ void LLVorbisDecodeState::flushBadFile()
|
||||
{
|
||||
if (mInFilep)
|
||||
{
|
||||
LL_WARNS() << "Flushing bad vorbis file from VFS for " << mUUID << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "Flushing bad vorbis file from VFS for " << mUUID << LL_ENDL;
|
||||
mInFilep->remove();
|
||||
}
|
||||
}
|
||||
@@ -576,7 +577,7 @@ public:
|
||||
void processQueue(const F32 num_secs = 0.005);
|
||||
|
||||
protected:
|
||||
LLLinkedQueue<LLUUID> mDecodeQueue;
|
||||
std::deque<LLUUID> mDecodeQueue;
|
||||
LLPointer<LLVorbisDecodeState> mCurrentDecodep;
|
||||
};
|
||||
|
||||
@@ -608,12 +609,16 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
|
||||
if (mCurrentDecodep->isDone() && !mCurrentDecodep->isValid())
|
||||
{
|
||||
// We had an error when decoding, abort.
|
||||
LL_WARNS() << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << mCurrentDecodep->getUUID() << " has invalid vorbis data, aborting decode" << LL_ENDL;
|
||||
mCurrentDecodep->flushBadFile();
|
||||
LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
|
||||
if(adp)
|
||||
|
||||
if (gAudiop)
|
||||
{
|
||||
adp->setLoadState(LLAudioData::STATE_LOAD_ERROR);
|
||||
LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
|
||||
if(adp)
|
||||
{
|
||||
adp->setLoadState(LLAudioData::STATE_LOAD_ERROR);
|
||||
}
|
||||
}
|
||||
mCurrentDecodep = NULL;
|
||||
done = TRUE;
|
||||
@@ -626,13 +631,13 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
|
||||
}
|
||||
else if (mCurrentDecodep)
|
||||
{
|
||||
if (mCurrentDecodep->finishDecode())
|
||||
if (gAudiop && mCurrentDecodep->finishDecode())
|
||||
{
|
||||
// We finished!
|
||||
LLAudioData *adp = gAudiop->getAudioData(mCurrentDecodep->getUUID());
|
||||
if (!adp)
|
||||
{
|
||||
LL_WARNS() << "Missing LLAudioData for decode of " << mCurrentDecodep->getUUID() << LL_ENDL;
|
||||
LL_WARNS("AudioEngine") << "Missing LLAudioData for decode of " << mCurrentDecodep->getUUID() << LL_ENDL;
|
||||
}
|
||||
else if (mCurrentDecodep->isValid() && mCurrentDecodep->isDone())
|
||||
{
|
||||
@@ -645,7 +650,7 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
|
||||
else
|
||||
{
|
||||
adp->setLoadState(LLAudioData::STATE_LOAD_ERROR);
|
||||
LL_INFOS() << "Vorbis decode failed for " << mCurrentDecodep->getUUID() << LL_ENDL;
|
||||
LL_INFOS("AudioEngine") << "Vorbis decode failed for " << mCurrentDecodep->getUUID() << LL_ENDL;
|
||||
}
|
||||
mCurrentDecodep = NULL;
|
||||
}
|
||||
@@ -655,7 +660,7 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
|
||||
|
||||
if (!done)
|
||||
{
|
||||
if (!mDecodeQueue.getLength())
|
||||
if (mDecodeQueue.empty())
|
||||
{
|
||||
// Nothing else on the queue.
|
||||
done = TRUE;
|
||||
@@ -663,8 +668,9 @@ void LLAudioDecodeMgr::Impl::processQueue(const F32 num_secs)
|
||||
else
|
||||
{
|
||||
LLUUID uuid;
|
||||
mDecodeQueue.pop(uuid);
|
||||
if (gAudiop->hasDecodedFile(uuid))
|
||||
uuid = mDecodeQueue.front();
|
||||
mDecodeQueue.pop_front();
|
||||
if (!gAudiop || gAudiop->hasDecodedFile(uuid))
|
||||
{
|
||||
// This file has already been decoded, don't decode it again.
|
||||
continue;
|
||||
@@ -715,11 +721,26 @@ void LLAudioDecodeMgr::processQueue(const F32 num_secs)
|
||||
|
||||
bool LLAudioDecodeMgr::addDecodeRequest(const LLUUID &uuid)
|
||||
{
|
||||
if(!uuid.notNull())
|
||||
return false;
|
||||
else if (!gAssetStorage || !gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
|
||||
return false;
|
||||
|
||||
mImpl->mDecodeQueue.push(uuid);
|
||||
return true;
|
||||
if(uuid.isNull())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (gAudiop && gAudiop->hasDecodedFile(uuid))
|
||||
{
|
||||
// Already have a decoded version, don't need to decode it.
|
||||
LL_DEBUGS("AudioEngine") << "addDecodeRequest for " << uuid << " has decoded file already" << LL_ENDL;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (gAssetStorage && gAssetStorage->hasLocalAsset(uuid, LLAssetType::AT_SOUND))
|
||||
{
|
||||
// Just put it on the decode queue.
|
||||
LL_DEBUGS("AudioEngine") << "addDecodeRequest for " << uuid << " has local asset file already" << LL_ENDL;
|
||||
mImpl->mDecodeQueue.push_back(uuid);
|
||||
return true;
|
||||
}
|
||||
|
||||
LL_DEBUGS("AudioEngine") << "addDecodeRequest for " << uuid << " no file available" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "stdtypes.h"
|
||||
|
||||
#include "lllinkedqueue.h"
|
||||
#include "lluuid.h"
|
||||
|
||||
#include "llassettype.h"
|
||||
|
||||
@@ -1046,8 +1046,12 @@ void LLAudioEngine::cleanupAudioSource(LLAudioSource *asp)
|
||||
LL_WARNS("AudioEngine") << "Cleaning up unknown audio source!" << LL_ENDL;
|
||||
return;
|
||||
}
|
||||
delete asp;
|
||||
mAllSources.erase(iter);
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("AudioEngine") << "Cleaning up audio sources for "<< asp->getID() <<LL_ENDL;
|
||||
delete asp;
|
||||
mAllSources.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
#include "fmod.hpp"
|
||||
#include "fmod_errors.h"
|
||||
#include "lldir.h"
|
||||
#include "llapr.h"
|
||||
|
||||
#include "sound_ids.h"
|
||||
|
||||
@@ -234,16 +233,16 @@ public:
|
||||
} gSoundCheck;
|
||||
|
||||
LLAudioEngine_FMODSTUDIO::LLAudioEngine_FMODSTUDIO(bool enable_profiler, bool verbose_debugging)
|
||||
: mInited(false)
|
||||
, mWindGen(NULL)
|
||||
, mWindDSPDesc(NULL)
|
||||
, mWindDSP(NULL)
|
||||
, mSystem(NULL)
|
||||
, mEnableProfiler(enable_profiler)
|
||||
{
|
||||
sVerboseDebugging = verbose_debugging;
|
||||
mInited = false;
|
||||
mWindGen = NULL;
|
||||
mWindDSP = NULL;
|
||||
mSystem = NULL;
|
||||
mEnableProfiler = enable_profiler;
|
||||
}
|
||||
|
||||
|
||||
LLAudioEngine_FMODSTUDIO::~LLAudioEngine_FMODSTUDIO()
|
||||
{
|
||||
}
|
||||
@@ -502,13 +501,13 @@ bool LLAudioEngine_FMODSTUDIO::initWind()
|
||||
|
||||
cleanupWind();
|
||||
|
||||
FMOD_DSP_DESCRIPTION dspdesc;
|
||||
memset(&dspdesc, 0, sizeof(FMOD_DSP_DESCRIPTION)); //Set everything to zero
|
||||
dspdesc.pluginsdkversion = FMOD_PLUGIN_SDK_VERSION;
|
||||
strncpy(dspdesc.name,"Wind Unit", sizeof(dspdesc.name)); //Set name to "Wind Unit"
|
||||
dspdesc.numoutputbuffers = 1;
|
||||
dspdesc.read = &windDSPCallback; //Assign callback.
|
||||
if (Check_FMOD_Error(mSystem->createDSP(&dspdesc, &mWindDSP), "FMOD::createDSP") || !mWindDSP)
|
||||
mWindDSPDesc = new FMOD_DSP_DESCRIPTION();
|
||||
memset(mWindDSPDesc, 0, sizeof(*mWindDSPDesc)); //Set everything to zero
|
||||
mWindDSPDesc->pluginsdkversion = FMOD_PLUGIN_SDK_VERSION;
|
||||
strncpy(mWindDSPDesc->name, "Wind Unit", sizeof(mWindDSPDesc->name)); //Set name to "Wind Unit"
|
||||
mWindDSPDesc->numoutputbuffers = 1;
|
||||
mWindDSPDesc->read = &windDSPCallback; //Assign callback.
|
||||
if (Check_FMOD_Error(mSystem->createDSP(mWindDSPDesc, &mWindDSP), "FMOD::createDSP") || !mWindDSP)
|
||||
return false;
|
||||
|
||||
int frequency = 44100;
|
||||
@@ -518,9 +517,9 @@ bool LLAudioEngine_FMODSTUDIO::initWind()
|
||||
mWindGen = new LLWindGen<MIXBUFFERFORMAT>((U32)frequency);
|
||||
|
||||
if (!Check_FMOD_Error(mWindDSP->setUserData((void*)mWindGen), "FMOD::DSP::setUserData") &&
|
||||
!Check_FMOD_Error(mSystem->playDSP(mWindDSP, NULL, false, 0), "FMOD::System::playDSP") &&
|
||||
!Check_FMOD_Error(mSystem->getSoftwareFormat(NULL, &mode, NULL), "FMOD::System::getSoftwareFormat") &&
|
||||
!Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat"))
|
||||
!Check_FMOD_Error(mWindDSP->setChannelFormat(FMOD_CHANNELMASK_STEREO, 2, mode), "FMOD::DSP::setChannelFormat") &&
|
||||
!Check_FMOD_Error(mSystem->playDSP(mWindDSP, NULL, false, 0), "FMOD::System::playDSP"))
|
||||
return true; //Success
|
||||
}
|
||||
|
||||
@@ -540,6 +539,9 @@ void LLAudioEngine_FMODSTUDIO::cleanupWind()
|
||||
mWindDSP = NULL;
|
||||
}
|
||||
|
||||
delete mWindDSPDesc;
|
||||
mWindDSPDesc = NULL;
|
||||
|
||||
delete mWindGen;
|
||||
mWindGen = NULL;
|
||||
}
|
||||
@@ -885,7 +887,7 @@ bool LLAudioBufferFMODSTUDIO::loadWAV(const std::string& filename)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!LLAPRFile::isExist(filename, LL_APR_RPB))
|
||||
if (!gDirUtilp->fileExists(filename))
|
||||
{
|
||||
// File not found, abort.
|
||||
return false;
|
||||
|
||||
@@ -48,6 +48,7 @@ namespace FMOD
|
||||
class Sound;
|
||||
class DSP;
|
||||
}
|
||||
typedef struct FMOD_DSP_DESCRIPTION FMOD_DSP_DESCRIPTION;
|
||||
|
||||
//Interfaces
|
||||
class LLAudioEngine_FMODSTUDIO : public LLAudioEngine
|
||||
@@ -81,6 +82,7 @@ protected:
|
||||
|
||||
LLWindGen<MIXBUFFERFORMAT> *mWindGen;
|
||||
|
||||
FMOD_DSP_DESCRIPTION *mWindDSPDesc;
|
||||
FMOD::DSP *mWindDSP;
|
||||
FMOD::System *mSystem;
|
||||
bool mEnableProfiler;
|
||||
|
||||
@@ -28,15 +28,18 @@
|
||||
|
||||
#include "lllistener.h"
|
||||
|
||||
#define DEFAULT_AT 0.0f,0.0f,-1.0f
|
||||
#define DEFAULT_UP 0.0f,1.0f,0.0f
|
||||
const LLVector3 DEFAULT_AT(0.0f, 0.0f, -1.0f);
|
||||
const LLVector3 DEFAULT_UP(0.0f, 1.0f, 0.0f);
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener::LLListener()
|
||||
: mPosition(LLVector3::zero),
|
||||
mListenAt(DEFAULT_AT),
|
||||
mListenUp(DEFAULT_UP),
|
||||
mVelocity(LLVector3::zero)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -44,15 +47,6 @@ LLListener::~LLListener()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::init(void)
|
||||
{
|
||||
mPosition.zeroVec();
|
||||
mListenAt.setVec(DEFAULT_AT);
|
||||
mListenUp.setVec(DEFAULT_UP);
|
||||
mVelocity.zeroVec();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::translate(LLVector3 offset)
|
||||
{
|
||||
@@ -99,9 +93,6 @@ void LLListener::orient(LLVector3 up, LLVector3 at)
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener::set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at)
|
||||
{
|
||||
mPosition = pos;
|
||||
mVelocity = vel;
|
||||
|
||||
setPosition(pos);
|
||||
setVelocity(vel);
|
||||
orient(up,at);
|
||||
|
||||
@@ -45,7 +45,6 @@ class LLListener
|
||||
public:
|
||||
LLListener();
|
||||
virtual ~LLListener();
|
||||
virtual void init();
|
||||
|
||||
virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at);
|
||||
|
||||
|
||||
@@ -39,10 +39,12 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// constructor
|
||||
//-----------------------------------------------------------------------
|
||||
LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system)
|
||||
LLListener_FMODSTUDIO::LLListener_FMODSTUDIO(FMOD::System *system)
|
||||
: LLListener(),
|
||||
mDopplerFactor(1.0f),
|
||||
mRolloffFactor(1.0f)
|
||||
{
|
||||
mSystem = system;
|
||||
init();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -50,21 +52,12 @@ LLListener_FMODSTUDIO::~LLListener_FMODSTUDIO()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::init(void)
|
||||
{
|
||||
// do inherited
|
||||
LLListener::init();
|
||||
mDopplerFactor = 1.0f;
|
||||
mRolloffFactor = 1.0f;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::translate(LLVector3 offset)
|
||||
{
|
||||
LLListener::translate(offset);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -72,7 +65,7 @@ void LLListener_FMODSTUDIO::setPosition(LLVector3 pos)
|
||||
{
|
||||
LLListener::setPosition(pos);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mPosition.mV, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -80,7 +73,7 @@ void LLListener_FMODSTUDIO::setVelocity(LLVector3 vel)
|
||||
{
|
||||
LLListener::setVelocity(vel);
|
||||
|
||||
mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, (FMOD_VECTOR*)mListenAt.mV, (FMOD_VECTOR*)mListenUp.mV);
|
||||
mSystem->set3DListenerAttributes(0, NULL, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------
|
||||
@@ -94,20 +87,25 @@ void LLListener_FMODSTUDIO::orient(LLVector3 up, LLVector3 at)
|
||||
//-----------------------------------------------------------------------
|
||||
void LLListener_FMODSTUDIO::commitDeferredChanges()
|
||||
{
|
||||
if(!mSystem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mSystem->update();
|
||||
}
|
||||
|
||||
|
||||
void LLListener_FMODSTUDIO::setRolloffFactor(F32 factor)
|
||||
{
|
||||
//An internal FMODEx optimization skips 3D updates if there have not been changes to the 3D sound environment.
|
||||
//An internal FMOD Studio optimization skips 3D updates if there have not been changes to the 3D sound environment.
|
||||
//Sadly, a change in rolloff is not accounted for, thus we must touch the listener properties as well.
|
||||
//In short: Changing the position ticks a dirtyflag inside fmodstudio, which makes it not skip 3D processing next update call.
|
||||
//In short: Changing the position ticks a dirtyflag inside fmod studio, which makes it not skip 3D processing next update call.
|
||||
if(mRolloffFactor != factor)
|
||||
{
|
||||
LLVector3 pos = mVelocity - LLVector3(0.f,0.f,.1f);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)pos.mV, NULL, NULL, NULL);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*)mVelocity.mV, NULL, NULL, NULL);
|
||||
LLVector3 tmp_pos = mPosition - LLVector3(0.f,0.f,.1f);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*) tmp_pos.mV, NULL, NULL, NULL);
|
||||
mSystem->set3DListenerAttributes(0, (FMOD_VECTOR*) mPosition.mV, NULL, NULL, NULL);
|
||||
}
|
||||
mRolloffFactor = factor;
|
||||
mSystem->set3DSettings(mDopplerFactor, 1.f, mRolloffFactor);
|
||||
|
||||
@@ -48,7 +48,6 @@ class LLListener_FMODSTUDIO : public LLListener
|
||||
public:
|
||||
LLListener_FMODSTUDIO(FMOD::System *system);
|
||||
virtual ~LLListener_FMODSTUDIO();
|
||||
virtual void init();
|
||||
|
||||
virtual void translate(LLVector3 offset);
|
||||
virtual void setPosition(LLVector3 pos);
|
||||
|
||||
@@ -31,21 +31,15 @@
|
||||
#include "lllistener_openal.h"
|
||||
|
||||
LLListener_OpenAL::LLListener_OpenAL()
|
||||
: LLListener(),
|
||||
mRolloffFactor(1.f)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
LLListener_OpenAL::~LLListener_OpenAL()
|
||||
{
|
||||
}
|
||||
|
||||
void LLListener_OpenAL::init()
|
||||
{
|
||||
// do inherited
|
||||
LLListener::init();
|
||||
mRolloffFactor = 1.0f;
|
||||
}
|
||||
|
||||
void LLListener_OpenAL::translate(LLVector3 offset)
|
||||
{
|
||||
//LL_INFOS() << "LLListener_OpenAL::translate() : " << offset << LL_ENDL;
|
||||
@@ -71,18 +65,20 @@ void LLListener_OpenAL::orient(LLVector3 up, LLVector3 at)
|
||||
|
||||
void LLListener_OpenAL::commitDeferredChanges()
|
||||
{
|
||||
ALfloat orientation[6];
|
||||
orientation[0] = mListenAt.mV[0];
|
||||
orientation[1] = mListenAt.mV[1];
|
||||
orientation[2] = mListenAt.mV[2];
|
||||
orientation[3] = mListenUp.mV[0];
|
||||
orientation[4] = mListenUp.mV[1];
|
||||
orientation[5] = mListenUp.mV[2];
|
||||
ALfloat orientation[] = {
|
||||
mListenAt.mV[0],
|
||||
mListenAt.mV[1],
|
||||
mListenAt.mV[2],
|
||||
mListenUp.mV[0],
|
||||
mListenUp.mV[1],
|
||||
mListenUp.mV[2],
|
||||
};
|
||||
|
||||
ALfloat velocity[3];
|
||||
velocity[0] = mVelocity.mV[0];
|
||||
velocity[1] = mVelocity.mV[1];
|
||||
velocity[2] = mVelocity.mV[2];
|
||||
ALfloat velocity[3] = {
|
||||
mVelocity.mV[0],
|
||||
mVelocity.mV[1],
|
||||
mVelocity.mV[2],
|
||||
};
|
||||
|
||||
alListenerfv(AL_ORIENTATION, orientation);
|
||||
alListenerfv(AL_POSITION, mPosition.mV);
|
||||
|
||||
@@ -38,7 +38,6 @@ class LLListener_OpenAL : public LLListener
|
||||
public:
|
||||
LLListener_OpenAL();
|
||||
virtual ~LLListener_OpenAL();
|
||||
virtual void init();
|
||||
|
||||
virtual void translate(LLVector3 offset);
|
||||
virtual void setPosition(LLVector3 pos);
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "llerror.h"
|
||||
#include "llrand.h"
|
||||
#include "llmath.h"
|
||||
#include "llapr.h"
|
||||
|
||||
//#if LL_DARWIN
|
||||
// MBW -- XXX -- Getting rid of SecondLifeVorbis for now -- no fmod means no name collisions.
|
||||
@@ -81,18 +80,20 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
|
||||
|
||||
error_msg.clear();
|
||||
|
||||
// ********************************
|
||||
LLAPRFile infile ;
|
||||
infile.open(in_fname,LL_APR_RB);
|
||||
// ********************************
|
||||
if (!infile.getFileHandle())
|
||||
//********************************
|
||||
llifstream instream(in_fname, std::ios::in | std::ios::binary);
|
||||
//********************************
|
||||
if (!instream.is_open())
|
||||
{
|
||||
error_msg = "CannotUploadSoundFile";
|
||||
return(LLVORBISENC_SOURCE_OPEN_ERR);
|
||||
}
|
||||
|
||||
infile.read(wav_header, 44);
|
||||
physical_file_size = infile.seek(APR_END,0);
|
||||
instream.read((char*)wav_header, 44);
|
||||
|
||||
instream.seekg(0, instream.end);
|
||||
physical_file_size = (U32) instream.tellg();
|
||||
instream.seekg(0, instream.beg);
|
||||
|
||||
if (strncmp((char *)&(wav_header[0]),"RIFF",4))
|
||||
{
|
||||
@@ -112,8 +113,8 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
|
||||
|
||||
while ((file_pos + 8)< physical_file_size)
|
||||
{
|
||||
infile.seek(APR_SET,file_pos);
|
||||
infile.read(wav_header, 44);
|
||||
instream.seekg(file_pos);
|
||||
instream.read((char*)wav_header, 44);
|
||||
|
||||
chunk_length = ((U32) wav_header[7] << 24)
|
||||
+ ((U32) wav_header[6] << 16)
|
||||
@@ -122,7 +123,7 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
|
||||
|
||||
if (chunk_length > physical_file_size - file_pos - 4)
|
||||
{
|
||||
infile.close();
|
||||
instream.close();
|
||||
error_msg = "SoundFileInvalidChunkSize";
|
||||
return(LLVORBISENC_CHUNK_SIZE_ERR);
|
||||
}
|
||||
@@ -153,9 +154,9 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
|
||||
file_pos += (chunk_length + 8);
|
||||
chunk_length = 0;
|
||||
}
|
||||
// ****************
|
||||
infile.close();
|
||||
// ****************
|
||||
//****************
|
||||
instream.close();
|
||||
//****************
|
||||
|
||||
if (!uncompressed_pcm)
|
||||
{
|
||||
@@ -233,20 +234,18 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname
|
||||
|
||||
S32 data_left = 0;
|
||||
|
||||
LLAPRFile infile ;
|
||||
infile.open(in_fname,LL_APR_RB);
|
||||
if (!infile.getFileHandle())
|
||||
llifstream instream(in_fname, std::ios::in | std::ios::binary);
|
||||
if (!instream.is_open())
|
||||
{
|
||||
LL_WARNS() << "Couldn't open temporary ogg file for writing: " << in_fname
|
||||
LL_WARNS() << "Couldn't open temporary ogg file for reading: " << in_fname
|
||||
<< LL_ENDL;
|
||||
return(LLVORBISENC_SOURCE_OPEN_ERR);
|
||||
}
|
||||
|
||||
LLAPRFile outfile ;
|
||||
outfile.open(out_fname,LL_APR_WPB);
|
||||
if (!outfile.getFileHandle())
|
||||
llofstream outstream(out_fname, std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
if (!outstream.is_open())
|
||||
{
|
||||
LL_WARNS() << "Couldn't open upload sound file for reading: " << in_fname
|
||||
LL_WARNS() << "Couldn't open upload sound file for writing: " << in_fname
|
||||
<< LL_ENDL;
|
||||
return(LLVORBISENC_DEST_OPEN_ERR);
|
||||
}
|
||||
@@ -255,10 +254,10 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname
|
||||
U32 chunk_length = 0;
|
||||
U32 file_pos = 12; // start at the first chunk (usually fmt but not always)
|
||||
|
||||
while (infile.eof() != APR_EOF)
|
||||
while (!instream.eof())
|
||||
{
|
||||
infile.seek(APR_SET,file_pos);
|
||||
infile.read(wav_header, 44);
|
||||
instream.seekg(file_pos);
|
||||
instream.read((char*)wav_header, 44);
|
||||
|
||||
chunk_length = ((U32) wav_header[7] << 24)
|
||||
+ ((U32) wav_header[6] << 16)
|
||||
@@ -278,7 +277,7 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname
|
||||
}
|
||||
else if (!(strncmp((char *)&(wav_header[0]),"data",4)))
|
||||
{
|
||||
infile.seek(APR_SET,file_pos+8);
|
||||
instream.seekg(file_pos + 8);
|
||||
// leave the file pointer at the beginning of the data chunk data
|
||||
data_left = chunk_length;
|
||||
break;
|
||||
@@ -351,8 +350,8 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname
|
||||
while(!eos){
|
||||
int result=ogg_stream_flush(&os,&og);
|
||||
if(result==0)break;
|
||||
outfile.write(og.header, og.header_len);
|
||||
outfile.write(og.body, og.body_len);
|
||||
outstream.write((char*)og.header, og.header_len);
|
||||
outstream.write((char*)og.body, og.body_len);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -362,7 +361,8 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname
|
||||
{
|
||||
long bytes_per_sample = bits_per_sample/8;
|
||||
|
||||
long bytes=(long)infile.read(readbuffer,llclamp((S32)(READ_BUFFER*num_channels*bytes_per_sample),0,data_left)); /* stereo hardwired here */
|
||||
instream.read((char*)readbuffer, llclamp((S32) (READ_BUFFER*num_channels*bytes_per_sample), 0, data_left)); /* stereo hardwired here */
|
||||
long bytes = (long) instream.gcount();
|
||||
|
||||
if (bytes==0)
|
||||
{
|
||||
@@ -470,8 +470,8 @@ S32 encode_vorbis_file(const std::string& in_fname, const std::string& out_fname
|
||||
if(result==0)
|
||||
break;
|
||||
|
||||
outfile.write(og.header, og.header_len);
|
||||
outfile.write(og.body, og.body_len);
|
||||
outstream.write((char*)og.header, og.header_len);
|
||||
outstream.write((char*)og.body, og.body_len);
|
||||
|
||||
/* this could be set above, but for illustrative purposes, I do
|
||||
it here (to show that vorbis does know where the stream ends) */
|
||||
|
||||
@@ -16,6 +16,10 @@ include_directories(
|
||||
${LLVFS_INCLUDE_DIRS}
|
||||
${LLXML_INCLUDE_DIRS}
|
||||
)
|
||||
include_directories(SYSTEM
|
||||
${LLCOMMON_SYSTEM_INCLUDE_DIRS}
|
||||
${LLXML_SYSTEM_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
set(llcharacter_SOURCE_FILES
|
||||
llanimationstates.cpp
|
||||
|
||||
@@ -35,10 +35,6 @@
|
||||
#include "llkeyframemotion.h"
|
||||
#include "llquantize.h"
|
||||
#include "llstl.h"
|
||||
#include "llapr.h"
|
||||
|
||||
|
||||
//using namespace std;
|
||||
|
||||
#define INCHES_TO_METERS 0.02540005f
|
||||
|
||||
@@ -219,9 +215,8 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
|
||||
//--------------------------------------------------------------------
|
||||
std::string path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,fileName);
|
||||
|
||||
LLAPRFile infile(path, LL_APR_R);
|
||||
apr_file_t *fp = infile.getFileHandle();
|
||||
if (!fp)
|
||||
llifstream infstream(path);
|
||||
if (!infstream.is_open())
|
||||
return E_ST_NO_XLT_FILE;
|
||||
|
||||
LL_INFOS() << "NOTE: Loading translation table: " << fileName << LL_ENDL;
|
||||
@@ -233,7 +228,7 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
|
||||
//--------------------------------------------------------------------
|
||||
// load header
|
||||
//--------------------------------------------------------------------
|
||||
if ( ! getLine(fp) )
|
||||
if ( ! getLine(infstream) )
|
||||
return E_ST_EOF;
|
||||
if ( strncmp(mLine, "Translations 1.0", 16) )
|
||||
return E_ST_NO_XLT_HEADER;
|
||||
@@ -243,7 +238,7 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
|
||||
//--------------------------------------------------------------------
|
||||
BOOL loadingGlobals = FALSE;
|
||||
Translation *trans = NULL;
|
||||
while ( getLine(fp) )
|
||||
while ( getLine(infstream) )
|
||||
{
|
||||
//----------------------------------------------------------------
|
||||
// check the 1st token on the line to determine if it's empty or a comment
|
||||
@@ -660,7 +655,7 @@ ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName)
|
||||
|
||||
}
|
||||
|
||||
infile.close() ;
|
||||
infstream.close() ;
|
||||
return E_ST_OK;
|
||||
}
|
||||
|
||||
@@ -1337,13 +1332,9 @@ void LLBVHLoader::reset()
|
||||
//------------------------------------------------------------------------
|
||||
// LLBVHLoader::getLine()
|
||||
//------------------------------------------------------------------------
|
||||
BOOL LLBVHLoader::getLine(apr_file_t* fp)
|
||||
BOOL LLBVHLoader::getLine(llifstream& stream)
|
||||
{
|
||||
if (apr_file_eof(fp) == APR_EOF)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
if ( apr_file_gets(mLine, BVH_PARSER_LINE_SIZE, fp) == APR_SUCCESS)
|
||||
if (stream.getline(mLine, BVH_PARSER_LINE_SIZE))
|
||||
{
|
||||
mLineNumber++;
|
||||
return TRUE;
|
||||
|
||||
@@ -2,31 +2,25 @@
|
||||
* @file llbvhloader.h
|
||||
* @brief Translates a BVH files to LindenLabAnimation format.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewergpl$
|
||||
*
|
||||
* Copyright (c) 2004-2009, Linden Research, Inc.
|
||||
*
|
||||
* $LicenseInfo:firstyear=2004&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* The source code in this file ("Source Code") is provided by Linden Lab
|
||||
* to you under the terms of the GNU General Public License, version 2.0
|
||||
* ("GPL"), unless you have obtained a separate licensing agreement
|
||||
* ("Other License"), formally executed by you and Linden Lab. Terms of
|
||||
* the GPL can be found in doc/GPL-license.txt in this distribution, or
|
||||
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* There are special exceptions to the terms and conditions of the GPL as
|
||||
* it is applied to this Source Code. View the full text of the exception
|
||||
* in the file doc/FLOSS-exception.txt in this software distribution, or
|
||||
* online at
|
||||
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
|
||||
* 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.
|
||||
*
|
||||
* By copying, modifying or distributing this software, you acknowledge
|
||||
* that you have read and understood your obligations described above,
|
||||
* and agree to abide by those obligations.
|
||||
* 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.
|
||||
*
|
||||
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
|
||||
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
|
||||
* COMPLETENESS OR PERFORMANCE.
|
||||
* 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$
|
||||
*/
|
||||
|
||||
@@ -36,32 +30,11 @@
|
||||
#include "v3math.h"
|
||||
#include "m3math.h"
|
||||
#include "llmath.h"
|
||||
#include "llapr.h"
|
||||
#include "llbvhconsts.h"
|
||||
|
||||
const S32 BVH_PARSER_LINE_SIZE = 2048;
|
||||
class LLDataPacker;
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// FileCloser
|
||||
//------------------------------------------------------------------------
|
||||
class FileCloser
|
||||
{
|
||||
public:
|
||||
FileCloser( apr_file_t *file )
|
||||
{
|
||||
mFile = file;
|
||||
}
|
||||
|
||||
~FileCloser()
|
||||
{
|
||||
apr_file_close(mFile);
|
||||
}
|
||||
protected:
|
||||
apr_file_t* mFile;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// Key
|
||||
//------------------------------------------------------------------------
|
||||
@@ -304,7 +277,7 @@ public:
|
||||
|
||||
protected:
|
||||
// Consumes one line of input from file.
|
||||
BOOL getLine(apr_file_t *fp);
|
||||
BOOL getLine(llifstream& stream);
|
||||
|
||||
// parser state
|
||||
char mLine[BVH_PARSER_LINE_SIZE]; /* Flawfinder: ignore */
|
||||
|
||||
@@ -225,6 +225,7 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
LL_CONT << "NULL";
|
||||
}
|
||||
LL_CONT << LL_ENDL;
|
||||
target.setVec(1.f, 1.f, 1.f);
|
||||
}
|
||||
|
||||
mTarget.setPosition( target + mParentJoint.getPosition());
|
||||
|
||||
@@ -36,6 +36,63 @@
|
||||
S32 LLJoint::sNumUpdates = 0;
|
||||
S32 LLJoint::sNumTouches = 0;
|
||||
|
||||
template <class T>
|
||||
bool attachment_map_iter_compare_key(const T& a, const T& b)
|
||||
{
|
||||
return a.first < b.first;
|
||||
}
|
||||
|
||||
bool LLPosOverrideMap::findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const
|
||||
{
|
||||
pos = LLVector3(0,0,0);
|
||||
mesh_id = LLUUID();
|
||||
bool found = false;
|
||||
|
||||
map_type::const_iterator it = std::max_element(m_map.begin(),
|
||||
m_map.end(),
|
||||
attachment_map_iter_compare_key<map_type::value_type>);
|
||||
if (it != m_map.end())
|
||||
{
|
||||
found = true;
|
||||
pos = it->second;
|
||||
mesh_id = it->first;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
void LLPosOverrideMap::showJointPosOverrides( std::ostringstream& os ) const
|
||||
{
|
||||
map_type::const_iterator max_it = std::max_element(m_map.begin(),
|
||||
m_map.end(),
|
||||
attachment_map_iter_compare_key<map_type::value_type>);
|
||||
for (map_type::const_iterator it = m_map.begin();
|
||||
it != m_map.end(); ++it)
|
||||
{
|
||||
const LLVector3& pos = it->second;
|
||||
os << " " << "[" << it->first <<": " << pos << "]" << ((it==max_it) ? "*" : "");
|
||||
}
|
||||
}
|
||||
|
||||
U32 LLPosOverrideMap::count() const
|
||||
{
|
||||
return m_map.size();
|
||||
}
|
||||
|
||||
void LLPosOverrideMap::add(const LLUUID& mesh_id, const LLVector3& pos)
|
||||
{
|
||||
m_map[mesh_id] = pos;
|
||||
}
|
||||
|
||||
bool LLPosOverrideMap::remove(const LLUUID& mesh_id)
|
||||
{
|
||||
U32 remove_count = m_map.erase(mesh_id);
|
||||
return (remove_count > 0);
|
||||
}
|
||||
|
||||
void LLPosOverrideMap::clear()
|
||||
{
|
||||
m_map.clear();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// LLJoint()
|
||||
// Class Constructor
|
||||
@@ -57,7 +114,6 @@ LLJoint::LLJoint() :
|
||||
{
|
||||
init();
|
||||
touch();
|
||||
mResetAfterRestoreOldXform = false;
|
||||
}
|
||||
|
||||
LLJoint::LLJoint(S32 joint_num) :
|
||||
@@ -65,7 +121,6 @@ LLJoint::LLJoint(S32 joint_num) :
|
||||
{
|
||||
init();
|
||||
touch();
|
||||
mResetAfterRestoreOldXform = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -233,54 +288,120 @@ const LLVector3& LLJoint::getPosition()
|
||||
return mXform.getPosition();
|
||||
}
|
||||
|
||||
bool do_debug_joint(const std::string& name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// setPosition()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::setPosition( const LLVector3& pos )
|
||||
{
|
||||
// if (mXform.getPosition() != pos)
|
||||
if (pos != getPosition())
|
||||
{
|
||||
mXform.setPosition(pos);
|
||||
touch(MATRIX_DIRTY | POSITION_DIRTY);
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << " joint " << getName() << " set pos " << pos << LL_ENDL;
|
||||
}
|
||||
}
|
||||
mXform.setPosition(pos);
|
||||
touch(MATRIX_DIRTY | POSITION_DIRTY);
|
||||
}
|
||||
|
||||
void showJointPosOverrides( const LLJoint& joint, const std::string& note, const std::string& av_info )
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << joint.m_posBeforeOverrides;
|
||||
joint.m_attachmentOverrides.showJointPosOverrides(os);
|
||||
LL_DEBUGS("Avatar") << av_info << " joint " << joint.getName() << " " << note << " " << os.str() << LL_ENDL;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// addAttachmentPosOverride()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info )
|
||||
{
|
||||
if (mesh_id.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!m_attachmentOverrides.count())
|
||||
{
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " saving m_posBeforeOverrides " << getPosition() << LL_ENDL;
|
||||
}
|
||||
m_posBeforeOverrides = getPosition();
|
||||
}
|
||||
m_attachmentOverrides.add(mesh_id,pos);
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " addAttachmentPosOverride for mesh " << mesh_id << " pos " << pos << LL_ENDL;
|
||||
}
|
||||
updatePos(av_info);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// removeAttachmentPosOverride()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info )
|
||||
{
|
||||
if (mesh_id.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (m_attachmentOverrides.remove(mesh_id))
|
||||
{
|
||||
if (do_debug_joint(getName()))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName()
|
||||
<< " removeAttachmentPosOverride for " << mesh_id << LL_ENDL;
|
||||
showJointPosOverrides(*this, "remove", av_info);
|
||||
}
|
||||
updatePos(av_info);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// setPosition()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::setDefaultFromCurrentXform( void )
|
||||
// hasAttachmentPosOverride()
|
||||
//--------------------------------------------------------------------
|
||||
bool LLJoint::hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const
|
||||
{
|
||||
mDefaultXform = mXform;
|
||||
touch(MATRIX_DIRTY | POSITION_DIRTY);
|
||||
|
||||
return m_attachmentOverrides.findActiveOverride(mesh_id,pos);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// storeCurrentXform()
|
||||
// clearAttachmentPosOverrides()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::storeCurrentXform( const LLVector3& pos )
|
||||
void LLJoint::clearAttachmentPosOverrides()
|
||||
{
|
||||
mOldXform = mXform;
|
||||
mResetAfterRestoreOldXform = true;
|
||||
setPosition( pos );
|
||||
if (m_attachmentOverrides.count())
|
||||
{
|
||||
m_attachmentOverrides.clear();
|
||||
setPosition(m_posBeforeOverrides);
|
||||
setId( LLUUID::null );
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
// restoreOldXform()
|
||||
// updatePos()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::restoreOldXform( void )
|
||||
void LLJoint::updatePos(const std::string& av_info)
|
||||
{
|
||||
mResetAfterRestoreOldXform = false;
|
||||
mXform = mOldXform;
|
||||
}
|
||||
//--------------------------------------------------------------------
|
||||
// restoreOldXform()
|
||||
//--------------------------------------------------------------------
|
||||
void LLJoint::restoreToDefaultXform( void )
|
||||
{
|
||||
mXform = mDefaultXform;
|
||||
setPosition( mXform.getPosition() );
|
||||
LLVector3 pos, found_pos;
|
||||
LLUUID mesh_id;
|
||||
if (m_attachmentOverrides.findActiveOverride(mesh_id,found_pos))
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner of " << m_attachmentOverrides.count() << " is mesh " << mesh_id << " pos " << found_pos << LL_ENDL;
|
||||
pos = found_pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_DEBUGS("Avatar") << "av " << av_info << " joint " << getName() << " updatePos, winner is posBeforeOverrides " << m_posBeforeOverrides << LL_ENDL;
|
||||
pos = m_posBeforeOverrides;
|
||||
}
|
||||
setPosition(pos);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------
|
||||
|
||||
@@ -46,6 +46,20 @@ const U32 LL_FACE_JOINT_NUM = 30;
|
||||
const S32 LL_CHARACTER_MAX_PRIORITY = 7;
|
||||
const F32 LL_MAX_PELVIS_OFFSET = 5.f;
|
||||
|
||||
class LLPosOverrideMap
|
||||
{
|
||||
public:
|
||||
LLPosOverrideMap() {}
|
||||
bool findActiveOverride(LLUUID& mesh_id, LLVector3& pos) const;
|
||||
void showJointPosOverrides(std::ostringstream& os) const;
|
||||
U32 count() const;
|
||||
void add(const LLUUID& mesh_id, const LLVector3& pos);
|
||||
bool remove(const LLUUID& mesh_id);
|
||||
void clear();
|
||||
private:
|
||||
typedef std::map<LLUUID,LLVector3> map_type;
|
||||
map_type m_map;
|
||||
};
|
||||
//-----------------------------------------------------------------------------
|
||||
// class LLJoint
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -79,8 +93,6 @@ protected:
|
||||
|
||||
// explicit transformation members
|
||||
LLXformMatrix mXform;
|
||||
LLXformMatrix mOldXform;
|
||||
LLXformMatrix mDefaultXform;
|
||||
|
||||
LLUUID mId;
|
||||
|
||||
@@ -88,8 +100,6 @@ public:
|
||||
U32 mDirtyFlags;
|
||||
BOOL mUpdateXform;
|
||||
|
||||
BOOL mResetAfterRestoreOldXform;
|
||||
|
||||
// describes the skin binding pose
|
||||
LLVector3 mSkinOffset;
|
||||
|
||||
@@ -103,6 +113,11 @@ public:
|
||||
static S32 sNumTouches;
|
||||
static S32 sNumUpdates;
|
||||
|
||||
LLPosOverrideMap m_attachmentOverrides;
|
||||
LLVector3 m_posBeforeOverrides;
|
||||
|
||||
void updatePos(const std::string& av_info);
|
||||
|
||||
public:
|
||||
LLJoint();
|
||||
LLJoint(S32 joint_num);
|
||||
@@ -183,22 +198,17 @@ public:
|
||||
virtual BOOL isAnimatable() const { return TRUE; }
|
||||
|
||||
S32 getJointNum() const { return mJointNum; }
|
||||
|
||||
void restoreOldXform( void );
|
||||
void restoreToDefaultXform( void );
|
||||
void setDefaultFromCurrentXform( void );
|
||||
void storeCurrentXform( const LLVector3& pos );
|
||||
|
||||
void addAttachmentPosOverride( const LLVector3& pos, const LLUUID& mesh_id, const std::string& av_info );
|
||||
void removeAttachmentPosOverride( const LLUUID& mesh_id, const std::string& av_info );
|
||||
bool hasAttachmentPosOverride( LLVector3& pos, LLUUID& mesh_id ) const;
|
||||
void clearAttachmentPosOverrides();
|
||||
|
||||
//Accessor for the joint id
|
||||
LLUUID getId( void ) { return mId; }
|
||||
//Setter for the joints id
|
||||
void setId( const LLUUID& id ) { mId = id;}
|
||||
|
||||
//If the old transform flag has been set, then the reset logic in avatar needs to be aware(test) of it
|
||||
const BOOL doesJointNeedToBeReset( void ) const { return mResetAfterRestoreOldXform; }
|
||||
//Setter for joint reset flag
|
||||
void setJointToBeReset( BOOL val ) { mResetAfterRestoreOldXform = val; }
|
||||
|
||||
// <edit>
|
||||
std::string exportString(U32 tabs = 0);
|
||||
// </edit>
|
||||
|
||||
@@ -70,22 +70,18 @@ protected:
|
||||
public:
|
||||
// Constructor
|
||||
LLJointState()
|
||||
{
|
||||
mUsage = 0;
|
||||
mJoint = NULL;
|
||||
mUsage = 0;
|
||||
mWeight = 0.f;
|
||||
mPriority = LLJoint::USE_MOTION_PRIORITY;
|
||||
}
|
||||
: mUsage(0)
|
||||
, mJoint(NULL)
|
||||
, mWeight(0.f)
|
||||
, mPriority(LLJoint::USE_MOTION_PRIORITY)
|
||||
{}
|
||||
|
||||
LLJointState(LLJoint* joint)
|
||||
{
|
||||
mUsage = 0;
|
||||
mJoint = joint;
|
||||
mUsage = 0;
|
||||
mWeight = 0.f;
|
||||
mPriority = LLJoint::USE_MOTION_PRIORITY;
|
||||
}
|
||||
: mUsage(0)
|
||||
, mJoint(joint)
|
||||
, mWeight(0.f)
|
||||
, mPriority(LLJoint::USE_MOTION_PRIORITY)
|
||||
{}
|
||||
|
||||
// joint that this state is applied to
|
||||
LLJoint* getJoint() { return mJoint; }
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "llvfile.h"
|
||||
#include "m3math.h"
|
||||
#include "message.h"
|
||||
#include <memory>
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Static Definitions
|
||||
@@ -700,7 +701,8 @@ BOOL LLKeyframeMotion::onActivate()
|
||||
//-----------------------------------------------------------------------------
|
||||
BOOL LLKeyframeMotion::onUpdate(F32 time, U8* joint_mask)
|
||||
{
|
||||
llassert(time >= 0.f);
|
||||
// llassert(time >= 0.f); // This will fire
|
||||
time = llmax(0.f, time);
|
||||
|
||||
if (mJointMotionList->mLoop)
|
||||
{
|
||||
@@ -965,7 +967,7 @@ void LLKeyframeMotion::deactivateConstraint(JointConstraint *constraintp)
|
||||
constraintp->mSourceVolume->mUpdateXform = FALSE;
|
||||
}
|
||||
|
||||
if (!constraintp->mSharedData->mConstraintTargetType == CONSTRAINT_TARGET_TYPE_GROUND)
|
||||
if (constraintp->mSharedData->mConstraintTargetType != CONSTRAINT_TARGET_TYPE_GROUND)
|
||||
{
|
||||
if (constraintp->mTargetVolume)
|
||||
{
|
||||
@@ -1284,16 +1286,6 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8
|
||||
}
|
||||
}
|
||||
|
||||
// Helper class.
|
||||
template<typename T>
|
||||
struct AIAutoDestruct
|
||||
{
|
||||
T* mPtr;
|
||||
AIAutoDestruct() : mPtr(NULL) { }
|
||||
~AIAutoDestruct() { delete mPtr; }
|
||||
void add(T* ptr) { mPtr = ptr; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// deserialize()
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -1495,18 +1487,12 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
|
||||
for(U32 i=0; i<num_motions; ++i)
|
||||
{
|
||||
AIAutoDestruct<JointMotion> watcher;
|
||||
|
||||
JointMotion* joint_motion = new JointMotion;
|
||||
JointMotion* joint_motion = new JointMotion;
|
||||
std::unique_ptr<JointMotion> watcher(joint_motion);
|
||||
if (singu_new_joint_motion_list)
|
||||
{
|
||||
// Pass ownership to mJointMotionList.
|
||||
mJointMotionList->mJointMotionArray.push_back(joint_motion);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Just delete this at the end.
|
||||
watcher.add(joint_motion);
|
||||
mJointMotionList->mJointMotionArray.push_back(watcher.release());
|
||||
}
|
||||
|
||||
std::string joint_name;
|
||||
@@ -1785,6 +1771,7 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
{
|
||||
// read in constraint data
|
||||
JointConstraintSharedData* constraintp = new JointConstraintSharedData;
|
||||
std::unique_ptr<JointConstraintSharedData> watcher(constraintp);
|
||||
U8 byte = 0;
|
||||
|
||||
if (!dp.unpackU8(byte, "chain_length"))
|
||||
@@ -1842,21 +1829,18 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
if (!dp.unpackVector3(constraintp->mSourceConstraintOffset, "source_offset"))
|
||||
{
|
||||
LL_WARNS() << "can't read constraint source offset" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( !(constraintp->mSourceConstraintOffset.isFinite()) )
|
||||
{
|
||||
LL_WARNS() << "non-finite constraint source offset" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!dp.unpackBinaryDataFixed(bin_data, BIN_DATA_LENGTH, "target_volume"))
|
||||
{
|
||||
LL_WARNS() << "can't read target volume name" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1876,28 +1860,24 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
if (!dp.unpackVector3(constraintp->mTargetConstraintOffset, "target_offset"))
|
||||
{
|
||||
LL_WARNS() << "can't read constraint target offset" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( !(constraintp->mTargetConstraintOffset.isFinite()) )
|
||||
{
|
||||
LL_WARNS() << "non-finite constraint target offset" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!dp.unpackVector3(constraintp->mTargetConstraintDir, "target_dir"))
|
||||
{
|
||||
LL_WARNS() << "can't read constraint target direction" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( !(constraintp->mTargetConstraintDir.isFinite()) )
|
||||
{
|
||||
LL_WARNS() << "non-finite constraint target direction" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1910,39 +1890,30 @@ BOOL LLKeyframeMotion::deserialize(LLDataPacker& dp)
|
||||
if (!dp.unpackF32(constraintp->mEaseInStartTime, "ease_in_start") || !std::isfinite(constraintp->mEaseInStartTime))
|
||||
{
|
||||
LL_WARNS() << "can't read constraint ease in start time" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!dp.unpackF32(constraintp->mEaseInStopTime, "ease_in_stop") || !std::isfinite(constraintp->mEaseInStopTime))
|
||||
{
|
||||
LL_WARNS() << "can't read constraint ease in stop time" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!dp.unpackF32(constraintp->mEaseOutStartTime, "ease_out_start") || !std::isfinite(constraintp->mEaseOutStartTime))
|
||||
{
|
||||
LL_WARNS() << "can't read constraint ease out start time" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!dp.unpackF32(constraintp->mEaseOutStopTime, "ease_out_stop") || !std::isfinite(constraintp->mEaseOutStopTime))
|
||||
{
|
||||
LL_WARNS() << "can't read constraint ease out stop time" << LL_ENDL;
|
||||
delete constraintp;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
AIAutoDestruct<JointConstraintSharedData> watcher;
|
||||
if (singu_new_joint_motion_list)
|
||||
{
|
||||
mJointMotionList->mConstraints.push_front(constraintp);
|
||||
}
|
||||
else
|
||||
{
|
||||
watcher.add(constraintp);
|
||||
mJointMotionList->mConstraints.push_front(watcher.release());
|
||||
}
|
||||
|
||||
constraintp->mJointStateIndices = new S32[constraintp->mChainLength + 1]; // note: mChainLength is size-limited - comes from a byte
|
||||
|
||||
@@ -36,6 +36,7 @@ set(llcommon_SOURCE_FILES
|
||||
llassettype.cpp
|
||||
llbase32.cpp
|
||||
llbase64.cpp
|
||||
llcallbacklist.cpp
|
||||
llcommon.cpp
|
||||
llcommonutils.cpp
|
||||
llcoros.cpp
|
||||
@@ -138,6 +139,7 @@ set(llcommon_HEADER_FILES
|
||||
llbase32.h
|
||||
llbase64.h
|
||||
llboost.h
|
||||
llcallbacklist.h
|
||||
llchat.h
|
||||
llclickaction.h
|
||||
llcommon.h
|
||||
@@ -230,9 +232,13 @@ set(llcommon_HEADER_FILES
|
||||
llthreadsafequeue.h
|
||||
lltimer.h
|
||||
lltreeiterators.h
|
||||
llunits.h
|
||||
llunittype.h
|
||||
lltypeinfolookup.h
|
||||
lluri.h
|
||||
lluuid.h
|
||||
llwin32headers.h
|
||||
llwin32headerslean.h
|
||||
llworkerthread.h
|
||||
metaclass.h
|
||||
metaclasst.h
|
||||
@@ -284,6 +290,7 @@ target_link_libraries(
|
||||
${Boost_REGEX_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_CHRONO_LIBRARY}
|
||||
${CORESERVICES_LIBRARY}
|
||||
)
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ LLAlignedArray<T, alignment>::LLAlignedArray()
|
||||
template <class T, U32 alignment>
|
||||
LLAlignedArray<T, alignment>::~LLAlignedArray()
|
||||
{
|
||||
ll_aligned_free(mArray);
|
||||
ll_aligned_free<alignment>(mArray);
|
||||
mArray = NULL;
|
||||
mElementCount = 0;
|
||||
mCapacity = 0;
|
||||
@@ -78,7 +78,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
|
||||
{
|
||||
mCapacity++;
|
||||
mCapacity *= 2;
|
||||
T* new_buf = (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment);
|
||||
T* new_buf = (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T));
|
||||
if (mArray)
|
||||
{
|
||||
ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount);
|
||||
@@ -90,7 +90,7 @@ void LLAlignedArray<T, alignment>::push_back(const T& elem)
|
||||
mArray[mElementCount++] = elem;
|
||||
|
||||
//delete old array here to prevent error on a.push_back(a[0])
|
||||
ll_aligned_free(old_buf);
|
||||
ll_aligned_free<alignment>(old_buf);
|
||||
}
|
||||
|
||||
template <class T, U32 alignment>
|
||||
@@ -99,11 +99,11 @@ void LLAlignedArray<T, alignment>::resize(U32 size)
|
||||
if (mCapacity < size)
|
||||
{
|
||||
mCapacity = size+mCapacity*2;
|
||||
T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc(mCapacity*sizeof(T), alignment) : NULL;
|
||||
T* new_buf = mCapacity > 0 ? (T*) ll_aligned_malloc<alignment>(mCapacity*sizeof(T)) : NULL;
|
||||
if (mArray)
|
||||
{
|
||||
ll_memcpy_nonaliased_aligned_16((char*) new_buf, (char*) mArray, sizeof(T)*mElementCount);
|
||||
ll_aligned_free(mArray);
|
||||
ll_aligned_free<alignment>(mArray);
|
||||
}
|
||||
|
||||
/*for (U32 i = mElementCount; i < mCapacity; ++i)
|
||||
|
||||
@@ -30,32 +30,36 @@
|
||||
#include "llbase64.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "apr_base64.h"
|
||||
|
||||
|
||||
// static
|
||||
std::string LLBase64::encode(const U8* input, size_t input_size)
|
||||
{
|
||||
if (!(input && input_size > 0)) return LLStringUtil::null;
|
||||
|
||||
// Yes, it returns int.
|
||||
int b64_buffer_length = apr_base64_encode_len(input_size);
|
||||
char* b64_buffer = new char[b64_buffer_length];
|
||||
|
||||
// This is faster than apr_base64_encode() if you know
|
||||
// you're not on an EBCDIC machine. Also, the output is
|
||||
// null terminated, even though the documentation doesn't
|
||||
// specify. See apr_base64.c for details. JC
|
||||
b64_buffer_length = apr_base64_encode_binary(
|
||||
b64_buffer,
|
||||
input,
|
||||
input_size);
|
||||
std::string result;
|
||||
result.assign(b64_buffer);
|
||||
delete[] b64_buffer;
|
||||
|
||||
return result;
|
||||
std::string output;
|
||||
if (input
|
||||
&& input_size > 0)
|
||||
{
|
||||
// Yes, it returns int.
|
||||
int b64_buffer_length = apr_base64_encode_len(input_size);
|
||||
char* b64_buffer = new char[b64_buffer_length];
|
||||
|
||||
// This is faster than apr_base64_encode() if you know
|
||||
// you're not on an EBCDIC machine. Also, the output is
|
||||
// null terminated, even though the documentation doesn't
|
||||
// specify. See apr_base64.c for details. JC
|
||||
b64_buffer_length = apr_base64_encode_binary(
|
||||
b64_buffer,
|
||||
input,
|
||||
input_size);
|
||||
output.assign(b64_buffer);
|
||||
delete[] b64_buffer;
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
std::string LLBase64::encode(const std::string& in_str)
|
||||
{
|
||||
|
||||
230
indra/llcommon/llcallbacklist.cpp
Normal file
230
indra/llcommon/llcallbacklist.cpp
Normal file
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
* @file llcallbacklist.cpp
|
||||
* @brief A simple list of callback functions to call.
|
||||
*
|
||||
* $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$
|
||||
*/
|
||||
|
||||
#include "llcallbacklist.h"
|
||||
#include "lleventtimer.h"
|
||||
#include "llerrorlegacy.h"
|
||||
|
||||
// Globals
|
||||
//
|
||||
LLCallbackList gIdleCallbacks;
|
||||
|
||||
//
|
||||
// Member functions
|
||||
//
|
||||
|
||||
LLCallbackList::LLCallbackList()
|
||||
{
|
||||
// nothing
|
||||
}
|
||||
|
||||
LLCallbackList::~LLCallbackList()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void LLCallbackList::addFunction( callback_t func, void *data)
|
||||
{
|
||||
if (!func)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// only add one callback per func/data pair
|
||||
//
|
||||
if (containsFunction(func))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
callback_pair_t t(func, data);
|
||||
mCallbackList.push_back(t);
|
||||
}
|
||||
|
||||
bool LLCallbackList::containsFunction( callback_t func, void *data)
|
||||
{
|
||||
callback_pair_t t(func, data);
|
||||
callback_list_t::iterator iter = find(func,data);
|
||||
if (iter != mCallbackList.end())
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LLCallbackList::deleteFunction( callback_t func, void *data)
|
||||
{
|
||||
callback_list_t::iterator iter = find(func,data);
|
||||
if (iter != mCallbackList.end())
|
||||
{
|
||||
mCallbackList.erase(iter);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
LLCallbackList::callback_list_t::iterator
|
||||
LLCallbackList::find(callback_t func, void *data)
|
||||
{
|
||||
callback_pair_t t(func, data);
|
||||
return std::find(mCallbackList.begin(), mCallbackList.end(), t);
|
||||
}
|
||||
|
||||
void LLCallbackList::deleteAllFunctions()
|
||||
{
|
||||
mCallbackList.clear();
|
||||
}
|
||||
|
||||
|
||||
void LLCallbackList::callFunctions()
|
||||
{
|
||||
for (callback_list_t::iterator iter = mCallbackList.begin(); iter != mCallbackList.end(); )
|
||||
{
|
||||
callback_list_t::iterator curiter = iter++;
|
||||
curiter->first(curiter->second);
|
||||
}
|
||||
}
|
||||
|
||||
// Shim class to allow arbitrary boost::bind
|
||||
// expressions to be run as one-time idle callbacks.
|
||||
class OnIdleCallbackOneTime
|
||||
{
|
||||
public:
|
||||
OnIdleCallbackOneTime(nullary_func_t callable):
|
||||
mCallable(callable)
|
||||
{
|
||||
}
|
||||
static void onIdle(void *data)
|
||||
{
|
||||
gIdleCallbacks.deleteFunction(onIdle, data);
|
||||
OnIdleCallbackOneTime* self = reinterpret_cast<OnIdleCallbackOneTime*>(data);
|
||||
self->call();
|
||||
delete self;
|
||||
}
|
||||
void call()
|
||||
{
|
||||
mCallable();
|
||||
}
|
||||
private:
|
||||
nullary_func_t mCallable;
|
||||
};
|
||||
|
||||
void doOnIdleOneTime(nullary_func_t callable)
|
||||
{
|
||||
OnIdleCallbackOneTime* cb_functor = new OnIdleCallbackOneTime(callable);
|
||||
gIdleCallbacks.addFunction(&OnIdleCallbackOneTime::onIdle,cb_functor);
|
||||
}
|
||||
|
||||
// Shim class to allow generic boost functions to be run as
|
||||
// recurring idle callbacks. Callable should return true when done,
|
||||
// false to continue getting called.
|
||||
class OnIdleCallbackRepeating
|
||||
{
|
||||
public:
|
||||
OnIdleCallbackRepeating(bool_func_t callable):
|
||||
mCallable(callable)
|
||||
{
|
||||
}
|
||||
// Will keep getting called until the callable returns true.
|
||||
static void onIdle(void *data)
|
||||
{
|
||||
OnIdleCallbackRepeating* self = reinterpret_cast<OnIdleCallbackRepeating*>(data);
|
||||
bool done = self->call();
|
||||
if (done)
|
||||
{
|
||||
gIdleCallbacks.deleteFunction(onIdle, data);
|
||||
delete self;
|
||||
}
|
||||
}
|
||||
bool call()
|
||||
{
|
||||
return mCallable();
|
||||
}
|
||||
private:
|
||||
bool_func_t mCallable;
|
||||
};
|
||||
|
||||
void doOnIdleRepeating(bool_func_t callable)
|
||||
{
|
||||
OnIdleCallbackRepeating* cb_functor = new OnIdleCallbackRepeating(callable);
|
||||
gIdleCallbacks.addFunction(&OnIdleCallbackRepeating::onIdle,cb_functor);
|
||||
}
|
||||
|
||||
class NullaryFuncEventTimer: public LLEventTimer
|
||||
{
|
||||
public:
|
||||
NullaryFuncEventTimer(nullary_func_t callable, F32 seconds):
|
||||
LLEventTimer(seconds),
|
||||
mCallable(callable)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
BOOL tick()
|
||||
{
|
||||
mCallable();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
nullary_func_t mCallable;
|
||||
};
|
||||
|
||||
// Call a given callable once after specified interval.
|
||||
void doAfterInterval(nullary_func_t callable, F32 seconds)
|
||||
{
|
||||
new NullaryFuncEventTimer(callable, seconds);
|
||||
}
|
||||
|
||||
class BoolFuncEventTimer: public LLEventTimer
|
||||
{
|
||||
public:
|
||||
BoolFuncEventTimer(bool_func_t callable, F32 seconds):
|
||||
LLEventTimer(seconds),
|
||||
mCallable(callable)
|
||||
{
|
||||
}
|
||||
private:
|
||||
BOOL tick()
|
||||
{
|
||||
return mCallable();
|
||||
}
|
||||
|
||||
bool_func_t mCallable;
|
||||
};
|
||||
|
||||
// Call a given callable every specified number of seconds, until it returns true.
|
||||
void doPeriodically(bool_func_t callable, F32 seconds)
|
||||
{
|
||||
new BoolFuncEventTimer(callable, seconds);
|
||||
}
|
||||
@@ -28,27 +28,35 @@
|
||||
#define LL_LLCALLBACKLIST_H
|
||||
|
||||
#include "llstl.h"
|
||||
#include <boost/function.hpp>
|
||||
#include <list>
|
||||
#include "stdtypes.h"
|
||||
|
||||
class LLCallbackList
|
||||
{
|
||||
public:
|
||||
typedef void (*callback_t)(void*);
|
||||
|
||||
typedef std::pair< callback_t,void* > callback_pair_t;
|
||||
// NOTE: It is confirmed that we DEPEND on the order provided by using a list :(
|
||||
//
|
||||
typedef std::list< callback_pair_t > callback_list_t;
|
||||
|
||||
LLCallbackList();
|
||||
~LLCallbackList();
|
||||
|
||||
void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
|
||||
BOOL containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair
|
||||
BOOL deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found
|
||||
void callFunctions(); // calls all functions
|
||||
void addFunction( callback_t func, void *data = NULL ); // register a callback, which will be called as func(data)
|
||||
bool containsFunction( callback_t func, void *data = NULL ); // true if list already contains the function/data pair
|
||||
bool deleteFunction( callback_t func, void *data = NULL ); // removes the first instance of this function/data pair from the list, false if not found
|
||||
void callFunctions(); // calls all functions
|
||||
void deleteAllFunctions();
|
||||
|
||||
static void test();
|
||||
|
||||
protected:
|
||||
// Use a list so that the callbacks are ordered in case that matters
|
||||
typedef std::pair<callback_t,void*> callback_pair_t;
|
||||
typedef std::list<callback_pair_t > callback_list_t;
|
||||
|
||||
inline callback_list_t::iterator find(callback_t func, void *data);
|
||||
|
||||
callback_list_t mCallbackList;
|
||||
};
|
||||
|
||||
@@ -55,8 +55,8 @@ LLDate::LLDate(const LLDate& date) :
|
||||
mSecondsSinceEpoch(date.mSecondsSinceEpoch)
|
||||
{}
|
||||
|
||||
LLDate::LLDate(F64 seconds_since_epoch) :
|
||||
mSecondsSinceEpoch(seconds_since_epoch)
|
||||
LLDate::LLDate(F64SecondsImplicit seconds_since_epoch) :
|
||||
mSecondsSinceEpoch(seconds_since_epoch.value())
|
||||
{}
|
||||
|
||||
LLDate::LLDate(const std::string& iso8601_date)
|
||||
@@ -83,7 +83,7 @@ std::string LLDate::asString() const
|
||||
// is one of the standards used and the prefered format
|
||||
std::string LLDate::asRFC1123() const
|
||||
{
|
||||
return toHTTPDateString(LLStringExplicit("%A, %d %b %Y %H:%M:%S GMT"));
|
||||
return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT"));
|
||||
}
|
||||
|
||||
LLFastTimer::DeclareTimer FT_DATE_FORMAT("Date Format");
|
||||
|
||||
@@ -38,9 +38,8 @@
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
|
||||
#include "llpreprocessor.h"
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include "llunits.h"
|
||||
|
||||
/**
|
||||
* @class LLDate
|
||||
@@ -64,9 +63,9 @@ public:
|
||||
/**
|
||||
* @brief Construct a date from a seconds since epoch value.
|
||||
*
|
||||
* @pararm seconds_since_epoch The number of seconds since UTC epoch.
|
||||
* @param seconds_since_epoch The number of seconds since UTC epoch.
|
||||
*/
|
||||
LLDate(F64 seconds_since_epoch);
|
||||
LLDate(F64SecondsImplicit seconds_since_epoch);
|
||||
|
||||
/**
|
||||
* @brief Construct a date from a string representation
|
||||
@@ -163,4 +162,6 @@ LL_COMMON_API std::ostream& operator<<(std::ostream& s, const LLDate& date);
|
||||
// Helper function to stream in a date
|
||||
LL_COMMON_API std::istream& operator>>(std::istream& s, LLDate& date);
|
||||
|
||||
|
||||
|
||||
#endif // LL_LLDATE_H
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
*/
|
||||
|
||||
// Specific error codes
|
||||
const int LL_ERR_NOERR = 0;
|
||||
const int LL_ERR_ASSET_REQUEST_FAILED = -1;
|
||||
//const int LL_ERR_ASSET_REQUEST_INVALID = -2;
|
||||
const int LL_ERR_ASSET_REQUEST_NONEXISTENT_FILE = -3;
|
||||
@@ -108,7 +107,7 @@ const int LL_ERR_PRICE_MISMATCH = -23018;
|
||||
: liru_slashpos2 == std::string::npos ? std::string(__FILE__)/*Apparently, we're in / or perhaps the top of the drive, print as is*/\
|
||||
: std::string(__FILE__).substr(1+liru_slashpos2))/*print foo/bar.cpp or perhaps foo\bar.cpp*/
|
||||
|
||||
#define llassert_always(func) do { if (LL_UNLIKELY(!(func))) LL_ERRS() << "\nASSERT(" #func ")\nfile:" << liru_assert_strip << " line:" << std::dec << __LINE__ << LL_ENDL; } while(0)
|
||||
//#define llassert_always(func) do { if (LL_UNLIKELY(!(func))) LL_ERRS() << "\nASSERT(" #func ")\nfile:" << liru_assert_strip << " line:" << std::dec << __LINE__ << LL_ENDL; } while(0)
|
||||
|
||||
#ifdef SHOW_ASSERT
|
||||
#define llassert(func) llassert_always(func)
|
||||
|
||||
@@ -65,7 +65,7 @@ LLEventTimer::~LLEventTimer()
|
||||
void LLEventTimer::updateClass()
|
||||
{
|
||||
std::list<LLEventTimer*> completed_timers;
|
||||
for (instance_iter iter = beginInstances(), iter_end = endInstances(); iter != iter_end;)
|
||||
for (instance_iter iter = beginInstances(), end_iter = endInstances(); iter != end_iter;)
|
||||
{
|
||||
LLEventTimer& timer = *iter++;
|
||||
F32 et = timer.mEventTimer.getElapsedTimeF32();
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
*/
|
||||
|
||||
#if LL_WINDOWS
|
||||
#include <windows.h>
|
||||
#include "llwin32headerslean.h"
|
||||
#include <stdlib.h> // Windows errno
|
||||
#else
|
||||
#include <errno.h>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <ctype.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include "llwin32headers.h"
|
||||
#include <winnt.h>
|
||||
#endif
|
||||
|
||||
@@ -183,7 +183,7 @@ canonise_fl(FL_Locale *l) {
|
||||
#define RML(pn,sn) MAKELANGID(LANG_##pn, SUBLANG_##sn)
|
||||
struct IDToCode {
|
||||
LANGID id;
|
||||
char* code;
|
||||
const char* code;
|
||||
};
|
||||
static const IDToCode both_to_code[] = {
|
||||
{ML(ENGLISH,US), "en_US.ISO_8859-1"},
|
||||
|
||||
@@ -30,7 +30,8 @@
|
||||
|
||||
LLFixedBuffer::LLFixedBuffer(const U32 max_lines)
|
||||
: LLLineBuffer(),
|
||||
mMaxLines(max_lines)
|
||||
mMaxLines(max_lines),
|
||||
mMutex()
|
||||
{
|
||||
mTimer.reset();
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
// Atomic reads of static variables.
|
||||
|
||||
// Return the number of seconds since the start of the application.
|
||||
static F64 getElapsedSeconds(void)
|
||||
static F64SecondsImplicit getElapsedSeconds(void)
|
||||
{
|
||||
// Loses msec precision after ~4.5 hours...
|
||||
sGlobalMutex.lock();
|
||||
|
||||
@@ -194,13 +194,6 @@ public:
|
||||
return mHandle;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef LLHandle<T> handle_type_t;
|
||||
LLHandleProvider()
|
||||
{
|
||||
// provided here to enforce T deriving from LLHandleProvider<T>
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
LLHandle<U> getDerivedHandle(typename boost::enable_if< typename boost::is_convertible<U*, T*> >::type* dummy = 0) const
|
||||
{
|
||||
@@ -209,6 +202,12 @@ protected:
|
||||
return downcast_handle;
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef LLHandle<T> handle_type_t;
|
||||
LLHandleProvider()
|
||||
{
|
||||
// provided here to enforce T deriving from LLHandleProvider<T>
|
||||
}
|
||||
|
||||
private:
|
||||
mutable LLRootHandle<T> mHandle;
|
||||
|
||||
@@ -88,46 +88,51 @@ LLLiveFile::~LLLiveFile()
|
||||
|
||||
bool LLLiveFile::Impl::check()
|
||||
{
|
||||
if (!mForceCheck && mRefreshTimer.getElapsedTimeF32() < mRefreshPeriod)
|
||||
bool detected_change = false;
|
||||
// Skip the check if not enough time has elapsed and we're not
|
||||
// forcing a check of the file
|
||||
if (mForceCheck || mRefreshTimer.getElapsedTimeF32() >= mRefreshPeriod)
|
||||
{
|
||||
// Skip the check if not enough time has elapsed and we're not
|
||||
// forcing a check of the file
|
||||
return false;
|
||||
}
|
||||
mForceCheck = false;
|
||||
mRefreshTimer.reset();
|
||||
mForceCheck = false; // force only forces one check
|
||||
mRefreshTimer.reset(); // don't check again until mRefreshPeriod has passed
|
||||
|
||||
// Stat the file to see if it exists and when it was last modified.
|
||||
llstat stat_data;
|
||||
int res = LLFile::stat(mFilename, &stat_data);
|
||||
|
||||
if (res)
|
||||
{
|
||||
// Couldn't stat the file, that means it doesn't exist or is
|
||||
// broken somehow. Clear flags and return.
|
||||
if (mLastExists)
|
||||
{
|
||||
mLastExists = false;
|
||||
return true; // no longer existing is a change!
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// The file exists, decide if we want to load it.
|
||||
if (mLastExists)
|
||||
{
|
||||
// The file existed last time, don't read it if it hasn't changed since
|
||||
// last time.
|
||||
if (stat_data.st_mtime <= mLastModTime)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We want to read the file. Update status info for the file.
|
||||
mLastExists = true;
|
||||
mLastStatTime = stat_data.st_mtime;
|
||||
return true;
|
||||
// Stat the file to see if it exists and when it was last modified.
|
||||
llstat stat_data;
|
||||
if (LLFile::stat(mFilename, &stat_data))
|
||||
{
|
||||
// Couldn't stat the file, that means it doesn't exist or is
|
||||
// broken somehow.
|
||||
if (mLastExists)
|
||||
{
|
||||
mLastExists = false;
|
||||
detected_change = true; // no longer existing is a change!
|
||||
LL_DEBUGS() << "detected deleted file '" << mFilename << "'" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The file exists
|
||||
if ( ! mLastExists )
|
||||
{
|
||||
// last check, it did not exist - that counts as a change
|
||||
LL_DEBUGS() << "detected created file '" << mFilename << "'" << LL_ENDL;
|
||||
detected_change = true;
|
||||
}
|
||||
else if ( stat_data.st_mtime > mLastModTime )
|
||||
{
|
||||
// file modification time is newer than last check
|
||||
LL_DEBUGS() << "detected updated file '" << mFilename << "'" << LL_ENDL;
|
||||
detected_change = true;
|
||||
}
|
||||
mLastExists = true;
|
||||
mLastStatTime = stat_data.st_mtime;
|
||||
}
|
||||
}
|
||||
if (detected_change)
|
||||
{
|
||||
LL_INFOS() << "detected file change '" << mFilename << "'" << LL_ENDL;
|
||||
}
|
||||
return detected_change;
|
||||
}
|
||||
|
||||
void LLLiveFile::Impl::changed()
|
||||
|
||||
@@ -119,6 +119,12 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) {
|
||||
|
||||
buffer_space = 64 - buffer_index; // how much space is left in buffer
|
||||
|
||||
// now, transform each 64-byte piece of the input, bypassing the buffer
|
||||
if (input == NULL || input_length == 0){
|
||||
std::cerr << "LLMD5::update: Invalid input!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Transform as many times as possible.
|
||||
if (input_length >= buffer_space) { // ie. we have enough to fill the buffer
|
||||
// fill the rest of the buffer and transform
|
||||
@@ -128,12 +134,6 @@ void LLMD5::update (const uint1 *input, const uint4 input_length) {
|
||||
buffer_space);
|
||||
transform (buffer);
|
||||
|
||||
// now, transform each 64-byte piece of the input, bypassing the buffer
|
||||
if (input == NULL || input_length == 0){
|
||||
std::cerr << "LLMD5::update: Invalid input!" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
for (input_index = buffer_space; input_index + 63 < input_length;
|
||||
input_index += 64)
|
||||
transform (input+input_index);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
//#endif
|
||||
|
||||
#if defined(LL_WINDOWS)
|
||||
//# include <windows.h>
|
||||
#include "llwin32headerslean.h"
|
||||
# include <psapi.h>
|
||||
#elif defined(LL_DARWIN)
|
||||
# include <sys/types.h>
|
||||
@@ -50,11 +50,11 @@
|
||||
|
||||
//static
|
||||
char* LLMemory::reserveMem = 0;
|
||||
U32 LLMemory::sAvailPhysicalMemInKB = U32_MAX ;
|
||||
U32 LLMemory::sMaxPhysicalMemInKB = 0;
|
||||
U32 LLMemory::sAllocatedMemInKB = 0;
|
||||
U32 LLMemory::sAllocatedPageSizeInKB = 0 ;
|
||||
U32 LLMemory::sMaxHeapSizeInKB = U32_MAX ;
|
||||
U32Kilobytes LLMemory::sAvailPhysicalMemInKB(U32_MAX);
|
||||
U32Kilobytes LLMemory::sMaxPhysicalMemInKB(0);
|
||||
U32Kilobytes LLMemory::sAllocatedMemInKB(0);
|
||||
U32Kilobytes LLMemory::sAllocatedPageSizeInKB(0);
|
||||
U32Kilobytes LLMemory::sMaxHeapSizeInKB(U32_MAX);
|
||||
BOOL LLMemory::sEnableMemoryFailurePrevention = FALSE;
|
||||
|
||||
#if __DEBUG_PRIVATE_MEM__
|
||||
@@ -93,9 +93,9 @@ void LLMemory::freeReserve()
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMemory::initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure)
|
||||
void LLMemory::initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure)
|
||||
{
|
||||
sMaxHeapSizeInKB = (U32)(max_heap_size_gb * 1024 * 1024) ;
|
||||
sMaxHeapSizeInKB = max_heap_size;
|
||||
sEnableMemoryFailurePrevention = prevent_heap_failure ;
|
||||
}
|
||||
|
||||
@@ -112,10 +112,10 @@ void LLMemory::updateMemoryInfo()
|
||||
return ;
|
||||
}
|
||||
|
||||
sAllocatedMemInKB = (U32)(counters.WorkingSetSize / 1024) ;
|
||||
sAllocatedPageSizeInKB = (U32)(counters.PagefileUsage / 1024) ;
|
||||
sAllocatedMemInKB = (U32Bytes)(counters.WorkingSetSize) ;
|
||||
sAllocatedPageSizeInKB = (U32Bytes)(counters.PagefileUsage) ;
|
||||
|
||||
U32 avail_phys, avail_virtual;
|
||||
U32Kilobytes avail_phys, avail_virtual;
|
||||
LLMemoryInfo::getAvailableMemoryKB(avail_phys, avail_virtual) ;
|
||||
sMaxPhysicalMemInKB = llmin(avail_phys + sAllocatedMemInKB, sMaxHeapSizeInKB);
|
||||
|
||||
@@ -125,14 +125,16 @@ void LLMemory::updateMemoryInfo()
|
||||
}
|
||||
else
|
||||
{
|
||||
sAvailPhysicalMemInKB = 0 ;
|
||||
sAvailPhysicalMemInKB = U32Kilobytes(0);
|
||||
}
|
||||
#else
|
||||
//not valid for other systems for now.
|
||||
sAllocatedMemInKB = (U32)(LLMemory::getCurrentRSS() / 1024) ;
|
||||
sMaxPhysicalMemInKB = U32_MAX ;
|
||||
sAvailPhysicalMemInKB = U32_MAX ;
|
||||
sAllocatedMemInKB = (U32Bytes)LLMemory::getCurrentRSS();
|
||||
sMaxPhysicalMemInKB = (U32Bytes)U32_MAX ;
|
||||
sAvailPhysicalMemInKB = (U32Bytes)U32_MAX ;
|
||||
#endif
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
//
|
||||
@@ -184,8 +186,8 @@ void LLMemory::logMemoryInfo(BOOL update)
|
||||
//static
|
||||
bool LLMemory::isMemoryPoolLow()
|
||||
{
|
||||
static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use
|
||||
const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
|
||||
static const U32Megabytes LOW_MEMORY_POOL_THRESHOLD(64);
|
||||
const static U32Megabytes MAX_SIZE_CHECKED_MEMORY_BLOCK(64);
|
||||
static void* last_reserved_address = NULL ;
|
||||
|
||||
if(!sEnableMemoryFailurePrevention)
|
||||
@@ -193,32 +195,32 @@ bool LLMemory::isMemoryPoolLow()
|
||||
return false ; //no memory failure prevention.
|
||||
}
|
||||
|
||||
if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory
|
||||
if(sAvailPhysicalMemInKB < (LOW_MEMORY_POOL_THRESHOLD / 4)) //out of physical memory
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space.
|
||||
if(sAllocatedPageSizeInKB + (LOW_MEMORY_POOL_THRESHOLD / 4) > sMaxHeapSizeInKB) //out of virtual address space.
|
||||
{
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB ||
|
||||
sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ;
|
||||
bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMORY_POOL_THRESHOLD
|
||||
|| sAllocatedPageSizeInKB + LOW_MEMORY_POOL_THRESHOLD > sMaxHeapSizeInKB) ;
|
||||
|
||||
//check the virtual address space fragmentation
|
||||
if(!is_low)
|
||||
{
|
||||
if(!last_reserved_address)
|
||||
{
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
|
||||
if(!last_reserved_address) //failed, try once more
|
||||
{
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
|
||||
last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK.value()) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,19 +231,19 @@ bool LLMemory::isMemoryPoolLow()
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLMemory::getAvailableMemKB()
|
||||
U32Kilobytes LLMemory::getAvailableMemKB()
|
||||
{
|
||||
return sAvailPhysicalMemInKB ;
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLMemory::getMaxMemKB()
|
||||
U32Kilobytes LLMemory::getMaxMemKB()
|
||||
{
|
||||
return sMaxPhysicalMemInKB ;
|
||||
}
|
||||
|
||||
//static
|
||||
U32 LLMemory::getAllocatedMemKB()
|
||||
U32Kilobytes LLMemory::getAllocatedMemKB()
|
||||
{
|
||||
return sAllocatedMemInKB ;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
#define LLMEMORY_H
|
||||
|
||||
#include "linden_common.h"
|
||||
|
||||
#include "llunits.h"
|
||||
#include "stdtypes.h"
|
||||
#include <new>
|
||||
#include <cstdlib>
|
||||
#if !LL_WINDOWS
|
||||
@@ -42,6 +43,21 @@ class LLMutex ;
|
||||
#define LL_CHECK_MEMORY
|
||||
#endif
|
||||
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define LL_ALIGN_OF __alignof
|
||||
#else
|
||||
#define LL_ALIGN_OF __align_of__
|
||||
#endif
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define LL_DEFAULT_HEAP_ALIGN 8
|
||||
#elif LL_DARWIN
|
||||
#define LL_DEFAULT_HEAP_ALIGN 16
|
||||
#elif LL_LINUX
|
||||
#define LL_DEFAULT_HEAP_ALIGN 8
|
||||
#endif
|
||||
|
||||
//<singu>
|
||||
// ll_assert_aligned seems to only exist to set breakpoints in case an alignment check fails.
|
||||
// However, the implementation was horrible: the test was done using a integer modulo after
|
||||
@@ -102,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)
|
||||
|
||||
inline void* ll_aligned_malloc( size_t size, int align )
|
||||
{
|
||||
#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));
|
||||
//------------------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------------------------
|
||||
// for enable buffer overrun detection predefine LL_DEBUG_BUFFER_OVERRUN in current library
|
||||
// change preprocessor code to: #if 1 && defined(LL_WINDOWS)
|
||||
|
||||
((void**)aligned)[-1] = mem;
|
||||
return aligned;
|
||||
#endif
|
||||
}
|
||||
|
||||
inline void ll_aligned_free( void* ptr )
|
||||
{
|
||||
#if defined(LL_WINDOWS)
|
||||
_aligned_free(ptr);
|
||||
#if 0 && defined(LL_WINDOWS)
|
||||
void* ll_aligned_malloc_fallback( size_t size, int align );
|
||||
void ll_aligned_free_fallback( void* ptr );
|
||||
//------------------------------------------------------------------------------------------------
|
||||
#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
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------
|
||||
|
||||
#if !LL_USE_TCMALLOC
|
||||
inline void* ll_aligned_malloc_16(size_t size) // returned hunk MUST be freed with ll_aligned_free_16().
|
||||
@@ -189,7 +217,7 @@ inline void* ll_aligned_malloc_32(size_t size) // returned hunk MUST be freed wi
|
||||
#if defined(LL_WINDOWS)
|
||||
return _aligned_malloc(size, 32);
|
||||
#elif defined(LL_DARWIN)
|
||||
return ll_aligned_malloc( size, 32 );
|
||||
return ll_aligned_malloc_fallback( size, 32 );
|
||||
#else
|
||||
void *rtn;
|
||||
if (LL_LIKELY(0 == posix_memalign(&rtn, 32, size)))
|
||||
@@ -204,12 +232,54 @@ inline void ll_aligned_free_32(void *p)
|
||||
#if defined(LL_WINDOWS)
|
||||
_aligned_free(p);
|
||||
#elif defined(LL_DARWIN)
|
||||
ll_aligned_free( p );
|
||||
ll_aligned_free_fallback( p );
|
||||
#else
|
||||
free(p); // posix_memalign() is compatible with heap deallocator
|
||||
#endif
|
||||
}
|
||||
|
||||
// general purpose dispatch functions that are forced inline so they can compile down to a single call
|
||||
template<size_t ALIGNMENT>
|
||||
LL_FORCE_INLINE void* ll_aligned_malloc(size_t size)
|
||||
{
|
||||
if (LL_DEFAULT_HEAP_ALIGN % ALIGNMENT == 0)
|
||||
{
|
||||
return malloc(size);
|
||||
}
|
||||
else if (ALIGNMENT == 16)
|
||||
{
|
||||
return ll_aligned_malloc_16(size);
|
||||
}
|
||||
else if (ALIGNMENT == 32)
|
||||
{
|
||||
return ll_aligned_malloc_32(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ll_aligned_malloc_fallback(size, ALIGNMENT);
|
||||
}
|
||||
}
|
||||
|
||||
template<size_t ALIGNMENT>
|
||||
LL_FORCE_INLINE void ll_aligned_free(void* ptr)
|
||||
{
|
||||
if (ALIGNMENT == LL_DEFAULT_HEAP_ALIGN)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
else if (ALIGNMENT == 16)
|
||||
{
|
||||
ll_aligned_free_16(ptr);
|
||||
}
|
||||
else if (ALIGNMENT == 32)
|
||||
{
|
||||
return ll_aligned_free_32(ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ll_aligned_free_fallback(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy words 16-byte blocks from src to dst. Source and destination MUST NOT OVERLAP.
|
||||
// Source and dest must be 16-byte aligned and size must be multiple of 16.
|
||||
@@ -297,22 +367,22 @@ public:
|
||||
static U64 getCurrentRSS();
|
||||
static U32 getWorkingSetSize();
|
||||
static void* tryToAlloc(void* address, U32 size);
|
||||
static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure);
|
||||
static void initMaxHeapSizeGB(F32Gigabytes max_heap_size, BOOL prevent_heap_failure);
|
||||
static void updateMemoryInfo() ;
|
||||
static void logMemoryInfo(BOOL update = FALSE);
|
||||
static bool isMemoryPoolLow();
|
||||
|
||||
static U32 getAvailableMemKB() ;
|
||||
static U32 getMaxMemKB() ;
|
||||
static U32 getAllocatedMemKB() ;
|
||||
static U32Kilobytes getAvailableMemKB() ;
|
||||
static U32Kilobytes getMaxMemKB() ;
|
||||
static U32Kilobytes getAllocatedMemKB() ;
|
||||
private:
|
||||
static char* reserveMem;
|
||||
static U32 sAvailPhysicalMemInKB ;
|
||||
static U32 sMaxPhysicalMemInKB ;
|
||||
static U32 sAllocatedMemInKB;
|
||||
static U32 sAllocatedPageSizeInKB ;
|
||||
static U32Kilobytes sAvailPhysicalMemInKB ;
|
||||
static U32Kilobytes sMaxPhysicalMemInKB ;
|
||||
static U32Kilobytes sAllocatedMemInKB;
|
||||
static U32Kilobytes sAllocatedPageSizeInKB ;
|
||||
|
||||
static U32 sMaxHeapSizeInKB;
|
||||
static U32Kilobytes sMaxHeapSizeInKB;
|
||||
static BOOL sEnableMemoryFailurePrevention;
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#define LLMORTICIAN_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include <list>
|
||||
|
||||
class LL_COMMON_API LLMortician
|
||||
{
|
||||
|
||||
@@ -32,9 +32,7 @@
|
||||
//#include <memory>
|
||||
|
||||
#if LL_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# include "llwin32headerslean.h"
|
||||
# define _interlockedbittestandset _renamed_interlockedbittestandset
|
||||
# define _interlockedbittestandreset _renamed_interlockedbittestandreset
|
||||
# include <intrin.h>
|
||||
@@ -881,7 +879,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL)
|
||||
|
||||
|
||||
LLProcessorInfo::~LLProcessorInfo() {}
|
||||
F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
|
||||
F64MegahertzImplicit LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); }
|
||||
bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); }
|
||||
bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); }
|
||||
bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); }
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#ifndef LLPROCESSOR_H
|
||||
#define LLPROCESSOR_H
|
||||
#include "llunits.h"
|
||||
|
||||
class LLProcessorInfoImpl;
|
||||
|
||||
class LL_COMMON_API LLProcessorInfo
|
||||
@@ -41,7 +43,7 @@ public:
|
||||
LLProcessorInfo();
|
||||
~LLProcessorInfo();
|
||||
|
||||
F64 getCPUFrequency() const;
|
||||
F64MegahertzImplicit getCPUFrequency() const;
|
||||
bool hasSSE() const;
|
||||
bool hasSSE2() const;
|
||||
bool hasAltivec() const;
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
LLQueuedThread::LLQueuedThread(const std::string& name, bool threaded, bool should_pause) :
|
||||
LLThread(name),
|
||||
mThreaded(threaded),
|
||||
mIdleThread(TRUE),
|
||||
mIdleThread(true),
|
||||
mNextHandle(0),
|
||||
mStarted(FALSE)
|
||||
{
|
||||
@@ -552,14 +552,15 @@ void LLQueuedThread::run()
|
||||
break;
|
||||
}
|
||||
|
||||
mIdleThread = FALSE;
|
||||
mIdleThread = false;
|
||||
|
||||
threadedUpdate();
|
||||
|
||||
int res = processNextRequest();
|
||||
if (res == 0)
|
||||
int pending_work = processNextRequest();
|
||||
|
||||
if (pending_work == 0)
|
||||
{
|
||||
mIdleThread = TRUE;
|
||||
mIdleThread = true;
|
||||
ms_sleep(1);
|
||||
}
|
||||
//LLThread::yield(); // thread should yield after each request
|
||||
|
||||
@@ -32,8 +32,6 @@
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include "llapr.h"
|
||||
|
||||
#include "llthread.h"
|
||||
#include "llsimplehash.h"
|
||||
|
||||
@@ -204,7 +202,7 @@ public:
|
||||
protected:
|
||||
BOOL mThreaded; // if false, run on main thread and do updates during update()
|
||||
BOOL mStarted; // required when mThreaded is false to call startThread() from update()
|
||||
LLAtomic32<BOOL> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
|
||||
LLAtomic32<bool> mIdleThread; // request queue is empty (or we are quitting) and the thread is idle
|
||||
|
||||
typedef std::set<QueuedRequest*, queued_request_less> request_queue_t;
|
||||
request_queue_t mRequestQueue;
|
||||
|
||||
@@ -31,15 +31,15 @@
|
||||
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
#include "llthread.h"
|
||||
#include "llapr.h"
|
||||
#endif
|
||||
|
||||
LLRefCount::LLRefCount(const LLRefCount& other)
|
||||
: mRef(0)
|
||||
{
|
||||
LLRefCount::LLRefCount(const LLRefCount& other) :
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
mCrashAtUnlock = FALSE ;
|
||||
mMutex(),
|
||||
mCrashAtUnlock(FALSE),
|
||||
#endif
|
||||
mRef(0)
|
||||
{
|
||||
}
|
||||
|
||||
LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
||||
@@ -49,11 +49,12 @@ LLRefCount& LLRefCount::operator=(const LLRefCount&)
|
||||
}
|
||||
|
||||
LLRefCount::LLRefCount() :
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
mMutex(),
|
||||
mCrashAtUnlock(FALSE),
|
||||
#endif
|
||||
mRef(0)
|
||||
{
|
||||
#if LL_REF_COUNT_DEBUG
|
||||
mCrashAtUnlock = FALSE ;
|
||||
#endif
|
||||
}
|
||||
|
||||
LLRefCount::~LLRefCount()
|
||||
|
||||
@@ -337,10 +337,9 @@ void clear_eol(std::istream& input)
|
||||
static unsigned get_till_eol(std::istream& input, char *buf, unsigned bufsize)
|
||||
{
|
||||
unsigned count = 0;
|
||||
char c;
|
||||
while (count < bufsize && input.good())
|
||||
{
|
||||
input.get(c);
|
||||
char c = input.get();
|
||||
buf[count++] = c;
|
||||
if (is_eol(c))
|
||||
break;
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "windows.h"
|
||||
#include "llwin32headerslean.h"
|
||||
#include "Dbghelp.h"
|
||||
|
||||
typedef USHORT NTAPI RtlCaptureStackBackTrace_Function(
|
||||
|
||||
@@ -37,7 +37,11 @@
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <typeinfo>
|
||||
#include "stdtypes.h"
|
||||
|
||||
// Use to compare the first element only of a pair
|
||||
// e.g. typedef std::set<std::pair<int, Data*>, compare_pair<int, Data*> > some_pair_set_t;
|
||||
|
||||
@@ -30,9 +30,7 @@
|
||||
#include "llerror.h"
|
||||
|
||||
#if LL_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include "llwin32headerslean.h"
|
||||
#include <winnls.h> // for WideCharToMultiByte
|
||||
#endif
|
||||
|
||||
|
||||
@@ -53,9 +53,7 @@
|
||||
using namespace llsd;
|
||||
|
||||
#if LL_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# include "llwin32headerslean.h"
|
||||
# include <psapi.h> // GetPerformanceInfo() et al.
|
||||
# include <VersionHelpers.h>
|
||||
#elif LL_DARWIN
|
||||
@@ -705,7 +703,7 @@ LLMemoryInfo::LLMemoryInfo()
|
||||
}
|
||||
|
||||
#if LL_WINDOWS
|
||||
static U32 LLMemoryAdjustKBResult(U32 inKB)
|
||||
static U32Kilobytes LLMemoryAdjustKBResult(U32Kilobytes inKB)
|
||||
{
|
||||
// Moved this here from llfloaterabout.cpp
|
||||
|
||||
@@ -716,16 +714,16 @@ static U32 LLMemoryAdjustKBResult(U32 inKB)
|
||||
// returned from the GetMemoryStatusEx function. Here we keep the
|
||||
// original adjustment from llfoaterabout.cpp until this can be
|
||||
// fixed somehow.
|
||||
inKB += 1024;
|
||||
inKB += U32Megabytes(1);
|
||||
|
||||
return inKB;
|
||||
}
|
||||
#endif
|
||||
|
||||
U32 LLMemoryInfo::getPhysicalMemoryKB() const
|
||||
U32Kilobytes LLMemoryInfo::getPhysicalMemoryKB() const
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
return LLMemoryAdjustKBResult(mStatsMap["Total Physical KB"].asInteger());
|
||||
return LLMemoryAdjustKBResult(U32Kilobytes(mStatsMap["Total Physical KB"].asInteger()));
|
||||
|
||||
#elif LL_DARWIN
|
||||
// This might work on Linux as well. Someone check...
|
||||
@@ -735,17 +733,17 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
|
||||
size_t len = sizeof(phys);
|
||||
sysctl(mib, 2, &phys, &len, NULL, 0);
|
||||
|
||||
return (U32)(phys >> 10);
|
||||
return U64Bytes(phys);
|
||||
|
||||
#elif LL_LINUX
|
||||
U64 phys = 0;
|
||||
phys = (U64)(getpagesize()) * (U64)(get_phys_pages());
|
||||
return (U32)(phys >> 10);
|
||||
return U64Bytes(phys);
|
||||
|
||||
#elif LL_SOLARIS
|
||||
U64 phys = 0;
|
||||
phys = (U64)(getpagesize()) * (U64)(sysconf(_SC_PHYS_PAGES));
|
||||
return (U32)(phys >> 10);
|
||||
return U64Bytes(phys);
|
||||
|
||||
#else
|
||||
return 0;
|
||||
@@ -753,32 +751,32 @@ U32 LLMemoryInfo::getPhysicalMemoryKB() const
|
||||
#endif
|
||||
}
|
||||
|
||||
U32 LLMemoryInfo::getPhysicalMemoryClamped() const
|
||||
U32Bytes LLMemoryInfo::getPhysicalMemoryClamped() const
|
||||
{
|
||||
// Return the total physical memory in bytes, but clamp it
|
||||
// to no more than U32_MAX
|
||||
|
||||
U32 phys_kb = getPhysicalMemoryKB();
|
||||
if (phys_kb >= 4194304 /* 4GB in KB */)
|
||||
U32Kilobytes phys_kb = getPhysicalMemoryKB();
|
||||
if (phys_kb >= U32Gigabytes(4))
|
||||
{
|
||||
return U32_MAX;
|
||||
return U32Bytes(U32_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
return phys_kb << 10;
|
||||
return phys_kb;
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
|
||||
void LLMemoryInfo::getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb)
|
||||
{
|
||||
#if LL_WINDOWS
|
||||
// Sigh, this shouldn't be a static method, then we wouldn't have to
|
||||
// reload this data separately from refresh()
|
||||
LLSD statsMap(loadStatsMap());
|
||||
|
||||
avail_physical_mem_kb = statsMap["Avail Physical KB"].asInteger();
|
||||
avail_virtual_mem_kb = statsMap["Avail Virtual KB"].asInteger();
|
||||
avail_physical_mem_kb = (U32Kilobytes)statsMap["Avail Physical KB"].asInteger();
|
||||
avail_virtual_mem_kb = (U32Kilobytes)statsMap["Avail Virtual KB"].asInteger();
|
||||
|
||||
#elif LL_DARWIN
|
||||
// mStatsMap is derived from vm_stat, look for (e.g.) "kb free":
|
||||
@@ -795,8 +793,8 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v
|
||||
// Pageins: 2097212.
|
||||
// Pageouts: 41759.
|
||||
// Object cache: 841598 hits of 7629869 lookups (11% hit rate)
|
||||
avail_physical_mem_kb = -1 ;
|
||||
avail_virtual_mem_kb = -1 ;
|
||||
avail_physical_mem_kb = (U32Kilobytes)-1 ;
|
||||
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
|
||||
|
||||
#elif LL_LINUX
|
||||
// mStatsMap is derived from MEMINFO_FILE:
|
||||
@@ -847,15 +845,15 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v
|
||||
// DirectMap4k: 434168 kB
|
||||
// DirectMap2M: 477184 kB
|
||||
// (could also run 'free', but easier to read a file than run a program)
|
||||
avail_physical_mem_kb = -1 ;
|
||||
avail_virtual_mem_kb = -1 ;
|
||||
avail_physical_mem_kb = (U32Kilobytes)-1 ;
|
||||
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
|
||||
|
||||
#else
|
||||
//do not know how to collect available memory info for other systems.
|
||||
//leave it blank here for now.
|
||||
|
||||
avail_physical_mem_kb = -1 ;
|
||||
avail_virtual_mem_kb = -1 ;
|
||||
avail_physical_mem_kb = (U32Kilobytes)-1 ;
|
||||
avail_virtual_mem_kb = (U32Kilobytes)-1 ;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -112,15 +112,15 @@ public:
|
||||
LLMemoryInfo(); ///< Default constructor
|
||||
void stream(std::ostream& s) const; ///< output text info to s
|
||||
|
||||
U32 getPhysicalMemoryKB() const; ///< Memory size in KiloBytes
|
||||
U32Kilobytes getPhysicalMemoryKB() const;
|
||||
|
||||
/*! Memory size in bytes, if total memory is >= 4GB then U32_MAX will
|
||||
** be returned.
|
||||
*/
|
||||
U32 getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
|
||||
U32Bytes getPhysicalMemoryClamped() const; ///< Memory size in clamped bytes
|
||||
|
||||
//get the available memory infomation in KiloBytes.
|
||||
static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb);
|
||||
static void getAvailableMemoryKB(U32Kilobytes& avail_physical_mem_kb, U32Kilobytes& avail_virtual_mem_kb);
|
||||
|
||||
// Retrieve a map of memory statistics. The keys of the map are platform-
|
||||
// dependent. The values are in kilobytes to try to avoid integer overflow.
|
||||
|
||||
@@ -31,11 +31,9 @@
|
||||
#include "u64.h"
|
||||
|
||||
#if LL_WINDOWS
|
||||
# define WIN32_LEAN_AND_MEAN
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
# include "llwin32headerslean.h"
|
||||
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
|
||||
# include <errno.h>
|
||||
# include <errno.h>
|
||||
# include <sys/time.h>
|
||||
#else
|
||||
# error "architecture not supported"
|
||||
@@ -81,10 +79,10 @@ void ms_sleep(U32 ms)
|
||||
|
||||
U32 micro_sleep(U64 us, U32 max_yields)
|
||||
{
|
||||
// max_yields is unused; just fiddle with it to avoid warnings.
|
||||
max_yields = 0;
|
||||
ms_sleep(us / 1000);
|
||||
return 0;
|
||||
// max_yields is unused; just fiddle with it to avoid warnings.
|
||||
max_yields = 0;
|
||||
ms_sleep((U32)(us / 1000));
|
||||
return 0;
|
||||
}
|
||||
#elif LL_LINUX || LL_SOLARIS || LL_DARWIN
|
||||
static void _sleep_loop(struct timespec& thiswait)
|
||||
@@ -216,56 +214,68 @@ U64 get_clock_count()
|
||||
#endif
|
||||
|
||||
|
||||
void update_clock_frequencies()
|
||||
TimerInfo::TimerInfo()
|
||||
: mClockFrequency(0.0),
|
||||
mTotalTimeClockCount(0),
|
||||
mLastTotalTimeClockCount(0)
|
||||
{}
|
||||
|
||||
void TimerInfo::update()
|
||||
{
|
||||
gClockFrequency = calc_clock_frequency();
|
||||
gClockFrequencyInv = 1.0/gClockFrequency;
|
||||
gClocksToMicroseconds = gClockFrequencyInv * SEC_TO_MICROSEC;
|
||||
mClockFrequency = calc_clock_frequency();
|
||||
mClockFrequencyInv = 1.0/mClockFrequency;
|
||||
mClocksToMicroseconds = mClockFrequencyInv;
|
||||
}
|
||||
|
||||
TimerInfo& get_timer_info()
|
||||
{
|
||||
static TimerInfo sTimerInfo;
|
||||
return sTimerInfo;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// returns a U64 number that represents the number of
|
||||
// microseconds since the Unix epoch - Jan 1, 1970
|
||||
U64 totalTime()
|
||||
U64MicrosecondsImplicit totalTime()
|
||||
{
|
||||
U64 current_clock_count = get_clock_count();
|
||||
if (!gTotalTimeClockCount)
|
||||
if (!get_timer_info().mTotalTimeClockCount || get_timer_info().mClocksToMicroseconds.value() == 0)
|
||||
{
|
||||
update_clock_frequencies();
|
||||
gTotalTimeClockCount = current_clock_count;
|
||||
get_timer_info().update();
|
||||
get_timer_info().mTotalTimeClockCount = current_clock_count;
|
||||
|
||||
#if LL_WINDOWS
|
||||
// Synch us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
|
||||
// Sync us up with local time (even though we PROBABLY don't need to, this is how it was implemented)
|
||||
// Unix platforms use gettimeofday so they are synced, although this probably isn't a good assumption to
|
||||
// make in the future.
|
||||
|
||||
gTotalTimeClockCount = (U64)(time(NULL) * gClockFrequency);
|
||||
get_timer_info().mTotalTimeClockCount = (U64)(time(NULL) * get_timer_info().mClockFrequency);
|
||||
#endif
|
||||
|
||||
// Update the last clock count
|
||||
gLastTotalTimeClockCount = current_clock_count;
|
||||
get_timer_info().mLastTotalTimeClockCount = current_clock_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (LL_LIKELY(current_clock_count >= gLastTotalTimeClockCount))
|
||||
if (current_clock_count >= get_timer_info().mLastTotalTimeClockCount)
|
||||
{
|
||||
// No wrapping, we're all okay.
|
||||
gTotalTimeClockCount += current_clock_count - gLastTotalTimeClockCount;
|
||||
get_timer_info().mTotalTimeClockCount += current_clock_count - get_timer_info().mLastTotalTimeClockCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
// We've wrapped. Compensate correctly
|
||||
gTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - gLastTotalTimeClockCount) + current_clock_count;
|
||||
get_timer_info().mTotalTimeClockCount += (0xFFFFFFFFFFFFFFFFULL - get_timer_info().mLastTotalTimeClockCount) + current_clock_count;
|
||||
}
|
||||
|
||||
// Update the last clock count
|
||||
gLastTotalTimeClockCount = current_clock_count;
|
||||
get_timer_info().mLastTotalTimeClockCount = current_clock_count;
|
||||
}
|
||||
|
||||
// Return the total clock tick count in microseconds.
|
||||
return (U64)(gTotalTimeClockCount*gClocksToMicroseconds);
|
||||
U64Microseconds time(get_timer_info().mTotalTimeClockCount*get_timer_info().mClocksToMicroseconds);
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
@@ -273,9 +283,9 @@ U64 totalTime()
|
||||
|
||||
LLTimer::LLTimer()
|
||||
{
|
||||
if (!gClockFrequency)
|
||||
if (!get_timer_info().mClockFrequency)
|
||||
{
|
||||
update_clock_frequencies();
|
||||
get_timer_info().update();
|
||||
}
|
||||
|
||||
mStarted = TRUE;
|
||||
@@ -283,20 +293,32 @@ LLTimer::LLTimer()
|
||||
}
|
||||
|
||||
LLTimer::~LLTimer()
|
||||
{}
|
||||
|
||||
// static
|
||||
void LLTimer::initClass()
|
||||
{
|
||||
if (!sTimer) sTimer = new LLTimer;
|
||||
}
|
||||
|
||||
// static
|
||||
U64 LLTimer::getTotalTime()
|
||||
void LLTimer::cleanupClass()
|
||||
{
|
||||
delete sTimer; sTimer = NULL;
|
||||
}
|
||||
|
||||
// static
|
||||
U64MicrosecondsImplicit LLTimer::getTotalTime()
|
||||
{
|
||||
// simply call into the implementation function.
|
||||
return totalTime();
|
||||
U64MicrosecondsImplicit total_time = totalTime();
|
||||
return total_time;
|
||||
}
|
||||
|
||||
// static
|
||||
F64 LLTimer::getTotalSeconds()
|
||||
F64SecondsImplicit LLTimer::getTotalSeconds()
|
||||
{
|
||||
return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64;
|
||||
return F64Microseconds(U64_to_F64(getTotalTime()));
|
||||
}
|
||||
|
||||
void LLTimer::reset()
|
||||
@@ -343,43 +365,43 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount)
|
||||
}
|
||||
|
||||
|
||||
F64 LLTimer::getElapsedTimeF64() const
|
||||
F64SecondsImplicit LLTimer::getElapsedTimeF64() const
|
||||
{
|
||||
U64 last = mLastClockCount;
|
||||
return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv;
|
||||
return (F64)getElapsedTimeAndUpdate(last) * get_timer_info().mClockFrequencyInv;
|
||||
}
|
||||
|
||||
F32 LLTimer::getElapsedTimeF32() const
|
||||
F32SecondsImplicit LLTimer::getElapsedTimeF32() const
|
||||
{
|
||||
return (F32)getElapsedTimeF64();
|
||||
}
|
||||
|
||||
F64 LLTimer::getElapsedTimeAndResetF64()
|
||||
F64SecondsImplicit LLTimer::getElapsedTimeAndResetF64()
|
||||
{
|
||||
return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv;
|
||||
return (F64)getElapsedTimeAndUpdate(mLastClockCount) * get_timer_info().mClockFrequencyInv;
|
||||
}
|
||||
|
||||
F32 LLTimer::getElapsedTimeAndResetF32()
|
||||
F32SecondsImplicit LLTimer::getElapsedTimeAndResetF32()
|
||||
{
|
||||
return (F32)getElapsedTimeAndResetF64();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void LLTimer::setTimerExpirySec(F32 expiration)
|
||||
void LLTimer::setTimerExpirySec(F32SecondsImplicit expiration)
|
||||
{
|
||||
mExpirationTicks = get_clock_count()
|
||||
+ (U64)((F32)(expiration * gClockFrequency));
|
||||
+ (U64)((F32)(expiration * get_timer_info().mClockFrequency.value()));
|
||||
}
|
||||
|
||||
F32 LLTimer::getRemainingTimeF32() const
|
||||
F32SecondsImplicit LLTimer::getRemainingTimeF32() const
|
||||
{
|
||||
U64 cur_ticks = get_clock_count();
|
||||
if (cur_ticks > mExpirationTicks)
|
||||
{
|
||||
return 0.0f;
|
||||
}
|
||||
return F32((mExpirationTicks - cur_ticks) * gClockFrequencyInv);
|
||||
return F32((mExpirationTicks - cur_ticks) * get_timer_info().mClockFrequencyInv);
|
||||
}
|
||||
|
||||
|
||||
@@ -392,7 +414,7 @@ BOOL LLTimer::checkExpirationAndReset(F32 expiration)
|
||||
}
|
||||
|
||||
mExpirationTicks = cur_ticks
|
||||
+ (U64)((F32)(expiration * gClockFrequency));
|
||||
+ (U64)((F32)(expiration * get_timer_info().mClockFrequency));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -491,20 +513,20 @@ BOOL is_daylight_savings()
|
||||
|
||||
struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
|
||||
{
|
||||
S32 pacific_offset_hours;
|
||||
S32Hours pacific_offset_hours;
|
||||
if (pacific_daylight_time)
|
||||
{
|
||||
pacific_offset_hours = 7;
|
||||
pacific_offset_hours = S32Hours(7);
|
||||
}
|
||||
else
|
||||
{
|
||||
pacific_offset_hours = 8;
|
||||
pacific_offset_hours = S32Hours(8);
|
||||
}
|
||||
|
||||
// We subtract off the PST/PDT offset _before_ getting
|
||||
// "UTC" time, because this will handle wrapping around
|
||||
// for 5 AM UTC -> 10 PM PDT of the previous day.
|
||||
utc_time -= pacific_offset_hours * MIN_PER_HOUR * SEC_PER_MIN;
|
||||
utc_time -= S32SecondsImplicit(pacific_offset_hours);
|
||||
|
||||
// Internal buffer to PST/PDT (see above)
|
||||
struct tm* internal_time = gmtime(&utc_time);
|
||||
@@ -521,7 +543,7 @@ struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time)
|
||||
}
|
||||
|
||||
|
||||
void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
|
||||
void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring)
|
||||
{
|
||||
U64 hours;
|
||||
U64 minutes;
|
||||
@@ -543,9 +565,9 @@ void microsecondsToTimecodeString(U64 current_time, std::string& tcstring)
|
||||
}
|
||||
|
||||
|
||||
void secondsToTimecodeString(F32 current_time, std::string& tcstring)
|
||||
void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring)
|
||||
{
|
||||
microsecondsToTimecodeString((U64)((F64)(SEC_TO_MICROSEC*current_time)), tcstring);
|
||||
microsecondsToTimecodeString(current_time, tcstring);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <string>
|
||||
#include <list>
|
||||
// units conversions
|
||||
#include "llunits.h"
|
||||
#ifndef USEC_PER_SEC
|
||||
const U32 USEC_PER_SEC = 1000000;
|
||||
#endif
|
||||
@@ -61,21 +62,28 @@ public:
|
||||
LLTimer();
|
||||
~LLTimer();
|
||||
|
||||
static void initClass() { if (!sTimer) sTimer = new LLTimer; }
|
||||
static void cleanupClass() { delete sTimer; sTimer = NULL; }
|
||||
static void initClass();
|
||||
static void cleanupClass();
|
||||
|
||||
// Return a high precision number of seconds since the start of
|
||||
// this application instance.
|
||||
static F64 getElapsedSeconds()
|
||||
static F64SecondsImplicit getElapsedSeconds()
|
||||
{
|
||||
if (sTimer)
|
||||
{
|
||||
return sTimer->getElapsedTimeF64();
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Return a high precision usec since epoch
|
||||
static U64 getTotalTime();
|
||||
static U64MicrosecondsImplicit getTotalTime();
|
||||
|
||||
// Return a high precision seconds since epoch
|
||||
static F64 getTotalSeconds();
|
||||
static F64SecondsImplicit getTotalSeconds();
|
||||
|
||||
|
||||
// MANIPULATORS
|
||||
@@ -83,19 +91,19 @@ public:
|
||||
void stop() { mStarted = FALSE; }
|
||||
void reset(); // Resets the timer
|
||||
void setLastClockCount(U64 current_count); // Sets the timer so that the next elapsed call will be relative to this time
|
||||
void setTimerExpirySec(F32 expiration);
|
||||
void setTimerExpirySec(F32SecondsImplicit expiration);
|
||||
BOOL checkExpirationAndReset(F32 expiration);
|
||||
BOOL hasExpired() const;
|
||||
F32 getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
|
||||
F64 getElapsedTimeAndResetF64();
|
||||
F32SecondsImplicit getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset
|
||||
F64SecondsImplicit getElapsedTimeAndResetF64();
|
||||
|
||||
F32 getRemainingTimeF32() const;
|
||||
F32SecondsImplicit getRemainingTimeF32() const;
|
||||
|
||||
static BOOL knownBadTimer();
|
||||
|
||||
// ACCESSORS
|
||||
F32 getElapsedTimeF32() const; // Returns elapsed time in seconds
|
||||
F64 getElapsedTimeF64() const; // Returns elapsed time in seconds
|
||||
F32SecondsImplicit getElapsedTimeF32() const; // Returns elapsed time in seconds
|
||||
F64SecondsImplicit getElapsedTimeF64() const; // Returns elapsed time in seconds
|
||||
|
||||
bool getStarted() const { return mStarted; }
|
||||
|
||||
@@ -106,6 +114,20 @@ public:
|
||||
//
|
||||
// Various functions for initializing/accessing clock and timing stuff. Don't use these without REALLY knowing how they work.
|
||||
//
|
||||
struct TimerInfo
|
||||
{
|
||||
TimerInfo();
|
||||
void update();
|
||||
|
||||
F64HertzImplicit mClockFrequency;
|
||||
F64SecondsImplicit mClockFrequencyInv;
|
||||
F64MicrosecondsImplicit mClocksToMicroseconds;
|
||||
U64 mTotalTimeClockCount;
|
||||
U64 mLastTotalTimeClockCount;
|
||||
};
|
||||
|
||||
TimerInfo& get_timer_info();
|
||||
|
||||
LL_COMMON_API U64 get_clock_count();
|
||||
LL_COMMON_API F64 calc_clock_frequency();
|
||||
LL_COMMON_API void update_clock_frequencies();
|
||||
@@ -160,10 +182,10 @@ LL_COMMON_API BOOL is_daylight_savings();
|
||||
// struct tm* internal_time = utc_to_pacific_time(utc_time, gDaylight);
|
||||
LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_daylight_time);
|
||||
|
||||
LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);
|
||||
LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring);
|
||||
LL_COMMON_API void microsecondsToTimecodeString(U64MicrosecondsImplicit current_time, std::string& tcstring);
|
||||
LL_COMMON_API void secondsToTimecodeString(F32SecondsImplicit current_time, std::string& tcstring);
|
||||
LL_COMMON_API void timeToFormattedString(time_t time, std::string format, std::string ×tr);
|
||||
LL_COMMON_API void timeStructToFormattedString(struct tm * time, std::string format, std::string ×tr);
|
||||
|
||||
U64 LL_COMMON_API totalTime(); // Returns current system time in microseconds
|
||||
U64MicrosecondsImplicit LL_COMMON_API totalTime(); // Returns current system time in microseconds
|
||||
#endif
|
||||
|
||||
129
indra/llcommon/llunits.h
Normal file
129
indra/llcommon/llunits.h
Normal file
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* @file llunits.h
|
||||
* @brief Unit definitions
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLUNITTYPE_H
|
||||
#define LL_LLUNITTYPE_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include "llunittype.h"
|
||||
|
||||
//
|
||||
// Unit declarations
|
||||
//
|
||||
|
||||
namespace LLUnits
|
||||
{
|
||||
LL_DECLARE_BASE_UNIT(Bytes, "B");
|
||||
// technically, these are kibibytes, mibibytes, etc. but we should stick with commonly accepted terminology
|
||||
LL_DECLARE_DERIVED_UNIT(Kilobytes, "KB", Bytes, / 1024);
|
||||
LL_DECLARE_DERIVED_UNIT(Megabytes, "MB", Kilobytes, / 1024);
|
||||
LL_DECLARE_DERIVED_UNIT(Gigabytes, "GB", Megabytes, / 1024);
|
||||
}
|
||||
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bytes);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobytes);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabytes);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabytes);
|
||||
|
||||
namespace LLUnits
|
||||
{
|
||||
// technically, these are kibibits, mibibits, etc. but we should stick with commonly accepted terminology
|
||||
LL_DECLARE_DERIVED_UNIT(Bits, "b", Bytes, * 8 );
|
||||
LL_DECLARE_DERIVED_UNIT(Kilobits, "Kb", Bits, / 1024);
|
||||
LL_DECLARE_DERIVED_UNIT(Megabits, "Mb", Kilobits, / 1024);
|
||||
LL_DECLARE_DERIVED_UNIT(Gigabits, "Gb", Megabits, / 1024);
|
||||
}
|
||||
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Bits);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilobits);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megabits);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigabits);
|
||||
|
||||
namespace LLUnits
|
||||
{
|
||||
LL_DECLARE_BASE_UNIT(Seconds, "s");
|
||||
LL_DECLARE_DERIVED_UNIT(Minutes, "min", Seconds, / 60);
|
||||
LL_DECLARE_DERIVED_UNIT(Hours, "h", Minutes, / 60);
|
||||
LL_DECLARE_DERIVED_UNIT(Days, "d", Hours, / 24);
|
||||
LL_DECLARE_DERIVED_UNIT(Milliseconds, "ms", Seconds, * 1000);
|
||||
LL_DECLARE_DERIVED_UNIT(Microseconds, "\x09\x3cs", Milliseconds, * 1000);
|
||||
LL_DECLARE_DERIVED_UNIT(Nanoseconds, "ns", Microseconds, * 1000);
|
||||
}
|
||||
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Seconds);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Minutes);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hours);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Days);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Milliseconds);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Microseconds);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Nanoseconds);
|
||||
|
||||
namespace LLUnits
|
||||
{
|
||||
LL_DECLARE_BASE_UNIT(Meters, "m");
|
||||
LL_DECLARE_DERIVED_UNIT(Kilometers, "km", Meters, / 1000);
|
||||
LL_DECLARE_DERIVED_UNIT(Centimeters, "cm", Meters, * 100);
|
||||
LL_DECLARE_DERIVED_UNIT(Millimeters, "mm", Meters, * 1000);
|
||||
}
|
||||
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Meters);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilometers);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Centimeters);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Millimeters);
|
||||
|
||||
namespace LLUnits
|
||||
{
|
||||
// rare units
|
||||
LL_DECLARE_BASE_UNIT(Hertz, "Hz");
|
||||
LL_DECLARE_DERIVED_UNIT(Kilohertz, "KHz", Hertz, / 1000);
|
||||
LL_DECLARE_DERIVED_UNIT(Megahertz, "MHz", Kilohertz, / 1000);
|
||||
LL_DECLARE_DERIVED_UNIT(Gigahertz, "GHz", Megahertz, / 1000);
|
||||
|
||||
LL_DECLARE_BASE_UNIT(Radians, "rad");
|
||||
LL_DECLARE_DERIVED_UNIT(Degrees, "deg", Radians, * 57.29578f);
|
||||
|
||||
LL_DECLARE_BASE_UNIT(Percent, "%");
|
||||
LL_DECLARE_DERIVED_UNIT(Ratio, "x", Percent, / 100);
|
||||
|
||||
LL_DECLARE_BASE_UNIT(Triangles, "tris");
|
||||
LL_DECLARE_DERIVED_UNIT(Kilotriangles, "ktris", Triangles, / 1000);
|
||||
|
||||
} // namespace LLUnits
|
||||
|
||||
// rare units
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Hertz);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilohertz);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Megahertz);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Gigahertz);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Radians);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Degrees);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Percent);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Ratio);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Triangles);
|
||||
LL_DECLARE_UNIT_TYPEDEFS(LLUnits, Kilotriangles);
|
||||
|
||||
|
||||
#endif // LL_LLUNITTYPE_H
|
||||
838
indra/llcommon/llunittype.h
Normal file
838
indra/llcommon/llunittype.h
Normal file
@@ -0,0 +1,838 @@
|
||||
/**
|
||||
* @file llunit.h
|
||||
* @brief Unit conversion classes
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2012, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_UNITTYPE_H
|
||||
#define LL_UNITTYPE_H
|
||||
|
||||
#include "stdtypes.h"
|
||||
#include "llpreprocessor.h"
|
||||
#include "llerror.h"
|
||||
|
||||
//lightweight replacement of type traits for simple type equality check
|
||||
template<typename S, typename T>
|
||||
struct LLIsSameType
|
||||
{
|
||||
static const bool value = false;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LLIsSameType<T, T>
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
// workaround for decltype() not existing and typeof() not working inline in gcc 4.2
|
||||
template<typename S, typename T>
|
||||
struct LLResultTypeAdd
|
||||
{
|
||||
typedef LL_TYPEOF(S() + T()) type_t;
|
||||
};
|
||||
|
||||
template<typename S, typename T>
|
||||
struct LLResultTypeSubtract
|
||||
{
|
||||
typedef LL_TYPEOF(S() - T()) type_t;
|
||||
};
|
||||
|
||||
template<typename S, typename T>
|
||||
struct LLResultTypeMultiply
|
||||
{
|
||||
typedef LL_TYPEOF(S() * T()) type_t;
|
||||
};
|
||||
|
||||
template<typename S, typename T>
|
||||
struct LLResultTypeDivide
|
||||
{
|
||||
typedef LL_TYPEOF(S() / T(1)) type_t;
|
||||
};
|
||||
|
||||
template<typename S, typename T>
|
||||
struct LLResultTypePromote
|
||||
{
|
||||
typedef LL_TYPEOF((true) ? S() : T()) type_t;
|
||||
};
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
struct LLUnit
|
||||
{
|
||||
typedef LLUnit<STORAGE_TYPE, UNITS> self_t;
|
||||
typedef STORAGE_TYPE storage_t;
|
||||
typedef void is_unit_t;
|
||||
|
||||
// value initialization
|
||||
LL_FORCE_INLINE explicit LLUnit(storage_t value = storage_t())
|
||||
: mValue(value)
|
||||
{}
|
||||
|
||||
|
||||
LL_FORCE_INLINE static self_t convert(self_t v)
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename FROM_STORAGE_TYPE>
|
||||
LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, UNITS> v)
|
||||
{
|
||||
self_t result;
|
||||
result.mValue = (STORAGE_TYPE)v.value();
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename FROM_UNITS>
|
||||
LL_FORCE_INLINE static self_t convert(LLUnit<STORAGE_TYPE, FROM_UNITS> v)
|
||||
{
|
||||
self_t result;
|
||||
STORAGE_TYPE divisor = ll_convert_units(v, result);
|
||||
result.mValue /= divisor;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename FROM_STORAGE_TYPE, typename FROM_UNITS>
|
||||
LL_FORCE_INLINE static self_t convert(LLUnit<FROM_STORAGE_TYPE, FROM_UNITS> v)
|
||||
{
|
||||
typedef typename LLResultTypePromote<FROM_STORAGE_TYPE, STORAGE_TYPE>::type_t result_storage_t;
|
||||
LLUnit<result_storage_t, UNITS> result;
|
||||
result_storage_t divisor = ll_convert_units(v, result);
|
||||
result.value(result.value() / divisor);
|
||||
return self_t(result.value());
|
||||
}
|
||||
|
||||
|
||||
// unit initialization and conversion
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE LLUnit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
|
||||
: mValue(convert(other).mValue)
|
||||
{}
|
||||
|
||||
LL_FORCE_INLINE storage_t value() const
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void value(storage_t value)
|
||||
{
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
template<typename NEW_UNITS>
|
||||
storage_t valueInUnits()
|
||||
{
|
||||
return LLUnit<storage_t, NEW_UNITS>(*this).value();
|
||||
}
|
||||
|
||||
template<typename NEW_UNITS>
|
||||
void valueInUnits(storage_t value)
|
||||
{
|
||||
*this = LLUnit<storage_t, NEW_UNITS>(value);
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator += (self_t other)
|
||||
{
|
||||
mValue += convert(other).mValue;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator -= (self_t other)
|
||||
{
|
||||
mValue -= convert(other).mValue;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator *= (storage_t multiplicand)
|
||||
{
|
||||
mValue *= multiplicand;
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator *= (self_t multiplicand)
|
||||
{
|
||||
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Multiplication of unit types not supported.");
|
||||
}
|
||||
|
||||
LL_FORCE_INLINE void operator /= (storage_t divisor)
|
||||
{
|
||||
mValue /= divisor;
|
||||
}
|
||||
|
||||
void operator /= (self_t divisor)
|
||||
{
|
||||
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "Illegal in-place division of unit types.");
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue == convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue != convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue < convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue <= convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue > convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return mValue >= convert(other).value();
|
||||
}
|
||||
|
||||
protected:
|
||||
storage_t mValue;
|
||||
};
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
std::ostream& operator <<(std::ostream& s, const LLUnit<STORAGE_TYPE, UNITS>& unit)
|
||||
{
|
||||
s << unit.value() << UNITS::getUnitLabel();
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
std::istream& operator >>(std::istream& s, LLUnit<STORAGE_TYPE, UNITS>& unit)
|
||||
{
|
||||
STORAGE_TYPE val;
|
||||
s >> val;
|
||||
unit.value(val);
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
struct LLUnitImplicit : public LLUnit<STORAGE_TYPE, UNITS>
|
||||
{
|
||||
typedef LLUnitImplicit<STORAGE_TYPE, UNITS> self_t;
|
||||
typedef typename LLUnit<STORAGE_TYPE, UNITS>::storage_t storage_t;
|
||||
typedef LLUnit<STORAGE_TYPE, UNITS> base_t;
|
||||
|
||||
LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t())
|
||||
: base_t(value)
|
||||
{}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE LLUnitImplicit(LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
|
||||
: base_t(other)
|
||||
{}
|
||||
|
||||
// unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD value (F32, S32, etc)
|
||||
// this allows for interoperability with legacy code
|
||||
LL_FORCE_INLINE operator storage_t() const
|
||||
{
|
||||
return base_t::value();
|
||||
}
|
||||
|
||||
using base_t::operator +=;
|
||||
LL_FORCE_INLINE void operator += (storage_t value)
|
||||
{
|
||||
base_t::mValue += value;
|
||||
}
|
||||
|
||||
// this overload exists to explicitly catch use of another implicit unit
|
||||
// without ambiguity between conversion to storage_t vs conversion to base_t
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE void operator += (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
|
||||
{
|
||||
base_t::mValue += base_t::convert(other).value();
|
||||
}
|
||||
|
||||
using base_t::operator -=;
|
||||
LL_FORCE_INLINE void operator -= (storage_t value)
|
||||
{
|
||||
base_t::mValue -= value;
|
||||
}
|
||||
|
||||
// this overload exists to explicitly catch use of another implicit unit
|
||||
// without ambiguity between conversion to storage_t vs conversion to base_t
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE void operator -= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other)
|
||||
{
|
||||
base_t::mValue -= base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator == (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue == base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator == (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue == base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator == (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue == other;
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator != (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue != convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator != (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue != base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator != (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue != other;
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator < (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue < base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator < (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue < base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator < (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue < other;
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator <= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue <= base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator <= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue <= base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator <= (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue <= other;
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator > (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue > base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator > (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue > base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator > (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue > other;
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator >= (LLUnit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue >= base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename OTHER_STORAGE_TYPE, typename OTHER_UNITS>
|
||||
LL_FORCE_INLINE bool operator >= (LLUnitImplicit<OTHER_STORAGE_TYPE, OTHER_UNITS> other) const
|
||||
{
|
||||
return base_t::mValue >= base_t::convert(other).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_T>
|
||||
LL_FORCE_INLINE bool operator >= (STORAGE_T other) const
|
||||
{
|
||||
return base_t::mValue >= other;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
std::ostream& operator <<(std::ostream& s, const LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
|
||||
{
|
||||
s << unit.value() << UNITS::getUnitLabel();
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
std::istream& operator >>(std::istream& s, LLUnitImplicit<STORAGE_TYPE, UNITS>& unit)
|
||||
{
|
||||
STORAGE_TYPE val;
|
||||
s >> val;
|
||||
unit = val;
|
||||
return s;
|
||||
}
|
||||
|
||||
template<typename S1, typename T1, typename S2, typename T2>
|
||||
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, T1> in, LLUnit<S2, T2>& out)
|
||||
{
|
||||
S2 divisor(1);
|
||||
|
||||
LL_STATIC_ASSERT((LLIsSameType<T1, T2>::value
|
||||
|| !LLIsSameType<T1, typename T1::base_unit_t>::value
|
||||
|| !LLIsSameType<T2, typename T2::base_unit_t>::value),
|
||||
"conversion requires compatible units");
|
||||
|
||||
if (LLIsSameType<T1, T2>::value)
|
||||
{
|
||||
// T1 and T2 same type, just assign
|
||||
out.value((S2)in.value());
|
||||
}
|
||||
else if (T1::sLevel > T2::sLevel)
|
||||
{
|
||||
// reduce T1
|
||||
LLUnit<S2, typename T1::base_unit_t> new_in;
|
||||
divisor *= (S2)ll_convert_units(in, new_in);
|
||||
divisor *= (S2)ll_convert_units(new_in, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
// reduce T2
|
||||
LLUnit<S2, typename T2::base_unit_t> new_out;
|
||||
divisor *= (S2)ll_convert_units(in, new_out);
|
||||
divisor *= (S2)ll_convert_units(new_out, out);
|
||||
}
|
||||
return divisor;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct LLStorageType
|
||||
{
|
||||
typedef T type_t;
|
||||
};
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS>
|
||||
struct LLStorageType<LLUnit<STORAGE_TYPE, UNITS> >
|
||||
{
|
||||
typedef STORAGE_TYPE type_t;
|
||||
};
|
||||
|
||||
// all of these operators need to perform type promotion on the storage type of the units, so they
|
||||
// cannot be expressed as operations on identical types with implicit unit conversion
|
||||
// e.g. typeof(S32Bytes(x) + F32Megabytes(y)) <==> F32Bytes
|
||||
|
||||
//
|
||||
// operator +
|
||||
//
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result += second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
|
||||
LLUnit<STORAGE_TYPE, UNITS> operator + (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
|
||||
{
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
|
||||
return LLUnit<STORAGE_TYPE, UNITS>(0);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
|
||||
LLUnit<STORAGE_TYPE, UNITS> operator + (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types");
|
||||
return LLUnit<STORAGE_TYPE, UNITS>(0);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result += second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result += second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator + (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result += LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator + (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeAdd<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
|
||||
result += second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::
|
||||
type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeAdd<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
|
||||
result += second;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// operator -
|
||||
//
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result -= second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
|
||||
LLUnit<STORAGE_TYPE, UNITS> operator - (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS second)
|
||||
{
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
|
||||
return LLUnit<STORAGE_TYPE, UNITS>(0);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS>
|
||||
LLUnit<STORAGE_TYPE, UNITS> operator - (UNITLESS first, LLUnit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types");
|
||||
return LLUnit<STORAGE_TYPE, UNITS>(0);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result -= second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result -= second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> operator - (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE1, STORAGE_TYPE2>::type_t, UNITS1> result(first);
|
||||
result -= LLUnitImplicit<STORAGE_TYPE1, UNITS1>(second);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator - (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeSubtract<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> result(first);
|
||||
result -= second;
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator - (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
LLUnitImplicit<typename LLResultTypeSubtract<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> result(first);
|
||||
result -= second;
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// operator *
|
||||
//
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LLUnit<STORAGE_TYPE1, UNITS1> operator * (LLUnit<STORAGE_TYPE1, UNITS1>, LLUnit<STORAGE_TYPE2, UNITS2>)
|
||||
{
|
||||
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
|
||||
return LLUnit<STORAGE_TYPE1, UNITS1>();
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
return LLUnit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() * second);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
return LLUnit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LLUnitImplicit<STORAGE_TYPE1, UNITS1> operator * (LLUnitImplicit<STORAGE_TYPE1, UNITS1>, LLUnitImplicit<STORAGE_TYPE2, UNITS2>)
|
||||
{
|
||||
// spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template
|
||||
LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE1, "multiplication of unit types results in new unit type - not supported.");
|
||||
return LLUnitImplicit<STORAGE_TYPE1, UNITS1>();
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator * (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
return LLUnitImplicit<typename LLResultTypeMultiply<STORAGE_TYPE, UNITLESS_TYPE>::type_t, UNITS>(first.value() * second);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnitImplicit<STORAGE_TYPE, UNITS> second)
|
||||
{
|
||||
return LLUnitImplicit<typename LLResultTypeMultiply<typename LLStorageType<UNITLESS_TYPE>::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value());
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// operator /
|
||||
//
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
return LLUnit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
return first.value() / first.convert(second).value();
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE, typename UNITS, typename UNITLESS_TYPE>
|
||||
LL_FORCE_INLINE LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS> operator / (LLUnitImplicit<STORAGE_TYPE, UNITS> first, UNITLESS_TYPE second)
|
||||
{
|
||||
return LLUnitImplicit<typename LLResultTypeDivide<STORAGE_TYPE, typename LLStorageType<UNITLESS_TYPE>::type_t>::type_t, UNITS>(first.value() / second);
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnit<STORAGE_TYPE1, UNITS1> first, LLUnitImplicit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
|
||||
}
|
||||
|
||||
template<typename STORAGE_TYPE1, typename UNITS1, typename STORAGE_TYPE2, typename UNITS2>
|
||||
LL_FORCE_INLINE typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t operator / (LLUnitImplicit<STORAGE_TYPE1, UNITS1> first, LLUnit<STORAGE_TYPE2, UNITS2> second)
|
||||
{
|
||||
return (typename LLResultTypeDivide<STORAGE_TYPE1, STORAGE_TYPE2>::type_t)(first.value() / first.convert(second).value());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct LLGetUnitLabel
|
||||
{
|
||||
static const char* getUnitLabel() { return ""; }
|
||||
};
|
||||
|
||||
template<typename T, typename STORAGE_T>
|
||||
struct LLGetUnitLabel<LLUnit<STORAGE_T, T> >
|
||||
{
|
||||
static const char* getUnitLabel() { return T::getUnitLabel(); }
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LLUnitLinearOps
|
||||
{
|
||||
typedef LLUnitLinearOps<T> self_t;
|
||||
|
||||
LLUnitLinearOps(T val)
|
||||
: mValue(val),
|
||||
mDivisor(1)
|
||||
{}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator * (OTHER_T other)
|
||||
{
|
||||
return mValue * other;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator / (OTHER_T other)
|
||||
{
|
||||
mDivisor *= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator + (OTHER_T other)
|
||||
{
|
||||
mValue += other * mDivisor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator - (OTHER_T other)
|
||||
{
|
||||
mValue -= other * mDivisor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T mValue;
|
||||
T mDivisor;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct LLUnitInverseLinearOps
|
||||
{
|
||||
typedef LLUnitInverseLinearOps<T> self_t;
|
||||
|
||||
LLUnitInverseLinearOps(T val)
|
||||
: mValue(val),
|
||||
mDivisor(1),
|
||||
mMultiplicand(1)
|
||||
{}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator * (OTHER_T other)
|
||||
{
|
||||
mDivisor *= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator / (OTHER_T other)
|
||||
{
|
||||
mValue *= other;
|
||||
mMultiplicand *= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator + (OTHER_T other)
|
||||
{
|
||||
mValue -= other * mMultiplicand;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename OTHER_T>
|
||||
self_t operator - (OTHER_T other)
|
||||
{
|
||||
mValue += other * mMultiplicand;
|
||||
return *this;
|
||||
}
|
||||
|
||||
T mValue;
|
||||
T mDivisor;
|
||||
T mMultiplicand;
|
||||
};
|
||||
|
||||
#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \
|
||||
struct base_unit_name \
|
||||
{ \
|
||||
static const int sLevel = 0; \
|
||||
typedef base_unit_name base_unit_t; \
|
||||
static const char* getUnitLabel() { return unit_label; } \
|
||||
template<typename T> \
|
||||
static LLUnit<T, base_unit_name> fromValue(T value) { return LLUnit<T, base_unit_name>(value); } \
|
||||
template<typename STORAGE_T, typename UNIT_T> \
|
||||
static LLUnit<STORAGE_T, base_unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
|
||||
{ return LLUnit<STORAGE_T, base_unit_name>(value); } \
|
||||
}
|
||||
|
||||
|
||||
#define LL_DECLARE_DERIVED_UNIT(unit_name, unit_label, base_unit_name, conversion_operation) \
|
||||
struct unit_name \
|
||||
{ \
|
||||
static const int sLevel = base_unit_name::sLevel + 1; \
|
||||
typedef base_unit_name base_unit_t; \
|
||||
static const char* getUnitLabel() { return unit_label; } \
|
||||
template<typename T> \
|
||||
static LLUnit<T, unit_name> fromValue(T value) { return LLUnit<T, unit_name>(value); } \
|
||||
template<typename STORAGE_T, typename UNIT_T> \
|
||||
static LLUnit<STORAGE_T, unit_name> fromValue(LLUnit<STORAGE_T, UNIT_T> value) \
|
||||
{ return LLUnit<STORAGE_T, unit_name>(value); } \
|
||||
}; \
|
||||
\
|
||||
template<typename S1, typename S2> \
|
||||
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, unit_name> in, LLUnit<S2, base_unit_name>& out) \
|
||||
{ \
|
||||
typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
|
||||
LLUnitInverseLinearOps<result_storage_t> result = \
|
||||
LLUnitInverseLinearOps<result_storage_t>(in.value()) conversion_operation; \
|
||||
out = LLUnit<S2, base_unit_name>((S2)result.mValue); \
|
||||
return result.mDivisor; \
|
||||
} \
|
||||
\
|
||||
template<typename S1, typename S2> \
|
||||
LL_FORCE_INLINE S2 ll_convert_units(LLUnit<S1, base_unit_name> in, LLUnit<S2, unit_name>& out) \
|
||||
{ \
|
||||
typedef typename LLResultTypePromote<S1, S2>::type_t result_storage_t; \
|
||||
LLUnitLinearOps<result_storage_t> result = \
|
||||
LLUnitLinearOps<result_storage_t>(in.value()) conversion_operation; \
|
||||
out = LLUnit<S2, unit_name>((S2)result.mValue); \
|
||||
return result.mDivisor; \
|
||||
}
|
||||
|
||||
#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name) \
|
||||
typedef LLUnit<F32, ns::unit_name> F32##unit_name; \
|
||||
typedef LLUnitImplicit<F32, ns::unit_name> F32##unit_name##Implicit;\
|
||||
typedef LLUnit<F64, ns::unit_name> F64##unit_name; \
|
||||
typedef LLUnitImplicit<F64, ns::unit_name> F64##unit_name##Implicit;\
|
||||
typedef LLUnit<S32, ns::unit_name> S32##unit_name; \
|
||||
typedef LLUnitImplicit<S32, ns::unit_name> S32##unit_name##Implicit;\
|
||||
typedef LLUnit<S64, ns::unit_name> S64##unit_name; \
|
||||
typedef LLUnitImplicit<S64, ns::unit_name> S64##unit_name##Implicit;\
|
||||
typedef LLUnit<U32, ns::unit_name> U32##unit_name; \
|
||||
typedef LLUnitImplicit<U32, ns::unit_name> U32##unit_name##Implicit;\
|
||||
typedef LLUnit<U64, ns::unit_name> U64##unit_name; \
|
||||
typedef LLUnitImplicit<U64, ns::unit_name> U64##unit_name##Implicit
|
||||
|
||||
#endif //LL_UNITTYPE_H
|
||||
@@ -27,9 +27,7 @@
|
||||
|
||||
// We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.
|
||||
#if LL_WINDOWS
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include "llwin32headers.h"
|
||||
#endif
|
||||
|
||||
#include "lldefs.h"
|
||||
|
||||
42
indra/llcommon/llwin32headers.h
Normal file
42
indra/llcommon/llwin32headers.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @file llwin32headers.h
|
||||
* @brief sanitized include of windows header files
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLWINDOWS_H
|
||||
#define LL_LLWINDOWS_H
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
// reset to default, which is lean
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#undef NOMINMAX
|
||||
#endif
|
||||
|
||||
#endif
|
||||
40
indra/llcommon/llwin32headerslean.h
Normal file
40
indra/llcommon/llwin32headerslean.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @file llwin32headerslean.h
|
||||
* @brief sanitized include of windows header files
|
||||
*
|
||||
* $LicenseInfo:firstyear=2001&license=viewerlgpl$
|
||||
* Second Life Viewer Source Code
|
||||
* Copyright (C) 2010, Linden Research, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation;
|
||||
* version 2.1 of the License only.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
|
||||
* $/LicenseInfo$
|
||||
*/
|
||||
|
||||
#ifndef LL_LLWINDOWS_H
|
||||
#define LL_LLWINDOWS_H
|
||||
|
||||
#ifdef LL_WINDOWS
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#undef NOMINMAX
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -37,7 +37,7 @@
|
||||
LLWorkerThread::LLWorkerThread(const std::string& name, bool threaded, bool should_pause) :
|
||||
LLQueuedThread(name, threaded, should_pause)
|
||||
{
|
||||
mDeleteMutex = new LLMutex;
|
||||
mDeleteMutex = new LLMutex();
|
||||
}
|
||||
|
||||
LLWorkerThread::~LLWorkerThread()
|
||||
@@ -199,6 +199,7 @@ LLWorkerClass::LLWorkerClass(LLWorkerThread* workerthread, const std::string& na
|
||||
mWorkerClassName(name),
|
||||
mRequestHandle(LLWorkerThread::nullHandle()),
|
||||
mRequestPriority(LLWorkerThread::PRIORITY_NORMAL),
|
||||
mMutex(),
|
||||
mWorkFlags(0)
|
||||
{
|
||||
if (!mWorkerThread)
|
||||
@@ -345,10 +346,14 @@ bool LLWorkerClass::checkWork(bool aborting)
|
||||
}
|
||||
|
||||
LLQueuedThread::status_t status = workreq->getStatus();
|
||||
if (status == LLWorkerThread::STATUS_COMPLETE || status == LLWorkerThread::STATUS_ABORTED)
|
||||
if (status == LLWorkerThread::STATUS_ABORTED)
|
||||
{
|
||||
complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED);
|
||||
abort = true;
|
||||
}
|
||||
else if (status == LLWorkerThread::STATUS_COMPLETE)
|
||||
{
|
||||
complete = !(workreq->getFlags() & LLWorkerThread::FLAG_LOCKED);
|
||||
abort = status == LLWorkerThread::STATUS_ABORTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -449,6 +449,10 @@ BOOL LLImageBMP::decodeColorMask32( U8* dst, U8* src )
|
||||
mBitfieldMask[2] = 0x000000FF;
|
||||
}
|
||||
|
||||
if (getWidth() * getHeight() * 4 > getDataSize() - mBitmapOffset)
|
||||
{ //here we have situation when data size in src less than actually needed
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
S32 src_row_span = getWidth() * 4;
|
||||
S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4
|
||||
@@ -482,6 +486,11 @@ BOOL LLImageBMP::decodeColorTable8( U8* dst, U8* src )
|
||||
S32 src_row_span = getWidth() * 1;
|
||||
S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4
|
||||
|
||||
if ((getWidth() * getHeight()) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset)
|
||||
{ //here we have situation when data size in src less than actually needed
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for( S32 row = 0; row < getHeight(); row++ )
|
||||
{
|
||||
for( S32 col = 0; col < getWidth(); col++ )
|
||||
@@ -507,6 +516,11 @@ BOOL LLImageBMP::decodeTruecolor24( U8* dst, U8* src )
|
||||
S32 src_row_span = getWidth() * 3;
|
||||
S32 alignment_bytes = (3 * src_row_span) % 4; // round up to nearest multiple of 4
|
||||
|
||||
if ((getWidth() * getHeight() * 3) + getHeight() * alignment_bytes > getDataSize() - mBitmapOffset)
|
||||
{ //here we have situation when data size in src less than actually needed
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for( S32 row = 0; row < getHeight(); row++ )
|
||||
{
|
||||
for( S32 col = 0; col < getWidth(); col++ )
|
||||
|
||||
@@ -437,7 +437,13 @@ BOOL LLImageTGA::decodeTruecolorNonRle( LLImageRaw* raw_image, BOOL &alpha_opaqu
|
||||
// Origin is the bottom left
|
||||
U8* dst = raw_image->getData();
|
||||
U8* src = getData() + mDataOffset;
|
||||
|
||||
S32 pixels = getWidth() * getHeight();
|
||||
|
||||
if (pixels * (mIs15Bit ? 2 : getComponents()) > getDataSize() - (S32)mDataOffset)
|
||||
{ //here we have situation when data size in src less than actually needed
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (getComponents() == 4)
|
||||
{
|
||||
|
||||
@@ -35,18 +35,20 @@
|
||||
LLImageDecodeThread::LLImageDecodeThread(bool threaded)
|
||||
: LLQueuedThread("imagedecode", threaded)
|
||||
{
|
||||
mCreationMutex = new LLMutex();
|
||||
}
|
||||
|
||||
//virtual
|
||||
LLImageDecodeThread::~LLImageDecodeThread()
|
||||
{
|
||||
delete mCreationMutex ;
|
||||
}
|
||||
|
||||
// MAIN THREAD
|
||||
// virtual
|
||||
S32 LLImageDecodeThread::update(F32 max_time_ms)
|
||||
{
|
||||
LLMutexLock lock(&mCreationMutex);
|
||||
LLMutexLock lock(mCreationMutex);
|
||||
for (creation_list_t::iterator iter = mCreationList.begin();
|
||||
iter != mCreationList.end(); ++iter)
|
||||
{
|
||||
@@ -69,7 +71,7 @@ S32 LLImageDecodeThread::update(F32 max_time_ms)
|
||||
LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted* image,
|
||||
U32 priority, S32 discard, BOOL needs_aux, Responder* responder)
|
||||
{
|
||||
LLMutexLock lock(&mCreationMutex);
|
||||
LLMutexLock lock(mCreationMutex);
|
||||
handle_t handle = generateHandle();
|
||||
mCreationList.push_back(creation_info(handle, image, priority, discard, needs_aux, responder));
|
||||
return handle;
|
||||
@@ -79,7 +81,7 @@ LLImageDecodeThread::handle_t LLImageDecodeThread::decodeImage(LLImageFormatted*
|
||||
// Returns the size of the mutex guarded list as an indication of sanity
|
||||
S32 LLImageDecodeThread::tut_size()
|
||||
{
|
||||
LLMutexLock lock(&mCreationMutex);
|
||||
LLMutexLock lock(mCreationMutex);
|
||||
S32 res = mCreationList.size();
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ private:
|
||||
};
|
||||
typedef std::list<creation_info> creation_list_t;
|
||||
creation_list_t mCreationList;
|
||||
LLMutex mCreationMutex;
|
||||
LLMutex* mCreationMutex;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,16 +26,7 @@
|
||||
#ifndef LL_LLPNGWRAPPER_H
|
||||
#define LL_LLPNGWRAPPER_H
|
||||
|
||||
#if LL_STANDALONE || (LL_LINUX && defined(__x86_64__))
|
||||
#include <png.h>
|
||||
#else
|
||||
// Workaround for wrongly packaged prebuilt.
|
||||
#if _MSC_VER >= 1800
|
||||
#include <libpng16/png.h>
|
||||
#else
|
||||
#include "libpng15/png.h"
|
||||
#endif
|
||||
#endif
|
||||
#include "png.h"
|
||||
#include "llimage.h"
|
||||
|
||||
class LLPngWrapper
|
||||
|
||||
@@ -1083,7 +1083,7 @@ void LLParcel::startSale(const LLUUID& buyer_id, BOOL is_buyer_group)
|
||||
mGroupID.setNull();
|
||||
}
|
||||
mSaleTimerExpires.start();
|
||||
mSaleTimerExpires.setTimerExpirySec(DEFAULT_USEC_SALE_TIMEOUT / SEC_TO_MICROSEC);
|
||||
mSaleTimerExpires.setTimerExpirySec(U64Microseconds(DEFAULT_USEC_SALE_TIMEOUT));
|
||||
mStatus = OS_LEASE_PENDING;
|
||||
mClaimDate = time(NULL);
|
||||
setAuctionID(0);
|
||||
|
||||
@@ -71,6 +71,9 @@ public:
|
||||
void quantize8(F32 lower, F32 upper); // changes the vector to reflect quatization
|
||||
void loadIdentity(); // Loads the quaternion that represents the identity rotation
|
||||
|
||||
bool isEqualEps(const LLQuaternion &quat, F32 epsilon) const;
|
||||
bool isNotEqualEps(const LLQuaternion &quat, F32 epsilon) const;
|
||||
|
||||
const LLQuaternion& set(F32 x, F32 y, F32 z, F32 w); // Sets Quaternion to normalize(x, y, z, w)
|
||||
const LLQuaternion& set(const LLQuaternion &quat); // Copies Quaternion
|
||||
const LLQuaternion& set(const F32 *q); // Sets Quaternion to normalize(quat[VX], quat[VY], quat[VZ], quat[VW])
|
||||
@@ -239,6 +242,21 @@ inline void LLQuaternion::loadIdentity()
|
||||
mQ[VW] = 1.0f;
|
||||
}
|
||||
|
||||
inline bool LLQuaternion::isEqualEps(const LLQuaternion &quat, F32 epsilon) const
|
||||
{
|
||||
return ( fabs(mQ[VX] - quat.mQ[VX]) < epsilon
|
||||
&& fabs(mQ[VY] - quat.mQ[VY]) < epsilon
|
||||
&& fabs(mQ[VZ] - quat.mQ[VZ]) < epsilon
|
||||
&& fabs(mQ[VS] - quat.mQ[VS]) < epsilon );
|
||||
}
|
||||
|
||||
inline bool LLQuaternion::isNotEqualEps(const LLQuaternion &quat, F32 epsilon) const
|
||||
{
|
||||
return ( fabs(mQ[VX] - quat.mQ[VX]) > epsilon
|
||||
|| fabs(mQ[VY] - quat.mQ[VY]) > epsilon
|
||||
|| fabs(mQ[VZ] - quat.mQ[VZ]) > epsilon
|
||||
|| fabs(mQ[VS] - quat.mQ[VS]) > epsilon );
|
||||
}
|
||||
|
||||
inline const LLQuaternion& LLQuaternion::set(F32 x, F32 y, F32 z, F32 w)
|
||||
{
|
||||
|
||||
@@ -2532,6 +2532,8 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
|
||||
|
||||
U32 cur_influence = 0;
|
||||
LLVector4 wght(0,0,0,0);
|
||||
U32 joints[4] = {0,0,0,0};
|
||||
LLVector4 joints_with_weights(0,0,0,0);
|
||||
|
||||
while (joint != END_INFLUENCES && idx < weights.size())
|
||||
{
|
||||
@@ -2539,7 +2541,9 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
|
||||
influence |= ((U16) weights[idx++] << 8);
|
||||
|
||||
F32 w = llclamp((F32) influence / 65535.f, 0.f, 0.99999f);
|
||||
wght.mV[cur_influence++] = (F32) joint + w;
|
||||
wght.mV[cur_influence] = w;
|
||||
joints[cur_influence] = joint;
|
||||
cur_influence++;
|
||||
|
||||
if (cur_influence >= 4)
|
||||
{
|
||||
@@ -2550,8 +2554,16 @@ bool LLVolume::unpackVolumeFaces(std::istream& is, S32 size)
|
||||
joint = weights[idx++];
|
||||
}
|
||||
}
|
||||
|
||||
face.mWeights[cur_vertex].loadua(wght.mV);
|
||||
F32 wsum = wght.mV[VX] + wght.mV[VY] + wght.mV[VZ] + wght.mV[VW];
|
||||
if (wsum <= 0.f)
|
||||
{
|
||||
wght = LLVector4(0.99999f,0.f,0.f,0.f);
|
||||
}
|
||||
for (U32 k=0; k<4; k++)
|
||||
{
|
||||
joints_with_weights[k] = (F32) joints[k] + wght[k];
|
||||
}
|
||||
face.mWeights[cur_vertex].loadua(joints_with_weights.mV);
|
||||
|
||||
cur_vertex++;
|
||||
}
|
||||
@@ -2679,6 +2691,17 @@ void LLVolume::setMeshAssetLoaded(BOOL loaded)
|
||||
mIsMeshAssetLoaded = loaded;
|
||||
}
|
||||
|
||||
void LLVolume::copyFacesTo(std::vector<LLVolumeFace> &faces) const
|
||||
{
|
||||
faces = mVolumeFaces;
|
||||
}
|
||||
|
||||
void LLVolume::copyFacesFrom(const std::vector<LLVolumeFace> &faces)
|
||||
{
|
||||
mVolumeFaces = faces;
|
||||
mSculptLevel = 0;
|
||||
}
|
||||
|
||||
void LLVolume::copyVolumeFaces(const LLVolume* volume)
|
||||
{
|
||||
mVolumeFaces = volume->mVolumeFaces;
|
||||
@@ -4645,7 +4668,7 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
|
||||
|
||||
if (src.mNormals)
|
||||
{
|
||||
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) src.mNormals, vert_size);
|
||||
}
|
||||
|
||||
if(src.mTexCoords)
|
||||
@@ -4653,27 +4676,17 @@ LLVolumeFace& LLVolumeFace::operator=(const LLVolumeFace& src)
|
||||
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) src.mTexCoords, tc_size);
|
||||
}
|
||||
|
||||
allocateTangents(src.mTangents ? src.mNumVertices : 0);
|
||||
if (src.mTangents)
|
||||
{
|
||||
allocateTangents(src.mNumVertices);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mTangents, (F32*) src.mTangents, vert_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ll_aligned_free_16(mTangents);
|
||||
mTangents = NULL;
|
||||
LLVector4a::memcpyNonAliased16((F32*)mTangents, (F32*)src.mTangents, vert_size);
|
||||
}
|
||||
|
||||
allocateWeights(src.mWeights ? src.mNumVertices : 0);
|
||||
if (src.mWeights)
|
||||
{
|
||||
allocateWeights(src.mNumVertices);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mWeights, (F32*) src.mWeights, vert_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
ll_aligned_free_16(mWeights);
|
||||
mWeights = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (mNumIndices)
|
||||
@@ -4699,19 +4712,10 @@ LLVolumeFace::~LLVolumeFace()
|
||||
|
||||
void LLVolumeFace::freeData()
|
||||
{
|
||||
ll_aligned_free(mPositions);
|
||||
mPositions = NULL;
|
||||
|
||||
//normals and texture coordinates are part of the same buffer as mPositions, do not free them separately
|
||||
mNormals = NULL;
|
||||
mTexCoords = NULL;
|
||||
|
||||
ll_aligned_free_16(mIndices);
|
||||
mIndices = NULL;
|
||||
ll_aligned_free_16(mTangents);
|
||||
mTangents = NULL;
|
||||
ll_aligned_free_16(mWeights);
|
||||
mWeights = NULL;
|
||||
allocateVertices(0);
|
||||
allocateTangents(0);
|
||||
allocateWeights(0);
|
||||
allocateIndices(0);
|
||||
|
||||
delete mOctree;
|
||||
mOctree = NULL;
|
||||
@@ -4871,7 +4875,7 @@ void LLVolumeFace::optimize(F32 angle_cutoff)
|
||||
//
|
||||
if (new_face.mNumVertices <= mNumVertices)
|
||||
{
|
||||
llassert(new_face.mNumIndices == mNumIndices);
|
||||
llassert(new_face.mNumIndices == mNumIndices);
|
||||
swapData(new_face);
|
||||
}
|
||||
}
|
||||
@@ -5146,12 +5150,12 @@ public:
|
||||
void LLVolumeFace::cacheOptimize()
|
||||
{ //optimize for vertex cache according to Forsyth method:
|
||||
// http://home.comcast.net/~tom_forsyth/papers/fast_vert_cache_opt.html
|
||||
|
||||
|
||||
llassert(!mOptimized);
|
||||
mOptimized = TRUE;
|
||||
|
||||
LLVCacheLRU cache;
|
||||
|
||||
|
||||
if (mNumVertices < 3)
|
||||
{ //nothing to do
|
||||
return;
|
||||
@@ -5163,17 +5167,17 @@ void LLVolumeFace::cacheOptimize()
|
||||
//mapping of triangles do vertices
|
||||
std::vector<LLVCacheTriangleData> triangle_data;
|
||||
|
||||
triangle_data.resize(mNumIndices/3);
|
||||
triangle_data.resize(mNumIndices / 3);
|
||||
vertex_data.resize(mNumVertices);
|
||||
|
||||
for (U32 i = 0; i < (U32)mNumIndices; i++)
|
||||
{ //populate vertex data and triangle data arrays
|
||||
U16 idx = mIndices[i];
|
||||
U32 tri_idx = i/3;
|
||||
U32 tri_idx = i / 3;
|
||||
|
||||
vertex_data[idx].mTriangles.push_back(&(triangle_data[tri_idx]));
|
||||
vertex_data[idx].mIdx = idx;
|
||||
triangle_data[tri_idx].mVertex[i%3] = &(vertex_data[idx]);
|
||||
triangle_data[tri_idx].mVertex[i % 3] = &(vertex_data[idx]);
|
||||
}
|
||||
|
||||
/*F32 pre_acmr = 1.f;
|
||||
@@ -5222,7 +5226,7 @@ void LLVolumeFace::cacheOptimize()
|
||||
tri->complete();
|
||||
|
||||
U32 breaks = 0;
|
||||
for (U32 i = 1; i < (U32)mNumIndices/3; ++i)
|
||||
for (U32 i = 1; i < (U32)mNumIndices / 3; ++i)
|
||||
{
|
||||
cache.updateScores();
|
||||
tri = cache.mBestTriangle;
|
||||
@@ -5237,8 +5241,8 @@ void LLVolumeFace::cacheOptimize()
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cache.addTriangle(tri);
|
||||
new_indices.push_back(tri->mVertex[0]->mIdx);
|
||||
new_indices.push_back(tri->mVertex[1]->mIdx);
|
||||
@@ -5264,29 +5268,36 @@ void LLVolumeFace::cacheOptimize()
|
||||
{
|
||||
test_cache.addVertex(&vertex_data[mIndices[i]]);
|
||||
}
|
||||
|
||||
|
||||
post_acmr = (F32) test_cache.mMisses/(mNumIndices/3);
|
||||
}*/
|
||||
|
||||
//optimize for pre-TnL cache
|
||||
|
||||
|
||||
//allocate space for new buffer
|
||||
S32 num_verts = mNumVertices;
|
||||
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
|
||||
LLVector4a* pos = (LLVector4a*) ll_aligned_malloc(sizeof(LLVector4a)*2*num_verts+size, 64);
|
||||
LLVector4a* norm = pos + num_verts;
|
||||
LLVector2* tc = (LLVector2*) (norm + num_verts);
|
||||
|
||||
LLVector4a* wght = NULL;
|
||||
if (mWeights)
|
||||
LLVector4a* old_pos = mPositions;
|
||||
LLVector4a* old_norm = old_pos + num_verts;
|
||||
LLVector2* old_tc = (LLVector2*)(old_norm + num_verts);
|
||||
mPositions = NULL;
|
||||
if (old_pos)
|
||||
{
|
||||
wght = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
||||
allocateVertices(num_verts);
|
||||
}
|
||||
|
||||
LLVector4a* binorm = NULL;
|
||||
if (mTangents)
|
||||
LLVector4a* old_wght = mWeights;
|
||||
mWeights = NULL;
|
||||
if (old_wght)
|
||||
{
|
||||
binorm = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
||||
allocateWeights(num_verts);
|
||||
}
|
||||
|
||||
LLVector4a* old_binorm = mTangents;
|
||||
mTangents = NULL;
|
||||
if (old_binorm)
|
||||
{
|
||||
allocateTangents(num_verts);
|
||||
}
|
||||
|
||||
//allocate mapping of old indices to new indices
|
||||
@@ -5302,16 +5313,16 @@ void LLVolumeFace::cacheOptimize()
|
||||
new_idx[idx] = cur_idx;
|
||||
|
||||
//copy vertex data
|
||||
pos[cur_idx] = mPositions[idx];
|
||||
norm[cur_idx] = mNormals[idx];
|
||||
tc[cur_idx] = mTexCoords[idx];
|
||||
mPositions[cur_idx] = old_pos[idx];
|
||||
mNormals[cur_idx] = old_norm[idx];
|
||||
mTexCoords[cur_idx] = old_tc[idx];
|
||||
if (mWeights)
|
||||
{
|
||||
wght[cur_idx] = mWeights[idx];
|
||||
mWeights[cur_idx] = old_wght[idx];
|
||||
}
|
||||
if (mTangents)
|
||||
{
|
||||
binorm[cur_idx] = mTangents[idx];
|
||||
mTangents[cur_idx] = old_binorm[idx];
|
||||
}
|
||||
|
||||
cur_idx++;
|
||||
@@ -5323,16 +5334,11 @@ void LLVolumeFace::cacheOptimize()
|
||||
mIndices[i] = new_idx[mIndices[i]];
|
||||
}
|
||||
|
||||
ll_aligned_free(mPositions);
|
||||
// DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
||||
ll_aligned_free_16(mWeights);
|
||||
ll_aligned_free_16(mTangents);
|
||||
ll_aligned_free<64>(old_pos);
|
||||
ll_aligned_free_16(old_binorm);
|
||||
ll_aligned_free_16(old_wght);
|
||||
|
||||
mPositions = pos;
|
||||
mNormals = norm;
|
||||
mTexCoords = tc;
|
||||
mWeights = wght;
|
||||
mTangents = binorm;
|
||||
// DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
||||
|
||||
//std::string result = llformat("ACMR pre/post: %.3f/%.3f -- %d triangles %d breaks", pre_acmr, post_acmr, mNumIndices/3, breaks);
|
||||
//LL_INFOS() << result << LL_ENDL;
|
||||
@@ -6041,32 +6047,9 @@ void LLVolumeFace::createTangents()
|
||||
|
||||
void LLVolumeFace::resizeVertices(S32 num_verts)
|
||||
{
|
||||
ll_aligned_free(mPositions);
|
||||
//DO NOT free mNormals and mTexCoords as they are part of mPositions buffer
|
||||
ll_aligned_free_16(mTangents);
|
||||
|
||||
mTangents = NULL;
|
||||
|
||||
if (num_verts)
|
||||
{
|
||||
//pad texture coordinate block end to allow for QWORD reads
|
||||
S32 size = ((num_verts*sizeof(LLVector2)) + 0xF) & ~0xF;
|
||||
|
||||
mPositions = (LLVector4a*) ll_aligned_malloc(sizeof(LLVector4a)*2*num_verts+size, 64);
|
||||
mNormals = mPositions+num_verts;
|
||||
mTexCoords = (LLVector2*) (mNormals+num_verts);
|
||||
|
||||
ll_assert_aligned(mPositions, 64);
|
||||
}
|
||||
else
|
||||
{
|
||||
mPositions = NULL;
|
||||
mNormals = NULL;
|
||||
mTexCoords = NULL;
|
||||
}
|
||||
|
||||
allocateTangents(0);
|
||||
allocateVertices(num_verts);
|
||||
mNumVertices = num_verts;
|
||||
mNumAllocatedVertices = num_verts;
|
||||
}
|
||||
|
||||
void LLVolumeFace::pushVertex(const LLVolumeFace::VertexData& cv)
|
||||
@@ -6081,48 +6064,10 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
|
||||
if (new_verts > mNumAllocatedVertices)
|
||||
{
|
||||
//double buffer size on expansion
|
||||
new_verts *= 2;
|
||||
|
||||
S32 new_tc_size = ((new_verts*8)+0xF) & ~0xF;
|
||||
S32 old_tc_size = ((mNumVertices*8)+0xF) & ~0xF;
|
||||
|
||||
S32 old_vsize = mNumVertices*16;
|
||||
|
||||
S32 new_size = new_verts*16*2+new_tc_size;
|
||||
|
||||
LLVector4a* old_buf = mPositions;
|
||||
|
||||
mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64);
|
||||
mNormals = mPositions+new_verts;
|
||||
mTexCoords = (LLVector2*) (mNormals+new_verts);
|
||||
|
||||
//<singu>
|
||||
llassert(mNumVertices || (old_buf == NULL && mTangents == NULL));
|
||||
if (mNumVertices) // It turns out this can be zero, in which case old_buf (and mTangents) is NULL.
|
||||
{
|
||||
//</singu>
|
||||
|
||||
//positions
|
||||
LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize);
|
||||
|
||||
//normals
|
||||
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize);
|
||||
|
||||
//tex coords
|
||||
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tc_size);
|
||||
|
||||
ll_aligned_free(old_buf);
|
||||
|
||||
//<singu>
|
||||
}
|
||||
//</singu>
|
||||
allocateVertices(new_verts * 2, true);
|
||||
|
||||
//just clear tangents
|
||||
ll_aligned_free_16(mTangents);
|
||||
mTangents = NULL;
|
||||
|
||||
mNumAllocatedVertices = new_verts;
|
||||
|
||||
allocateTangents(0);
|
||||
}
|
||||
|
||||
mPositions[mNumVertices] = pos;
|
||||
@@ -6135,47 +6080,101 @@ void LLVolumeFace::pushVertex(const LLVector4a& pos, const LLVector4a& norm, con
|
||||
void LLVolumeFace::allocateTangents(S32 num_verts)
|
||||
{
|
||||
ll_aligned_free_16(mTangents);
|
||||
mTangents = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
||||
mTangents = NULL;
|
||||
if (num_verts)
|
||||
{
|
||||
mTangents = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVolumeFace::allocateWeights(S32 num_verts)
|
||||
{
|
||||
ll_aligned_free_16(mWeights);
|
||||
mWeights = (LLVector4a*) ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
||||
mWeights = NULL;
|
||||
if (num_verts)
|
||||
{
|
||||
mWeights = (LLVector4a*)ll_aligned_malloc_16(sizeof(LLVector4a)*num_verts);
|
||||
}
|
||||
}
|
||||
|
||||
void LLVolumeFace::resizeIndices(S32 num_indices)
|
||||
void LLVolumeFace::allocateVertices(S32 num_verts, bool copy)
|
||||
{
|
||||
if (!copy || !num_verts)
|
||||
{
|
||||
ll_aligned_free<64>(mPositions);
|
||||
mPositions = NULL;
|
||||
mNormals = NULL;
|
||||
mTexCoords = NULL;
|
||||
}
|
||||
|
||||
if (num_verts)
|
||||
{
|
||||
const U32 new_vsize = num_verts * sizeof(LLVector4a);
|
||||
const U32 new_nsize = new_vsize;
|
||||
const U32 new_tcsize = (num_verts * sizeof(LLVector2) + 0xF) & ~0xF;
|
||||
const U32 new_size = new_vsize + new_nsize + new_tcsize;
|
||||
|
||||
//allocate new buffer space
|
||||
LLVector4a* old_buf = mPositions;
|
||||
mPositions = (LLVector4a*)ll_aligned_malloc<64>(new_size);
|
||||
mNormals = mPositions + num_verts;
|
||||
mTexCoords = (LLVector2*)(mNormals + num_verts);
|
||||
|
||||
if (copy && old_buf)
|
||||
{
|
||||
U32 verts_to_copy = std::min(mNumVertices, num_verts);
|
||||
if (verts_to_copy)
|
||||
{
|
||||
const U32 old_vsize = verts_to_copy * sizeof(LLVector4a);
|
||||
const U32 old_nsize = old_vsize;
|
||||
const U32 old_tcsize = (verts_to_copy * sizeof(LLVector2) + 0xF) & ~0xF;
|
||||
|
||||
LLVector4a::memcpyNonAliased16((F32*)mPositions, (F32*)old_buf, old_vsize);
|
||||
LLVector4a::memcpyNonAliased16((F32*)mNormals, (F32*)(old_buf + mNumVertices), old_nsize);
|
||||
LLVector4a::memcpyNonAliased16((F32*)mTexCoords, (F32*)(old_buf + mNumVertices * 2), old_tcsize);
|
||||
}
|
||||
ll_aligned_free<64>(old_buf);
|
||||
}
|
||||
}
|
||||
mNumAllocatedVertices = num_verts;
|
||||
}
|
||||
|
||||
void LLVolumeFace::allocateIndices(S32 num_indices, bool copy)
|
||||
{
|
||||
if (num_indices == mNumIndices)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
S32 new_size = ((num_indices * sizeof(U16)) + 0xF) & ~0xF;
|
||||
if (copy && num_indices && mIndices && mNumIndices)
|
||||
{
|
||||
S32 old_size = ((mNumIndices * sizeof(U16)) + 0xF) & ~0xF;
|
||||
|
||||
mIndices = (U16*)ll_aligned_realloc_16(mIndices, new_size, old_size);
|
||||
|
||||
mNumIndices = num_indices;
|
||||
return;
|
||||
}
|
||||
ll_aligned_free_16(mIndices);
|
||||
|
||||
mIndices = NULL;
|
||||
if (num_indices)
|
||||
{
|
||||
//pad index block end to allow for QWORD reads
|
||||
S32 size = ((num_indices*sizeof(U16)) + 0xF) & ~0xF;
|
||||
|
||||
mIndices = (U16*) ll_aligned_malloc_16(size);
|
||||
}
|
||||
else
|
||||
{
|
||||
mIndices = NULL;
|
||||
mIndices = (U16*)ll_aligned_malloc_16(new_size);
|
||||
}
|
||||
|
||||
mNumIndices = num_indices;
|
||||
}
|
||||
void LLVolumeFace::resizeIndices(S32 num_indices)
|
||||
{
|
||||
allocateIndices(num_indices);
|
||||
}
|
||||
|
||||
void LLVolumeFace::pushIndex(const U16& idx)
|
||||
{
|
||||
S32 new_count = mNumIndices + 1;
|
||||
S32 new_size = ((new_count*2)+0xF) & ~0xF;
|
||||
allocateIndices(mNumIndices + 1, true);
|
||||
|
||||
S32 old_size = ((mNumIndices*2)+0xF) & ~0xF;
|
||||
if (new_size != old_size)
|
||||
{
|
||||
mIndices = (U16*) ll_aligned_realloc_16(mIndices, new_size, old_size);
|
||||
ll_assert_aligned(mIndices,16);
|
||||
}
|
||||
|
||||
mIndices[mNumIndices++] = idx;
|
||||
mIndices[mNumIndices-1] = idx;
|
||||
}
|
||||
|
||||
void LLVolumeFace::fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx)
|
||||
@@ -6212,24 +6211,7 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
|
||||
LL_ERRS() << "Cannot append empty face." << LL_ENDL;
|
||||
}
|
||||
|
||||
U32 old_vsize = mNumVertices*16;
|
||||
U32 new_vsize = new_count * 16;
|
||||
U32 old_tcsize = (mNumVertices*sizeof(LLVector2)+0xF) & ~0xF;
|
||||
U32 new_tcsize = (new_count*sizeof(LLVector2)+0xF) & ~0xF;
|
||||
U32 new_size = new_vsize * 2 + new_tcsize;
|
||||
|
||||
//allocate new buffer space
|
||||
LLVector4a* old_buf = mPositions;
|
||||
mPositions = (LLVector4a*) ll_aligned_malloc(new_size, 64);
|
||||
mNormals = mPositions + new_count;
|
||||
mTexCoords = (LLVector2*) (mNormals+new_count);
|
||||
|
||||
mNumAllocatedVertices = new_count;
|
||||
|
||||
LLVector4a::memcpyNonAliased16((F32*) mPositions, (F32*) old_buf, old_vsize);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mNormals, (F32*) (old_buf+mNumVertices), old_vsize);
|
||||
LLVector4a::memcpyNonAliased16((F32*) mTexCoords, (F32*) (old_buf+mNumVertices*2), old_tcsize);
|
||||
|
||||
allocateVertices(new_count, true);
|
||||
mNumVertices = new_count;
|
||||
|
||||
//get destination address of appended face
|
||||
@@ -6273,9 +6255,8 @@ void LLVolumeFace::appendFace(const LLVolumeFace& face, LLMatrix4& mat_in, LLMat
|
||||
|
||||
new_count = mNumIndices + face.mNumIndices;
|
||||
|
||||
//allocate new index buffer
|
||||
mIndices = (U16*) ll_aligned_realloc_16(mIndices, (new_count*sizeof(U16)+0xF) & ~0xF, (mNumIndices*sizeof(U16)+0xF) & ~0xF);
|
||||
|
||||
allocateIndices(mNumIndices + face.mNumIndices, true);
|
||||
|
||||
//get destination address into new index buffer
|
||||
U16* dst_idx = mIndices+mNumIndices;
|
||||
mNumIndices = new_count;
|
||||
@@ -6310,6 +6291,8 @@ BOOL LLVolumeFace::createSide(LLVolume* volume, BOOL partial_build)
|
||||
num_vertices = mNumS*mNumT;
|
||||
num_indices = (mNumS-1)*(mNumT-1)*6;
|
||||
|
||||
partial_build = (num_vertices > mNumVertices || num_indices > mNumIndices) ? FALSE : partial_build;
|
||||
|
||||
if (!partial_build)
|
||||
{
|
||||
resizeVertices(num_vertices);
|
||||
|
||||
@@ -194,8 +194,12 @@ const U8 LL_SCULPT_TYPE_MESH = 5;
|
||||
const U8 LL_SCULPT_TYPE_MASK = LL_SCULPT_TYPE_SPHERE | LL_SCULPT_TYPE_TORUS | LL_SCULPT_TYPE_PLANE |
|
||||
LL_SCULPT_TYPE_CYLINDER | LL_SCULPT_TYPE_MESH;
|
||||
|
||||
// for value checks, assign new value after adding new types
|
||||
const U8 LL_SCULPT_TYPE_MAX = LL_SCULPT_TYPE_MESH;
|
||||
|
||||
const U8 LL_SCULPT_FLAG_INVERT = 64;
|
||||
const U8 LL_SCULPT_FLAG_MIRROR = 128;
|
||||
const U8 LL_SCULPT_FLAG_MASK = LL_SCULPT_FLAG_INVERT | LL_SCULPT_FLAG_MIRROR;
|
||||
|
||||
const S32 LL_SCULPT_MESH_MAX_FACES = 8;
|
||||
|
||||
@@ -872,6 +876,8 @@ public:
|
||||
void resizeVertices(S32 num_verts);
|
||||
void allocateTangents(S32 num_verts);
|
||||
void allocateWeights(S32 num_verts);
|
||||
void allocateVertices(S32 num_verts, bool copy = false);
|
||||
void allocateIndices(S32 num_indices, bool copy = false);
|
||||
void resizeIndices(S32 num_indices);
|
||||
void fillFromLegacyData(std::vector<LLVolumeFace::VertexData>& v, std::vector<U16>& idx);
|
||||
|
||||
@@ -972,6 +978,7 @@ protected:
|
||||
~LLVolume(); // use unref
|
||||
|
||||
public:
|
||||
typedef std::vector<LLVolumeFace> face_list_t;
|
||||
|
||||
struct FaceParams
|
||||
{
|
||||
@@ -1044,11 +1051,16 @@ public:
|
||||
// conversion if *(LLVolume*) to LLVolume&
|
||||
const LLVolumeFace &getVolumeFace(const S32 f) const {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE
|
||||
|
||||
LLVolumeFace &getVolumeFace(const S32 f) {return mVolumeFaces[f];} // DO NOT DELETE VOLUME WHILE USING THIS REFERENCE, OR HOLD A POINTER TO THIS VOLUMEFACE
|
||||
|
||||
face_list_t& getVolumeFaces() { return mVolumeFaces; }
|
||||
U32 mFaceMask; // bit array of which faces exist in this volume
|
||||
LLVector3 mLODScaleBias; // vector for biasing LOD based on scale
|
||||
|
||||
void sculpt(U16 sculpt_width, U16 sculpt_height, S8 sculpt_components, const U8* sculpt_data, S32 sculpt_level);
|
||||
void copyVolumeFaces(const LLVolume* volume);
|
||||
void copyFacesTo(std::vector<LLVolumeFace> &faces) const;
|
||||
void copyFacesFrom(const std::vector<LLVolumeFace> &faces);
|
||||
void cacheOptimize();
|
||||
|
||||
private:
|
||||
|
||||
@@ -214,7 +214,7 @@ void LLVolumeMgr::useMutex()
|
||||
{
|
||||
if (!mDataMutex)
|
||||
{
|
||||
mDataMutex = new LLMutex;
|
||||
mDataMutex = new LLMutex();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -274,6 +274,19 @@ const LLMatrix4& LLMatrix4::invert(void)
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Convenience func for simplifying comparison-heavy code by
|
||||
// intentionally stomping values in [-FLT_EPS,FLT_EPS] to 0.0f
|
||||
//
|
||||
void LLMatrix4::condition(void)
|
||||
{
|
||||
U32 i;
|
||||
U32 j;
|
||||
for (i = 0; i < 3;i++)
|
||||
for (j = 0; j < 3;j++)
|
||||
mMatrix[i][j] = ((mMatrix[i][j] > -FLT_EPSILON)
|
||||
&& (mMatrix[i][j] < FLT_EPSILON)) ? 0.0f : mMatrix[i][j];
|
||||
}
|
||||
|
||||
LLVector4 LLMatrix4::getFwdRow4() const
|
||||
{
|
||||
return LLVector4(mMatrix[VX][VX], mMatrix[VX][VY], mMatrix[VX][VZ], mMatrix[VX][VW]);
|
||||
|
||||
@@ -180,6 +180,11 @@ public:
|
||||
const LLMatrix4& setTranslation(const LLVector4 &translation);
|
||||
const LLMatrix4& setTranslation(const LLVector3 &translation);
|
||||
|
||||
// Convenience func for simplifying comparison-heavy code by
|
||||
// intentionally stomping values [-FLT_EPS,FLT_EPS] to 0.0
|
||||
//
|
||||
void condition(void);
|
||||
|
||||
///////////////////////////
|
||||
//
|
||||
// Get properties of a matrix
|
||||
|
||||
@@ -162,12 +162,26 @@ void LLAres::getSrvRecords(const std::string &name, SrvResponder *resp)
|
||||
}
|
||||
|
||||
void LLAres::rewriteURI(const std::string &uri, UriRewriteResponder *resp)
|
||||
{
|
||||
LL_INFOS() << "Rewriting " << uri << LL_ENDL;
|
||||
{
|
||||
if (resp && uri.size())
|
||||
{
|
||||
LLURI* pURI = new LLURI(uri);
|
||||
|
||||
resp->mUri = LLURI(uri);
|
||||
search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(),
|
||||
RES_SRV, resp);
|
||||
resp->mUri = *pURI;
|
||||
|
||||
delete pURI;
|
||||
|
||||
if (!resp->mUri.scheme().size() || !resp->mUri.hostName().size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//LL_INFOS() << "LLAres::rewriteURI (" << uri << ") search: '" << "_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName() << "'" << LL_ENDL;
|
||||
|
||||
search("_" + resp->mUri.scheme() + "._tcp." + resp->mUri.hostName(), RES_SRV, resp);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
LLQueryResponder::LLQueryResponder()
|
||||
|
||||
@@ -93,5 +93,12 @@ private:
|
||||
|
||||
void LLAresListener::rewriteURI(const LLSD& data)
|
||||
{
|
||||
mAres->rewriteURI(data["uri"], new UriRewriteResponder(data));
|
||||
if (mAres)
|
||||
{
|
||||
mAres->rewriteURI(data["uri"], new UriRewriteResponder(data));
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_INFOS() << "LLAresListener::rewriteURI requested without Ares present. Ignoring: " << data << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,8 +190,8 @@ LLSD LLAssetRequest::getTerseDetails() const
|
||||
sd["asset_id"] = getUUID();
|
||||
sd["type_long"] = LLAssetType::lookupHumanReadable(getType());
|
||||
sd["type"] = LLAssetType::lookup(getType());
|
||||
sd["time"] = mTime;
|
||||
time_t timestamp = (time_t) mTime;
|
||||
sd["time"] = mTime.value();
|
||||
time_t timestamp = (time_t) mTime.value();
|
||||
std::ostringstream time_string;
|
||||
time_string << ctime(×tamp);
|
||||
sd["time_string"] = time_string.str();
|
||||
@@ -337,7 +337,7 @@ void LLAssetStorage::checkForTimeouts()
|
||||
|
||||
void LLAssetStorage::_cleanupRequests(BOOL all, S32 error)
|
||||
{
|
||||
F64 mt_secs = LLMessageSystem::getMessageTimeSeconds();
|
||||
F64Seconds mt_secs = LLMessageSystem::getMessageTimeSeconds();
|
||||
|
||||
request_list_t timed_out;
|
||||
S32 rt;
|
||||
@@ -638,6 +638,10 @@ void LLAssetStorage::downloadCompleteCallback(
|
||||
vfile.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// we will be deleting elements of mPendingDownloads which req might be part of, save id and type for reference
|
||||
LLUUID callback_id = req->getUUID();
|
||||
LLAssetType::EType callback_type = req->getType();
|
||||
|
||||
// find and callback ALL pending requests for this UUID
|
||||
// SJB: We process the callbacks in reverse order, I do not know if this is important,
|
||||
@@ -661,7 +665,7 @@ void LLAssetStorage::downloadCompleteCallback(
|
||||
LLAssetRequest* tmp = *curiter;
|
||||
if (tmp->mDownCallback)
|
||||
{
|
||||
tmp->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), tmp->mUserData, result, ext_status);
|
||||
tmp->mDownCallback(gAssetStorage->mVFS, callback_id, callback_type, tmp->mUserData, result, ext_status);
|
||||
}
|
||||
delete tmp;
|
||||
}
|
||||
@@ -1390,7 +1394,7 @@ void LLAssetStorage::storeAssetData(
|
||||
bool is_priority,
|
||||
bool store_local,
|
||||
bool user_waiting,
|
||||
F64 timeout)
|
||||
F64Seconds timeout)
|
||||
{
|
||||
LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL;
|
||||
// LLAssetStorage metric: Virtual base call
|
||||
@@ -1409,7 +1413,7 @@ void LLAssetStorage::storeAssetData(
|
||||
bool store_local,
|
||||
const LLUUID& requesting_agent_id,
|
||||
bool user_waiting,
|
||||
F64 timeout)
|
||||
F64Seconds timeout)
|
||||
{
|
||||
LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL;
|
||||
// LLAssetStorage metric: Virtual base call
|
||||
@@ -1427,7 +1431,7 @@ void LLAssetStorage::storeAssetData(
|
||||
bool temp_file,
|
||||
bool is_priority,
|
||||
bool user_waiting,
|
||||
F64 timeout)
|
||||
F64Seconds timeout)
|
||||
{
|
||||
LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL;
|
||||
// LLAssetStorage metric: Virtual base call
|
||||
@@ -1445,7 +1449,7 @@ void LLAssetStorage::storeAssetData(
|
||||
bool temp_file,
|
||||
bool is_priority,
|
||||
bool user_waiting,
|
||||
F64 timeout)
|
||||
F64Seconds timeout)
|
||||
{
|
||||
LL_WARNS() << "storeAssetData: wrong version called" << LL_ENDL;
|
||||
// LLAssetStorage metric: Virtual base call
|
||||
|
||||
@@ -49,7 +49,8 @@ class LLSD;
|
||||
|
||||
// anything that takes longer than this to download will abort.
|
||||
// HTTP Uploads also timeout if they take longer than this.
|
||||
const F32 LL_ASSET_STORAGE_TIMEOUT = 5 * 60.0f;
|
||||
const F32Minutes LL_ASSET_STORAGE_TIMEOUT(5);
|
||||
|
||||
|
||||
// Specific error codes
|
||||
const int LL_ERR_ASSET_REQUEST_FAILED = -1;
|
||||
@@ -102,7 +103,7 @@ public:
|
||||
|
||||
void setUUID(const LLUUID& id) { mUUID = id; }
|
||||
void setType(LLAssetType::EType type) { mType = type; }
|
||||
void setTimeout (F64 timeout) { mTimeout = timeout; }
|
||||
void setTimeout (F64Seconds timeout) { mTimeout = timeout; }
|
||||
|
||||
protected:
|
||||
LLUUID mUUID;
|
||||
@@ -118,8 +119,8 @@ public:
|
||||
BOOL mIsTemp;
|
||||
BOOL mIsLocal;
|
||||
BOOL mIsUserWaiting; // We don't want to try forever if a user is waiting for a result.
|
||||
F64 mTime; // Message system time
|
||||
F64 mTimeout; // Amount of time before timing out.
|
||||
F64Seconds mTime; // Message system time
|
||||
F64Seconds mTimeout; // Amount of time before timing out.
|
||||
BOOL mIsPriority;
|
||||
BOOL mDataSentInFirstPacket;
|
||||
BOOL mDataIsInVFS;
|
||||
@@ -162,7 +163,7 @@ public:
|
||||
void *mUserData;
|
||||
LLHost mHost;
|
||||
BOOL mIsTemp;
|
||||
F64 mTime; // Message system time
|
||||
F64Seconds mTime; // Message system time
|
||||
BOOL mIsPriority;
|
||||
BOOL mDataSentInFirstPacket;
|
||||
BOOL mDataIsInVFS;
|
||||
@@ -192,7 +193,7 @@ public:
|
||||
void *mUserData;
|
||||
LLHost mHost;
|
||||
BOOL mIsTemp;
|
||||
F64 mTime; // Message system time
|
||||
F64Seconds mTime; // Message system time
|
||||
BOOL mIsPriority;
|
||||
BOOL mDataSentInFirstPacket;
|
||||
BOOL mDataIsInVFS;
|
||||
@@ -284,7 +285,7 @@ public:
|
||||
bool is_priority = false,
|
||||
bool store_local = false,
|
||||
bool user_waiting= false,
|
||||
F64 timeout=LL_ASSET_STORAGE_TIMEOUT);
|
||||
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
|
||||
|
||||
/*
|
||||
* AssetID version
|
||||
@@ -300,7 +301,7 @@ public:
|
||||
bool store_local = false,
|
||||
const LLUUID& requesting_agent_id = LLUUID::null,
|
||||
bool user_waiting= false,
|
||||
F64 timeout=LL_ASSET_STORAGE_TIMEOUT);
|
||||
F64Seconds timeout=LL_ASSET_STORAGE_TIMEOUT);
|
||||
|
||||
virtual void checkForTimeouts();
|
||||
|
||||
@@ -408,7 +409,7 @@ public:
|
||||
bool temp_file = false,
|
||||
bool is_priority = false,
|
||||
bool user_waiting = false,
|
||||
F64 timeout = LL_ASSET_STORAGE_TIMEOUT);
|
||||
F64Seconds timeout = LL_ASSET_STORAGE_TIMEOUT);
|
||||
|
||||
/*
|
||||
* TransactionID version
|
||||
@@ -422,7 +423,7 @@ public:
|
||||
bool temp_file = false,
|
||||
bool is_priority = false,
|
||||
bool user_waiting = false,
|
||||
F64 timeout = LL_ASSET_STORAGE_TIMEOUT);
|
||||
F64Seconds timeout = LL_ASSET_STORAGE_TIMEOUT);
|
||||
|
||||
static void legacyGetDataCallback(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType, void *user_data, S32 status, LLExtStat ext_status);
|
||||
static void legacyStoreDataCallback(const LLUUID &uuid, void *user_data, S32 status, LLExtStat ext_status);
|
||||
|
||||
@@ -365,9 +365,7 @@ void LLAvatarNameCache::requestNamesViaCapability()
|
||||
|
||||
if (!url.empty())
|
||||
{
|
||||
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability requested "
|
||||
<< ids << " ids"
|
||||
<< LL_ENDL;
|
||||
LL_INFOS("AvNameCache") << "LLAvatarNameCache::requestNamesViaCapability getting " << ids << " ids" << LL_ENDL;
|
||||
LLHTTPClient::get(url, new LLAvatarNameResponder(agent_ids));
|
||||
}
|
||||
}
|
||||
@@ -391,8 +389,7 @@ void LLAvatarNameCache::legacyNameFetch(const LLUUID& agent_id,
|
||||
const std::string& full_name,
|
||||
bool is_group)
|
||||
{
|
||||
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::legacyNameFetch "
|
||||
<< "agent " << agent_id << " "
|
||||
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache agent " << agent_id << " "
|
||||
<< "full name '" << full_name << "'"
|
||||
<< ( is_group ? " [group]" : "" )
|
||||
<< LL_ENDL;
|
||||
@@ -439,12 +436,13 @@ void LLAvatarNameCache::cleanupClass()
|
||||
sCache.clear();
|
||||
}
|
||||
|
||||
void LLAvatarNameCache::importFile(std::istream& istr)
|
||||
bool LLAvatarNameCache::importFile(std::istream& istr)
|
||||
{
|
||||
LLSD data;
|
||||
if (LLSDParser::PARSE_FAILURE == LLSDSerialize::fromXMLDocument(data, istr))
|
||||
{
|
||||
return;
|
||||
LL_WARNS("AvNameCache") << "avatar name cache data xml parse failed" << LL_ENDL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// by convention LLSD storage is a map
|
||||
@@ -460,17 +458,19 @@ void LLAvatarNameCache::importFile(std::istream& istr)
|
||||
av_name.fromLLSD( it->second );
|
||||
sCache[agent_id] = av_name;
|
||||
}
|
||||
LL_INFOS("AvNameCache") << "loaded " << sCache.size() << LL_ENDL;
|
||||
|
||||
LL_INFOS("AvNameCache") << "LLAvatarNameCache loaded " << sCache.size() << LL_ENDL;
|
||||
// Some entries may have expired since the cache was stored,
|
||||
// but they will be flushed in the first call to eraseUnrefreshed
|
||||
// from LLAvatarNameResponder::idle
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLAvatarNameCache::exportFile(std::ostream& ostr)
|
||||
{
|
||||
LLSD agents;
|
||||
F64 max_unrefreshed = LLFrameTimer::getTotalSeconds() - MAX_UNREFRESHED_TIME;
|
||||
LL_INFOS("AvNameCache") << "LLAvatarNameCache at exit cache has " << sCache.size() << LL_ENDL;
|
||||
cache_t::const_iterator it = sCache.begin();
|
||||
for ( ; it != sCache.end(); ++it)
|
||||
{
|
||||
@@ -483,6 +483,7 @@ void LLAvatarNameCache::exportFile(std::ostream& ostr)
|
||||
agents[agent_id.asString()] = av_name.asLLSD();
|
||||
}
|
||||
}
|
||||
LL_INFOS("AvNameCache") << "LLAvatarNameCache returning " << agents.size() << LL_ENDL;
|
||||
LLSD data;
|
||||
data["agents"] = agents;
|
||||
LLSDSerialize::toPrettyXML(data, ostr);
|
||||
@@ -525,6 +526,7 @@ void LLAvatarNameCache::idle()
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS_ONCE("AvNameCache") << "LLAvatarNameCache still using legacy api" << LL_ENDL;
|
||||
requestNamesViaLegacy();
|
||||
}
|
||||
}
|
||||
@@ -562,24 +564,26 @@ void LLAvatarNameCache::eraseUnrefreshed()
|
||||
if (!sLastExpireCheck || sLastExpireCheck < max_unrefreshed)
|
||||
{
|
||||
sLastExpireCheck = now;
|
||||
|
||||
S32 expired = 0;
|
||||
for (cache_t::iterator it = sCache.begin(); it != sCache.end();)
|
||||
{
|
||||
const LLAvatarName& av_name = it->second;
|
||||
if (av_name.mExpires < max_unrefreshed)
|
||||
{
|
||||
LL_DEBUGS("AvNameCache") << it->first
|
||||
LL_DEBUGS("AvNameCacheExpired") << "LLAvatarNameCache " << it->first
|
||||
<< " user '" << av_name.getAccountName() << "' "
|
||||
<< "expired " << now - av_name.mExpires << " secs ago"
|
||||
<< LL_ENDL;
|
||||
sCache.erase(it++);
|
||||
expired++;
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
}
|
||||
LL_INFOS("AvNameCache") << sCache.size() << " cached avatar names" << LL_ENDL;
|
||||
LL_INFOS("AvNameCache") << "LLAvatarNameCache expired " << expired << " cached avatar names, "
|
||||
<< sCache.size() << " remaining" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -600,8 +604,7 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
|
||||
{
|
||||
if (!isRequestPending(agent_id))
|
||||
{
|
||||
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::get "
|
||||
<< "refresh agent " << agent_id
|
||||
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache refresh agent " << agent_id
|
||||
<< LL_ENDL;
|
||||
sAskQueue.insert(agent_id);
|
||||
}
|
||||
@@ -623,9 +626,7 @@ bool LLAvatarNameCache::get(const LLUUID& agent_id, LLAvatarName *av_name)
|
||||
|
||||
if (!isRequestPending(agent_id))
|
||||
{
|
||||
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache::get "
|
||||
<< "queue request for agent " << agent_id
|
||||
<< LL_ENDL;
|
||||
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache queue request for agent " << agent_id << LL_ENDL;
|
||||
sAskQueue.insert(agent_id);
|
||||
}
|
||||
|
||||
@@ -784,7 +785,7 @@ bool LLAvatarNameCache::expirationFromCacheControl(AIHTTPReceivedHeaders const&
|
||||
fromCacheControl = true;
|
||||
}
|
||||
}
|
||||
LL_DEBUGS("AvNameCache")
|
||||
LL_DEBUGS("AvNameCache") << "LLAvatarNameCache "
|
||||
<< ( fromCacheControl ? "expires based on cache control " : "default expiration " )
|
||||
<< "in " << *expires - now << " seconds"
|
||||
<< LL_ENDL;
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace LLAvatarNameCache
|
||||
void cleanupClass();
|
||||
|
||||
// Import/export the name cache to file.
|
||||
void importFile(std::istream& istr);
|
||||
bool importFile(std::istream& istr);
|
||||
void exportFile(std::ostream& ostr);
|
||||
|
||||
// On the viewer, usually a simulator capabilitity.
|
||||
|
||||
@@ -306,7 +306,7 @@ public:
|
||||
typedef std::list<LLSegment> segment_list_t;
|
||||
typedef segment_list_t::const_iterator const_segment_iterator_t;
|
||||
typedef segment_list_t::iterator segment_iterator_t;
|
||||
static size_t const npos = (size_t)-1; // (U8*)npos is used as a magic address.
|
||||
enum { npos = 0xffffffff };
|
||||
|
||||
LLBufferArray();
|
||||
~LLBufferArray();
|
||||
|
||||
@@ -61,12 +61,12 @@
|
||||
const S32 PING_START_BLOCK = 3; // How many pings behind we have to be to consider ourself blocked.
|
||||
const S32 PING_RELEASE_BLOCK = 2; // How many pings behind we have to be to consider ourself unblocked.
|
||||
|
||||
const F32 TARGET_PERIOD_LENGTH = 5.f; // seconds
|
||||
const F32 LL_DUPLICATE_SUPPRESSION_TIMEOUT = 60.f; //seconds - this can be long, as time-based cleanup is
|
||||
const F32Seconds TARGET_PERIOD_LENGTH(5.f);
|
||||
const F32Seconds LL_DUPLICATE_SUPPRESSION_TIMEOUT(60.f); //this can be long, as time-based cleanup is
|
||||
// only done when wrapping packetids, now...
|
||||
|
||||
LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id,
|
||||
const F32 circuit_heartbeat_interval, const F32 circuit_timeout)
|
||||
const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout)
|
||||
: mHost (host),
|
||||
mWrapID(0),
|
||||
mPacketsOutID(0),
|
||||
@@ -85,7 +85,7 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id,
|
||||
mPingsInTransit(0),
|
||||
mLastPingID(0),
|
||||
mPingDelay(INITIAL_PING_VALUE_MSEC),
|
||||
mPingDelayAveraged((F32)INITIAL_PING_VALUE_MSEC),
|
||||
mPingDelayAveraged(INITIAL_PING_VALUE_MSEC),
|
||||
mUnackedPacketCount(0),
|
||||
mUnackedPacketBytes(0),
|
||||
mLastPacketInTime(0.0),
|
||||
@@ -104,6 +104,7 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id,
|
||||
mPeakBPSOut(0.f),
|
||||
mPeriodTime(0.0),
|
||||
mExistenceTimer(),
|
||||
mAckCreationTime(0.f),
|
||||
mCurrentResendCount(0),
|
||||
mLastPacketGap(0),
|
||||
mHeartbeatInterval(circuit_heartbeat_interval),
|
||||
@@ -111,13 +112,13 @@ LLCircuitData::LLCircuitData(const LLHost &host, TPACKETID in_id,
|
||||
{
|
||||
// Need to guarantee that this time is up to date, we may be creating a circuit even though we haven't been
|
||||
// running a message system loop.
|
||||
F64 mt_sec = LLMessageSystem::getMessageTimeSeconds(TRUE);
|
||||
F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds(TRUE);
|
||||
F32 distribution_offset = ll_frand();
|
||||
|
||||
mPingTime = mt_sec;
|
||||
mLastPingSendTime = mt_sec + mHeartbeatInterval * distribution_offset;
|
||||
mLastPingReceivedTime = mt_sec;
|
||||
mNextPingSendTime = mLastPingSendTime + 0.95*mHeartbeatInterval + ll_frand(0.1f*mHeartbeatInterval);
|
||||
mNextPingSendTime = mLastPingSendTime + 0.95*mHeartbeatInterval + F32Seconds(ll_frand(0.1f*mHeartbeatInterval.value()));
|
||||
mPeriodTime = mt_sec;
|
||||
|
||||
mLocalEndPointID.generate();
|
||||
@@ -208,7 +209,7 @@ void LLCircuitData::ackReliablePacket(TPACKETID packet_num)
|
||||
}
|
||||
if (packetp->mCallback)
|
||||
{
|
||||
if (packetp->mTimeout < 0.f) // negative timeout will always return timeout even for successful ack, for debugging
|
||||
if (packetp->mTimeout < F32Seconds(0.f)) // negative timeout will always return timeout even for successful ack, for debugging
|
||||
{
|
||||
packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
|
||||
}
|
||||
@@ -242,7 +243,7 @@ void LLCircuitData::ackReliablePacket(TPACKETID packet_num)
|
||||
}
|
||||
if (packetp->mCallback)
|
||||
{
|
||||
if (packetp->mTimeout < 0.f) // negative timeout will always return timeout even for successful ack, for debugging
|
||||
if (packetp->mTimeout < F32Seconds(0.f)) // negative timeout will always return timeout even for successful ack, for debugging
|
||||
{
|
||||
packetp->mCallback(packetp->mCallbackData,LL_ERR_TCP_TIMEOUT);
|
||||
}
|
||||
@@ -269,7 +270,7 @@ void LLCircuitData::ackReliablePacket(TPACKETID packet_num)
|
||||
|
||||
|
||||
|
||||
S32 LLCircuitData::resendUnackedPackets(const F64 now)
|
||||
S32 LLCircuitData::resendUnackedPackets(const F64Seconds now)
|
||||
{
|
||||
S32 resent_packets = 0;
|
||||
LLReliablePacket *packetp;
|
||||
@@ -356,7 +357,7 @@ S32 LLCircuitData::resendUnackedPackets(const F64 now)
|
||||
// The new method, retry time based on ping
|
||||
if (packetp->mPingBasedRetry)
|
||||
{
|
||||
packetp->mExpirationTime = now + llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, (LL_RELIABLE_TIMEOUT_FACTOR * getPingDelayAveraged()));
|
||||
packetp->mExpirationTime = now + llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * getPingDelayAveraged()));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -428,10 +429,11 @@ S32 LLCircuitData::resendUnackedPackets(const F64 now)
|
||||
}
|
||||
|
||||
|
||||
LLCircuit::LLCircuit(const F32 circuit_heartbeat_interval, const F32 circuit_timeout) : mLastCircuit(NULL),
|
||||
mHeartbeatInterval(circuit_heartbeat_interval), mHeartbeatTimeout(circuit_timeout)
|
||||
{
|
||||
}
|
||||
LLCircuit::LLCircuit(const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout)
|
||||
: mLastCircuit(NULL),
|
||||
mHeartbeatInterval(circuit_heartbeat_interval),
|
||||
mHeartbeatTimeout(circuit_timeout)
|
||||
{}
|
||||
|
||||
LLCircuit::~LLCircuit()
|
||||
{
|
||||
@@ -522,17 +524,17 @@ void LLCircuitData::setAllowTimeout(BOOL allow)
|
||||
// Reset per-period counters if necessary.
|
||||
void LLCircuitData::checkPeriodTime()
|
||||
{
|
||||
F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
|
||||
F64 period_length = mt_sec - mPeriodTime;
|
||||
F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
|
||||
F64Seconds period_length = mt_sec - mPeriodTime;
|
||||
if ( period_length > TARGET_PERIOD_LENGTH)
|
||||
{
|
||||
F32 bps_in = (F32)(mBytesInThisPeriod * 8.f / period_length);
|
||||
F32 bps_in = F32Bits(mBytesInThisPeriod).value() / period_length.value();
|
||||
if (bps_in > mPeakBPSIn)
|
||||
{
|
||||
mPeakBPSIn = bps_in;
|
||||
}
|
||||
|
||||
F32 bps_out = (F32)(mBytesOutThisPeriod * 8.f / period_length);
|
||||
F32 bps_out = F32Bits(mBytesOutThisPeriod).value() / period_length.value();
|
||||
if (bps_out > mPeakBPSOut)
|
||||
{
|
||||
mPeakBPSOut = bps_out;
|
||||
@@ -540,23 +542,23 @@ void LLCircuitData::checkPeriodTime()
|
||||
|
||||
mBytesInLastPeriod = mBytesInThisPeriod;
|
||||
mBytesOutLastPeriod = mBytesOutThisPeriod;
|
||||
mBytesInThisPeriod = 0;
|
||||
mBytesOutThisPeriod = 0;
|
||||
mLastPeriodLength = (F32)period_length;
|
||||
mBytesInThisPeriod = S32Bytes(0);
|
||||
mBytesOutThisPeriod = S32Bytes(0);
|
||||
mLastPeriodLength = period_length;
|
||||
|
||||
mPeriodTime = mt_sec;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LLCircuitData::addBytesIn(S32 bytes)
|
||||
void LLCircuitData::addBytesIn(S32Bytes bytes)
|
||||
{
|
||||
mBytesIn += bytes;
|
||||
mBytesInThisPeriod += bytes;
|
||||
}
|
||||
|
||||
|
||||
void LLCircuitData::addBytesOut(S32 bytes)
|
||||
void LLCircuitData::addBytesOut(S32Bytes bytes)
|
||||
{
|
||||
mBytesOut += bytes;
|
||||
mBytesOutThisPeriod += bytes;
|
||||
@@ -585,7 +587,7 @@ void LLCircuitData::addReliablePacket(S32 mSocket, U8 *buf_ptr, S32 buf_len, LLR
|
||||
|
||||
void LLCircuit::resendUnackedPackets(S32& unacked_list_length, S32& unacked_list_size)
|
||||
{
|
||||
F64 now = LLMessageSystem::getMessageTimeSeconds();
|
||||
F64Seconds now = LLMessageSystem::getMessageTimeSeconds();
|
||||
unacked_list_length = 0;
|
||||
unacked_list_size = 0;
|
||||
|
||||
@@ -727,7 +729,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
|
||||
}
|
||||
else if (!receive_resent) // don't freak out over out-of-order reliable resends
|
||||
{
|
||||
U64 time = LLMessageSystem::getMessageTimeUsecs();
|
||||
U64Microseconds time = LLMessageSystem::getMessageTimeUsecs();
|
||||
TPACKETID index = mPacketsInID;
|
||||
S32 gap_count = 0;
|
||||
if ((index < id) && ((id - index) < 16))
|
||||
@@ -781,7 +783,7 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
|
||||
|
||||
void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys)
|
||||
{
|
||||
F64 cur_time = LLMessageSystem::getMessageTimeSeconds();
|
||||
F64Seconds cur_time = LLMessageSystem::getMessageTimeSeconds();
|
||||
S32 count = mPingSet.size();
|
||||
S32 cur = 0;
|
||||
|
||||
@@ -819,7 +821,7 @@ void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys)
|
||||
if (cdp->updateWatchDogTimers(msgsys))
|
||||
{
|
||||
// Randomize our pings a bit by doing some up to 5% early or late
|
||||
F64 dt = 0.95f*mHeartbeatInterval + ll_frand(0.1f*mHeartbeatInterval);
|
||||
F64Seconds dt = 0.95f*mHeartbeatInterval + F32Seconds(ll_frand(0.1f*mHeartbeatInterval.value()));
|
||||
|
||||
// Remove it, and reinsert it with the new next ping time.
|
||||
// Always remove before changing the sorting key.
|
||||
@@ -847,7 +849,7 @@ void LLCircuit::updateWatchDogTimers(LLMessageSystem *msgsys)
|
||||
|
||||
BOOL LLCircuitData::updateWatchDogTimers(LLMessageSystem *msgsys)
|
||||
{
|
||||
F64 cur_time = LLMessageSystem::getMessageTimeSeconds();
|
||||
F64Seconds cur_time = LLMessageSystem::getMessageTimeSeconds();
|
||||
mLastPingSendTime = cur_time;
|
||||
|
||||
if (!checkCircuitTimeout())
|
||||
@@ -964,12 +966,12 @@ BOOL LLCircuitData::updateWatchDogTimers(LLMessageSystem *msgsys)
|
||||
// be considered lost
|
||||
|
||||
LLCircuitData::packet_time_map::iterator it;
|
||||
U64 timeout = (U64)(1000000.0*llmin(LL_MAX_LOST_TIMEOUT, getPingDelayAveraged() * LL_LOST_TIMEOUT_FACTOR));
|
||||
U64Microseconds timeout = llmin(LL_MAX_LOST_TIMEOUT, F32Seconds(getPingDelayAveraged()) * LL_LOST_TIMEOUT_FACTOR);
|
||||
|
||||
U64 mt_usec = LLMessageSystem::getMessageTimeUsecs();
|
||||
U64Microseconds mt_usec = LLMessageSystem::getMessageTimeUsecs();
|
||||
for (it = mPotentialLostPackets.begin(); it != mPotentialLostPackets.end(); )
|
||||
{
|
||||
U64 delta_t_usec = mt_usec - (*it).second;
|
||||
U64Microseconds delta_t_usec = mt_usec - (*it).second;
|
||||
if (delta_t_usec > timeout)
|
||||
{
|
||||
// let's call this one a loss!
|
||||
@@ -1015,7 +1017,7 @@ void LLCircuitData::clearDuplicateList(TPACKETID oldest_id)
|
||||
// Do timeout checks on everything with an ID > mHighestPacketID.
|
||||
// This should be empty except for wrapping IDs. Thus, this should be
|
||||
// highly rare.
|
||||
U64 mt_usec = LLMessageSystem::getMessageTimeUsecs();
|
||||
U64Microseconds mt_usec = LLMessageSystem::getMessageTimeUsecs();
|
||||
|
||||
packet_time_map::iterator pit;
|
||||
for(pit = mRecentlyReceivedReliablePackets.upper_bound(mHighestPacketID);
|
||||
@@ -1026,8 +1028,8 @@ void LLCircuitData::clearDuplicateList(TPACKETID oldest_id)
|
||||
{
|
||||
LL_WARNS() << "Probably incorrectly timing out non-wrapped packets!" << LL_ENDL;
|
||||
}
|
||||
U64 delta_t_usec = mt_usec - (*pit).second;
|
||||
F64 delta_t_sec = delta_t_usec * SEC_PER_USEC;
|
||||
U64Microseconds delta_t_usec = mt_usec - (*pit).second;
|
||||
F64Seconds delta_t_sec = delta_t_usec;
|
||||
if (delta_t_sec > LL_DUPLICATE_SUPPRESSION_TIMEOUT)
|
||||
{
|
||||
// enough time has elapsed we're not likely to get a duplicate on this one
|
||||
@@ -1044,7 +1046,7 @@ void LLCircuitData::clearDuplicateList(TPACKETID oldest_id)
|
||||
|
||||
BOOL LLCircuitData::checkCircuitTimeout()
|
||||
{
|
||||
F64 time_since_last_ping = LLMessageSystem::getMessageTimeSeconds() - mLastPingReceivedTime;
|
||||
F64Seconds time_since_last_ping = LLMessageSystem::getMessageTimeSeconds() - mLastPingReceivedTime;
|
||||
|
||||
// Nota Bene: This needs to be turned off if you are debugging multiple simulators
|
||||
if (time_since_last_ping > mHeartbeatTimeout)
|
||||
@@ -1078,22 +1080,30 @@ BOOL LLCircuitData::collectRAck(TPACKETID packet_num)
|
||||
}
|
||||
|
||||
mAcks.push_back(packet_num);
|
||||
if (mAckCreationTime == 0)
|
||||
{
|
||||
mAckCreationTime = getAgeInSeconds();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// this method is called during the message system processAcks() to
|
||||
// send out any acks that did not get sent already.
|
||||
void LLCircuit::sendAcks()
|
||||
void LLCircuit::sendAcks(F32 collect_time)
|
||||
{
|
||||
collect_time = llclamp(collect_time, 0.f, LL_COLLECT_ACK_TIME_MAX);
|
||||
LLCircuitData* cd;
|
||||
circuit_data_map::iterator end = mSendAckMap.end();
|
||||
for(circuit_data_map::iterator it = mSendAckMap.begin(); it != end; ++it)
|
||||
circuit_data_map::iterator it = mSendAckMap.begin();
|
||||
while (it != mSendAckMap.end())
|
||||
{
|
||||
cd = (*it).second;
|
||||
|
||||
circuit_data_map::iterator cur_it = it++;
|
||||
cd = (*cur_it).second;
|
||||
S32 count = (S32)cd->mAcks.size();
|
||||
if(count > 0)
|
||||
F32 age = cd->getAgeInSeconds() - cd->mAckCreationTime;
|
||||
if (age > collect_time || count == 0)
|
||||
{
|
||||
if (count>0)
|
||||
{
|
||||
// send the packet acks
|
||||
S32 acks_this_packet = 0;
|
||||
for(S32 i = 0; i < count; ++i)
|
||||
@@ -1125,13 +1135,14 @@ void LLCircuit::sendAcks()
|
||||
LL_INFOS() << str.str() << LL_ENDL;
|
||||
}
|
||||
|
||||
// empty out the acks list
|
||||
cd->mAcks.clear();
|
||||
// empty out the acks list
|
||||
cd->mAcks.clear();
|
||||
cd->mAckCreationTime = 0.f;
|
||||
}
|
||||
// remove data map
|
||||
mSendAckMap.erase(cur_it);
|
||||
}
|
||||
}
|
||||
|
||||
// All acks have been sent, clear the map
|
||||
mSendAckMap.clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -1140,40 +1151,40 @@ std::ostream& operator<<(std::ostream& s, LLCircuitData& circuit)
|
||||
F32 age = circuit.mExistenceTimer.getElapsedTimeF32();
|
||||
|
||||
using namespace std;
|
||||
s << "Circuit " << circuit.mHost << " ";
|
||||
s << circuit.mRemoteID << " ";
|
||||
s << (circuit.mbAlive ? "Alive" : "Not Alive") << " ";
|
||||
s << (circuit.mbAllowTimeout ? "Timeout Allowed" : "Timeout Not Allowed");
|
||||
s << endl;
|
||||
s << "Circuit " << circuit.mHost << " "
|
||||
<< circuit.mRemoteID << " "
|
||||
<< (circuit.mbAlive ? "Alive" : "Not Alive") << " "
|
||||
<< (circuit.mbAllowTimeout ? "Timeout Allowed" : "Timeout Not Allowed")
|
||||
<< endl;
|
||||
|
||||
s << " Packets Lost: " << circuit.mPacketsLost;
|
||||
s << " Measured Ping: " << circuit.mPingDelay;
|
||||
s << " Averaged Ping: " << circuit.mPingDelayAveraged;
|
||||
s << endl;
|
||||
s << " Packets Lost: " << circuit.mPacketsLost
|
||||
<< " Measured Ping: " << circuit.mPingDelay
|
||||
<< " Averaged Ping: " << circuit.mPingDelayAveraged
|
||||
<< endl;
|
||||
|
||||
s << "Global In/Out " << S32(age) << " sec";
|
||||
s << " KBytes: " << circuit.mBytesIn / 1024 << "/" << circuit.mBytesOut / 1024;
|
||||
s << " Kbps: ";
|
||||
s << S32(circuit.mBytesIn * 8.f / circuit.mExistenceTimer.getElapsedTimeF32() / 1024.f);
|
||||
s << "/";
|
||||
s << S32(circuit.mBytesOut * 8.f / circuit.mExistenceTimer.getElapsedTimeF32() / 1024.f);
|
||||
s << " Packets: " << circuit.mPacketsIn << "/" << circuit.mPacketsOut;
|
||||
s << endl;
|
||||
s << "Global In/Out " << S32(age) << " sec"
|
||||
<< " KBytes: " << circuit.mBytesIn.valueInUnits<LLUnits::Kilobytes>() << "/" << circuit.mBytesOut.valueInUnits<LLUnits::Kilobytes>()
|
||||
<< " Kbps: "
|
||||
<< S32(circuit.mBytesIn.valueInUnits<LLUnits::Kilobits>() / circuit.mExistenceTimer.getElapsedTimeF32().value())
|
||||
<< "/"
|
||||
<< S32(circuit.mBytesOut.valueInUnits<LLUnits::Kilobits>() / circuit.mExistenceTimer.getElapsedTimeF32().value())
|
||||
<< " Packets: " << circuit.mPacketsIn << "/" << circuit.mPacketsOut
|
||||
<< endl;
|
||||
|
||||
s << "Recent In/Out " << S32(circuit.mLastPeriodLength) << " sec";
|
||||
s << " KBytes: ";
|
||||
s << circuit.mBytesInLastPeriod / 1024;
|
||||
s << "/";
|
||||
s << circuit.mBytesOutLastPeriod / 1024;
|
||||
s << " Kbps: ";
|
||||
s << S32(circuit.mBytesInLastPeriod * 8.f / circuit.mLastPeriodLength / 1024.f);
|
||||
s << "/";
|
||||
s << S32(circuit.mBytesOutLastPeriod * 8.f / circuit.mLastPeriodLength / 1024.f);
|
||||
s << " Peak kbps: ";
|
||||
s << S32(circuit.mPeakBPSIn / 1024.f);
|
||||
s << "/";
|
||||
s << S32(circuit.mPeakBPSOut / 1024.f);
|
||||
s << endl;
|
||||
s << "Recent In/Out " << circuit.mLastPeriodLength
|
||||
<< " KBytes: "
|
||||
<< circuit.mBytesInLastPeriod.valueInUnits<LLUnits::Kilobytes>()
|
||||
<< "/"
|
||||
<< circuit.mBytesOutLastPeriod.valueInUnits<LLUnits::Kilobytes>()
|
||||
<< " Kbps: "
|
||||
<< (S32)(circuit.mBytesInLastPeriod.valueInUnits<LLUnits::Kilobits>() / circuit.mLastPeriodLength.value())
|
||||
<< "/"
|
||||
<< (S32)(circuit.mBytesOutLastPeriod.valueInUnits<LLUnits::Kilobits>() / circuit.mLastPeriodLength.value())
|
||||
<< " Peak kbps: "
|
||||
<< S32(circuit.mPeakBPSIn / 1024.f)
|
||||
<< "/"
|
||||
<< S32(circuit.mPeakBPSOut / 1024.f)
|
||||
<< endl;
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -1268,11 +1279,11 @@ void LLCircuitData::setPacketInID(TPACKETID id)
|
||||
|
||||
void LLCircuitData::pingTimerStop(const U8 ping_id)
|
||||
{
|
||||
F64 mt_secs = LLMessageSystem::getMessageTimeSeconds();
|
||||
F64Seconds mt_secs = LLMessageSystem::getMessageTimeSeconds();
|
||||
|
||||
// Nota Bene: no averaging of ping times until we get a feel for how this works
|
||||
F64 time = mt_secs - mPingTime;
|
||||
if (time == 0.0)
|
||||
F64Seconds time = mt_secs - mPingTime;
|
||||
if (time == F32Seconds(0.0))
|
||||
{
|
||||
// Ack, we got our ping response on the same frame! Sigh, let's get a real time otherwise
|
||||
// all of our ping calculations will be skewed.
|
||||
@@ -1288,7 +1299,7 @@ void LLCircuitData::pingTimerStop(const U8 ping_id)
|
||||
delta_ping += 256;
|
||||
}
|
||||
|
||||
U32 msec = (U32) ((delta_ping*mHeartbeatInterval + time) * 1000.f);
|
||||
U32Milliseconds msec = delta_ping*mHeartbeatInterval + time;
|
||||
setPingDelay(msec);
|
||||
|
||||
mPingsInTransit = delta_ping;
|
||||
@@ -1317,13 +1328,13 @@ U32 LLCircuitData::getPacketsIn() const
|
||||
}
|
||||
|
||||
|
||||
S32 LLCircuitData::getBytesIn() const
|
||||
S32Bytes LLCircuitData::getBytesIn() const
|
||||
{
|
||||
return mBytesIn;
|
||||
}
|
||||
|
||||
|
||||
S32 LLCircuitData::getBytesOut() const
|
||||
S32Bytes LLCircuitData::getBytesOut() const
|
||||
{
|
||||
return mBytesOut;
|
||||
}
|
||||
@@ -1365,41 +1376,41 @@ BOOL LLCircuitData::getAllowTimeout() const
|
||||
}
|
||||
|
||||
|
||||
U32 LLCircuitData::getPingDelay() const
|
||||
U32Milliseconds LLCircuitData::getPingDelay() const
|
||||
{
|
||||
return mPingDelay;
|
||||
}
|
||||
|
||||
|
||||
F32 LLCircuitData::getPingInTransitTime()
|
||||
F32Milliseconds LLCircuitData::getPingInTransitTime()
|
||||
{
|
||||
// This may be inaccurate in the case of a circuit that was "dead" and then revived,
|
||||
// but only until the first round trip ping is sent - djs
|
||||
F32 time_since_ping_was_sent = 0;
|
||||
F32Milliseconds time_since_ping_was_sent(0);
|
||||
|
||||
if (mPingsInTransit)
|
||||
{
|
||||
time_since_ping_was_sent = (F32)((mPingsInTransit*mHeartbeatInterval - 1)
|
||||
+ (LLMessageSystem::getMessageTimeSeconds() - mPingTime))*1000.f;
|
||||
time_since_ping_was_sent = ((mPingsInTransit*mHeartbeatInterval - F32Seconds(1))
|
||||
+ (LLMessageSystem::getMessageTimeSeconds() - mPingTime));
|
||||
}
|
||||
|
||||
return time_since_ping_was_sent;
|
||||
}
|
||||
|
||||
|
||||
void LLCircuitData::setPingDelay(U32 ping)
|
||||
void LLCircuitData::setPingDelay(U32Milliseconds ping)
|
||||
{
|
||||
mPingDelay = ping;
|
||||
mPingDelayAveraged = llmax((F32)ping, getPingDelayAveraged());
|
||||
mPingDelayAveraged = llmax((F32Milliseconds)ping, getPingDelayAveraged());
|
||||
mPingDelayAveraged = ((1.f - LL_AVERAGED_PING_ALPHA) * mPingDelayAveraged)
|
||||
+ (LL_AVERAGED_PING_ALPHA * (F32) ping);
|
||||
+ (LL_AVERAGED_PING_ALPHA * (F32Milliseconds) ping);
|
||||
mPingDelayAveraged = llclamp(mPingDelayAveraged,
|
||||
LL_AVERAGED_PING_MIN,
|
||||
LL_AVERAGED_PING_MAX);
|
||||
}
|
||||
|
||||
|
||||
F32 LLCircuitData::getPingDelayAveraged()
|
||||
F32Milliseconds LLCircuitData::getPingDelayAveraged()
|
||||
{
|
||||
return llmin(llmax(getPingInTransitTime(), mPingDelayAveraged), LL_AVERAGED_PING_MAX);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "llerror.h"
|
||||
|
||||
#include "lltimer.h"
|
||||
#include "timing.h"
|
||||
#include "net.h"
|
||||
#include "llhost.h"
|
||||
#include "llpacketack.h"
|
||||
@@ -45,10 +44,10 @@
|
||||
// Constants
|
||||
//
|
||||
const F32 LL_AVERAGED_PING_ALPHA = 0.2f; // relaxation constant on ping running average
|
||||
const F32 LL_AVERAGED_PING_MAX = 2000; // msec
|
||||
const F32 LL_AVERAGED_PING_MIN = 100; // msec // IW: increased to avoid retransmits when a process is slow
|
||||
const F32Milliseconds LL_AVERAGED_PING_MAX(2000);
|
||||
const F32Milliseconds LL_AVERAGED_PING_MIN(100); // increased to avoid retransmits when a process is slow
|
||||
|
||||
const U32 INITIAL_PING_VALUE_MSEC = 1000; // initial value for the ping delay, or for ping delay for an unknown circuit
|
||||
const U32Milliseconds INITIAL_PING_VALUE_MSEC(1000); // initial value for the ping delay, or for ping delay for an unknown circuit
|
||||
|
||||
const TPACKETID LL_MAX_OUT_PACKET_ID = 0x01000000;
|
||||
const int LL_ERR_CIRCUIT_GONE = -23017;
|
||||
@@ -61,6 +60,7 @@ const U8 LL_PACKET_ID_SIZE = 6;
|
||||
|
||||
const S32 LL_MAX_RESENT_PACKETS_PER_FRAME = 100;
|
||||
const S32 LL_MAX_ACKED_PACKETS_PER_FRAME = 200;
|
||||
const F32 LL_COLLECT_ACK_TIME_MAX = 2.f;
|
||||
|
||||
//
|
||||
// Prototypes and Predefines
|
||||
@@ -78,10 +78,10 @@ class LLCircuitData
|
||||
{
|
||||
public:
|
||||
LLCircuitData(const LLHost &host, TPACKETID in_id,
|
||||
const F32 circuit_heartbeat_interval, const F32 circuit_timeout);
|
||||
const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout);
|
||||
~LLCircuitData();
|
||||
|
||||
S32 resendUnackedPackets(const F64 now);
|
||||
S32 resendUnackedPackets(const F64Seconds now);
|
||||
void clearDuplicateList(TPACKETID oldest_id);
|
||||
|
||||
|
||||
@@ -107,18 +107,18 @@ public:
|
||||
// mLocalEndPointID should only ever be setup in the LLCircuitData constructor
|
||||
const LLUUID& getLocalEndPointID() const { return mLocalEndPointID; }
|
||||
|
||||
U32 getPingDelay() const;
|
||||
U32Milliseconds getPingDelay() const;
|
||||
S32 getPingsInTransit() const { return mPingsInTransit; }
|
||||
|
||||
// ACCESSORS
|
||||
BOOL isAlive() const;
|
||||
BOOL isBlocked() const;
|
||||
BOOL getAllowTimeout() const;
|
||||
F32 getPingDelayAveraged();
|
||||
F32 getPingInTransitTime();
|
||||
F32Milliseconds getPingDelayAveraged();
|
||||
F32Milliseconds getPingInTransitTime();
|
||||
U32 getPacketsIn() const;
|
||||
S32 getBytesIn() const;
|
||||
S32 getBytesOut() const;
|
||||
S32Bytes getBytesIn() const;
|
||||
S32Bytes getBytesOut() const;
|
||||
U32 getPacketsOut() const;
|
||||
U32 getPacketsLost() const;
|
||||
TPACKETID getPacketOutID() const;
|
||||
@@ -126,10 +126,10 @@ public:
|
||||
F32 getAgeInSeconds() const;
|
||||
S32 getUnackedPacketCount() const { return mUnackedPacketCount; }
|
||||
S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; }
|
||||
F64 getNextPingSendTime() const { return mNextPingSendTime; }
|
||||
F64Seconds getNextPingSendTime() const { return mNextPingSendTime; }
|
||||
U32 getLastPacketGap() const { return mLastPacketGap; }
|
||||
LLHost getHost() const { return mHost; }
|
||||
F64 getLastPacketInTime() const { return mLastPacketInTime; }
|
||||
F64Seconds getLastPacketInTime() const { return mLastPacketInTime; }
|
||||
|
||||
LLThrottleGroup &getThrottleGroup() { return mThrottles; }
|
||||
|
||||
@@ -165,11 +165,11 @@ protected:
|
||||
TPACKETID nextPacketOutID();
|
||||
void setPacketInID(TPACKETID id);
|
||||
void checkPacketInID(TPACKETID id, BOOL receive_resent);
|
||||
void setPingDelay(U32 ping);
|
||||
void setPingDelay(U32Milliseconds ping);
|
||||
BOOL checkCircuitTimeout(); // Return FALSE if the circuit is dead and should be cleaned up
|
||||
|
||||
void addBytesIn(S32 bytes);
|
||||
void addBytesOut(S32 bytes);
|
||||
void addBytesIn(S32Bytes bytes);
|
||||
void addBytesOut(S32Bytes bytes);
|
||||
|
||||
U8 nextPingID() { mLastPingID++; return mLastPingID; }
|
||||
|
||||
@@ -220,24 +220,25 @@ protected:
|
||||
BOOL mBlocked; // Blocked is true if the circuit is hosed, i.e. far behind on pings
|
||||
|
||||
// Not sure what the difference between this and mLastPingSendTime is
|
||||
F64 mPingTime; // Time at which a ping was sent.
|
||||
F64Seconds mPingTime; // Time at which a ping was sent.
|
||||
|
||||
F64 mLastPingSendTime; // Time we last sent a ping
|
||||
F64 mLastPingReceivedTime; // Time we last received a ping
|
||||
F64 mNextPingSendTime; // Time to try and send the next ping
|
||||
S32 mPingsInTransit; // Number of pings in transit
|
||||
U8 mLastPingID; // ID of the last ping that we sent out
|
||||
F64Seconds mLastPingSendTime; // Time we last sent a ping
|
||||
F64Seconds mLastPingReceivedTime; // Time we last received a ping
|
||||
F64Seconds mNextPingSendTime; // Time to try and send the next ping
|
||||
S32 mPingsInTransit; // Number of pings in transit
|
||||
U8 mLastPingID; // ID of the last ping that we sent out
|
||||
|
||||
|
||||
// Used for determining the resend time for reliable resends.
|
||||
U32 mPingDelay; // raw ping delay
|
||||
F32 mPingDelayAveraged; // averaged ping delay (fast attack/slow decay)
|
||||
U32Milliseconds mPingDelay; // raw ping delay
|
||||
F32Milliseconds mPingDelayAveraged; // averaged ping delay (fast attack/slow decay)
|
||||
|
||||
typedef std::map<TPACKETID, U64> packet_time_map;
|
||||
typedef std::map<TPACKETID, U64Microseconds> packet_time_map;
|
||||
|
||||
packet_time_map mPotentialLostPackets;
|
||||
packet_time_map mRecentlyReceivedReliablePackets;
|
||||
std::vector<TPACKETID> mAcks;
|
||||
F32 mAckCreationTime; // first ack creation time
|
||||
|
||||
typedef std::map<TPACKETID, LLReliablePacket *> reliable_map;
|
||||
typedef reliable_map::iterator reliable_iter;
|
||||
@@ -248,7 +249,7 @@ protected:
|
||||
S32 mUnackedPacketCount;
|
||||
S32 mUnackedPacketBytes;
|
||||
|
||||
F64 mLastPacketInTime; // Time of last packet arrival
|
||||
F64Seconds mLastPacketInTime; // Time of last packet arrival
|
||||
|
||||
LLUUID mLocalEndPointID;
|
||||
|
||||
@@ -260,24 +261,24 @@ protected:
|
||||
U32 mPacketsOut;
|
||||
U32 mPacketsIn;
|
||||
S32 mPacketsLost;
|
||||
S32 mBytesIn;
|
||||
S32 mBytesOut;
|
||||
S32Bytes mBytesIn,
|
||||
mBytesOut;
|
||||
|
||||
F32 mLastPeriodLength; // seconds
|
||||
S32 mBytesInLastPeriod;
|
||||
S32 mBytesOutLastPeriod;
|
||||
S32 mBytesInThisPeriod;
|
||||
S32 mBytesOutThisPeriod;
|
||||
F32Seconds mLastPeriodLength;
|
||||
S32Bytes mBytesInLastPeriod;
|
||||
S32Bytes mBytesOutLastPeriod;
|
||||
S32Bytes mBytesInThisPeriod;
|
||||
S32Bytes mBytesOutThisPeriod;
|
||||
F32 mPeakBPSIn; // bits per second, max of all period bps
|
||||
F32 mPeakBPSOut; // bits per second, max of all period bps
|
||||
F64 mPeriodTime;
|
||||
F64Seconds mPeriodTime;
|
||||
LLTimer mExistenceTimer; // initialized when circuit created, used to track bandwidth numbers
|
||||
|
||||
S32 mCurrentResendCount; // Number of resent packets since last spam
|
||||
U32 mLastPacketGap; // Gap in sequence number of last packet.
|
||||
|
||||
const F32 mHeartbeatInterval;
|
||||
const F32 mHeartbeatTimeout;
|
||||
const F32Seconds mHeartbeatInterval;
|
||||
const F32Seconds mHeartbeatTimeout;
|
||||
};
|
||||
|
||||
|
||||
@@ -287,7 +288,7 @@ class LLCircuit
|
||||
{
|
||||
public:
|
||||
// CREATORS
|
||||
LLCircuit(const F32 circuit_heartbeat_interval, const F32 circuit_timeout);
|
||||
LLCircuit(const F32Seconds circuit_heartbeat_interval, const F32Seconds circuit_timeout);
|
||||
~LLCircuit();
|
||||
|
||||
// ACCESSORS
|
||||
@@ -303,7 +304,7 @@ public:
|
||||
|
||||
// this method is called during the message system processAcks()
|
||||
// to send out any acks that did not get sent already.
|
||||
void sendAcks();
|
||||
void sendAcks(F32 collect_time);
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& s, LLCircuit &circuit);
|
||||
void getInfo(LLSD& info) const;
|
||||
@@ -346,7 +347,7 @@ protected:
|
||||
mutable LLCircuitData* mLastCircuit;
|
||||
|
||||
private:
|
||||
const F32 mHeartbeatInterval;
|
||||
const F32 mHeartbeatTimeout;
|
||||
const F32Seconds mHeartbeatInterval;
|
||||
const F32Seconds mHeartbeatTimeout;
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace
|
||||
{
|
||||
typedef std::map<LLHost, LLHTTPSender*> SenderMap;
|
||||
static SenderMap senderMap;
|
||||
static LLHTTPSender* defaultSender = new LLHTTPSender();
|
||||
static LLPointer<LLHTTPSender> defaultSender(new LLHTTPSender());
|
||||
}
|
||||
|
||||
//virtual
|
||||
@@ -90,6 +90,5 @@ void LLHTTPSender::clearSender(const LLHost& host)
|
||||
//static
|
||||
void LLHTTPSender::setDefaultSender(LLHTTPSender* sender)
|
||||
{
|
||||
delete defaultSender;
|
||||
defaultSender = sender;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
class LLHost;
|
||||
class LLSD;
|
||||
|
||||
class LLHTTPSender
|
||||
class LLHTTPSender : public LLThreadSafeRefCount
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ LLReliablePacket::LLReliablePacket(
|
||||
mHost = params->mHost;
|
||||
mRetries = params->mRetries;
|
||||
mPingBasedRetry = params->mPingBasedRetry;
|
||||
mTimeout = params->mTimeout;
|
||||
mTimeout = F32Seconds(params->mTimeout);
|
||||
mCallback = params->mCallback;
|
||||
mCallbackData = params->mCallbackData;
|
||||
mMessageName = params->mMessageName;
|
||||
@@ -59,13 +59,13 @@ LLReliablePacket::LLReliablePacket(
|
||||
{
|
||||
mRetries = 0;
|
||||
mPingBasedRetry = TRUE;
|
||||
mTimeout = 0.f;
|
||||
mTimeout = F32Seconds(0.f);
|
||||
mCallback = NULL;
|
||||
mCallbackData = NULL;
|
||||
mMessageName = NULL;
|
||||
}
|
||||
|
||||
mExpirationTime = (F64)((S64)totalTime())/1000000.0 + mTimeout;
|
||||
mExpirationTime = (F64Seconds)totalTime() + mTimeout;
|
||||
mPacketID = ntohl(*((U32*)(&buf_ptr[PHL_PACKET_ID])));
|
||||
|
||||
mSocket = socket;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#define LL_LLPACKETACK_H
|
||||
|
||||
#include "llhost.h"
|
||||
#include "llunits.h"
|
||||
|
||||
class LLReliablePacketParams
|
||||
{
|
||||
@@ -35,7 +36,7 @@ public:
|
||||
LLHost mHost;
|
||||
S32 mRetries;
|
||||
BOOL mPingBasedRetry;
|
||||
F32 mTimeout;
|
||||
F32Seconds mTimeout;
|
||||
void (*mCallback)(void **,S32);
|
||||
void** mCallbackData;
|
||||
char* mMessageName;
|
||||
@@ -53,7 +54,7 @@ public:
|
||||
mHost.invalidate();
|
||||
mRetries = 0;
|
||||
mPingBasedRetry = TRUE;
|
||||
mTimeout = 0.f;
|
||||
mTimeout = F32Seconds(0.f);
|
||||
mCallback = NULL;
|
||||
mCallbackData = NULL;
|
||||
mMessageName = NULL;
|
||||
@@ -63,7 +64,7 @@ public:
|
||||
const LLHost& host,
|
||||
S32 retries,
|
||||
BOOL ping_based_retry,
|
||||
F32 timeout,
|
||||
F32Seconds timeout,
|
||||
void (*callback)(void**,S32),
|
||||
void** callback_data, char* name)
|
||||
{
|
||||
@@ -98,7 +99,7 @@ protected:
|
||||
LLHost mHost;
|
||||
S32 mRetries;
|
||||
BOOL mPingBasedRetry;
|
||||
F32 mTimeout;
|
||||
F32Seconds mTimeout;
|
||||
void (*mCallback)(void**,S32);
|
||||
void** mCallbackData;
|
||||
char* mMessageName;
|
||||
@@ -108,7 +109,7 @@ protected:
|
||||
|
||||
TPACKETID mPacketID;
|
||||
|
||||
F64 mExpirationTime;
|
||||
F64Seconds mExpirationTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "llpacketbuffer.h"
|
||||
|
||||
#include "net.h"
|
||||
#include "timing.h"
|
||||
#include "lltimer.h"
|
||||
#include "llhost.h"
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
@@ -41,7 +41,6 @@
|
||||
#include "llproxy.h"
|
||||
#include "llrand.h"
|
||||
#include "message.h"
|
||||
#include "timing.h"
|
||||
#include "u64.h"
|
||||
|
||||
//<edit>
|
||||
|
||||
@@ -115,9 +115,9 @@ S32 LLProxy::proxyHandshake(LLHost proxy)
|
||||
U32 request_size = socks_username.size() + socks_password.size() + 3;
|
||||
char * password_auth = new char[request_size];
|
||||
password_auth[0] = 0x01;
|
||||
password_auth[1] = (char)socks_username.size();
|
||||
password_auth[1] = static_cast<char>(socks_username.size());
|
||||
memcpy(&password_auth[2], socks_username.c_str(), socks_username.size());
|
||||
password_auth[socks_username.size() + 2] = (char)socks_password.size();
|
||||
password_auth[socks_username.size() + 2] = static_cast<char>(socks_password.size());
|
||||
memcpy(&password_auth[socks_username.size() + 3], socks_password.c_str(), socks_password.size());
|
||||
|
||||
authmethod_password_reply_t password_reply;
|
||||
|
||||
@@ -53,8 +53,8 @@ F32 LLThrottle::getAvailable()
|
||||
{
|
||||
// use a temporary bits_available
|
||||
// since we don't want to change mBitsAvailable every time
|
||||
F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime);
|
||||
return mAvailable + (mRate * elapsed_time);
|
||||
F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime;
|
||||
return mAvailable + (mRate * elapsed_time.value());
|
||||
}
|
||||
|
||||
BOOL LLThrottle::checkOverflow(const F32 amount)
|
||||
@@ -65,8 +65,8 @@ BOOL LLThrottle::checkOverflow(const F32 amount)
|
||||
|
||||
// use a temporary bits_available
|
||||
// since we don't want to change mBitsAvailable every time
|
||||
F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime);
|
||||
F32 amount_available = mAvailable + (mRate * elapsed_time);
|
||||
F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime;
|
||||
F32 amount_available = mAvailable + (mRate * elapsed_time.value());
|
||||
|
||||
if ((amount_available >= lookahead_amount) || (amount_available > amount))
|
||||
{
|
||||
@@ -80,17 +80,17 @@ BOOL LLThrottle::checkOverflow(const F32 amount)
|
||||
|
||||
BOOL LLThrottle::throttleOverflow(const F32 amount)
|
||||
{
|
||||
F32 elapsed_time;
|
||||
F32Seconds elapsed_time;
|
||||
F32 lookahead_amount;
|
||||
BOOL retval = TRUE;
|
||||
|
||||
lookahead_amount = mRate * mLookaheadSecs;
|
||||
|
||||
F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
|
||||
elapsed_time = (F32)(mt_sec - mLastSendTime);
|
||||
F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
|
||||
elapsed_time = mt_sec - mLastSendTime;
|
||||
mLastSendTime = mt_sec;
|
||||
|
||||
mAvailable += mRate * elapsed_time;
|
||||
mAvailable += mRate * elapsed_time.value();
|
||||
|
||||
if (mAvailable >= lookahead_amount)
|
||||
{
|
||||
@@ -222,7 +222,7 @@ void LLThrottleGroup::unpackThrottle(LLDataPacker &dp)
|
||||
// into NOT resetting the system.
|
||||
void LLThrottleGroup::resetDynamicAdjust()
|
||||
{
|
||||
F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
|
||||
F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
|
||||
S32 i;
|
||||
for (i = 0; i < TC_EOF; i++)
|
||||
{
|
||||
@@ -269,8 +269,8 @@ S32 LLThrottleGroup::getAvailable(S32 throttle_cat)
|
||||
|
||||
// use a temporary bits_available
|
||||
// since we don't want to change mBitsAvailable every time
|
||||
F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
|
||||
F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
|
||||
F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat];
|
||||
F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time.value());
|
||||
|
||||
if (bits_available >= lookahead_bits)
|
||||
{
|
||||
@@ -294,8 +294,8 @@ BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
|
||||
|
||||
// use a temporary bits_available
|
||||
// since we don't want to change mBitsAvailable every time
|
||||
F32 elapsed_time = (F32)(LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat]);
|
||||
F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time);
|
||||
F32Seconds elapsed_time = LLMessageSystem::getMessageTimeSeconds() - mLastSendTime[throttle_cat];
|
||||
F32 bits_available = mBitsAvailable[throttle_cat] + (category_bps * elapsed_time.value());
|
||||
|
||||
if (bits_available >= lookahead_bits)
|
||||
{
|
||||
@@ -315,7 +315,7 @@ BOOL LLThrottleGroup::checkOverflow(S32 throttle_cat, F32 bits)
|
||||
|
||||
BOOL LLThrottleGroup::throttleOverflow(S32 throttle_cat, F32 bits)
|
||||
{
|
||||
F32 elapsed_time;
|
||||
F32Seconds elapsed_time;
|
||||
F32 category_bps;
|
||||
F32 lookahead_bits;
|
||||
BOOL retval = TRUE;
|
||||
@@ -323,10 +323,10 @@ BOOL LLThrottleGroup::throttleOverflow(S32 throttle_cat, F32 bits)
|
||||
category_bps = mCurrentBPS[throttle_cat];
|
||||
lookahead_bits = category_bps * THROTTLE_LOOKAHEAD_TIME;
|
||||
|
||||
F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
|
||||
elapsed_time = (F32)(mt_sec - mLastSendTime[throttle_cat]);
|
||||
F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
|
||||
elapsed_time = mt_sec - mLastSendTime[throttle_cat];
|
||||
mLastSendTime[throttle_cat] = mt_sec;
|
||||
mBitsAvailable[throttle_cat] += category_bps * elapsed_time;
|
||||
mBitsAvailable[throttle_cat] += category_bps * elapsed_time.value();
|
||||
|
||||
if (mBitsAvailable[throttle_cat] >= lookahead_bits)
|
||||
{
|
||||
@@ -356,7 +356,7 @@ BOOL LLThrottleGroup::throttleOverflow(S32 throttle_cat, F32 bits)
|
||||
|
||||
BOOL LLThrottleGroup::dynamicAdjust()
|
||||
{
|
||||
const F32 DYNAMIC_ADJUST_TIME = 1.0f; // seconds
|
||||
const F32Seconds DYNAMIC_ADJUST_TIME(1.0f);
|
||||
const F32 CURRENT_PERIOD_WEIGHT = .25f; // how much weight to give to last period while determining BPS utilization
|
||||
const F32 BUSY_PERCENT = 0.75f; // if use more than this fraction of BPS, you are busy
|
||||
const F32 IDLE_PERCENT = 0.70f; // if use less than this fraction, you are "idle"
|
||||
@@ -365,7 +365,7 @@ BOOL LLThrottleGroup::dynamicAdjust()
|
||||
|
||||
S32 i;
|
||||
|
||||
F64 mt_sec = LLMessageSystem::getMessageTimeSeconds();
|
||||
F64Seconds mt_sec = LLMessageSystem::getMessageTimeSeconds();
|
||||
|
||||
// Only dynamically adjust every few seconds
|
||||
if ((mt_sec - mDynamicAdjustTime) < DYNAMIC_ADJUST_TIME)
|
||||
@@ -405,7 +405,7 @@ BOOL LLThrottleGroup::dynamicAdjust()
|
||||
for (i = 0; i < TC_EOF; i++)
|
||||
{
|
||||
// Is this a busy channel?
|
||||
if (mBitsSentHistory[i] >= BUSY_PERCENT * DYNAMIC_ADJUST_TIME * mCurrentBPS[i])
|
||||
if (mBitsSentHistory[i] >= BUSY_PERCENT * DYNAMIC_ADJUST_TIME.value() * mCurrentBPS[i])
|
||||
{
|
||||
// this channel is busy
|
||||
channels_busy = TRUE;
|
||||
@@ -418,7 +418,7 @@ BOOL LLThrottleGroup::dynamicAdjust()
|
||||
}
|
||||
|
||||
// Is this an idle channel?
|
||||
if ((mBitsSentHistory[i] < IDLE_PERCENT * DYNAMIC_ADJUST_TIME * mCurrentBPS[i]) &&
|
||||
if ((mBitsSentHistory[i] < IDLE_PERCENT * DYNAMIC_ADJUST_TIME.value() * mCurrentBPS[i]) &&
|
||||
(mBitsAvailable[i] > 0))
|
||||
{
|
||||
channel_idle[i] = TRUE;
|
||||
@@ -462,7 +462,7 @@ BOOL LLThrottleGroup::dynamicAdjust()
|
||||
// Therefore it's a candidate to give up some bandwidth.
|
||||
// Figure out how much bandwidth it has been using, and how
|
||||
// much is available to steal.
|
||||
used_bps = mBitsSentHistory[i] / DYNAMIC_ADJUST_TIME;
|
||||
used_bps = mBitsSentHistory[i] / DYNAMIC_ADJUST_TIME.value();
|
||||
|
||||
// CRO make sure to keep a minimum amount of throttle available
|
||||
// CRO NB: channels set to < MINIMUM_BPS will never give up bps,
|
||||
|
||||
@@ -50,7 +50,7 @@ private:
|
||||
F32 mLookaheadSecs; // Seconds to look ahead, maximum
|
||||
F32 mRate; // BPS available, dynamically adjusted
|
||||
F32 mAvailable; // Bits available to send right now on each channel
|
||||
F64 mLastSendTime; // Time since last send on this channel
|
||||
F64Seconds mLastSendTime; // Time since last send on this channel
|
||||
};
|
||||
|
||||
typedef enum e_throttle_categories
|
||||
@@ -93,8 +93,8 @@ protected:
|
||||
F32 mBitsSentThisPeriod[TC_EOF]; // Sent in this dynamic allocation period
|
||||
F32 mBitsSentHistory[TC_EOF]; // Sent before this dynamic allocation period, adjusted to one period length
|
||||
|
||||
F64 mLastSendTime[TC_EOF]; // Time since last send on this channel
|
||||
F64 mDynamicAdjustTime; // Only dynamic adjust every 2 seconds or so.
|
||||
F64Seconds mLastSendTime[TC_EOF]; // Time since last send on this channel
|
||||
F64Seconds mDynamicAdjustTime; // Only dynamic adjust every 2 seconds or so.
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -606,16 +606,21 @@ void LLTransferManager::processTransferAbort(LLMessageSystem *msgp, void **)
|
||||
void LLTransferManager::reliablePacketCallback(void **user_data, S32 result)
|
||||
{
|
||||
LLUUID *transfer_idp = (LLUUID *)user_data;
|
||||
if (result)
|
||||
if (result &&
|
||||
transfer_idp != NULL)
|
||||
{
|
||||
LL_WARNS() << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << LL_ENDL;
|
||||
LLTransferSource *tsp = gTransferManager.findTransferSource(*transfer_idp);
|
||||
if (tsp)
|
||||
{
|
||||
LL_WARNS() << "Aborting reliable transfer " << *transfer_idp << " due to failed reliable resends!" << LL_ENDL;
|
||||
LLTransferSourceChannel *tscp = tsp->mChannelp;
|
||||
tsp->abortTransfer();
|
||||
tscp->deleteTransfer(tsp);
|
||||
}
|
||||
else
|
||||
{
|
||||
LL_WARNS() << "Aborting reliable transfer " << *transfer_idp << " but can't find the LLTransferSource object" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
delete transfer_idp;
|
||||
}
|
||||
@@ -815,7 +820,7 @@ void LLTransferSourceChannel::updateTransfers()
|
||||
gMessageSystem->addS32("Status", status);
|
||||
gMessageSystem->addBinaryData("Data", datap, data_size);
|
||||
sent_bytes = gMessageSystem->getCurrentSendTotal();
|
||||
gMessageSystem->sendReliable(getHost(), LL_DEFAULT_RELIABLE_RETRIES, TRUE, 0.f,
|
||||
gMessageSystem->sendReliable(getHost(), LL_DEFAULT_RELIABLE_RETRIES, TRUE, F32Seconds(0.f),
|
||||
LLTransferManager::reliablePacketCallback, (void**)cb_uuid);
|
||||
|
||||
// Do bookkeeping for the throttle
|
||||
@@ -892,22 +897,26 @@ LLTransferSource *LLTransferSourceChannel::findTransferSource(const LLUUID &tran
|
||||
}
|
||||
|
||||
|
||||
BOOL LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)
|
||||
void LLTransferSourceChannel::deleteTransfer(LLTransferSource *tsp)
|
||||
{
|
||||
|
||||
LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
|
||||
for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
|
||||
if (tsp)
|
||||
{
|
||||
if (iter->second == tsp)
|
||||
LLPriQueueMap<LLTransferSource *>::pqm_iter iter;
|
||||
for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++)
|
||||
{
|
||||
delete tsp;
|
||||
mTransferSources.mMap.erase(iter);
|
||||
return TRUE;
|
||||
if (iter->second == tsp)
|
||||
{
|
||||
delete tsp;
|
||||
mTransferSources.mMap.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LL_ERRS() << "Unable to find transfer source to delete!" << LL_ENDL;
|
||||
return FALSE;
|
||||
LL_WARNS() << "Unable to find transfer source id "
|
||||
<< tsp->getID()
|
||||
<< " to delete!"
|
||||
<< LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1008,21 +1017,26 @@ LLTransferTarget *LLTransferTargetChannel::findTransferTarget(const LLUUID &tran
|
||||
}
|
||||
|
||||
|
||||
BOOL LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)
|
||||
void LLTransferTargetChannel::deleteTransfer(LLTransferTarget *ttp)
|
||||
{
|
||||
tt_iter iter;
|
||||
for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
|
||||
if (ttp)
|
||||
{
|
||||
if (*iter == ttp)
|
||||
tt_iter iter;
|
||||
for (iter = mTransferTargets.begin(); iter != mTransferTargets.end(); iter++)
|
||||
{
|
||||
delete ttp;
|
||||
mTransferTargets.erase(iter);
|
||||
return TRUE;
|
||||
if (*iter == ttp)
|
||||
{
|
||||
delete ttp;
|
||||
mTransferTargets.erase(iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LL_ERRS() << "Unable to find transfer target to delete!" << LL_ENDL;
|
||||
return FALSE;
|
||||
LL_WARNS() << "Unable to find transfer target id "
|
||||
<< ttp->getID()
|
||||
<< " to delete!"
|
||||
<< LL_ENDL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1246,9 +1260,13 @@ bool LLTransferTarget::addDelayedPacket(
|
||||
size);
|
||||
|
||||
#ifdef _DEBUG
|
||||
if (mDelayedPacketMap.find(packet_id) != mDelayedPacketMap.end())
|
||||
transfer_packet_map::iterator iter = mDelayedPacketMap.find(packet_id);
|
||||
if (iter != mDelayedPacketMap.end())
|
||||
{
|
||||
LL_ERRS() << "Packet ALREADY in delayed packet map!" << LL_ENDL;
|
||||
if (!(iter->second->mSize == size) && !(iter->second->mDatap == datap))
|
||||
{
|
||||
LL_ERRS() << "Packet ALREADY in delayed packet map!" << LL_ENDL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user