diff --git a/autobuild.xml b/autobuild.xml index b3f547659..a5327c0f4 100644 --- a/autobuild.xml +++ b/autobuild.xml @@ -2658,11 +2658,11 @@ archive hash - b41376a689fb4c9e9846d838283fdc5d + 7a619778a2ea5c3113549529dd4f7288 hash_algorithm md5 url - http://depot.alchemyviewer.org/pub/windows/lib-vc14/xmlrpc_epi-0.54.2-windows-201601151034.tar.bz2 + http://depot.alchemyviewer.org/pub/windows/lib-vc14/xmlrpc_epi-0.54.2-windows-201603261505.tar.bz2 name windows diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 59735a520..b480efd8e 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -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) diff --git a/indra/cmake/Boost.cmake b/indra/cmake/Boost.cmake index 844d5dc49..81727aef6 100644 --- a/indra/cmake/Boost.cmake +++ b/indra/cmake/Boost.cmake @@ -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) diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index ed2f43e01..28082a3a5 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -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) diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index e016b4790..27519722a 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -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. diff --git a/indra/llappearance/llavatarappearance.h b/indra/llappearance/llavatarappearance.h index f691d7378..00b485389 100644 --- a/indra/llappearance/llavatarappearance.h +++ b/indra/llappearance/llavatarappearance.h @@ -159,11 +159,17 @@ protected: BOOL mIsBuilt; // state of deferred character building typedef std::vector 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: diff --git a/indra/llappearance/llavatarappearancedefines.cpp b/indra/llappearance/llavatarappearancedefines.cpp index f1c78946a..9c8d48914 100644 --- a/indra/llappearance/llavatarappearancedefines.cpp +++ b/indra/llappearance/llavatarappearancedefines.cpp @@ -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 diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index 4853a6670..64ec9cd8d 100644 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -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(); diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 873169cba..400a14066 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -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); diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index b0f922b95..1648c1114 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -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); } } diff --git a/indra/llappearance/llwearabledata.cpp b/indra/llappearance/llwearabledata.cpp index 24c011d6f..1015cec69 100644 --- a/indra/llappearance/llwearabledata.cpp +++ b/indra/llappearance/llwearabledata.cpp @@ -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]; diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index 18635737b..5f5696e37 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -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 //VS2010 +#include +#include 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; } // // 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; } // } // 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 mDecodeQueue; + std::deque mDecodeQueue; LLPointer 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; } diff --git a/indra/llaudio/llaudiodecodemgr.h b/indra/llaudio/llaudiodecodemgr.h index 3ff894dba..e2319a32f 100644 --- a/indra/llaudio/llaudiodecodemgr.h +++ b/indra/llaudio/llaudiodecodemgr.h @@ -28,7 +28,6 @@ #include "stdtypes.h" -#include "lllinkedqueue.h" #include "lluuid.h" #include "llassettype.h" diff --git a/indra/llaudio/llaudioengine.cpp b/indra/llaudio/llaudioengine.cpp index 99e151f12..61aa25be1 100644 --- a/indra/llaudio/llaudioengine.cpp +++ b/indra/llaudio/llaudioengine.cpp @@ -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() <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((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; diff --git a/indra/llaudio/llaudioengine_fmodstudio.h b/indra/llaudio/llaudioengine_fmodstudio.h index 730a702a1..ff45d3ecb 100644 --- a/indra/llaudio/llaudioengine_fmodstudio.h +++ b/indra/llaudio/llaudioengine_fmodstudio.h @@ -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 *mWindGen; + FMOD_DSP_DESCRIPTION *mWindDSPDesc; FMOD::DSP *mWindDSP; FMOD::System *mSystem; bool mEnableProfiler; diff --git a/indra/llaudio/lllistener.cpp b/indra/llaudio/lllistener.cpp index df2366c8c..0723fdbeb 100644 --- a/indra/llaudio/lllistener.cpp +++ b/indra/llaudio/lllistener.cpp @@ -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); diff --git a/indra/llaudio/lllistener.h b/indra/llaudio/lllistener.h index 41836bf03..11c1ad2ae 100644 --- a/indra/llaudio/lllistener.h +++ b/indra/llaudio/lllistener.h @@ -45,7 +45,6 @@ class LLListener public: LLListener(); virtual ~LLListener(); - virtual void init(); virtual void set(LLVector3 pos, LLVector3 vel, LLVector3 up, LLVector3 at); diff --git a/indra/llaudio/lllistener_fmodstudio.cpp b/indra/llaudio/lllistener_fmodstudio.cpp index e2074ce2d..42d819ef6 100644 --- a/indra/llaudio/lllistener_fmodstudio.cpp +++ b/indra/llaudio/lllistener_fmodstudio.cpp @@ -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); diff --git a/indra/llaudio/lllistener_fmodstudio.h b/indra/llaudio/lllistener_fmodstudio.h index 516f4eae8..de9a5e9ca 100644 --- a/indra/llaudio/lllistener_fmodstudio.h +++ b/indra/llaudio/lllistener_fmodstudio.h @@ -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); diff --git a/indra/llaudio/lllistener_openal.cpp b/indra/llaudio/lllistener_openal.cpp index 462484e33..d1734a930 100644 --- a/indra/llaudio/lllistener_openal.cpp +++ b/indra/llaudio/lllistener_openal.cpp @@ -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); diff --git a/indra/llaudio/lllistener_openal.h b/indra/llaudio/lllistener_openal.h index 96af86d99..cb163b11a 100644 --- a/indra/llaudio/lllistener_openal.h +++ b/indra/llaudio/lllistener_openal.h @@ -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); diff --git a/indra/llaudio/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp index c0c9d6d6b..2e7fdb1db 100644 --- a/indra/llaudio/llvorbisencode.cpp +++ b/indra/llaudio/llvorbisencode.cpp @@ -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) */ diff --git a/indra/llcharacter/CMakeLists.txt b/indra/llcharacter/CMakeLists.txt index 1c4ab0b2d..a698a9847 100644 --- a/indra/llcharacter/CMakeLists.txt +++ b/indra/llcharacter/CMakeLists.txt @@ -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 diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index 5bffb1270..1c811a924 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.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; diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h index 38617bd6d..d1c48e446 100644 --- a/indra/llcharacter/llbvhloader.h +++ b/indra/llcharacter/llbvhloader.h @@ -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 */ diff --git a/indra/llcharacter/lleditingmotion.cpp b/indra/llcharacter/lleditingmotion.cpp index 8813064dd..41a0ed86d 100644 --- a/indra/llcharacter/lleditingmotion.cpp +++ b/indra/llcharacter/lleditingmotion.cpp @@ -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()); diff --git a/indra/llcharacter/lljoint.cpp b/indra/llcharacter/lljoint.cpp index 0175a2fe4..d4c73143b 100644 --- a/indra/llcharacter/lljoint.cpp +++ b/indra/llcharacter/lljoint.cpp @@ -36,6 +36,63 @@ S32 LLJoint::sNumUpdates = 0; S32 LLJoint::sNumTouches = 0; +template +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); + 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); + 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); } //-------------------------------------------------------------------- diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 2196f47bb..5ac63e633 100644 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -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 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; } - // std::string exportString(U32 tabs = 0); // diff --git a/indra/llcharacter/lljointstate.h b/indra/llcharacter/lljointstate.h index e40cf2673..15e7af5ab 100644 --- a/indra/llcharacter/lljointstate.h +++ b/indra/llcharacter/lljointstate.h @@ -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; } diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index 35b9ab8a1..ac99e0698 100644 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -42,6 +42,7 @@ #include "llvfile.h" #include "m3math.h" #include "message.h" +#include //----------------------------------------------------------------------------- // 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 -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 watcher; - - JointMotion* joint_motion = new JointMotion; + JointMotion* joint_motion = new JointMotion; + std::unique_ptr 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 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 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 diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 00c4b4109..497d09255 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -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} ) diff --git a/indra/llcommon/llalignedarray.h b/indra/llcommon/llalignedarray.h index 14e25e78d..d6ab5ed3d 100644 --- a/indra/llcommon/llalignedarray.h +++ b/indra/llcommon/llalignedarray.h @@ -64,7 +64,7 @@ LLAlignedArray::LLAlignedArray() template LLAlignedArray::~LLAlignedArray() { - ll_aligned_free(mArray); + ll_aligned_free(mArray); mArray = NULL; mElementCount = 0; mCapacity = 0; @@ -78,7 +78,7 @@ void LLAlignedArray::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(mCapacity*sizeof(T)); if (mArray) { ll_memcpy_nonaliased_aligned_16((char*)new_buf, (char*)mArray, sizeof(T)*mElementCount); @@ -90,7 +90,7 @@ void LLAlignedArray::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(old_buf); } template @@ -99,11 +99,11 @@ void LLAlignedArray::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(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(mArray); } /*for (U32 i = mElementCount; i < mCapacity; ++i) diff --git a/indra/llcommon/llbase64.cpp b/indra/llcommon/llbase64.cpp index 4e75e4591..6705a6542 100644 --- a/indra/llcommon/llbase64.cpp +++ b/indra/llcommon/llbase64.cpp @@ -30,32 +30,36 @@ #include "llbase64.h" #include + #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) { diff --git a/indra/llcommon/llcallbacklist.cpp b/indra/llcommon/llcallbacklist.cpp new file mode 100644 index 000000000..541ff75ee --- /dev/null +++ b/indra/llcommon/llcallbacklist.cpp @@ -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(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(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); +} diff --git a/indra/newview/llcallbacklist.h b/indra/llcommon/llcallbacklist.h similarity index 76% rename from indra/newview/llcallbacklist.h rename to indra/llcommon/llcallbacklist.h index 0516c9cdb..1fdb8ca09 100644 --- a/indra/newview/llcallbacklist.h +++ b/indra/llcommon/llcallbacklist.h @@ -28,27 +28,35 @@ #define LL_LLCALLBACKLIST_H #include "llstl.h" +#include +#include +#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_pair_t; - typedef std::list callback_list_t; + + inline callback_list_t::iterator find(callback_t func, void *data); + callback_list_t mCallbackList; }; diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 065a72215..e5af5ced2 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -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"); diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 7e8ae6368..863c3d02a 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -38,9 +38,8 @@ #include #include -#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 diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index 730733109..b4c3739e4 100644 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.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) diff --git a/indra/llcommon/lleventtimer.cpp b/indra/llcommon/lleventtimer.cpp index 957b502dc..c491e37cb 100644 --- a/indra/llcommon/lleventtimer.cpp +++ b/indra/llcommon/lleventtimer.cpp @@ -65,7 +65,7 @@ LLEventTimer::~LLEventTimer() void LLEventTimer::updateClass() { std::list 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(); diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index 7660baa90..4f8ec6756 100644 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -28,7 +28,7 @@ */ #if LL_WINDOWS -#include +#include "llwin32headerslean.h" #include // Windows errno #else #include diff --git a/indra/llcommon/llfindlocale.cpp b/indra/llcommon/llfindlocale.cpp index 505f5c540..d91620926 100644 --- a/indra/llcommon/llfindlocale.cpp +++ b/indra/llcommon/llfindlocale.cpp @@ -39,7 +39,7 @@ #include #ifdef WIN32 -#include +#include "llwin32headers.h" #include #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"}, diff --git a/indra/llcommon/llfixedbuffer.cpp b/indra/llcommon/llfixedbuffer.cpp index 4b5cdbe28..bd4db8be8 100644 --- a/indra/llcommon/llfixedbuffer.cpp +++ b/indra/llcommon/llfixedbuffer.cpp @@ -30,7 +30,8 @@ LLFixedBuffer::LLFixedBuffer(const U32 max_lines) : LLLineBuffer(), - mMaxLines(max_lines) + mMaxLines(max_lines), + mMutex() { mTimer.reset(); } diff --git a/indra/llcommon/llframetimer.h b/indra/llcommon/llframetimer.h index 5ebf14247..a2b3ffa39 100644 --- a/indra/llcommon/llframetimer.h +++ b/indra/llcommon/llframetimer.h @@ -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(); diff --git a/indra/llcommon/llhandle.h b/indra/llcommon/llhandle.h index 6af5e198d..401e4d759 100644 --- a/indra/llcommon/llhandle.h +++ b/indra/llcommon/llhandle.h @@ -194,13 +194,6 @@ public: return mHandle; } -protected: - typedef LLHandle handle_type_t; - LLHandleProvider() - { - // provided here to enforce T deriving from LLHandleProvider - } - template LLHandle getDerivedHandle(typename boost::enable_if< typename boost::is_convertible >::type* dummy = 0) const { @@ -209,6 +202,12 @@ protected: return downcast_handle; } +protected: + typedef LLHandle handle_type_t; + LLHandleProvider() + { + // provided here to enforce T deriving from LLHandleProvider + } private: mutable LLRootHandle mHandle; diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index ce6ac4fac..88274a91c 100644 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp @@ -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() diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 46775313d..1881620e6 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -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); diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index aba33abde..f843f3c96 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -32,7 +32,7 @@ //#endif #if defined(LL_WINDOWS) -//# include +#include "llwin32headerslean.h" # include #elif defined(LL_DARWIN) # include @@ -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 ; } diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index 48cd2b7b2..efd61590a 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -27,7 +27,8 @@ #define LLMEMORY_H #include "linden_common.h" - +#include "llunits.h" +#include "stdtypes.h" #include #include #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 + // // 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 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 +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 +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; }; diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h index 59d284182..074e38fe4 100644 --- a/indra/llcommon/llmortician.h +++ b/indra/llcommon/llmortician.h @@ -34,6 +34,7 @@ #define LLMORTICIAN_H #include "stdtypes.h" +#include class LL_COMMON_API LLMortician { diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 5c731c691..f86923f9d 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -32,9 +32,7 @@ //#include #if LL_WINDOWS -# define WIN32_LEAN_AND_MEAN -# include -# include +# include "llwin32headerslean.h" # define _interlockedbittestandset _renamed_interlockedbittestandset # define _interlockedbittestandreset _renamed_interlockedbittestandreset # include @@ -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(); } diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index fc2c8dacf..681dd6314 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -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; diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 5ba7b8bd8..8fe3acf54 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -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 diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h index dda7bf69c..2da59b8ed 100644 --- a/indra/llcommon/llqueuedthread.h +++ b/indra/llcommon/llqueuedthread.h @@ -32,8 +32,6 @@ #include #include -#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 mIdleThread; // request queue is empty (or we are quitting) and the thread is idle + LLAtomic32 mIdleThread; // request queue is empty (or we are quitting) and the thread is idle typedef std::set request_queue_t; request_queue_t mRequestQueue; diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp index 297c5bb7c..74f4c046f 100644 --- a/indra/llcommon/llrefcount.cpp +++ b/indra/llcommon/llrefcount.cpp @@ -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() diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 0ffb0e9e1..72e6ac611 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -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; diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp index e0446c5d0..5f47f8544 100644 --- a/indra/llcommon/llstacktrace.cpp +++ b/indra/llcommon/llstacktrace.cpp @@ -39,7 +39,7 @@ #include #include -#include "windows.h" +#include "llwin32headerslean.h" #include "Dbghelp.h" typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index 9c66bc886..e506db68d 100644 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -37,7 +37,11 @@ #include #include #include +#include +#include +#include #include +#include "stdtypes.h" // Use to compare the first element only of a pair // e.g. typedef std::set, compare_pair > some_pair_set_t; diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f898efe04..93aa4b4f8 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -30,9 +30,7 @@ #include "llerror.h" #if LL_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include -#include +#include "llwin32headerslean.h" #include // for WideCharToMultiByte #endif diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index fd724365e..96fca1496 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -53,9 +53,7 @@ using namespace llsd; #if LL_WINDOWS -# define WIN32_LEAN_AND_MEAN -# include -# include +# include "llwin32headerslean.h" # include // GetPerformanceInfo() et al. # include #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 } diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 52b884e5a..accdbb5d2 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -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. diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 1ef4aa414..e458cc66a 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -31,11 +31,9 @@ #include "u64.h" #if LL_WINDOWS -# define WIN32_LEAN_AND_MEAN -# include -# include +# include "llwin32headerslean.h" #elif LL_LINUX || LL_SOLARIS || LL_DARWIN -# include +# include # include #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); } diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 0d2e8e86d..d43267bb6 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -37,6 +37,7 @@ #include #include // 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 diff --git a/indra/llcommon/llunits.h b/indra/llcommon/llunits.h new file mode 100644 index 000000000..0fcb8281a --- /dev/null +++ b/indra/llcommon/llunits.h @@ -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 diff --git a/indra/llcommon/llunittype.h b/indra/llcommon/llunittype.h new file mode 100644 index 000000000..ac8504ca6 --- /dev/null +++ b/indra/llcommon/llunittype.h @@ -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 +struct LLIsSameType +{ + static const bool value = false; +}; + +template +struct LLIsSameType +{ + static const bool value = true; +}; + +// workaround for decltype() not existing and typeof() not working inline in gcc 4.2 +template +struct LLResultTypeAdd +{ + typedef LL_TYPEOF(S() + T()) type_t; +}; + +template +struct LLResultTypeSubtract +{ + typedef LL_TYPEOF(S() - T()) type_t; +}; + +template +struct LLResultTypeMultiply +{ + typedef LL_TYPEOF(S() * T()) type_t; +}; + +template +struct LLResultTypeDivide +{ + typedef LL_TYPEOF(S() / T(1)) type_t; +}; + +template +struct LLResultTypePromote +{ + typedef LL_TYPEOF((true) ? S() : T()) type_t; +}; + +template +struct LLUnit +{ + typedef LLUnit 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 + LL_FORCE_INLINE static self_t convert(LLUnit v) + { + self_t result; + result.mValue = (STORAGE_TYPE)v.value(); + return result; + } + + template + LL_FORCE_INLINE static self_t convert(LLUnit v) + { + self_t result; + STORAGE_TYPE divisor = ll_convert_units(v, result); + result.mValue /= divisor; + return result; + } + + template + LL_FORCE_INLINE static self_t convert(LLUnit v) + { + typedef typename LLResultTypePromote::type_t result_storage_t; + LLUnit 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 + LL_FORCE_INLINE LLUnit(LLUnit 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 + storage_t valueInUnits() + { + return LLUnit(*this).value(); + } + + template + void valueInUnits(storage_t value) + { + *this = LLUnit(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 + LL_FORCE_INLINE bool operator == (LLUnit other) const + { + return mValue == convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator != (LLUnit other) const + { + return mValue != convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator < (LLUnit other) const + { + return mValue < convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator <= (LLUnit other) const + { + return mValue <= convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator > (LLUnit other) const + { + return mValue > convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator >= (LLUnit other) const + { + return mValue >= convert(other).value(); + } + +protected: + storage_t mValue; +}; + +template +std::ostream& operator <<(std::ostream& s, const LLUnit& unit) +{ + s << unit.value() << UNITS::getUnitLabel(); + return s; +} + +template +std::istream& operator >>(std::istream& s, LLUnit& unit) +{ + STORAGE_TYPE val; + s >> val; + unit.value(val); + return s; +} + +template +struct LLUnitImplicit : public LLUnit +{ + typedef LLUnitImplicit self_t; + typedef typename LLUnit::storage_t storage_t; + typedef LLUnit base_t; + + LL_FORCE_INLINE LLUnitImplicit(storage_t value = storage_t()) + : base_t(value) + {} + + template + LL_FORCE_INLINE LLUnitImplicit(LLUnit 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 + LL_FORCE_INLINE void operator += (LLUnitImplicit 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 + LL_FORCE_INLINE void operator -= (LLUnitImplicit other) + { + base_t::mValue -= base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator == (LLUnit other) const + { + return base_t::mValue == base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator == (LLUnitImplicit other) const + { + return base_t::mValue == base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator == (STORAGE_T other) const + { + return base_t::mValue == other; + } + + template + LL_FORCE_INLINE bool operator != (LLUnit other) const + { + return base_t::mValue != convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator != (LLUnitImplicit other) const + { + return base_t::mValue != base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator != (STORAGE_T other) const + { + return base_t::mValue != other; + } + + template + LL_FORCE_INLINE bool operator < (LLUnit other) const + { + return base_t::mValue < base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator < (LLUnitImplicit other) const + { + return base_t::mValue < base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator < (STORAGE_T other) const + { + return base_t::mValue < other; + } + + template + LL_FORCE_INLINE bool operator <= (LLUnit other) const + { + return base_t::mValue <= base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator <= (LLUnitImplicit other) const + { + return base_t::mValue <= base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator <= (STORAGE_T other) const + { + return base_t::mValue <= other; + } + + template + LL_FORCE_INLINE bool operator > (LLUnit other) const + { + return base_t::mValue > base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator > (LLUnitImplicit other) const + { + return base_t::mValue > base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator > (STORAGE_T other) const + { + return base_t::mValue > other; + } + + template + LL_FORCE_INLINE bool operator >= (LLUnit other) const + { + return base_t::mValue >= base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator >= (LLUnitImplicit other) const + { + return base_t::mValue >= base_t::convert(other).value(); + } + + template + LL_FORCE_INLINE bool operator >= (STORAGE_T other) const + { + return base_t::mValue >= other; + } +}; + +template +std::ostream& operator <<(std::ostream& s, const LLUnitImplicit& unit) +{ + s << unit.value() << UNITS::getUnitLabel(); + return s; +} + +template +std::istream& operator >>(std::istream& s, LLUnitImplicit& unit) +{ + STORAGE_TYPE val; + s >> val; + unit = val; + return s; +} + +template +LL_FORCE_INLINE S2 ll_convert_units(LLUnit in, LLUnit& out) +{ + S2 divisor(1); + + LL_STATIC_ASSERT((LLIsSameType::value + || !LLIsSameType::value + || !LLIsSameType::value), + "conversion requires compatible units"); + + if (LLIsSameType::value) + { + // T1 and T2 same type, just assign + out.value((S2)in.value()); + } + else if (T1::sLevel > T2::sLevel) + { + // reduce T1 + LLUnit new_in; + divisor *= (S2)ll_convert_units(in, new_in); + divisor *= (S2)ll_convert_units(new_in, out); + } + else + { + // reduce T2 + LLUnit new_out; + divisor *= (S2)ll_convert_units(in, new_out); + divisor *= (S2)ll_convert_units(new_out, out); + } + return divisor; +} + +template +struct LLStorageType +{ + typedef T type_t; +}; + +template +struct LLStorageType > +{ + 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 +LL_FORCE_INLINE LLUnit::type_t, UNITS1> operator + (LLUnit first, LLUnit second) +{ + LLUnit::type_t, UNITS1> result(first); + result += second; + return result; +} + +template +LLUnit operator + (LLUnit first, UNITLESS second) +{ + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types"); + return LLUnit(0); +} + +template +LLUnit operator + (UNITLESS first, LLUnit second) +{ + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator + requires compatible unit types"); + return LLUnit(0); +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator + (LLUnitImplicit first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result += second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator + (LLUnit first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result += second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator + (LLUnitImplicit first, LLUnit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result += LLUnitImplicit(second); + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t>::type_t, UNITS> operator + (LLUnitImplicit first, UNITLESS_TYPE second) +{ + LLUnitImplicit::type_t>::type_t, UNITS> result(first); + result += second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, STORAGE_TYPE>:: + type_t, UNITS> operator + (UNITLESS_TYPE first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, STORAGE_TYPE>::type_t, UNITS> result(first); + result += second; + return result; +} + +// +// operator - +// +template +LL_FORCE_INLINE LLUnit::type_t, UNITS1> operator - (LLUnit first, LLUnit second) +{ + LLUnit::type_t, UNITS1> result(first); + result -= second; + return result; +} + +template +LLUnit operator - (LLUnit first, UNITLESS second) +{ + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types"); + return LLUnit(0); +} + +template +LLUnit operator - (UNITLESS first, LLUnit second) +{ + LL_BAD_TEMPLATE_INSTANTIATION(STORAGE_TYPE, "operator - requires compatible unit types"); + return LLUnit(0); +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator - (LLUnitImplicit first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result -= second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator - (LLUnit first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result -= second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, UNITS1> operator - (LLUnitImplicit first, LLUnit second) +{ + LLUnitImplicit::type_t, UNITS1> result(first); + result -= LLUnitImplicit(second); + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t>::type_t, UNITS> operator - (LLUnitImplicit first, UNITLESS_TYPE second) +{ + LLUnitImplicit::type_t>::type_t, UNITS> result(first); + result -= second; + return result; +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, STORAGE_TYPE>::type_t, UNITS> operator - (UNITLESS_TYPE first, LLUnitImplicit second) +{ + LLUnitImplicit::type_t, STORAGE_TYPE>::type_t, UNITS> result(first); + result -= second; + return result; +} + +// +// operator * +// +template +LLUnit operator * (LLUnit, LLUnit) +{ + // 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(); +} + +template +LL_FORCE_INLINE LLUnit::type_t>::type_t, UNITS> operator * (LLUnit first, UNITLESS_TYPE second) +{ + return LLUnit::type_t>::type_t, UNITS>(first.value() * second); +} + +template +LL_FORCE_INLINE LLUnit::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnit second) +{ + return LLUnit::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value()); +} + +template +LLUnitImplicit operator * (LLUnitImplicit, LLUnitImplicit) +{ + // 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(); +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t>::type_t, UNITS> operator * (LLUnitImplicit first, UNITLESS_TYPE second) +{ + return LLUnitImplicit::type_t, UNITS>(first.value() * second); +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t, STORAGE_TYPE>::type_t, UNITS> operator * (UNITLESS_TYPE first, LLUnitImplicit second) +{ + return LLUnitImplicit::type_t, STORAGE_TYPE>::type_t, UNITS>(first * second.value()); +} + + +// +// operator / +// + +template +LL_FORCE_INLINE LLUnit::type_t>::type_t, UNITS> operator / (LLUnit first, UNITLESS_TYPE second) +{ + return LLUnit::type_t>::type_t, UNITS>(first.value() / second); +} + +template +LL_FORCE_INLINE typename LLResultTypeDivide::type_t operator / (LLUnit first, LLUnit second) +{ + return first.value() / first.convert(second).value(); +} + +template +LL_FORCE_INLINE LLUnitImplicit::type_t>::type_t, UNITS> operator / (LLUnitImplicit first, UNITLESS_TYPE second) +{ + return LLUnitImplicit::type_t>::type_t, UNITS>(first.value() / second); +} + +template +LL_FORCE_INLINE typename LLResultTypeDivide::type_t operator / (LLUnitImplicit first, LLUnitImplicit second) +{ + return (typename LLResultTypeDivide::type_t)(first.value() / first.convert(second).value()); +} + +template +LL_FORCE_INLINE typename LLResultTypeDivide::type_t operator / (LLUnit first, LLUnitImplicit second) +{ + return (typename LLResultTypeDivide::type_t)(first.value() / first.convert(second).value()); +} + +template +LL_FORCE_INLINE typename LLResultTypeDivide::type_t operator / (LLUnitImplicit first, LLUnit second) +{ + return (typename LLResultTypeDivide::type_t)(first.value() / first.convert(second).value()); +} + +template +struct LLGetUnitLabel +{ + static const char* getUnitLabel() { return ""; } +}; + +template +struct LLGetUnitLabel > +{ + static const char* getUnitLabel() { return T::getUnitLabel(); } +}; + +template +struct LLUnitLinearOps +{ + typedef LLUnitLinearOps self_t; + + LLUnitLinearOps(T val) + : mValue(val), + mDivisor(1) + {} + + template + self_t operator * (OTHER_T other) + { + return mValue * other; + } + + template + self_t operator / (OTHER_T other) + { + mDivisor *= other; + return *this; + } + + template + self_t operator + (OTHER_T other) + { + mValue += other * mDivisor; + return *this; + } + + template + self_t operator - (OTHER_T other) + { + mValue -= other * mDivisor; + return *this; + } + + T mValue; + T mDivisor; +}; + +template +struct LLUnitInverseLinearOps +{ + typedef LLUnitInverseLinearOps self_t; + + LLUnitInverseLinearOps(T val) + : mValue(val), + mDivisor(1), + mMultiplicand(1) + {} + + template + self_t operator * (OTHER_T other) + { + mDivisor *= other; + return *this; + } + + template + self_t operator / (OTHER_T other) + { + mValue *= other; + mMultiplicand *= other; + return *this; + } + + template + self_t operator + (OTHER_T other) + { + mValue -= other * mMultiplicand; + return *this; + } + + template + 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 \ + static LLUnit fromValue(T value) { return LLUnit(value); } \ + template \ + static LLUnit fromValue(LLUnit value) \ + { return LLUnit(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 \ + static LLUnit fromValue(T value) { return LLUnit(value); } \ + template \ + static LLUnit fromValue(LLUnit value) \ + { return LLUnit(value); } \ +}; \ + \ +template \ +LL_FORCE_INLINE S2 ll_convert_units(LLUnit in, LLUnit& out) \ +{ \ + typedef typename LLResultTypePromote::type_t result_storage_t; \ + LLUnitInverseLinearOps result = \ + LLUnitInverseLinearOps(in.value()) conversion_operation; \ + out = LLUnit((S2)result.mValue); \ + return result.mDivisor; \ +} \ + \ +template \ +LL_FORCE_INLINE S2 ll_convert_units(LLUnit in, LLUnit& out) \ +{ \ + typedef typename LLResultTypePromote::type_t result_storage_t; \ + LLUnitLinearOps result = \ + LLUnitLinearOps(in.value()) conversion_operation; \ + out = LLUnit((S2)result.mValue); \ + return result.mDivisor; \ +} + +#define LL_DECLARE_UNIT_TYPEDEFS(ns, unit_name) \ + typedef LLUnit F32##unit_name; \ + typedef LLUnitImplicit F32##unit_name##Implicit;\ + typedef LLUnit F64##unit_name; \ + typedef LLUnitImplicit F64##unit_name##Implicit;\ + typedef LLUnit S32##unit_name; \ + typedef LLUnitImplicit S32##unit_name##Implicit;\ + typedef LLUnit S64##unit_name; \ + typedef LLUnitImplicit S64##unit_name##Implicit;\ + typedef LLUnit U32##unit_name; \ + typedef LLUnitImplicit U32##unit_name##Implicit;\ + typedef LLUnit U64##unit_name; \ + typedef LLUnitImplicit U64##unit_name##Implicit + +#endif //LL_UNITTYPE_H diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index ce83fbf55..3952a63eb 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -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 -#include +#include "llwin32headers.h" #endif #include "lldefs.h" diff --git a/indra/llcommon/llwin32headers.h b/indra/llcommon/llwin32headers.h new file mode 100644 index 000000000..8cfa40ada --- /dev/null +++ b/indra/llcommon/llwin32headers.h @@ -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 +#include +// reset to default, which is lean +#define WIN32_LEAN_AND_MEAN +#undef NOMINMAX +#endif + +#endif diff --git a/indra/llcommon/llwin32headerslean.h b/indra/llcommon/llwin32headerslean.h new file mode 100644 index 000000000..314e7a85d --- /dev/null +++ b/indra/llcommon/llwin32headerslean.h @@ -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 +#include +#undef NOMINMAX +#endif + +#endif diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index e66c570f4..20b99bdc8 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -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 { diff --git a/indra/llimage/llimagebmp.cpp b/indra/llimage/llimagebmp.cpp index dafcc5c82..901d7732d 100644 --- a/indra/llimage/llimagebmp.cpp +++ b/indra/llimage/llimagebmp.cpp @@ -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++ ) diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp index a8de77067..01b3c3243 100644 --- a/indra/llimage/llimagetga.cpp +++ b/indra/llimage/llimagetga.cpp @@ -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) { diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp index d710a065d..c4b8c0994 100644 --- a/indra/llimage/llimageworker.cpp +++ b/indra/llimage/llimageworker.cpp @@ -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; } diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index 6d9ae3fe9..1bfb0ddfd 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -98,7 +98,7 @@ private: }; typedef std::list creation_list_t; creation_list_t mCreationList; - LLMutex mCreationMutex; + LLMutex* mCreationMutex; }; #endif diff --git a/indra/llimage/llpngwrapper.h b/indra/llimage/llpngwrapper.h index 410583024..27d7df3be 100644 --- a/indra/llimage/llpngwrapper.h +++ b/indra/llimage/llpngwrapper.h @@ -26,16 +26,7 @@ #ifndef LL_LLPNGWRAPPER_H #define LL_LLPNGWRAPPER_H -#if LL_STANDALONE || (LL_LINUX && defined(__x86_64__)) -#include -#else -// Workaround for wrongly packaged prebuilt. -#if _MSC_VER >= 1800 -#include -#else -#include "libpng15/png.h" -#endif -#endif +#include "png.h" #include "llimage.h" class LLPngWrapper diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index 02cc55e1e..b3924ed6e 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -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); diff --git a/indra/llmath/llquaternion.h b/indra/llmath/llquaternion.h index 236ce442b..4106f9ffe 100644 --- a/indra/llmath/llquaternion.h +++ b/indra/llmath/llquaternion.h @@ -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) { diff --git a/indra/llmath/llvolume.cpp b/indra/llmath/llvolume.cpp index 3de6dab3c..92bad58cd 100644 --- a/indra/llmath/llvolume.cpp +++ b/indra/llmath/llvolume.cpp @@ -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 &faces) const +{ + faces = mVolumeFaces; +} + +void LLVolume::copyFacesFrom(const std::vector &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 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); - - // - 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. - { - // - - //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); - - // - } - // + 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& v, std::vector& 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); diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index 058d17132..0912c3d09 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -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& v, std::vector& idx); @@ -972,6 +978,7 @@ protected: ~LLVolume(); // use unref public: + typedef std::vector 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 &faces) const; + void copyFacesFrom(const std::vector &faces); void cacheOptimize(); private: diff --git a/indra/llmath/llvolumemgr.cpp b/indra/llmath/llvolumemgr.cpp index 07d174926..07df1ccaa 100644 --- a/indra/llmath/llvolumemgr.cpp +++ b/indra/llmath/llvolumemgr.cpp @@ -214,7 +214,7 @@ void LLVolumeMgr::useMutex() { if (!mDataMutex) { - mDataMutex = new LLMutex; + mDataMutex = new LLMutex(); } } diff --git a/indra/llmath/m4math.cpp b/indra/llmath/m4math.cpp index a1fd34047..09253c75b 100644 --- a/indra/llmath/m4math.cpp +++ b/indra/llmath/m4math.cpp @@ -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]); diff --git a/indra/llmath/m4math.h b/indra/llmath/m4math.h index 9330ec332..bf031678c 100644 --- a/indra/llmath/m4math.h +++ b/indra/llmath/m4math.h @@ -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 diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp index 029bcc124..6939a5029 100644 --- a/indra/llmessage/llares.cpp +++ b/indra/llmessage/llares.cpp @@ -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() diff --git a/indra/llmessage/llareslistener.cpp b/indra/llmessage/llareslistener.cpp index 58b8a05a9..3d65906b9 100644 --- a/indra/llmessage/llareslistener.cpp +++ b/indra/llmessage/llareslistener.cpp @@ -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; + } } diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 09216e5ad..3f7963dd2 100644 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -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 diff --git a/indra/llmessage/llassetstorage.h b/indra/llmessage/llassetstorage.h index 755d0a207..d39711db7 100644 --- a/indra/llmessage/llassetstorage.h +++ b/indra/llmessage/llassetstorage.h @@ -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); diff --git a/indra/llmessage/llavatarnamecache.cpp b/indra/llmessage/llavatarnamecache.cpp index 83e376858..2e39e17b5 100644 --- a/indra/llmessage/llavatarnamecache.cpp +++ b/indra/llmessage/llavatarnamecache.cpp @@ -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; diff --git a/indra/llmessage/llavatarnamecache.h b/indra/llmessage/llavatarnamecache.h index e80b3d010..457adcfc1 100644 --- a/indra/llmessage/llavatarnamecache.h +++ b/indra/llmessage/llavatarnamecache.h @@ -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. diff --git a/indra/llmessage/llbuffer.h b/indra/llmessage/llbuffer.h index c7624bde3..b7b0fe014 100644 --- a/indra/llmessage/llbuffer.h +++ b/indra/llmessage/llbuffer.h @@ -306,7 +306,7 @@ public: typedef std::list 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(); diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp index ada598a16..75ae8fff7 100644 --- a/indra/llmessage/llcircuit.cpp +++ b/indra/llmessage/llcircuit.cpp @@ -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() << "/" << circuit.mBytesOut.valueInUnits() + << " Kbps: " + << S32(circuit.mBytesIn.valueInUnits() / circuit.mExistenceTimer.getElapsedTimeF32().value()) + << "/" + << S32(circuit.mBytesOut.valueInUnits() / 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() + << "/" + << circuit.mBytesOutLastPeriod.valueInUnits() + << " Kbps: " + << (S32)(circuit.mBytesInLastPeriod.valueInUnits() / circuit.mLastPeriodLength.value()) + << "/" + << (S32)(circuit.mBytesOutLastPeriod.valueInUnits() / 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); } diff --git a/indra/llmessage/llcircuit.h b/indra/llmessage/llcircuit.h index ab9ebc2d8..d3db96790 100644 --- a/indra/llmessage/llcircuit.h +++ b/indra/llmessage/llcircuit.h @@ -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 packet_time_map; + typedef std::map packet_time_map; packet_time_map mPotentialLostPackets; packet_time_map mRecentlyReceivedReliablePackets; std::vector mAcks; + F32 mAckCreationTime; // first ack creation time typedef std::map 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 diff --git a/indra/llmessage/llhttpsender.cpp b/indra/llmessage/llhttpsender.cpp index 643735fc1..5363088d7 100644 --- a/indra/llmessage/llhttpsender.cpp +++ b/indra/llmessage/llhttpsender.cpp @@ -38,7 +38,7 @@ namespace { typedef std::map SenderMap; static SenderMap senderMap; - static LLHTTPSender* defaultSender = new LLHTTPSender(); + static LLPointer defaultSender(new LLHTTPSender()); } //virtual @@ -90,6 +90,5 @@ void LLHTTPSender::clearSender(const LLHost& host) //static void LLHTTPSender::setDefaultSender(LLHTTPSender* sender) { - delete defaultSender; defaultSender = sender; } diff --git a/indra/llmessage/llhttpsender.h b/indra/llmessage/llhttpsender.h index 88920db24..ff8fa2f95 100644 --- a/indra/llmessage/llhttpsender.h +++ b/indra/llmessage/llhttpsender.h @@ -32,7 +32,7 @@ class LLHost; class LLSD; -class LLHTTPSender +class LLHTTPSender : public LLThreadSafeRefCount { public: diff --git a/indra/llmessage/llpacketack.cpp b/indra/llmessage/llpacketack.cpp index f08d3404e..c3c022c29 100644 --- a/indra/llmessage/llpacketack.cpp +++ b/indra/llmessage/llpacketack.cpp @@ -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; diff --git a/indra/llmessage/llpacketack.h b/indra/llmessage/llpacketack.h index 2ef3c48e4..f0ed923f1 100644 --- a/indra/llmessage/llpacketack.h +++ b/indra/llmessage/llpacketack.h @@ -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 diff --git a/indra/llmessage/llpacketbuffer.cpp b/indra/llmessage/llpacketbuffer.cpp index 21cdf1b16..ccf991b1a 100644 --- a/indra/llmessage/llpacketbuffer.cpp +++ b/indra/llmessage/llpacketbuffer.cpp @@ -29,7 +29,7 @@ #include "llpacketbuffer.h" #include "net.h" -#include "timing.h" +#include "lltimer.h" #include "llhost.h" /////////////////////////////////////////////////////////// diff --git a/indra/llmessage/llpacketring.cpp b/indra/llmessage/llpacketring.cpp index c3ebbaab5..93c458b37 100644 --- a/indra/llmessage/llpacketring.cpp +++ b/indra/llmessage/llpacketring.cpp @@ -41,7 +41,6 @@ #include "llproxy.h" #include "llrand.h" #include "message.h" -#include "timing.h" #include "u64.h" // diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index a18c40d57..97d97e742 100644 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -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(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(socks_password.size()); memcpy(&password_auth[socks_username.size() + 3], socks_password.c_str(), socks_password.size()); authmethod_password_reply_t password_reply; diff --git a/indra/llmessage/llthrottle.cpp b/indra/llmessage/llthrottle.cpp index 1cf034534..7605da4d3 100644 --- a/indra/llmessage/llthrottle.cpp +++ b/indra/llmessage/llthrottle.cpp @@ -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, diff --git a/indra/llmessage/llthrottle.h b/indra/llmessage/llthrottle.h index ed0aeb460..e43e54f61 100644 --- a/indra/llmessage/llthrottle.h +++ b/indra/llmessage/llthrottle.h @@ -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. }; diff --git a/indra/llmessage/lltransfermanager.cpp b/indra/llmessage/lltransfermanager.cpp index e647df1c1..ec7b21d8b 100644 --- a/indra/llmessage/lltransfermanager.cpp +++ b/indra/llmessage/lltransfermanager.cpp @@ -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::pqm_iter iter; - for (iter = mTransferSources.mMap.begin(); iter != mTransferSources.mMap.end(); iter++) + if (tsp) { - if (iter->second == tsp) + LLPriQueueMap::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 diff --git a/indra/llmessage/lltransfermanager.h b/indra/llmessage/lltransfermanager.h index 252e05d1d..6aad153c2 100644 --- a/indra/llmessage/lltransfermanager.h +++ b/indra/llmessage/lltransfermanager.h @@ -199,7 +199,7 @@ public: void addTransferSource(LLTransferSource *sourcep); LLTransferSource *findTransferSource(const LLUUID &transfer_id); - BOOL deleteTransfer(LLTransferSource *tsp); + void deleteTransfer(LLTransferSource *tsp); void setThrottleID(const S32 throttle_id) { mThrottleID = throttle_id; } @@ -232,7 +232,7 @@ public: const F32 priority); LLTransferTarget *findTransferTarget(const LLUUID &transfer_id); - BOOL deleteTransfer(LLTransferTarget *ttp); + void deleteTransfer(LLTransferTarget *ttp); LLTransferChannelType getChannelType() const { return mChannelType; } diff --git a/indra/llmessage/llxfermanager.cpp b/indra/llmessage/llxfermanager.cpp index 1ea3c576e..0ab67b8dd 100644 --- a/indra/llmessage/llxfermanager.cpp +++ b/indra/llmessage/llxfermanager.cpp @@ -261,7 +261,7 @@ U32 LLXferManager::numActiveListEntries(LLXfer *list_head) while (list_head) { - if (list_head->mStatus == e_LL_XFER_IN_PROGRESS) + if (list_head->mStatus == e_LL_XFER_IN_PROGRESS) { num_entries++; } @@ -677,7 +677,7 @@ void LLXferManager::processReceiveData (LLMessageSystem *mesgsys, void ** /*user ack_info.mID = id; ack_info.mPacketNum = decodePacketNum(packetnum); ack_info.mRemoteHost = mesgsys->getSender(); - mXferAckQueue.push(ack_info); + mXferAckQueue.push_back(ack_info); } if (isLastPacket(packetnum)) @@ -1088,15 +1088,15 @@ void LLXferManager::retransmitUnackedPackets () // so we don't blow through bandwidth. // - while (mXferAckQueue.getLength()) + while (mXferAckQueue.size()) { if (mAckThrottle.checkOverflow(1000.0f*8.0f)) { break; } - //LL_INFOS() << "Confirm packet queue length:" << mXferAckQueue.getLength() << LL_ENDL; - LLXferAckInfo ack_info; - mXferAckQueue.pop(ack_info); + //LL_INFOS() << "Confirm packet queue length:" << mXferAckQueue.size() << LL_ENDL; + LLXferAckInfo ack_info = mXferAckQueue.front(); + mXferAckQueue.pop_front(); //LL_INFOS() << "Sending confirm packet" << LL_ENDL; sendConfirmPacket(gMessageSystem, ack_info.mID, ack_info.mPacketNum, ack_info.mRemoteHost); mAckThrottle.throttleOverflow(1000.f*8.f); // Assume 1000 bytes/packet diff --git a/indra/llmessage/llxfermanager.h b/indra/llmessage/llxfermanager.h index b84bccb5b..b3d110e7a 100644 --- a/indra/llmessage/llxfermanager.h +++ b/indra/llmessage/llxfermanager.h @@ -41,7 +41,7 @@ class LLVFS; #include "message.h" #include "llassetstorage.h" #include "lldir.h" -#include "lllinkedqueue.h" +#include #include "llthrottle.h" class LLHostStatus @@ -80,7 +80,7 @@ class LLXferManager S32 mMaxIncomingXfers; BOOL mUseAckThrottling; // Use ack throttling to cap file xfer bandwidth - LLLinkedQueue mXferAckQueue; + std::deque mXferAckQueue; LLThrottle mAckThrottle; public: diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 5037a9284..0ac2378c0 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -85,7 +85,7 @@ extern AIHTTPTimeoutPolicy fnPtrResponder_timeout; // Constants //const char* MESSAGE_LOG_FILENAME = "message.log"; -static const F32 CIRCUIT_DUMP_TIMEOUT = 30.f; +static const F32Seconds CIRCUIT_DUMP_TIMEOUT(30.f); static const S32 TRUST_TIME_WINDOW = 3; // *NOTE: This needs to be moved into a seperate file so that it never gets @@ -246,7 +246,7 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, S32 version_patch, bool failure_is_fatal, const F32 circuit_heartbeat_interval, const F32 circuit_timeout) : - mCircuitInfo(circuit_heartbeat_interval, circuit_timeout), + mCircuitInfo(F32Seconds(circuit_heartbeat_interval), F32Seconds(circuit_timeout)), mLastMessageFromTrustedMessageService(false), mPacketRing(new LLPacketRing) { @@ -268,7 +268,7 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, mSendPacketFailureCount = 0; - mCircuitPrintFreq = 60.f; // seconds + mCircuitPrintFreq = F32Seconds(60.f); loadTemplateFile(filename, failure_is_fatal); @@ -307,20 +307,20 @@ LLMessageSystem::LLMessageSystem(const std::string& filename, U32 port, mPollInfop->mPollFD.desc.s = aprSocketp; mPollInfop->mPollFD.client_data = NULL; - F64 mt_sec = getMessageTimeSeconds(); + F64Seconds mt_sec = getMessageTimeSeconds(); mResendDumpTime = mt_sec; mMessageCountTime = mt_sec; mCircuitPrintTime = mt_sec; - mCurrentMessageTimeSeconds = mt_sec; + mCurrentMessageTime = F64Seconds(mt_sec); // Constants for dumping output based on message processing time/count mNumMessageCounts = 0; mMaxMessageCounts = 200; // >= 0 means dump warnings - mMaxMessageTime = 1.f; + mMaxMessageTime = F32Seconds(1.f); mTrueReceiveSize = 0; - mReceiveTime = 0.f; + mReceiveTime = F32Seconds(0.f); } @@ -538,7 +538,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) { // This is the first message being handled after a resetReceiveCounts, // we must be starting the message processing loop. Reset the timers. - mCurrentMessageTimeSeconds = totalTime() * SEC_PER_USEC; + mCurrentMessageTime = totalTime(); mMessageCountTime = getMessageTimeSeconds(); } @@ -765,7 +765,7 @@ BOOL LLMessageSystem::checkMessages( S64 frame_count ) } } while (!valid_packet && receive_size > 0); - F64 mt_sec = getMessageTimeSeconds(); + F64Seconds mt_sec = getMessageTimeSeconds(); // Check to see if we need to print debug info if ((mt_sec - mCircuitPrintTime) > mCircuitPrintFreq) { @@ -794,9 +794,9 @@ S32 LLMessageSystem::getReceiveBytes() const } -void LLMessageSystem::processAcks() +void LLMessageSystem::processAcks(F32 collect_time) { - F64 mt_sec = getMessageTimeSeconds(); + F64Seconds mt_sec = getMessageTimeSeconds(); { gTransferManager.updateTransfers(); @@ -820,7 +820,7 @@ void LLMessageSystem::processAcks() mCircuitInfo.resendUnackedPackets(mUnackedListDepth, mUnackedListSize); //cycle through ack list for each host we need to send acks to - mCircuitInfo.sendAcks(); + mCircuitInfo.sendAcks(collect_time); if (!mDenyTrustedCircuitSet.empty()) { @@ -840,10 +840,10 @@ void LLMessageSystem::processAcks() } } - if (mMaxMessageTime >= 0.f) + if (mMaxMessageTime >= F32Seconds(0.f)) { // This is one of the only places where we're required to get REAL message system time. - mReceiveTime = (F32)(getMessageTimeSeconds(TRUE) - mMessageCountTime); + mReceiveTime = getMessageTimeSeconds(TRUE) - mMessageCountTime; if (mReceiveTime > mMaxMessageTime) { dump = TRUE; @@ -1017,13 +1017,13 @@ S32 LLMessageSystem::sendReliable(const LLHost &host) S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data) { - F32 timeout; + F32Seconds timeout; LLCircuitData *cdp = mCircuitInfo.findCircuit(host); if (cdp) { timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS, - LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()); + F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged())); } else { @@ -1039,7 +1039,7 @@ S32 LLMessageSystem::sendSemiReliable(const LLHost &host, void (*callback)(void S32 LLMessageSystem::sendReliable( const LLHost &host, S32 retries, BOOL ping_based_timeout, - F32 timeout, + F32Seconds timeout, void (*callback)(void **,S32), void ** callback_data) { @@ -1048,11 +1048,11 @@ S32 LLMessageSystem::sendReliable( const LLHost &host, LLCircuitData *cdp = mCircuitInfo.findCircuit(host); if (cdp) { - timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()); + timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged())); } else { - timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX); + timeout = llmax(LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS, F32Seconds(LL_RELIABLE_TIMEOUT_FACTOR * LL_AVERAGED_PING_MAX)); } } @@ -1084,7 +1084,7 @@ void LLMessageSystem::forwardReliable(const U32 circuit_code) S32 LLMessageSystem::forwardReliable( const LLHost &host, S32 retries, BOOL ping_based_timeout, - F32 timeout, + F32Seconds timeout, void (*callback)(void **,S32), void ** callback_data) { @@ -1094,13 +1094,13 @@ S32 LLMessageSystem::forwardReliable( const LLHost &host, S32 LLMessageSystem::flushSemiReliable(const LLHost &host, void (*callback)(void **,S32), void ** callback_data) { - F32 timeout; + F32Seconds timeout; LLCircuitData *cdp = mCircuitInfo.findCircuit(host); if (cdp) { timeout = llmax(LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS, - LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged()); + F32Seconds(LL_SEMIRELIABLE_TIMEOUT_FACTOR * cdp->getPingDelayAveraged())); } else { @@ -1344,7 +1344,7 @@ S32 LLMessageSystem::sendMessage(const LLHost &host) else { // mCircuitInfo already points to the correct circuit data - cdp->addBytesOut( buffer_length ); + cdp->addBytesOut( (S32Bytes)buffer_length ); } if(mVerboseLog) @@ -1471,7 +1471,7 @@ void LLMessageSystem::logValidMsg(LLCircuitData *cdp, const LLHost& host, BOOL r { // update circuit packet ID tracking (missing/out of order packets) cdp->checkPacketInID( mCurrentRecvPacketID, recv_resent ); - cdp->addBytesIn( mTrueReceiveSize ); + cdp->addBytesIn( (S32Bytes)mTrueReceiveSize ); } if(mVerboseLog) @@ -1738,7 +1738,7 @@ LLHost LLMessageSystem::findHost(const U32 circuit_code) void LLMessageSystem::setMaxMessageTime(const F32 seconds) { - mMaxMessageTime = seconds; + mMaxMessageTime = F32Seconds(seconds); } void LLMessageSystem::setMaxMessageCounts(const S32 num) @@ -2755,7 +2755,7 @@ void LLMessageSystem::dumpReceiveCounts() if(mNumMessageCounts > 0) { - LL_DEBUGS("Messaging") << "Dump: " << mNumMessageCounts << " m essages processed in " << mReceiveTime << " seconds" << LL_ENDL; + LL_DEBUGS("Messaging") << "Dump: " << mNumMessageCounts << " messages processed in " << mReceiveTime << " seconds" << LL_ENDL; for (message_template_name_map_t::const_iterator iter = mMessageTemplates.begin(), end = mMessageTemplates.end(); iter != end; iter++) @@ -2764,7 +2764,7 @@ void LLMessageSystem::dumpReceiveCounts() if (mt->mReceiveCount > 0) { LL_INFOS("Messaging") << "Num: " << std::setw(3) << mt->mReceiveCount << " Bytes: " << std::setw(6) << mt->mReceiveBytes - << " Invalid: " << std::setw(3) << mt->mReceiveInvalid << " " << mt->mName << " " << ll_round(100 * mt->mDecodeTimeThisFrame / mReceiveTime) << "%" << LL_ENDL; + << " Invalid: " << std::setw(3) << mt->mReceiveInvalid << " " << mt->mName << " " << ll_round(100 * mt->mDecodeTimeThisFrame / mReceiveTime.value()) << "%" << LL_ENDL; } } } @@ -3412,15 +3412,15 @@ void LLMessageSystem::dumpPacketToLog() //static -U64 LLMessageSystem::getMessageTimeUsecs(const BOOL update) +U64Microseconds LLMessageSystem::getMessageTimeUsecs(const BOOL update) { if (gMessageSystem) { if (update) { - gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC; + gMessageSystem->mCurrentMessageTime = totalTime(); } - return (U64)(gMessageSystem->mCurrentMessageTimeSeconds * USEC_PER_SEC); + return gMessageSystem->mCurrentMessageTime; } else { @@ -3429,19 +3429,19 @@ U64 LLMessageSystem::getMessageTimeUsecs(const BOOL update) } //static -F64 LLMessageSystem::getMessageTimeSeconds(const BOOL update) +F64Seconds LLMessageSystem::getMessageTimeSeconds(const BOOL update) { if (gMessageSystem) { if (update) { - gMessageSystem->mCurrentMessageTimeSeconds = totalTime()*SEC_PER_USEC; + gMessageSystem->mCurrentMessageTime = totalTime(); } - return gMessageSystem->mCurrentMessageTimeSeconds; + return gMessageSystem->mCurrentMessageTime; } else { - return totalTime()*SEC_PER_USEC; + return F64Seconds(totalTime()); } } diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index ced674700..1d5bc81c5 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -148,18 +148,15 @@ enum EPacketHeaderLayout const S32 LL_DEFAULT_RELIABLE_RETRIES = 3; -const F32 LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS = 1.f; -const F32 LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS = 1.f; -const F32 LL_PING_BASED_TIMEOUT_DUMMY = 0.0f; +const F32Seconds LL_MINIMUM_RELIABLE_TIMEOUT_SECONDS(1.f); +const F32Seconds LL_MINIMUM_SEMIRELIABLE_TIMEOUT_SECONDS(1.f); +const F32Seconds LL_PING_BASED_TIMEOUT_DUMMY(0.0f); -// *NOTE: Maybe these factors shouldn't include the msec to sec conversion -// implicitly. -// However, all units should be MKS. -const F32 LL_SEMIRELIABLE_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping -const F32 LL_RELIABLE_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping -const F32 LL_FILE_XFER_TIMEOUT_FACTOR = 5.f / 1000.f; // factor * averaged ping -const F32 LL_LOST_TIMEOUT_FACTOR = 16.f / 1000.f; // factor * averaged ping for marking packets "Lost" -const F32 LL_MAX_LOST_TIMEOUT = 5.f; // Maximum amount of time before considering something "lost" +const F32 LL_SEMIRELIABLE_TIMEOUT_FACTOR = 5.f; // averaged ping +const F32 LL_RELIABLE_TIMEOUT_FACTOR = 5.f; // averaged ping +const F32 LL_FILE_XFER_TIMEOUT_FACTOR = 5.f; //averaged ping +const F32 LL_LOST_TIMEOUT_FACTOR = 16.f; // averaged ping for marking packets "Lost" +const F32Seconds LL_MAX_LOST_TIMEOUT(5.f); // Maximum amount of time before considering something "lost" const S32 MAX_MESSAGE_COUNT_NUM = 1024; @@ -279,8 +276,8 @@ public: BOOL mSendReliable; // does the outgoing message require a pos ack? LLCircuit mCircuitInfo; - F64 mCircuitPrintTime; // used to print circuit debug info every couple minutes - F32 mCircuitPrintFreq; // seconds + F64Seconds mCircuitPrintTime; // used to print circuit debug info every couple minutes + F32Seconds mCircuitPrintFreq; std::map mIPPortToCircuitCode; std::map mCircuitCodeToIPPort; @@ -344,7 +341,7 @@ public: BOOL poll(F32 seconds); // Number of seconds that we want to block waiting for data, returns if data was received BOOL checkMessages(S64 frame_count = 0); - void processAcks(); + void processAcks(F32 collect_time = 0.f); BOOL isMessageFast(const char *msg); BOOL isMessage(const char *msg) @@ -478,7 +475,7 @@ public: S32 sendReliable( const LLHost &host, S32 retries, BOOL ping_based_retries, - F32 timeout, + F32Seconds timeout, void (*callback)(void **,S32), void ** callback_data); @@ -498,7 +495,7 @@ public: const LLHost &host, S32 retries, BOOL ping_based_timeout, - F32 timeout, + F32Seconds timeout, void (*callback)(void **,S32), void ** callback_data); @@ -692,8 +689,8 @@ public: void setMaxMessageTime(const F32 seconds); // Max time to process messages before warning and dumping (neg to disable) void setMaxMessageCounts(const S32 num); // Max number of messages before dumping (neg to disable) - static U64 getMessageTimeUsecs(const BOOL update = FALSE); // Get the current message system time in microseconds - static F64 getMessageTimeSeconds(const BOOL update = FALSE); // Get the current message system time in seconds + static U64Microseconds getMessageTimeUsecs(const BOOL update = FALSE); // Get the current message system time in microseconds + static F64Seconds getMessageTimeSeconds(const BOOL update = FALSE); // Get the current message system time in seconds static void setTimeDecodes(BOOL b); static void setTimeDecodesSpamThreshold(F32 seconds); @@ -792,16 +789,16 @@ private: BOOL mbError; S32 mErrorCode; - F64 mResendDumpTime; // The last time we dumped resends + F64Seconds mResendDumpTime; // The last time we dumped resends LLMessageCountInfo mMessageCountList[MAX_MESSAGE_COUNT_NUM]; S32 mNumMessageCounts; - F32 mReceiveTime; - F32 mMaxMessageTime; // Max number of seconds for processing messages + F32Seconds mReceiveTime; + F32Seconds mMaxMessageTime; // Max number of seconds for processing messages S32 mMaxMessageCounts; // Max number of messages to process before dumping. - F64 mMessageCountTime; + F64Seconds mMessageCountTime; - F64 mCurrentMessageTimeSeconds; // The current "message system time" (updated the first call to checkMessages after a resetReceiveCount + F64Seconds mCurrentMessageTime; // The current "message system time" (updated the first call to checkMessages after a resetReceiveCount // message system exceptions typedef std::pair exception_t; diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 396f946b4..523bcbb60 100644 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -32,9 +32,7 @@ #include #if LL_WINDOWS - #define WIN32_LEAN_AND_MEAN - #include - #include +#include "llwin32headerslean.h" #else #include #include diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index e2c4d5295..b688e746e 100644 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -9,22 +9,30 @@ include(LLMessage) include(LLXML) include(LLPhysicsExtensions) include(Colladadom) +include(LLCharacter) include_directories( ${LLCOMMON_INCLUDE_DIRS} ${LLMATH_INCLUDE_DIRS} ${LLMESSAGE_INCLUDE_DIRS} ${LLXML_INCLUDE_DIRS} - ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} ${COLLADADOM_INCLUDE_DIRS} + ${LLCHARACTER_INCLUDE_DIRS} + ) +include_directories(SYSTEM + ${LLCOMMON_SYSTEM_INCLUDE_DIRS} + ${LLXML_SYSTEM_INCLUDE_DIRS} + ${LLPHYSICSEXTENSIONS_INCLUDE_DIRS} ) set(llprimitive_SOURCE_FILES + lldaeloader.cpp llmaterialid.cpp llmaterial.cpp llmaterialtable.cpp llmediaentry.cpp llmodel.cpp + llmodelloader.cpp llprimitive.cpp llprimtexturelist.cpp lltextureanim.cpp @@ -37,13 +45,14 @@ set(llprimitive_SOURCE_FILES set(llprimitive_HEADER_FILES CMakeLists.txt - + lldaeloader.h legacy_object_types.h llmaterial.h llmaterialid.h llmaterialtable.h llmediaentry.h llmodel.h + llmodelloader.h llprimitive.h llprimtexturelist.h lltextureanim.h diff --git a/indra/llprimitive/lldaeloader.cpp b/indra/llprimitive/lldaeloader.cpp new file mode 100644 index 000000000..89ca130b6 --- /dev/null +++ b/indra/llprimitive/lldaeloader.cpp @@ -0,0 +1,2605 @@ +/** + * @file lldaeloader.cpp + * @brief LLDAELoader class implementation + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#if LL_MSVC +#pragma warning (disable : 4263) +#pragma warning (disable : 4264) +#endif +#include "dae.h" +#include "dom/domAsset.h" +#include "dom/domBind_material.h" +#include "dom/domCOLLADA.h" +#include "dom/domConstants.h" +#include "dom/domController.h" +#include "dom/domEffect.h" +#include "dom/domGeometry.h" +#include "dom/domInstance_geometry.h" +#include "dom/domInstance_material.h" +#include "dom/domInstance_node.h" +#include "dom/domInstance_effect.h" +#include "dom/domMaterial.h" +#include "dom/domMatrix.h" +#include "dom/domNode.h" +#include "dom/domProfile_COMMON.h" +#include "dom/domRotate.h" +#include "dom/domScale.h" +#include "dom/domTranslate.h" +#include "dom/domVisual_scene.h" +#if LL_MSVC +#pragma warning (default : 4263) +#pragma warning (default : 4264) +#endif + +#include + +#include "lldaeloader.h" +#include "llsdserialize.h" +#include "lljoint.h" + +#include "llmatrix4a.h" + +#include +#include + +std::string colladaVersion[VERSIONTYPE_COUNT+1] = +{ + "1.4.0", + "1.4.1", + "Unsupported" +}; + +static const std::string lod_suffix[LLModel::NUM_LODS] = +{ + "_LOD0", + "_LOD1", + "_LOD2", + "", + "_PHYS", +}; + +const U32 LIMIT_MATERIALS_OUTPUT = 12; +bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride, + domSource* &pos_source, domSource* &tc_source, domSource* &norm_source) +{ + idx_stride = 0; + + for (U32 j = 0; j < inputs.getCount(); ++j) + { + idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride); + + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0) + { //found vertex array + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + domVertices* vertices = (domVertices*) elem.cast(); + if ( !vertices ) + { + return false; + } + + domInputLocal_Array& v_inp = vertices->getInput_array(); + + + for (U32 k = 0; k < v_inp.getCount(); ++k) + { + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) + { + pos_offset = inputs[j]->getOffset(); + + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + pos_source = (domSource*) elem.cast(); + } + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0) + { + norm_offset = inputs[j]->getOffset(); + + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + norm_source = (domSource*) elem.cast(); + } + } + } + + if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0) + { + //found normal array for this triangle list + norm_offset = inputs[j]->getOffset(); + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + norm_source = (domSource*) elem.cast(); + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0) + { //found texCoords + tc_offset = inputs[j]->getOffset(); + const domURIFragmentType& uri = inputs[j]->getSource(); + daeElementRef elem = uri.getElement(); + tc_source = (domSource*) elem.cast(); + } + } + + idx_stride += 1; + + return true; +} + +LLModel::EModelStatus load_face_from_dom_triangles(std::vector& face_list, std::vector& materials, domTrianglesRef& tri) +{ + LLVolumeFace face; + std::vector verts; + std::vector indices; + + const domInputLocalOffset_Array& inputs = tri->getInput_array(); + + S32 pos_offset = -1; + S32 tc_offset = -1; + S32 norm_offset = -1; + + domSource* pos_source = NULL; + domSource* tc_source = NULL; + domSource* norm_source = NULL; + + S32 idx_stride = 0; + + if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source ) + { + LL_WARNS() << "Could not find dom sources for basic geo data; invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + if (!pos_source || !pos_source->getFloat_array()) + { + LL_WARNS() << "Unable to process mesh without position data; invalid model; invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + domPRef p = tri->getP(); + domListOfUInts& idx = p->getValue(); + + domListOfFloats dummy ; + domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy ; + domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy ; + domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy ; + + U32 index_count = idx.getCount(); + U32 vertex_count = pos_source ? v.getCount() : 0; + U32 tc_count = tc_source ? tc.getCount() : 0; + U32 norm_count = norm_source ? n.getCount() : 0; + + if (pos_source) + { + if (vertex_count == 0) + { + LL_WARNS() << "Unable to process mesh with empty position array; invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + face.mExtents[0].set(v[0], v[1], v[2]); + face.mExtents[1].set(v[0], v[1], v[2]); + + + LLVolumeFace::VertexMapData::PointMap point_map; + + for (U32 i = 0; i < index_count; i += idx_stride) + { + LLVolumeFace::VertexData cv; + if (pos_source) + { + // guard against model data specifiying out of range indices or verts + // + if (((i + pos_offset) > index_count) + || ((idx[i+pos_offset]*3+2) > vertex_count)) + { + LL_WARNS() << "Out of range index data; invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0], + v[idx[i+pos_offset]*3+1], + v[idx[i+pos_offset]*3+2])); + + if (!cv.getPosition().isFinite3()) + { + LL_WARNS() << "Nan positional data, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + if (tc_source) + { + // guard against model data specifiying out of range indices or tcs + // + + if (((i + tc_offset) > index_count) + || ((idx[i+tc_offset]*2+1) > tc_count)) + { + LL_WARNS() << "Out of range TC indices." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0], + tc[idx[i+tc_offset]*2+1]); + + if (!cv.mTexCoord.isFinite()) + { + LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + if (norm_source) + { + // guard against model data specifiying out of range indices or norms + // + if (((i + norm_offset) > index_count) + || ((idx[i+norm_offset]*3+2) > norm_count)) + { + LL_WARNS() << "Found out of range norm indices, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0], + n[idx[i+norm_offset]*3+1], + n[idx[i+norm_offset]*3+2])); + + if (!cv.getNormal().isFinite3()) + { + LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + BOOL found = FALSE; + + LLVolumeFace::VertexMapData::PointMap::iterator point_iter; + point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); + + if (point_iter != point_map.end()) + { + for (U32 j = 0; j < point_iter->second.size(); ++j) + { + // We have a matching loc + // + if ((point_iter->second)[j] == cv) + { + U16 shared_index = (point_iter->second)[j].mIndex; + + // Don't share verts within the same tri, degenerate + // + U32 indx_size = indices.size(); + U32 verts_new_tri = indx_size % 3; + if ((verts_new_tri < 1 || indices[indx_size - 1] != shared_index) + && (verts_new_tri < 2 || indices[indx_size - 2] != shared_index)) + { + found = true; + indices.push_back(shared_index); + } + break; + } + } + } + + if (!found) + { + update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); + verts.push_back(cv); + if (verts.size() >= 65535) + { + //LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; + return LLModel::VERTEX_NUMBER_OVERFLOW ; + } + U16 index = (U16) (verts.size()-1); + indices.push_back(index); + + LLVolumeFace::VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); + } + } + + if (indices.size()%3 == 0 && verts.size() >= 65532) + { + std::string material; + + if (tri->getMaterial()) + { + material = std::string(tri->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + face = LLVolumeFace(); + point_map.clear(); + } + } + + if (!verts.empty()) + { + std::string material; + + if (tri->getMaterial()) + { + material = std::string(tri->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + + face_list.rbegin()->fillFromLegacyData(verts, indices); + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS ; +} + +LLModel::EModelStatus load_face_from_dom_polylist(std::vector& face_list, std::vector& materials, domPolylistRef& poly) +{ + domPRef p = poly->getP(); + domListOfUInts& idx = p->getValue(); + + if (idx.getCount() == 0) + { + return LLModel::NO_ERRORS ; + } + + const domInputLocalOffset_Array& inputs = poly->getInput_array(); + + + domListOfUInts& vcount = poly->getVcount()->getValue(); + + S32 pos_offset = -1; + S32 tc_offset = -1; + S32 norm_offset = -1; + + domSource* pos_source = NULL; + domSource* tc_source = NULL; + domSource* norm_source = NULL; + + S32 idx_stride = 0; + + if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source)) + { + LL_WARNS() << "Could not get DOM sources for basic geo data, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + LLVolumeFace face; + + std::vector indices; + std::vector verts; + + domListOfFloats v; + domListOfFloats tc; + domListOfFloats n; + + if (pos_source) + { + v = pos_source->getFloat_array()->getValue(); + face.mExtents[0].set(v[0], v[1], v[2]); + face.mExtents[1].set(v[0], v[1], v[2]); + } + + if (tc_source) + { + tc = tc_source->getFloat_array()->getValue(); + } + + if (norm_source) + { + n = norm_source->getFloat_array()->getValue(); + } + + LLVolumeFace::VertexMapData::PointMap point_map; + + U32 index_count = idx.getCount(); + U32 vertex_count = pos_source ? v.getCount() : 0; + U32 tc_count = tc_source ? tc.getCount() : 0; + U32 norm_count = norm_source ? n.getCount() : 0; + + U32 cur_idx = 0; + for (U32 i = 0; i < vcount.getCount(); ++i) + { //for each polygon + U32 first_index = 0; + U32 last_index = 0; + for (U32 j = 0; j < vcount[i]; ++j) + { //for each vertex + + LLVolumeFace::VertexData cv; + + if (pos_source) + { + // guard against model data specifiying out of range indices or verts + // + if (((cur_idx + pos_offset) > index_count) + || ((idx[cur_idx+pos_offset]*3+2) > vertex_count)) + { + LL_WARNS() << "Out of range position indices, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0], + v[idx[cur_idx+pos_offset]*3+1], + v[idx[cur_idx+pos_offset]*3+2]); + + if (!cv.getPosition().isFinite3()) + { + LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + } + + if (tc_source) + { + // guard against model data specifiying out of range indices or tcs + // + if (((cur_idx + tc_offset) > index_count) + || ((idx[cur_idx+tc_offset]*2+1) > tc_count)) + { + LL_WARNS() << "Out of range TC indices, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0], + tc[idx[cur_idx+tc_offset]*2+1]); + + if (!cv.mTexCoord.isFinite()) + { + LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + if (norm_source) + { + // guard against model data specifiying out of range indices or norms + // + if (((cur_idx + norm_offset) > index_count) + || ((idx[cur_idx+norm_offset]*3+2) > norm_count)) + { + LL_WARNS() << "Out of range norm indices, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + + cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0], + n[idx[cur_idx+norm_offset]*3+1], + n[idx[cur_idx+norm_offset]*3+2]); + + if (!cv.getNormal().isFinite3()) + { + LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + cur_idx += idx_stride; + + BOOL found = FALSE; + + LLVolumeFace::VertexMapData::PointMap::iterator point_iter; + LLVector3 pos3(cv.getPosition().getF32ptr()); + point_iter = point_map.find(pos3); + + if (point_iter != point_map.end()) + { + for (U32 k = 0; k < point_iter->second.size(); ++k) + { + if ((point_iter->second)[k] == cv) + { + found = TRUE; + U32 index = (point_iter->second)[k].mIndex; + if (j == 0) + { + first_index = index; + } + else if (j == 1) + { + last_index = index; + } + else + { + // if these are the same, we have a very, very skinny triangle (coincident verts on one or more edges) + // + llassert((first_index != last_index) && (last_index != index) && (first_index != index)); + indices.push_back(first_index); + indices.push_back(last_index); + indices.push_back(index); + last_index = index; + } + + break; + } + } + } + + if (!found) + { + update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); + verts.push_back(cv); + if (verts.size() >= 65535) + { + //LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; + return LLModel::VERTEX_NUMBER_OVERFLOW ; + } + U16 index = (U16) (verts.size()-1); + + if (j == 0) + { + first_index = index; + } + else if (j == 1) + { + last_index = index; + } + else + { + // detect very skinny degenerate triangles with collapsed edges + // + llassert((first_index != last_index) && (last_index != index) && (first_index != index)); + indices.push_back(first_index); + indices.push_back(last_index); + indices.push_back(index); + last_index = index; + } + + LLVolumeFace::VertexMapData d; + d.setPosition(cv.getPosition()); + d.mTexCoord = cv.mTexCoord; + d.setNormal(cv.getNormal()); + d.mIndex = index; + if (point_iter != point_map.end()) + { + point_iter->second.push_back(d); + } + else + { + point_map[pos3].push_back(d); + } + } + + if (indices.size()%3 == 0 && indices.size() >= 65532) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + + face = LLVolumeFace(); + verts.clear(); + indices.clear(); + point_map.clear(); + } + } + } + + if (!verts.empty()) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(verts, indices); + + LLVolumeFace& new_face = *face_list.rbegin(); + if (!norm_source) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!tc_source) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS ; +} + +LLModel::EModelStatus load_face_from_dom_polygons(std::vector& face_list, std::vector& materials, domPolygonsRef& poly) +{ + LLVolumeFace face; + std::vector indices; + std::vector verts; + + const domInputLocalOffset_Array& inputs = poly->getInput_array(); + + S32 v_offset = -1; + S32 n_offset = -1; + S32 t_offset = -1; + + domListOfFloats* v = NULL; + domListOfFloats* n = NULL; + domListOfFloats* t = NULL; + + U32 stride = 0; + for (U32 i = 0; i < inputs.getCount(); ++i) + { + stride = llmax((U32) inputs[i]->getOffset()+1, stride); + + if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0) + { //found vertex array + v_offset = inputs[i]->getOffset(); + + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domVertices* vertices = (domVertices*) elem.cast(); + if (!vertices) + { + LL_WARNS() << "Could not find vertex source, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + domInputLocal_Array& v_inp = vertices->getInput_array(); + + for (U32 k = 0; k < v_inp.getCount(); ++k) + { + if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) + { + const domURIFragmentType& uri = v_inp[k]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + if (!src) + { + LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + v = &(src->getFloat_array()->getValue()); + } + } + } + else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0) + { + n_offset = inputs[i]->getOffset(); + //found normal array for this triangle list + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + if (!src) + { + LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + n = &(src->getFloat_array()->getValue()); + } + else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0) + { //found texCoords + t_offset = inputs[i]->getOffset(); + const domURIFragmentType& uri = inputs[i]->getSource(); + daeElementRef elem = uri.getElement(); + domSource* src = (domSource*) elem.cast(); + if (!src) + { + LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + t = &(src->getFloat_array()->getValue()); + } + } + + domP_Array& ps = poly->getP_array(); + + //make a triangle list in + for (U32 i = 0; i < ps.getCount(); ++i) + { //for each polygon + domListOfUInts& idx = ps[i]->getValue(); + for (U32 j = 0; j < idx.getCount()/stride; ++j) + { //for each vertex + if (j > 2) + { + U32 size = verts.size(); + LLVolumeFace::VertexData v0 = verts[size-3]; + LLVolumeFace::VertexData v1 = verts[size-1]; + + verts.push_back(v0); + verts.push_back(v1); + } + + LLVolumeFace::VertexData vert; + + + if (v) + { + U32 v_idx = idx[j*stride+v_offset]*3; + v_idx = llclamp(v_idx, (U32) 0, (U32) v->getCount()); + vert.getPosition().set(v->get(v_idx), + v->get(v_idx+1), + v->get(v_idx+2)); + + if (!vert.getPosition().isFinite3()) + { + LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + + //bounds check n and t lookups because some FBX to DAE converters + //use negative indices and empty arrays to indicate data does not exist + //for a particular channel + if (n && n->getCount() > 0) + { + U32 n_idx = idx[j*stride+n_offset]*3; + n_idx = llclamp(n_idx, (U32) 0, (U32) n->getCount()); + vert.getNormal().set(n->get(n_idx), + n->get(n_idx+1), + n->get(n_idx+2)); + + if (!vert.getNormal().isFinite3()) + { + LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + else + { + vert.getNormal().clear(); + } + + + if (t && t->getCount() > 0) + { + U32 t_idx = idx[j*stride+t_offset]*2; + t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount()); + vert.mTexCoord.setVec(t->get(t_idx), + t->get(t_idx+1)); + + if (!vert.mTexCoord.isFinite()) + { + LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; + return LLModel::BAD_ELEMENT; + } + } + else + { + vert.mTexCoord.clear(); + } + + + verts.push_back(vert); + } + } + + if (verts.empty()) + { + return LLModel::NO_ERRORS; + } + + face.mExtents[0] = verts[0].getPosition(); + face.mExtents[1] = verts[0].getPosition(); + + //create a map of unique vertices to indices + std::map vert_idx; + + U32 cur_idx = 0; + for (U32 i = 0; i < verts.size(); ++i) + { + std::map::iterator iter = vert_idx.find(verts[i]); + if (iter == vert_idx.end()) + { + vert_idx[verts[i]] = cur_idx++; + } + } + + //build vertex array from map + std::vector new_verts; + new_verts.resize(vert_idx.size()); + + for (std::map::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter) + { + new_verts[iter->second] = iter->first; + update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition()); + } + + //build index array from map + indices.resize(verts.size()); + + for (U32 i = 0; i < verts.size(); ++i) + { + indices[i] = vert_idx[verts[i]]; + llassert(!i || (indices[i-1] != indices[i])); + } + + // DEBUG just build an expanded triangle list + /*for (U32 i = 0; i < verts.size(); ++i) + { + indices.push_back((U16) i); + update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition()); + }*/ + + if (!new_verts.empty()) + { + std::string material; + + if (poly->getMaterial()) + { + material = std::string(poly->getMaterial()); + } + + materials.push_back(material); + face_list.push_back(face); + face_list.rbegin()->fillFromLegacyData(new_verts, indices); + + LLVolumeFace& new_face = *face_list.rbegin(); + if (!n) + { + //ll_aligned_free_16(new_face.mNormals); + new_face.mNormals = NULL; + } + + if (!t) + { + //ll_aligned_free_16(new_face.mTexCoords); + new_face.mTexCoords = NULL; + } + } + + return LLModel::NO_ERRORS ; +} + +//----------------------------------------------------------------------------- +// LLDAELoader +//----------------------------------------------------------------------------- +LLDAELoader::LLDAELoader( + std::string filename, + S32 lod, + load_callback_t load_cb, + joint_lookup_func_t joint_lookup_func, + texture_load_func_t texture_load_func, + state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointMap, + JointSet& jointsFromNodes, + U32 modelLimit, + bool preprocess) +: LLModelLoader( + filename, + lod, + load_cb, + joint_lookup_func, + texture_load_func, + state_cb, + opaque_userdata, + jointMap, + jointsFromNodes), +mGeneratedModelLimit(modelLimit), +mPreprocessDAE(preprocess) +{ +} + +LLDAELoader::~LLDAELoader() +{ +} + +struct ModelSort +{ + bool operator()(const LLPointer< LLModel >& lhs, const LLPointer< LLModel >& rhs) + { + if (lhs->mSubmodelID < rhs->mSubmodelID) + { + return true; + } + return LLStringUtil::compareInsensitive(lhs->mLabel, rhs->mLabel) < 0; + } +}; + +bool LLDAELoader::OpenFile(const std::string& filename) +{ + //no suitable slm exists, load from the .dae file + DAE dae; + domCOLLADA* dom; + if (mPreprocessDAE) + { + dom = dae.openFromMemory(filename, preprocessDAE(filename).c_str()); + } + else + { + LL_INFOS() << "Skipping dae preprocessing" << LL_ENDL; + dom = dae.open(filename); + } + + if (!dom) + { + LL_INFOS() <<" Error with dae - traditionally indicates a corrupt file."<getVersion(); + //0=1.4 + //1=1.4.1 + //2=Currently unsupported, however may work + if (docVersion > 1) + { + docVersion = VERSIONTYPE_COUNT; + } + LL_INFOS()<<"Dae version "<getElementCount(NULL, COLLADA_TYPE_MESH); + + daeDocument* doc = dae.getDoc(filename); + if (!doc) + { + LL_WARNS() << "can't find internal doc" << LL_ENDL; + return false; + } + + daeElement* root = doc->getDomRoot(); + if (!root) + { + LL_WARNS() << "document has no root" << LL_ENDL; + return false; + } + + //Verify some basic properties of the dae + //1. Basic validity check on controller + U32 controllerCount = (int) db->getElementCount(NULL, "controller"); + bool result = false; + for (U32 i = 0; i < controllerCount; ++i) + { + domController* pController = NULL; + db->getElement((daeElement**) &pController, i , NULL, "controller"); + result = verifyController( pController ); + if (!result) + { + LL_INFOS() << "Could not verify controller" << LL_ENDL; + setLoadState(ERROR_PARSING); + return true; + } + } + + //get unit scale + mTransform.setIdentity(); + + domAsset::domUnit* unit = daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID()))); + + if (unit) + { + F32 meter = unit->getMeter(); + mTransform.mMatrix[0][0] = meter; + mTransform.mMatrix[1][1] = meter; + mTransform.mMatrix[2][2] = meter; + } + + //get up axis rotation + LLMatrix4 rotation; + + domUpAxisType up = UPAXISTYPE_Y_UP; // default is Y_UP + domAsset::domUp_axis* up_axis = + daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID()))); + + if (up_axis) + { + up = up_axis->getValue(); + } + + if (up == UPAXISTYPE_X_UP) + { + rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f); + } + else if (up == UPAXISTYPE_Y_UP) + { + rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f); + } + + rotation *= mTransform; + mTransform = rotation; + + mTransform.condition(); + + U32 submodel_limit = count > 0 ? mGeneratedModelLimit/count : 0; + for (daeInt idx = 0; idx < count; ++idx) + { //build map of domEntities to LLModel + domMesh* mesh = NULL; + db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH); + + if (mesh) + { + + std::vector models; + + loadModelsFromDomMesh(mesh, models, submodel_limit); + + std::vector::iterator i; + i = models.begin(); + while (i != models.end()) + { + LLModel* mdl = *i; + if(mdl->getStatus() != LLModel::NO_ERRORS) + { + setLoadState(ERROR_MODEL + mdl->getStatus()) ; + return false; //abort + } + + if (mdl && validate_model(mdl)) + { + mModelList.push_back(mdl); + mModelsMap[mesh].push_back(mdl); + } + i++; + } + } + } + + std::sort(mModelList.begin(), mModelList.end(), ModelSort()); + + model_list::iterator model_iter = mModelList.begin(); + while (model_iter != mModelList.end()) + { + LLModel* mdl = *model_iter; + U32 material_count = mdl->mMaterialList.size(); + LL_INFOS() << "Importing " << mdl->mLabel << " model with " << material_count << " material references" << LL_ENDL; + std::vector::iterator mat_iter = mdl->mMaterialList.begin(); + std::vector::iterator end_iter = material_count > LIMIT_MATERIALS_OUTPUT + ? mat_iter + LIMIT_MATERIALS_OUTPUT + : mdl->mMaterialList.end(); + while (mat_iter != end_iter) + { + LL_INFOS() << mdl->mLabel << " references " << (*mat_iter) << LL_ENDL; + mat_iter++; + } + model_iter++; + } + + count = db->getElementCount(NULL, COLLADA_TYPE_SKIN); + for (daeInt idx = 0; idx < count; ++idx) + { //add skinned meshes as instances + domSkin* skin = NULL; + db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN); + + if (skin) + { + domGeometry* geom = daeSafeCast(skin->getSource().getElement()); + + if (geom) + { + domMesh* mesh = geom->getMesh(); + if (mesh) + { + std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin(); + while (i != mModelsMap[mesh].end()) + { + LLPointer mdl = *i; + LLDAELoader::processDomModel(mdl, &dae, root, mesh, skin); + i++; + } + } + } + } + } + + LL_INFOS()<< "Collada skins processed: " << count <getDescendant("visual_scene"); + + if (!scene) + { + LL_WARNS() << "document has no visual_scene" << LL_ENDL; + setLoadState( ERROR_PARSING ); + return true; + } + + setLoadState( DONE ); + + bool badElement = false; + + processElement( scene, badElement, &dae ); + + if ( badElement ) + { + LL_INFOS()<<"Scene could not be parsed"<getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); + + LLMatrix4 normalized_transformation; + normalized_transformation.setTranslation(mesh_translation_vector); + + LLMatrix4 mesh_scale; + mesh_scale.initScale(mesh_scale_vector); + mesh_scale *= normalized_transformation; + normalized_transformation = mesh_scale; + + LLMatrix4a inv_mat; + inv_mat.loadu(normalized_transformation); + inv_mat.invert(); + + LLMatrix4 inverse_normalized_transformation(inv_mat.getF32ptr()); + + domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix(); + + if (bind_mat) + { //get bind shape matrix + domFloat4x4& dom_value = bind_mat->getValue(); + + LLMeshSkinInfo& skin_info = model->mSkinInfo; + + for (int i = 0; i < 4; i++) + { + for(int j = 0; j < 4; j++) + { + skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4]; + } + } + + LLMatrix4 trans = normalized_transformation; + trans *= skin_info.mBindShapeMatrix; + skin_info.mBindShapeMatrix = trans; + } + + + //Some collada setup for accessing the skeleton + daeElement* pElement = 0; + dae->getDatabase()->getElement( &pElement, 0, 0, "skeleton" ); + + //Try to get at the skeletal instance controller + domInstance_controller::domSkeleton* pSkeleton = daeSafeCast( pElement ); + bool missingSkeletonOrScene = false; + + //If no skeleton, do a breadth-first search to get at specific joints + bool rootNode = false; + + //Need to test for a skeleton that does not have a root node + //This occurs when your instance controller does not have an associated scene + if ( pSkeleton ) + { + daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); + if ( pSkeletonRootNode ) + { + rootNode = true; + } + + } + if ( !pSkeleton || !rootNode ) + { + daeElement* pScene = root->getDescendant("visual_scene"); + if ( !pScene ) + { + LL_WARNS()<<"No visual scene - unable to parse bone offsets "< > children = pScene->getChildren(); + S32 childCount = children.getCount(); + + //Process any children that are joints + //Not all children are joints, some code be ambient lights, cameras, geometry etc.. + for (S32 i = 0; i < childCount; ++i) + { + domNode* pNode = daeSafeCast(children[i]); + if ( isNodeAJoint( pNode ) ) + { + processJointNode( pNode, mJointList ); + } + } + } + } + else + //Has Skeleton + { + //Get the root node of the skeleton + daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); + if ( pSkeletonRootNode ) + { + //Once we have the root node - start acccessing it's joint components + const int jointCnt = mJointMap.size(); + JointMap :: const_iterator jointIt = mJointMap.begin(); + + //Loop over all the possible joints within the .dae - using the allowed joint list in the ctor. + for ( int i=0; i( resolver.getElement() ); + if ( pJoint ) + { + //Pull out the translate id and store it in the jointTranslations map + daeSIDResolver jointResolverA( pJoint, "./translate" ); + domTranslate* pTranslateA = daeSafeCast( jointResolverA.getElement() ); + daeSIDResolver jointResolverB( pJoint, "./location" ); + domTranslate* pTranslateB = daeSafeCast( jointResolverB.getElement() ); + + LLMatrix4 workingTransform; + + //Translation via SID + if ( pTranslateA ) + { + extractTranslation( pTranslateA, workingTransform ); + } + else + if ( pTranslateB ) + { + extractTranslation( pTranslateB, workingTransform ); + } + else + { + //Translation via child from element + daeElement* pTranslateElement = getChildFromElement( pJoint, "translate" ); + if ( pTranslateElement && pTranslateElement->typeID() != domTranslate::ID() ) + { + LL_WARNS()<< "The found element is not a translate node" <getJoints(); + + domInputLocal_Array& joint_input = joints->getInput_array(); + + for (size_t i = 0; i < joint_input.getCount(); ++i) + { + domInputLocal* input = joint_input.get(i); + xsNMTOKEN semantic = input->getSemantic(); + + if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0) + { //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames + daeElement* elem = input->getSource().getElement(); + + domSource* source = daeSafeCast(elem); + if (source) + { + + + domName_array* names_source = source->getName_array(); + + if (names_source) + { + domListOfNames &names = names_source->getValue(); + + for (size_t j = 0; j < names.getCount(); ++j) + { + std::string name(names.get(j)); + if (mJointMap.find(name) != mJointMap.end()) + { + name = mJointMap[name]; + } + model->mSkinInfo.mJointNames.push_back(name); + model->mSkinInfo.mJointMap[name] = j; + } + } + else + { + domIDREF_array* names_source = source->getIDREF_array(); + if (names_source) + { + xsIDREFS& names = names_source->getValue(); + + for (size_t j = 0; j < names.getCount(); ++j) + { + std::string name(names.get(j).getID()); + if (mJointMap.find(name) != mJointMap.end()) + { + name = mJointMap[name]; + } + model->mSkinInfo.mJointNames.push_back(name); + model->mSkinInfo.mJointMap[name] = j; + } + } + } + } + } + else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0) + { //found inv_bind_matrix array, fill model->mInvBindMatrix + domSource* source = daeSafeCast(input->getSource().getElement()); + if (source) + { + domFloat_array* t = source->getFloat_array(); + if (t) + { + domListOfFloats& transform = t->getValue(); + S32 count = transform.getCount()/16; + + for (S32 k = 0; k < count; ++k) + { + LLMatrix4 mat; + + for (int i = 0; i < 4; i++) + { + for(int j = 0; j < 4; j++) + { + mat.mMatrix[i][j] = transform[k*16 + i + j*4]; + } + } + + model->mSkinInfo.mInvBindMatrix.push_back(mat); + } + } + } + } + } + + //Now that we've parsed the joint array, let's determine if we have a full rig + //(which means we have all the joint sthat are required for an avatar versus + //a skinned asset attached to a node in a file that contains an entire skeleton, + //but does not use the skeleton). + buildJointToNodeMappingFromScene( root ); + critiqueRigForUploadApplicability( model->mSkinInfo.mJointNames ); + + if ( !missingSkeletonOrScene ) + { + //Set the joint translations on the avatar - if it's a full mapping + //The joints are reset in the dtor + if ( getRigWithSceneParity() ) + { + JointMap :: const_iterator masterJointIt = mJointMap.begin(); + JointMap :: const_iterator masterJointItEnd = mJointMap.end(); + for (;masterJointIt!=masterJointItEnd;++masterJointIt ) + { + std::string lookingForJoint = (*masterJointIt).first.c_str(); + + if ( mJointList.find( lookingForJoint ) != mJointList.end() ) + { + //LL_INFOS()<<"joint "<addAttachmentPosOverride( jointTransform.getTranslation(), fake_mesh_id, ""); + } + else + { + //Most likely an error in the asset. + LL_WARNS()<<"Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL; + } + } + } + } + } //missingSkeletonOrScene + + //We need to construct the alternate bind matrix (which contains the new joint positions) + //in the same order as they were stored in the joint buffer. The joints associated + //with the skeleton are not stored in the same order as they are in the exported joint buffer. + //This remaps the skeletal joints to be in the same order as the joints stored in the model. + std::vector :: const_iterator jointIt = model->mSkinInfo.mJointNames.begin(); + const int jointCnt = model->mSkinInfo.mJointNames.size(); + for ( int i=0; imSkinInfo.mInvBindMatrix[i]; + newInverse.setTranslation( mJointList[lookingForJoint].getTranslation() ); + model->mSkinInfo.mAlternateBindMatrix.push_back( newInverse ); + } + else + { + LL_WARNS()<<"Possibly misnamed/missing joint [" <getVertices(); + if (verts) + { + domInputLocal_Array& inputs = verts->getInput_array(); + for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i) + { + if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0) + { + domSource* pos_source = daeSafeCast(inputs[i]->getSource().getElement()); + if (pos_source) + { + domFloat_array* pos_array = pos_source->getFloat_array(); + if (pos_array) + { + domListOfFloats& pos = pos_array->getValue(); + + for (size_t j = 0; j < pos.getCount(); j += 3) + { + if (pos.getCount() <= j+2) + { + LL_ERRS() << "Invalid position array size." << LL_ENDL; + } + + LLVector3 v(pos[j], pos[j+1], pos[j+2]); + + //transform from COLLADA space to volume space + v = v * inverse_normalized_transformation; + + model->mPosition.push_back(v); + } + } + } + } + } + } + + //grab skin weights array + domSkin::domVertex_weights* weights = skin->getVertex_weights(); + if (weights) + { + domInputLocalOffset_Array& inputs = weights->getInput_array(); + domFloat_array* vertex_weights = NULL; + for (size_t i = 0; i < inputs.getCount(); ++i) + { + if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0) + { + domSource* weight_source = daeSafeCast(inputs[i]->getSource().getElement()); + if (weight_source) + { + vertex_weights = weight_source->getFloat_array(); + } + } + } + + if (vertex_weights) + { + domListOfFloats& w = vertex_weights->getValue(); + domListOfUInts& vcount = weights->getVcount()->getValue(); + domListOfInts& v = weights->getV()->getValue(); + + U32 c_idx = 0; + for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx) + { //for each vertex + daeUInt count = vcount[vc_idx]; + + //create list of weights that influence this vertex + LLModel::weight_list weight_list; + + for (daeUInt i = 0; i < count; ++i) + { //for each weight + daeInt joint_idx = v[c_idx++]; + daeInt weight_idx = v[c_idx++]; + + if (joint_idx == -1) + { + //ignore bindings to bind_shape_matrix + continue; + } + + F32 weight_value = w[weight_idx]; + + weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value)); + } + + //sort by joint weight + std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater()); + + std::vector wght; + + F32 total = 0.f; + + for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i) + { //take up to 4 most significant weights + if (weight_list[i].mWeight > 0.f) + { + wght.push_back( weight_list[i] ); + total += weight_list[i].mWeight; + } + } + + F32 scale = 1.f/total; + if (scale != 1.f) + { //normalize weights + for (U32 i = 0; i < wght.size(); ++i) + { + wght[i].mWeight *= scale; + } + } + + model->mSkinWeights[model->mPosition[vc_idx]] = wght; + } + } + + } + //add instance to scene for this model + + LLMatrix4 transformation; + transformation.initScale(mesh_scale_vector); + transformation.setTranslation(mesh_translation_vector); + transformation *= mTransform; + + std::map materials; + for (U32 i = 0; i < model->mMaterialList.size(); ++i) + { + materials[model->mMaterialList[i]] = LLImportMaterial(); + } + mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials)); + stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); + } +} + +//----------------------------------------------------------------------------- +// buildJointToNodeMappingFromScene() +//----------------------------------------------------------------------------- +void LLDAELoader::buildJointToNodeMappingFromScene( daeElement* pRoot ) +{ + daeElement* pScene = pRoot->getDescendant("visual_scene"); + if (pScene) + { + daeTArray< daeSmartRef > children = pScene->getChildren(); + S32 childCount = children.getCount(); + for (S32 i = 0; i < childCount; ++i) + { + domNode* pNode = daeSafeCast(children[i]); + processJointToNodeMapping(pNode); + } + } +} +//----------------------------------------------------------------------------- +// processJointToNodeMapping() +//----------------------------------------------------------------------------- +void LLDAELoader::processJointToNodeMapping( domNode* pNode ) +{ + if (isNodeAJoint(pNode)) + { + //1.Store the parent + std::string nodeName = pNode->getName(); + if (!nodeName.empty()) + { + mJointsFromNode.push_front(pNode->getName()); + } + //2. Handle the kiddo's + processChildJoints(pNode); + } + else + { + //Determine if the're any children wrt to this failed node. + //This occurs when an armature is exported and ends up being what essentially amounts to + //as the root for the visual_scene + if (pNode) + { + processChildJoints(pNode); + } + else + { + LL_INFOS() <<"Node is NULL"< > childOfChild = pParentNode->getChildren(); + S32 childOfChildCount = childOfChild.getCount(); + for (S32 i = 0; i < childOfChildCount; ++i) + { + domNode* pChildNode = daeSafeCast(childOfChild[i]); + if (pChildNode) + { + processJointToNodeMapping(pChildNode); + } + } +} + +//----------------------------------------------------------------------------- +// isNodeAJoint() +//----------------------------------------------------------------------------- +bool LLDAELoader::isNodeAJoint( domNode* pNode ) +{ + if ( !pNode || !pNode->getName() ) + { + LL_INFOS()<<"Created node is NULL or invalid"<getName()); +} +//----------------------------------------------------------------------------- +// verifyCount +//----------------------------------------------------------------------------- +bool LLDAELoader::verifyCount(int expected, int result) +{ + if (expected != result) + { + LL_INFOS() << "Error: (expected/got)"<getSkin(); + + if ( pSkin ) + { + xsAnyURI & uri = pSkin->getSource(); + domElement* pElement = uri.getElement(); + + if ( !pElement ) + { + LL_INFOS()<<"Can't resolve skin source"<getTypeName(); + if ( stricmp(type_str, "geometry") == 0 ) + { + //Skin is reference directly by geometry and get the vertex count from skin + domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights(); + U32 vertexWeightsCount = pVertexWeights->getCount(); + domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement(); + domMesh* pMesh = pGeometry->getMesh(); + + if ( pMesh ) + { + //Get vertex count from geometry + domVertices* pVertices = pMesh->getVertices(); + if (!pVertices) + { + LL_INFOS() <<"No vertices!"<getInput_array()[0]->getSource(); + domSource* pSource = (domSource*) (domElement*) src.getElement(); + U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount(); + result = verifyCount(verticesCount, vertexWeightsCount); + if (!result) + { + return result; + } + } + } + + U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount(); + result = verifyCount(vcountCount, vertexWeightsCount); + if (!result) + { + return result; + } + + domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array(); + U32 sum = 0; + for (size_t i = 0; i < vcountCount; i++) + { + sum += pVertexWeights->getVcount()->getValue()[i]; + } + result = verifyCount(sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount()); + } + } + + return result; +} + +//----------------------------------------------------------------------------- +// extractTranslation() +//----------------------------------------------------------------------------- +void LLDAELoader::extractTranslation( domTranslate* pTranslate, LLMatrix4& transform ) +{ + domFloat3 jointTrans = pTranslate->getValue(); + LLVector3 singleJointTranslation(jointTrans[0], jointTrans[1], jointTrans[2]); + transform.setTranslation(singleJointTranslation); +} + +//----------------------------------------------------------------------------- +// extractTranslationViaElement() +//----------------------------------------------------------------------------- +void LLDAELoader::extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform ) +{ + if (pTranslateElement) + { + domTranslate* pTranslateChild = dynamic_cast(pTranslateElement); + domFloat3 translateChild = pTranslateChild->getValue(); + LLVector3 singleJointTranslation(translateChild[0], translateChild[1], translateChild[2]); + transform.setTranslation(singleJointTranslation); + } +} +//----------------------------------------------------------------------------- +// extractTranslationViaSID() +//----------------------------------------------------------------------------- +void LLDAELoader::extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform ) +{ + if (pElement) + { + daeSIDResolver resolver(pElement, "./transform"); + domMatrix* pMatrix = daeSafeCast(resolver.getElement()); + //We are only extracting out the translational component atm + LLMatrix4 workingTransform; + if (pMatrix) + { + domFloat4x4 domArray = pMatrix->getValue(); + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + workingTransform.mMatrix[i][j] = domArray[i + j*4]; + } + } + LLVector3 trans = workingTransform.getTranslation(); + transform.setTranslation(trans); + } + } + else + { + LL_WARNS() << "Element is nonexistent - empty/unsupported node." << LL_ENDL; + } +} +//----------------------------------------------------------------------------- +// processJointNode() +//----------------------------------------------------------------------------- +void LLDAELoader::processJointNode( domNode* pNode, JointTransformMap& jointTransforms ) +{ + if (pNode->getName() == NULL) + { + LL_WARNS() << "nameless node, can't process" << LL_ENDL; + return; + } + + //llwarns<<"ProcessJointNode# Node:" <getName()<(jointResolverA.getElement()); + daeSIDResolver jointResolverB(pNode, "./location"); + domTranslate* pTranslateB = daeSafeCast(jointResolverB.getElement()); + + //Translation via SID was successful + if (pTranslateA) + { + extractTranslation(pTranslateA, workingTransform); + } + else + if (pTranslateB) + { + extractTranslation(pTranslateB, workingTransform); + } + else + { + //Translation via child from element + daeElement* pTranslateElement = getChildFromElement(pNode, "translate"); + if (!pTranslateElement || pTranslateElement->typeID() != domTranslate::ID()) + { + //llwarns<< "The found element is not a translate node" <(jointResolver.getElement()); + if (pMatrix) + { + //LL_INFOS() <<"A matrix SID was however found!"<getValue(); + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + workingTransform.mMatrix[i][j] = domArray[i + j*4]; + } + } + } + else + { + LL_WARNS() << "The found element is not translate or matrix node - most likely a corrupt export!" << LL_ENDL; + } + } + else + { + extractTranslationViaElement(pTranslateElement, workingTransform); + } + } + + //Store the working transform relative to the nodes name. + jointTransforms[ pNode->getName() ] = workingTransform; + + //2. handle the nodes children + + //Gather and handle the incoming nodes children + daeTArray< daeSmartRef > childOfChild = pNode->getChildren(); + S32 childOfChildCount = childOfChild.getCount(); + + for (S32 i = 0; i < childOfChildCount; ++i) + { + domNode* pChildNode = daeSafeCast(childOfChild[i]); + if (pChildNode) + { + processJointNode(pChildNode, jointTransforms); + } + } +} + +//----------------------------------------------------------------------------- +// getChildFromElement() +//----------------------------------------------------------------------------- +daeElement* LLDAELoader::getChildFromElement( daeElement* pElement, std::string const & name ) +{ + daeElement* pChildOfElement = pElement->getChild(name.c_str()); + if (pChildOfElement) + { + return pChildOfElement; + } + LL_WARNS() << "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL; + return NULL; +} + +void LLDAELoader::processElement( daeElement* element, bool& badElement, DAE* dae ) +{ + LLMatrix4 saved_transform; + bool pushed_mat = false; + + domNode* node = daeSafeCast(element); + if (node) + { + pushed_mat = true; + saved_transform = mTransform; + } + + domTranslate* translate = daeSafeCast(element); + if (translate) + { + domFloat3 dom_value = translate->getValue(); + + LLMatrix4 translation; + translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2])); + + translation *= mTransform; + mTransform = translation; + mTransform.condition(); + } + + domRotate* rotate = daeSafeCast(element); + if (rotate) + { + domFloat4 dom_value = rotate->getValue(); + + LLMatrix4 rotation; + rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0)); + + rotation *= mTransform; + mTransform = rotation; + mTransform.condition(); + } + + domScale* scale = daeSafeCast(element); + if (scale) + { + domFloat3 dom_value = scale->getValue(); + + + LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]); + scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes + LLMatrix4 scaling; + scaling.initScale(scale_vector); + + scaling *= mTransform; + mTransform = scaling; + mTransform.condition(); + } + + domMatrix* matrix = daeSafeCast(element); + if (matrix) + { + domFloat4x4 dom_value = matrix->getValue(); + + LLMatrix4 matrix_transform; + + for (int i = 0; i < 4; i++) + { + for (int j = 0; j < 4; j++) + { + matrix_transform.mMatrix[i][j] = dom_value[i + j*4]; + } + } + + matrix_transform *= mTransform; + mTransform = matrix_transform; + mTransform.condition(); + } + + domInstance_geometry* instance_geo = daeSafeCast(element); + if (instance_geo) + { + domGeometry* geo = daeSafeCast(instance_geo->getUrl().getElement()); + if (geo) + { + domMesh* mesh = daeSafeCast(geo->getDescendant(daeElement::matchType(domMesh::ID()))); + if (mesh) + { + + std::vector< LLPointer< LLModel > >::iterator i = mModelsMap[mesh].begin(); + while (i != mModelsMap[mesh].end()) + { + LLModel* model = *i; + + LLMatrix4 transformation = mTransform; + + if (mTransform.determinant() < 0) + { //negative scales are not supported + LL_INFOS() << "Negative scale detected, unsupported transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL; + badElement = true; + } + + LLModelLoader::material_map materials = getMaterials(model, instance_geo, dae); + + // adjust the transformation to compensate for mesh normalization + LLVector3 mesh_scale_vector; + LLVector3 mesh_translation_vector; + model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); + + LLMatrix4 mesh_translation; + mesh_translation.setTranslation(mesh_translation_vector); + mesh_translation *= transformation; + transformation = mesh_translation; + + LLMatrix4 mesh_scale; + mesh_scale.initScale(mesh_scale_vector); + mesh_scale *= transformation; + transformation = mesh_scale; + + if (transformation.determinant() < 0) + { //negative scales are not supported + LL_INFOS() << "Negative scale detected, unsupported post-normalization transform. domInstance_geometry: " << getElementLabel(instance_geo) << LL_ENDL; + badElement = true; + } + + std::string label; + + if (model->mLabel.empty()) + { + label = getLodlessLabel(instance_geo); + + llassert(!label.empty()); + + if (model->mSubmodelID) + { + label += (char)((int)'a' + model->mSubmodelID); + } + + model->mLabel = label + lod_suffix[mLod]; + } + else + { + // Don't change model's name if possible, it will play havoc with scenes that already use said model. + size_t ext_pos = getSuffixPosition(model->mLabel); + if (ext_pos != -1) + { + label = model->mLabel.substr(0, ext_pos); + } + else + { + label = model->mLabel; + } + } + + mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials)); + stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); + i++; + } + } + } + else + { + LL_INFOS() <<"Unable to resolve geometry URL."<(element); + if (instance_node) + { + daeElement* instance = instance_node->getUrl().getElement(); + if (instance) + { + processElement(instance,badElement, dae); + } + } + + //process children + daeTArray< daeSmartRef > children = element->getChildren(); + int childCount = children.getCount(); + for (S32 i = 0; i < childCount; i++) + { + processElement(children[i],badElement, dae); + } + + if (pushed_mat) + { //this element was a node, restore transform before processiing siblings + mTransform = saved_transform; + } +} + +std::map LLDAELoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo, DAE* dae) +{ + std::map materials; + for (U32 i = 0; i < model->mMaterialList.size(); i++) + { + LLImportMaterial import_material; + + domInstance_material* instance_mat = NULL; + + domBind_material::domTechnique_common* technique = + daeSafeCast(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID()))); + + if (technique) + { + daeTArray< daeSmartRef > inst_materials = technique->getChildrenByType(); + for (U32 j = 0; j < inst_materials.getCount(); j++) + { + std::string symbol(inst_materials[j]->getSymbol()); + + if (symbol == model->mMaterialList[i]) // found the binding + { + instance_mat = inst_materials[j]; + break; + } + } + } + + if (instance_mat) + { + domMaterial* material = daeSafeCast(instance_mat->getTarget().getElement()); + if (material) + { + domInstance_effect* instance_effect = + daeSafeCast(material->getDescendant(daeElement::matchType(domInstance_effect::ID()))); + if (instance_effect) + { + domEffect* effect = daeSafeCast(instance_effect->getUrl().getElement()); + if (effect) + { + domProfile_COMMON* profile = + daeSafeCast(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID()))); + if (profile) + { + import_material = profileToMaterial(profile, dae); + } + } + } + } + } + + import_material.mBinding = model->mMaterialList[i]; + materials[model->mMaterialList[i]] = import_material; + } + + return materials; +} + +LLImportMaterial LLDAELoader::profileToMaterial(domProfile_COMMON* material, DAE* dae) +{ + LLImportMaterial mat; + mat.mFullbright = FALSE; + + daeElement* diffuse = material->getDescendant("diffuse"); + if (diffuse) + { + domCommon_color_or_texture_type_complexType::domTexture* texture = + daeSafeCast(diffuse->getDescendant("texture")); + if (texture) + { + domCommon_newparam_type_Array newparams = material->getNewparam_array(); + if (newparams.getCount()) + { + + for (S32 i = 0; i < newparams.getCount(); i++) + { + domFx_surface_common* surface = newparams[i]->getSurface(); + if (surface) + { + domFx_surface_init_common* init = surface->getFx_surface_init_common(); + if (init) + { + domFx_surface_init_from_common_Array init_from = init->getInit_from_array(); + + if (init_from.getCount() > i) + { + domImage* image = daeSafeCast(init_from[i]->getValue().getElement()); + if (image) + { + // we only support init_from now - embedded data will come later + domImage::domInit_from* init = image->getInit_from(); + if (init) + { + mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str()); + mat.mDiffuseMapLabel = getElementLabel(material); + } + } + } + } + } + } + } + else if (texture->getTexture()) + { + domImage* image = NULL; + dae->getDatabase()->getElement((daeElement**) &image, 0, texture->getTexture(), COLLADA_TYPE_IMAGE); + if (image) + { + // we only support init_from now - embedded data will come later + domImage::domInit_from* init = image->getInit_from(); + if (init) + { + std::string image_path_value = cdom::uriToNativePath(init->getValue().str()); + +#if LL_WINDOWS + // Work-around DOM tendency to resort to UNC names which are only confusing for downstream... + // + std::string::iterator i = image_path_value.begin(); + while (*i == '\\') + i++; + mat.mDiffuseMapFilename.assign(i, image_path_value.end()); +#else + mat.mDiffuseMapFilename = image_path_value; +#endif + mat.mDiffuseMapLabel = getElementLabel(material); + } + } + } + } + + domCommon_color_or_texture_type_complexType::domColor* color = + daeSafeCast(diffuse->getDescendant("color")); + if (color) + { + domFx_color_common domfx_color = color->getValue(); + LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); + mat.mDiffuseColor = value; + } + } + + daeElement* emission = material->getDescendant("emission"); + if (emission) + { + LLColor4 emission_color = getDaeColor(emission); + if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25) + { + mat.mFullbright = TRUE; + } + } + + return mat; +} + +// try to get a decent label for this element +std::string LLDAELoader::getElementLabel(daeElement *element) +{ + // if we have a name attribute, use it + std::string name = element->getAttribute("name"); + if (name.length()) + { + return name; + } + + // if we have an ID attribute, use it + if (element->getID()) + { + return std::string(element->getID()); + } + + // if we have a parent, use it + daeElement* parent = element->getParent(); + std::string index_string; + if (parent) + { + // retrieve index to distinguish items inside same parent + size_t ind = 0; + parent->getChildren().find(element, ind); + index_string = "_" + boost::lexical_cast(ind); + + // if parent has a name or ID, use it + std::string name = parent->getAttribute("name"); + if (!name.length()) + { + name = std::string(parent->getID()); + } + + if (name.length()) + { + // make sure that index won't mix up with pre-named lod extensions + size_t ext_pos = getSuffixPosition(name); + + if (ext_pos == -1) + { + return name + index_string; + } + else + { + return name.insert(ext_pos, index_string); + } + } + } + + // try to use our type + daeString element_name = element->getElementName(); + if (element_name) + { + return std::string(element_name) + index_string; + } + + // if all else fails, use "object" + return std::string("object") + index_string; +} + +// static +size_t LLDAELoader::getSuffixPosition(std::string label) +{ + if ((label.find("_LOD") != std::string::npos) || (label.find("_PHYS") != std::string::npos)) + { + return label.rfind('_'); + } + return -1; +} + +// static +std::string LLDAELoader::getLodlessLabel(daeElement *element) +{ + std::string label = getElementLabel(element); + size_t ext_pos = getSuffixPosition(label); + if (ext_pos != -1) + { + return label.substr(0, ext_pos); + } + return label; +} + +LLColor4 LLDAELoader::getDaeColor(daeElement* element) +{ + LLColor4 value; + domCommon_color_or_texture_type_complexType::domColor* color = + daeSafeCast(element->getDescendant("color")); + if (color) + { + domFx_color_common domfx_color = color->getValue(); + value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); + } + + return value; +} + +bool LLDAELoader::addVolumeFacesFromDomMesh(LLModel* pModel,domMesh* mesh) +{ + LLModel::EModelStatus status = LLModel::NO_ERRORS; + domTriangles_Array& tris = mesh->getTriangles_array(); + + for (U32 i = 0; i < tris.getCount(); ++i) + { + domTrianglesRef& tri = tris.get(i); + + status = load_face_from_dom_triangles(pModel->getVolumeFaces(), pModel->getMaterialList(), tri); + pModel->mStatus = status; + if(status != LLModel::NO_ERRORS) + { + pModel->ClearFacesAndMaterials(); + return false; + } + } + + domPolylist_Array& polys = mesh->getPolylist_array(); + for (U32 i = 0; i < polys.getCount(); ++i) + { + domPolylistRef& poly = polys.get(i); + status = load_face_from_dom_polylist(pModel->getVolumeFaces(), pModel->getMaterialList(), poly); + + if(status != LLModel::NO_ERRORS) + { + pModel->ClearFacesAndMaterials(); + return false; + } + } + + domPolygons_Array& polygons = mesh->getPolygons_array(); + + for (U32 i = 0; i < polygons.getCount(); ++i) + { + domPolygonsRef& poly = polygons.get(i); + status = load_face_from_dom_polygons(pModel->getVolumeFaces(), pModel->getMaterialList(), poly); + + if(status != LLModel::NO_ERRORS) + { + pModel->ClearFacesAndMaterials(); + return false; + } + } + + return (status == LLModel::NO_ERRORS); +} + +//static +LLModel* LLDAELoader::loadModelFromDomMesh(domMesh *mesh) +{ + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + LLModel* ret = new LLModel(volume_params, 0.f); + createVolumeFacesFromDomMesh(ret, mesh); + if (ret->mLabel.empty()) + { + ret->mLabel = getElementLabel(mesh); + } + return ret; +} + +//static diff version supports creating multiple models when material counts spill +// over the 8 face server-side limit +// +bool LLDAELoader::loadModelsFromDomMesh(domMesh* mesh, std::vector& models_out, U32 submodel_limit) +{ + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + + models_out.clear(); + + LLModel* ret = new LLModel(volume_params, 0.f); + + std::string model_name = getLodlessLabel(mesh); + ret->mLabel = model_name + lod_suffix[mLod]; + + llassert(!ret->mLabel.empty()); + + // Like a monkey, ready to be shot into space + // + ret->ClearFacesAndMaterials(); + + // Get the whole set of volume faces + // + addVolumeFacesFromDomMesh(ret, mesh); + + U32 volume_faces = ret->getNumVolumeFaces(); + + // Side-steps all manner of issues when splitting models + // and matching lower LOD materials to base models + // + ret->sortVolumeFacesByMaterialName(); + + bool normalized = false; + + int submodelID = 0; + + // remove all faces that definitely won't fit into one model and submodel limit + U32 face_limit = (submodel_limit + 1) * LL_SCULPT_MESH_MAX_FACES; + if (face_limit < volume_faces) + { + ret->setNumVolumeFaces(face_limit); + } + + LLVolume::face_list_t remainder; + do + { + // Insure we do this once with the whole gang and not per-model + // + if (!normalized && !mNoNormalize) + { + normalized = true; + ret->normalizeVolumeFaces(); + } + + ret->trimVolumeFacesToSize(LL_SCULPT_MESH_MAX_FACES, &remainder); + + if (!mNoOptimize) + { + ret->optimizeVolumeFaces(); + } + + volume_faces = remainder.size(); + + models_out.push_back(ret); + + // If we have left-over volume faces, create another model + // to absorb them... + // + if (volume_faces) + { + LLModel* next = new LLModel(volume_params, 0.f); + next->mSubmodelID = ++submodelID; + next->mLabel = model_name + (char)((int)'a' + next->mSubmodelID) + lod_suffix[mLod]; + next->getVolumeFaces() = remainder; + next->mNormalizedScale = ret->mNormalizedScale; + next->mNormalizedTranslation = ret->mNormalizedTranslation; + if ( ret->mMaterialList.size() > LL_SCULPT_MESH_MAX_FACES) + { + next->mMaterialList.assign(ret->mMaterialList.begin() + LL_SCULPT_MESH_MAX_FACES, ret->mMaterialList.end()); + } + ret = next; + } + + remainder.clear(); + + } while (volume_faces); + + return true; +} + +bool LLDAELoader::createVolumeFacesFromDomMesh(LLModel* pModel, domMesh* mesh) +{ + if (mesh) + { + pModel->ClearFacesAndMaterials(); + + addVolumeFacesFromDomMesh(pModel, mesh); + + if (pModel->getNumVolumeFaces() > 0) + { + pModel->normalizeVolumeFaces(); + pModel->optimizeVolumeFaces(); + + if (pModel->getNumVolumeFaces() > 0) + { + return true; + } + } + } + else + { + LL_WARNS() << "no mesh found" << LL_ENDL; + } + + return false; +} + diff --git a/indra/llprimitive/lldaeloader.h b/indra/llprimitive/lldaeloader.h new file mode 100644 index 000000000..27db5326d --- /dev/null +++ b/indra/llprimitive/lldaeloader.h @@ -0,0 +1,111 @@ +/** + * @file lldaeloader.h + * @brief LLDAELoader class definition + * + * $LicenseInfo:firstyear=2013&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2013, 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_LLDAELOADER_H +#define LL_LLDAELOADER_H + +#include "llmodelloader.h" + +class DAE; +class daeElement; +class domProfile_COMMON; +class domInstance_geometry; +class domNode; +class domTranslate; +class domController; +class domSkin; +class domMesh; + +class LLDAELoader : public LLModelLoader +{ +public: + typedef std::map material_map; + typedef std::map > > dae_model_map; + dae_model_map mModelsMap; + + LLDAELoader( + std::string filename, + S32 lod, + LLModelLoader::load_callback_t load_cb, + LLModelLoader::joint_lookup_func_t joint_lookup_func, + LLModelLoader::texture_load_func_t texture_load_func, + LLModelLoader::state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointMap, + JointSet& jointsFromNodes, + U32 modelLimit, + bool preprocess); + virtual ~LLDAELoader() ; + + virtual bool OpenFile(const std::string& filename); + +protected: + + void processElement(daeElement* element, bool& badElement, DAE* dae); + void processDomModel(LLModel* model, DAE* dae, daeElement* pRoot, domMesh* mesh, domSkin* skin); + + material_map getMaterials(LLModel* model, domInstance_geometry* instance_geo, DAE* dae); + LLImportMaterial profileToMaterial(domProfile_COMMON* material, DAE* dae); + LLColor4 getDaeColor(daeElement* element); + + daeElement* getChildFromElement( daeElement* pElement, std::string const & name ); + + bool isNodeAJoint( domNode* pNode ); + void processJointNode( domNode* pNode, std::map& jointTransforms ); + void extractTranslation( domTranslate* pTranslate, LLMatrix4& transform ); + void extractTranslationViaElement( daeElement* pTranslateElement, LLMatrix4& transform ); + void extractTranslationViaSID( daeElement* pElement, LLMatrix4& transform ); + void buildJointToNodeMappingFromScene( daeElement* pRoot ); + void processJointToNodeMapping( domNode* pNode ); + void processChildJoints( domNode* pParentNode ); + + bool verifyCount( int expected, int result ); + + //Verify that a controller matches vertex counts + bool verifyController( domController* pController ); + + static bool addVolumeFacesFromDomMesh(LLModel* model, domMesh* mesh); + static bool createVolumeFacesFromDomMesh(LLModel* model, domMesh *mesh); + + static LLModel* loadModelFromDomMesh(domMesh* mesh); + + // Loads a mesh breaking it into one or more models as necessary + // to get around volume face limitations while retaining >8 materials + // + bool loadModelsFromDomMesh(domMesh* mesh, std::vector& models_out, U32 submodel_limit); + + static std::string getElementLabel(daeElement *element); + static size_t getSuffixPosition(std::string label); + static std::string getLodlessLabel(daeElement *element); + + static std::string preprocessDAE(std::string filename); + +private: + U32 mGeneratedModelLimit; // Attempt to limit amount of generated submodels + bool mPreprocessDAE; + +}; +#endif // LL_LLDAELLOADER_H diff --git a/indra/llprimitive/llmodel.cpp b/indra/llprimitive/llmodel.cpp index cf3c685b1..d8f233a66 100644 --- a/indra/llprimitive/llmodel.cpp +++ b/indra/llprimitive/llmodel.cpp @@ -32,20 +32,6 @@ #include "llsdserialize.h" #include "llvector4a.h" #include "llmatrix4a.h" -#if LL_MSVC -#pragma warning (push) -#pragma warning (disable : 4068) -#pragma warning (disable : 4263) -#pragma warning (disable : 4264) -#endif -#pragma GCC diagnostic ignored "-Woverloaded-virtual" -#include "dae.h" -#include "dae/daeErrorHandler.h" -#include "dom/domConstants.h" -#include "dom/domMesh.h" -#if LL_MSVC -#pragma warning (pop) -#endif #ifdef LL_STANDALONE # include @@ -80,805 +66,6 @@ LLModel::~LLModel() } } - -bool get_dom_sources(const domInputLocalOffset_Array& inputs, S32& pos_offset, S32& tc_offset, S32& norm_offset, S32 &idx_stride, - domSource* &pos_source, domSource* &tc_source, domSource* &norm_source) -{ - idx_stride = 0; - - for (U32 j = 0; j < inputs.getCount(); ++j) - { - idx_stride = llmax((S32) inputs[j]->getOffset(), idx_stride); - - if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[j]->getSemantic()) == 0) - { //found vertex array - const domURIFragmentType& uri = inputs[j]->getSource(); - daeElementRef elem = uri.getElement(); - domVertices* vertices = (domVertices*) elem.cast(); - if ( !vertices ) - { - return false; - } - - domInputLocal_Array& v_inp = vertices->getInput_array(); - - - for (U32 k = 0; k < v_inp.getCount(); ++k) - { - if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) - { - pos_offset = inputs[j]->getOffset(); - - const domURIFragmentType& uri = v_inp[k]->getSource(); - daeElementRef elem = uri.getElement(); - pos_source = (domSource*) elem.cast(); - } - - if (strcmp(COMMON_PROFILE_INPUT_NORMAL, v_inp[k]->getSemantic()) == 0) - { - norm_offset = inputs[j]->getOffset(); - - const domURIFragmentType& uri = v_inp[k]->getSource(); - daeElementRef elem = uri.getElement(); - norm_source = (domSource*) elem.cast(); - } - } - } - - if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[j]->getSemantic()) == 0) - { - //found normal array for this triangle list - norm_offset = inputs[j]->getOffset(); - const domURIFragmentType& uri = inputs[j]->getSource(); - daeElementRef elem = uri.getElement(); - norm_source = (domSource*) elem.cast(); - } - else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[j]->getSemantic()) == 0) - { //found texCoords - tc_offset = inputs[j]->getOffset(); - const domURIFragmentType& uri = inputs[j]->getSource(); - daeElementRef elem = uri.getElement(); - tc_source = (domSource*) elem.cast(); - } - } - - idx_stride += 1; - - return true; -} - -LLModel::EModelStatus load_face_from_dom_triangles(std::vector& face_list, std::vector& materials, domTrianglesRef& tri) -{ - LLVolumeFace face; - std::vector verts; - std::vector indices; - - const domInputLocalOffset_Array& inputs = tri->getInput_array(); - - S32 pos_offset = -1; - S32 tc_offset = -1; - S32 norm_offset = -1; - - domSource* pos_source = NULL; - domSource* tc_source = NULL; - domSource* norm_source = NULL; - - S32 idx_stride = 0; - - if ( !get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source) || !pos_source ) - { - LL_WARNS() << "Could not find dom sources for basic geo data; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - if (!pos_source) - { - LL_WARNS() << "Unable to process mesh without position data; invalid model; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - domPRef p = tri->getP(); - domListOfUInts& idx = p->getValue(); - - domListOfFloats dummy ; - domListOfFloats& v = pos_source ? pos_source->getFloat_array()->getValue() : dummy ; - domListOfFloats& tc = tc_source ? tc_source->getFloat_array()->getValue() : dummy ; - domListOfFloats& n = norm_source ? norm_source->getFloat_array()->getValue() : dummy ; - - LLVolumeFace::VertexMapData::PointMap point_map; - - U32 index_count = idx.getCount(); - U32 vertex_count = pos_source ? v.getCount() : 0; - U32 tc_count = tc_source ? tc.getCount() : 0; - U32 norm_count = norm_source ? n.getCount() : 0; - - if (vertex_count == 0) - { - LL_WARNS() << "Unable to process mesh with empty position array; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - face.mExtents[0].set(v[0], v[1], v[2]); - face.mExtents[1].set(v[0], v[1], v[2]); - - for (U32 i = 0; i < index_count; i += idx_stride) - { - LLVolumeFace::VertexData cv; - if (pos_source) - { - // guard against model data specifiying out of range indices or verts - // - if (((i + pos_offset) > index_count) - || ((idx[i+pos_offset]*3+2) > vertex_count)) - { - LL_WARNS() << "Out of range index data; invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.setPosition(LLVector4a(v[idx[i+pos_offset]*3+0], - v[idx[i+pos_offset]*3+1], - v[idx[i+pos_offset]*3+2])); - - if (!cv.getPosition().isFinite3()) - { - LL_WARNS() << "Nan positional data, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - if (tc_source) - { - // guard against model data specifiying out of range indices or tcs - // - - if (((i + tc_offset) > index_count) - || ((idx[i+tc_offset]*2+1) > tc_count)) - { - LL_WARNS() << "Out of range TC indices." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.mTexCoord.setVec(tc[idx[i+tc_offset]*2+0], - tc[idx[i+tc_offset]*2+1]); - - if (!cv.mTexCoord.isFinite()) - { - LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - if (norm_source) - { - // guard against model data specifiying out of range indices or norms - // - if (((i + norm_offset) > index_count) - || ((idx[i+norm_offset]*3+2) > norm_count)) - { - LL_WARNS() << "Found out of range norm indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.setNormal(LLVector4a(n[idx[i+norm_offset]*3+0], - n[idx[i+norm_offset]*3+1], - n[idx[i+norm_offset]*3+2])); - - if (!cv.getNormal().isFinite3()) - { - LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - BOOL found = FALSE; - - LLVolumeFace::VertexMapData::PointMap::iterator point_iter; - point_iter = point_map.find(LLVector3(cv.getPosition().getF32ptr())); - - if (point_iter != point_map.end()) - { - for (U32 j = 0; j < point_iter->second.size(); ++j) - { - if ((point_iter->second)[j] == cv) - { - found = TRUE; - indices.push_back((point_iter->second)[j].mIndex); - break; - } - } - } - - if (!found) - { - update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); - verts.push_back(cv); - if (verts.size() >= 65535) - { - //LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; - return LLModel::VERTEX_NUMBER_OVERFLOW ; - } - U16 index = (U16) (verts.size()-1); - indices.push_back(index); - - LLVolumeFace::VertexMapData d; - d.setPosition(cv.getPosition()); - d.mTexCoord = cv.mTexCoord; - d.setNormal(cv.getNormal()); - d.mIndex = index; - if (point_iter != point_map.end()) - { - point_iter->second.push_back(d); - } - else - { - point_map[LLVector3(d.getPosition().getF32ptr())].push_back(d); - } - } - - if (indices.size()%3 == 0 && verts.size() >= 65532) - { - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(verts, indices); - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - - face = LLVolumeFace(); - point_map.clear(); - } - } - - if (!verts.empty()) - { - std::string material; - - if (tri->getMaterial()) - { - material = std::string(tri->getMaterial()); - } - - materials.push_back(material); - face_list.push_back(face); - - face_list.rbegin()->fillFromLegacyData(verts, indices); - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - } - - return LLModel::NO_ERRORS ; -} - -LLModel::EModelStatus load_face_from_dom_polylist(std::vector& face_list, std::vector& materials, domPolylistRef& poly) -{ - domPRef p = poly->getP(); - domListOfUInts& idx = p->getValue(); - - if (idx.getCount() == 0) - { - return LLModel::NO_ERRORS ; - } - - const domInputLocalOffset_Array& inputs = poly->getInput_array(); - - - domListOfUInts& vcount = poly->getVcount()->getValue(); - - S32 pos_offset = -1; - S32 tc_offset = -1; - S32 norm_offset = -1; - - domSource* pos_source = NULL; - domSource* tc_source = NULL; - domSource* norm_source = NULL; - - S32 idx_stride = 0; - - if (!get_dom_sources(inputs, pos_offset, tc_offset, norm_offset, idx_stride, pos_source, tc_source, norm_source)) - { - LL_WARNS() << "Could not get DOM sources for basic geo data, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - LLVolumeFace face; - - std::vector indices; - std::vector verts; - - domListOfFloats v; - domListOfFloats tc; - domListOfFloats n; - - if (pos_source) - { - v = pos_source->getFloat_array()->getValue(); - face.mExtents[0].set(v[0], v[1], v[2]); - face.mExtents[1].set(v[0], v[1], v[2]); - } - - if (tc_source) - { - tc = tc_source->getFloat_array()->getValue(); - } - - if (norm_source) - { - n = norm_source->getFloat_array()->getValue(); - } - - LLVolumeFace::VertexMapData::PointMap point_map; - - U32 index_count = idx.getCount(); - U32 vertex_count = pos_source ? v.getCount() : 0; - U32 tc_count = tc_source ? tc.getCount() : 0; - U32 norm_count = norm_source ? n.getCount() : 0; - - U32 cur_idx = 0; - for (U32 i = 0; i < vcount.getCount(); ++i) - { //for each polygon - U32 first_index = 0; - U32 last_index = 0; - for (U32 j = 0; j < vcount[i]; ++j) - { //for each vertex - - LLVolumeFace::VertexData cv; - - if (pos_source) - { - // guard against model data specifiying out of range indices or verts - // - if (((cur_idx + pos_offset) > index_count) - || ((idx[cur_idx+pos_offset]*3+2) > vertex_count)) - { - LL_WARNS() << "Out of range position indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.getPosition().set(v[idx[cur_idx+pos_offset]*3+0], - v[idx[cur_idx+pos_offset]*3+1], - v[idx[cur_idx+pos_offset]*3+2]); - - if (!cv.getPosition().isFinite3()) - { - LL_WARNS() << "Found NaN while loading positions from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - } - - if (tc_source) - { - // guard against model data specifiying out of range indices or tcs - // - if (((cur_idx + tc_offset) > index_count) - || ((idx[cur_idx+tc_offset]*2+1) > tc_count)) - { - LL_WARNS() << "Out of range TC indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.mTexCoord.setVec(tc[idx[cur_idx+tc_offset]*2+0], - tc[idx[cur_idx+tc_offset]*2+1]); - - if (!cv.mTexCoord.isFinite()) - { - LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - if (norm_source) - { - // guard against model data specifiying out of range indices or norms - // - if (((cur_idx + norm_offset) > index_count) - || ((idx[cur_idx+norm_offset]*3+2) > norm_count)) - { - LL_WARNS() << "Out of range norm indices, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - - cv.getNormal().set(n[idx[cur_idx+norm_offset]*3+0], - n[idx[cur_idx+norm_offset]*3+1], - n[idx[cur_idx+norm_offset]*3+2]); - - if (!cv.getNormal().isFinite3()) - { - LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - cur_idx += idx_stride; - - BOOL found = FALSE; - - LLVolumeFace::VertexMapData::PointMap::iterator point_iter; - LLVector3 pos3(cv.getPosition().getF32ptr()); - point_iter = point_map.find(pos3); - - if (point_iter != point_map.end()) - { - for (U32 k = 0; k < point_iter->second.size(); ++k) - { - if ((point_iter->second)[k] == cv) - { - found = TRUE; - U32 index = (point_iter->second)[k].mIndex; - if (j == 0) - { - first_index = index; - } - else if (j == 1) - { - last_index = index; - } - else - { - indices.push_back(first_index); - indices.push_back(last_index); - indices.push_back(index); - last_index = index; - } - - break; - } - } - } - - if (!found) - { - update_min_max(face.mExtents[0], face.mExtents[1], cv.getPosition()); - verts.push_back(cv); - if (verts.size() >= 65535) - { - //LL_ERRS() << "Attempted to write model exceeding 16-bit index buffer limitation." << LL_ENDL; - return LLModel::VERTEX_NUMBER_OVERFLOW ; - } - U16 index = (U16) (verts.size()-1); - - if (j == 0) - { - first_index = index; - } - else if (j == 1) - { - last_index = index; - } - else - { - indices.push_back(first_index); - indices.push_back(last_index); - indices.push_back(index); - last_index = index; - } - - LLVolumeFace::VertexMapData d; - d.setPosition(cv.getPosition()); - d.mTexCoord = cv.mTexCoord; - d.setNormal(cv.getNormal()); - d.mIndex = index; - if (point_iter != point_map.end()) - { - point_iter->second.push_back(d); - } - else - { - point_map[pos3].push_back(d); - } - } - - if (indices.size()%3 == 0 && indices.size() >= 65532) - { - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(verts, indices); - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - - face = LLVolumeFace(); - verts.clear(); - indices.clear(); - point_map.clear(); - } - } - } - - if (!verts.empty()) - { - std::string material; - - if (poly->getMaterial()) - { - material = std::string(poly->getMaterial()); - } - - materials.push_back(material); - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(verts, indices); - - LLVolumeFace& new_face = *face_list.rbegin(); - if (!norm_source) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!tc_source) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - } - - return LLModel::NO_ERRORS ; -} - -LLModel::EModelStatus load_face_from_dom_polygons(std::vector& face_list, std::vector& materials, domPolygonsRef& poly) -{ - LLVolumeFace face; - std::vector indices; - std::vector verts; - - const domInputLocalOffset_Array& inputs = poly->getInput_array(); - - S32 v_offset = -1; - S32 n_offset = -1; - S32 t_offset = -1; - - domListOfFloats* v = NULL; - domListOfFloats* n = NULL; - domListOfFloats* t = NULL; - - U32 stride = 0; - for (U32 i = 0; i < inputs.getCount(); ++i) - { - stride = llmax((U32) inputs[i]->getOffset()+1, stride); - - if (strcmp(COMMON_PROFILE_INPUT_VERTEX, inputs[i]->getSemantic()) == 0) - { //found vertex array - v_offset = inputs[i]->getOffset(); - - const domURIFragmentType& uri = inputs[i]->getSource(); - daeElementRef elem = uri.getElement(); - domVertices* vertices = (domVertices*) elem.cast(); - if (!vertices) - { - LL_WARNS() << "Could not find vertex source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - domInputLocal_Array& v_inp = vertices->getInput_array(); - - for (U32 k = 0; k < v_inp.getCount(); ++k) - { - if (strcmp(COMMON_PROFILE_INPUT_POSITION, v_inp[k]->getSemantic()) == 0) - { - const domURIFragmentType& uri = v_inp[k]->getSource(); - daeElementRef elem = uri.getElement(); - domSource* src = (domSource*) elem.cast(); - if (!src) - { - LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - v = &(src->getFloat_array()->getValue()); - } - } - } - else if (strcmp(COMMON_PROFILE_INPUT_NORMAL, inputs[i]->getSemantic()) == 0) - { - n_offset = inputs[i]->getOffset(); - //found normal array for this triangle list - const domURIFragmentType& uri = inputs[i]->getSource(); - daeElementRef elem = uri.getElement(); - domSource* src = (domSource*) elem.cast(); - if (!src) - { - LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - n = &(src->getFloat_array()->getValue()); - } - else if (strcmp(COMMON_PROFILE_INPUT_TEXCOORD, inputs[i]->getSemantic()) == 0 && inputs[i]->getSet() == 0) - { //found texCoords - t_offset = inputs[i]->getOffset(); - const domURIFragmentType& uri = inputs[i]->getSource(); - daeElementRef elem = uri.getElement(); - domSource* src = (domSource*) elem.cast(); - if (!src) - { - LL_WARNS() << "Could not find DOM source, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - t = &(src->getFloat_array()->getValue()); - } - } - - domP_Array& ps = poly->getP_array(); - - //make a triangle list in - for (U32 i = 0; i < ps.getCount(); ++i) - { //for each polygon - domListOfUInts& idx = ps[i]->getValue(); - for (U32 j = 0; j < idx.getCount()/stride; ++j) - { //for each vertex - if (j > 2) - { - U32 size = verts.size(); - LLVolumeFace::VertexData v0 = verts[size-3]; - LLVolumeFace::VertexData v1 = verts[size-1]; - - verts.push_back(v0); - verts.push_back(v1); - } - - LLVolumeFace::VertexData vert; - - - if (v) - { - U32 v_idx = idx[j*stride+v_offset]*3; - v_idx = llclamp(v_idx, (U32) 0, (U32) v->getCount()); - vert.getPosition().set(v->get(v_idx), - v->get(v_idx+1), - v->get(v_idx+2)); - - if (!vert.getPosition().isFinite3()) - { - LL_WARNS() << "Found NaN while loading position data from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - - //bounds check n and t lookups because some FBX to DAE converters - //use negative indices and empty arrays to indicate data does not exist - //for a particular channel - if (n && n->getCount() > 0) - { - U32 n_idx = idx[j*stride+n_offset]*3; - n_idx = llclamp(n_idx, (U32) 0, (U32) n->getCount()); - vert.getNormal().set(n->get(n_idx), - n->get(n_idx+1), - n->get(n_idx+2)); - - if (!vert.getNormal().isFinite3()) - { - LL_WARNS() << "Found NaN while loading normals from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - else - { - vert.getNormal().clear(); - } - - - if (t && t->getCount() > 0) - { - U32 t_idx = idx[j*stride+t_offset]*2; - t_idx = llclamp(t_idx, (U32) 0, (U32) t->getCount()); - vert.mTexCoord.setVec(t->get(t_idx), - t->get(t_idx+1)); - - if (!vert.mTexCoord.isFinite()) - { - LL_WARNS() << "Found NaN while loading tex coords from DAE-Model, invalid model." << LL_ENDL; - return LLModel::BAD_ELEMENT; - } - } - else - { - vert.mTexCoord.clear(); - } - - - verts.push_back(vert); - } - } - - if (verts.empty()) - { - return LLModel::NO_ERRORS; - } - - face.mExtents[0] = verts[0].getPosition(); - face.mExtents[1] = verts[0].getPosition(); - - //create a map of unique vertices to indices - std::map vert_idx; - - U32 cur_idx = 0; - for (U32 i = 0; i < verts.size(); ++i) - { - std::map::iterator iter = vert_idx.find(verts[i]); - if (iter == vert_idx.end()) - { - vert_idx[verts[i]] = cur_idx++; - } - } - - //build vertex array from map - std::vector new_verts; - new_verts.resize(vert_idx.size()); - - for (std::map::iterator iter = vert_idx.begin(); iter != vert_idx.end(); ++iter) - { - new_verts[iter->second] = iter->first; - update_min_max(face.mExtents[0], face.mExtents[1], iter->first.getPosition()); - } - - //build index array from map - indices.resize(verts.size()); - - for (U32 i = 0; i < verts.size(); ++i) - { - indices[i] = vert_idx[verts[i]]; - } - - // DEBUG just build an expanded triangle list - /*for (U32 i = 0; i < verts.size(); ++i) - { - indices.push_back((U16) i); - update_min_max(face.mExtents[0], face.mExtents[1], verts[i].getPosition()); - }*/ - - if (!new_verts.empty()) - { - std::string material; - - if (poly->getMaterial()) - { - material = std::string(poly->getMaterial()); - } - - materials.push_back(material); - face_list.push_back(face); - face_list.rbegin()->fillFromLegacyData(new_verts, indices); - - LLVolumeFace& new_face = *face_list.rbegin(); - if (!n) - { - //ll_aligned_free_16(new_face.mNormals); - new_face.mNormals = NULL; - } - - if (!t) - { - //ll_aligned_free_16(new_face.mTexCoords); - new_face.mTexCoords = NULL; - } - } - - return LLModel::NO_ERRORS ; -} - //static std::string LLModel::getStatusString(U32 status) { @@ -898,83 +85,6 @@ std::string LLModel::getStatusString(U32 status) return std::string() ; } -void LLModel::addVolumeFacesFromDomMesh(domMesh* mesh) -{ - domTriangles_Array& tris = mesh->getTriangles_array(); - - for (U32 i = 0; i < tris.getCount(); ++i) - { - domTrianglesRef& tri = tris.get(i); - - mStatus = load_face_from_dom_triangles(mVolumeFaces, mMaterialList, tri); - - if(mStatus != NO_ERRORS) - { - mVolumeFaces.clear() ; - mMaterialList.clear() ; - return ; //abort - } - } - - domPolylist_Array& polys = mesh->getPolylist_array(); - for (U32 i = 0; i < polys.getCount(); ++i) - { - domPolylistRef& poly = polys.get(i); - mStatus = load_face_from_dom_polylist(mVolumeFaces, mMaterialList, poly); - - if(mStatus != NO_ERRORS) - { - mVolumeFaces.clear() ; - mMaterialList.clear() ; - return ; //abort - } - } - - domPolygons_Array& polygons = mesh->getPolygons_array(); - - for (U32 i = 0; i < polygons.getCount(); ++i) - { - domPolygonsRef& poly = polygons.get(i); - mStatus = load_face_from_dom_polygons(mVolumeFaces, mMaterialList, poly); - - if(mStatus != NO_ERRORS) - { - mVolumeFaces.clear() ; - mMaterialList.clear() ; - return ; //abort - } - } - -} - -BOOL LLModel::createVolumeFacesFromDomMesh(domMesh* mesh) -{ - if (mesh) - { - mVolumeFaces.clear(); - mMaterialList.clear(); - - addVolumeFacesFromDomMesh(mesh); - - if (getNumVolumeFaces() > 0) - { - normalizeVolumeFaces(); - optimizeVolumeFaces(); - - if (getNumVolumeFaces() > 0) - { - return TRUE; - } - } - } - else - { - LL_WARNS() << "no mesh found" << LL_ENDL; - } - - return FALSE; -} - void LLModel::offsetMesh( const LLVector3& pivotPoint ) { LLVector4a pivot( pivotPoint[VX], pivotPoint[VY], pivotPoint[VZ] ); @@ -996,7 +106,73 @@ void LLModel::optimizeVolumeFaces() { for (U32 i = 0; i < (U32)getNumVolumeFaces(); ++i) { + validate_face(mVolumeFaces[i]); mVolumeFaces[i].optimize(); + validate_face(mVolumeFaces[i]); + } +} + +struct MaterialBinding +{ + int index; + std::string matName; +}; + +struct MaterialSort +{ + bool operator()(const MaterialBinding& lhs, const MaterialBinding& rhs) + { + return LLStringUtil::compareInsensitive(lhs.matName, rhs.matName) < 0; + } +}; + +void LLModel::sortVolumeFacesByMaterialName() +{ + std::vector bindings; + bindings.resize(mVolumeFaces.size()); + + for (U32 i = 0; i < bindings.size(); i++) + { + bindings[i].index = i; + if(i < mMaterialList.size()) + { + bindings[i].matName = mMaterialList[i]; + } + } + std::sort(bindings.begin(), bindings.end(), MaterialSort()); + std::vector< LLVolumeFace > new_faces; + + // remap the faces to be in the same order the mats now are... + // + new_faces.resize(bindings.size()); + for (U32 i = 0; i < bindings.size(); i++) + { + new_faces[i] = mVolumeFaces[bindings[i].index]; + if(i < mMaterialList.size()) + { + mMaterialList[i] = bindings[i].matName; + } + } + + mVolumeFaces = new_faces; +} + +void LLModel::trimVolumeFacesToSize(S32 new_count, LLVolume::face_list_t* remainder) +{ + llassert(new_count <= LL_SCULPT_MESH_MAX_FACES); + + if (new_count && (getNumVolumeFaces() > new_count)) + { + // Copy out remaining volume faces for alternative handling, if provided + // + if (remainder) + { + (*remainder).assign(mVolumeFaces.begin() + new_count, mVolumeFaces.end()); + } + + // Trim down to the final set of volume faces (now stuffed to the gills!) + // + mVolumeFaces.resize(new_count); } } @@ -1343,7 +519,9 @@ void LLModel::generateNormals(F32 angle_cutoff) } //weld vertices in temporary face, respecting angle_cutoff (step 2) + validate_face(faceted); faceted.optimize(angle_cutoff); + validate_face(faceted); //generate normals for welded face based on new topology (step 3) @@ -1475,74 +653,17 @@ void LLModel::generateNormals(F32 angle_cutoff) } //remove redundant vertices from new face (step 6) + validate_face(new_face); new_face.optimize(); + validate_face(new_face); mVolumeFaces[j] = new_face; } } -//static -std::string LLModel::getElementLabel(daeElement *element) -{ // try to get a decent label for this element - // if we have a name attribute, use it - std::string name = element->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if we have an ID attribute, use it - if (element->getID()) - { - return std::string(element->getID()); - } - - // if we have a parent, use it - daeElement* parent = element->getParent(); - if (parent) - { - // if parent has a name, use it - std::string name = parent->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if parent has an ID, use it - if (parent->getID()) - { - return std::string(parent->getID()); - } - } - - // try to use our type - daeString element_name = element->getElementName(); - if (element_name) - { - return std::string(element_name); - } - - // if all else fails, use "object" - return std::string("object"); -} - -//static -LLModel* LLModel::loadModelFromDomMesh(domMesh *mesh) -{ - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - LLModel* ret = new LLModel(volume_params, 0.f); - ret->createVolumeFacesFromDomMesh(mesh); - ret->mLabel = getElementLabel(mesh); - return ret; -} - std::string LLModel::getName() const { - if (!mRequestedLabel.empty()) - return mRequestedLabel; - else - return mLabel; + return mRequestedLabel.empty() ? mLabel : mRequestedLabel; } //static @@ -1557,7 +678,8 @@ LLSD LLModel::writeModel( BOOL upload_skin, BOOL upload_joints, BOOL nowrite, - BOOL as_slm) + BOOL as_slm, + int submodel_id) { LLSD mdl; @@ -1586,6 +708,14 @@ LLSD LLModel::writeModel( model[LLModel::LOD_PHYSICS] = NULL; } } + else if (submodel_id) + { + const LLModel::Decomposition fake_decomp; + mdl["secondary"] = true; + mdl["submodel_id"] = submodel_id; + mdl["physics_convex"] = fake_decomp.asLLSD(); + model[LLModel::LOD_PHYSICS] = NULL; + } if (as_slm) { //save material list names @@ -1597,7 +727,7 @@ LLSD LLModel::writeModel( for (U32 idx = 0; idx < MODEL_NAMES_LENGTH; ++idx) { - if (model[idx] && model[idx]->getNumVolumeFaces() > 0) + if (model[idx] && (model[idx]->getNumVolumeFaces() > 0) && model[idx]->getVolumeFace(0).mPositions != NULL) { LLVector3 min_pos = LLVector3(model[idx]->getVolumeFace(0).mPositions[0].getF32ptr()); LLVector3 max_pos = min_pos; @@ -1682,11 +812,11 @@ LLSD LLModel::writeModel( } } - F32* src_tc = (F32*) face.mTexCoords[j].mV; - //texcoord if (face.mTexCoords) { + F32* src_tc = (F32*) face.mTexCoords[j].mV; + for (U32 k = 0; k < 2; ++k) { //for each component //convert to 16-bit normalized @@ -1830,6 +960,11 @@ LLSD LLModel::writeModelToStream(std::ostream& ostr, LLSD& mdl, BOOL nowrite, BO } } + if (mdl.has("submodel_id")) + { //write out submodel id + header["submodel_id"] = (LLSD::Integer)mdl["submodel_id"]; + } + std::string out[MODEL_NAMES_LENGTH]; for (S32 i = 0; i < MODEL_NAMES_LENGTH; i++) @@ -2015,15 +1150,17 @@ bool LLModel::loadModel(std::istream& is) mSubmodelID = header.has("submodel_id") ? header["submodel_id"].asInteger() : false; - static const std::array lod_name = {{ + static const std::array lod_name = {{ "lowest_lod", "low_lod", "medium_lod", "high_lod", "physics_mesh", - }}; + }}; - S32 lod = llclamp((S32) mDetail, 0, (S32)lod_name.size() - 1); + const S32 MODEL_LODS = lod_name.size(); + + S32 lod = llclamp((S32) mDetail, 0, MODEL_LODS); if (header[lod_name[lod]]["offset"].asInteger() == -1 || header[lod_name[lod]]["size"].asInteger() == 0 ) @@ -2646,3 +1783,228 @@ void LLModel::Decomposition::merge(const LLModel::Decomposition* rhs) } } +bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance) +{ + // small area check + { + LLVector4a edge1; edge1.setSub( a, b ); + LLVector4a edge2; edge2.setSub( a, c ); + ////////////////////////////////////////////////////////////////////////// + /// Linden Modified + ////////////////////////////////////////////////////////////////////////// + + // If no one edge is more than 10x longer than any other edge, we weaken + // the tolerance by a factor of 1e-4f. + + LLVector4a edge3; edge3.setSub( c, b ); + const F32 len1sq = edge1.dot3(edge1).getF32(); + const F32 len2sq = edge2.dot3(edge2).getF32(); + const F32 len3sq = edge3.dot3(edge3).getF32(); + bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq); + bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq); + bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq); + if ( abOK && acOK && cbOK ) + { + tolerance *= 1e-4f; + } + + ////////////////////////////////////////////////////////////////////////// + /// End Modified + ////////////////////////////////////////////////////////////////////////// + + LLVector4a cross; cross.setCross3( edge1, edge2 ); + + LLVector4a edge1b; edge1b.setSub( b, a ); + LLVector4a edge2b; edge2b.setSub( b, c ); + LLVector4a crossb; crossb.setCross3( edge1b, edge2b ); + + if ( ( cross.dot3(cross).getF32() < tolerance ) || ( crossb.dot3(crossb).getF32() < tolerance )) + { + return true; + } + } + + // point triangle distance check + { + LLVector4a Q; Q.setSub(a, b); + LLVector4a R; R.setSub(c, b); + + const F32 QQ = dot3fpu(Q, Q); + const F32 RR = dot3fpu(R, R); + const F32 QR = dot3fpu(R, Q); + + volatile F32 QQRR = QQ * RR; + volatile F32 QRQR = QR * QR; + F32 Det = (QQRR - QRQR); + + if( Det == 0.0f ) + { + return true; + } + } + + return false; +} + +bool validate_face(const LLVolumeFace& face) +{ + for (S32 i = 0; i < face.mNumIndices; ++i) + { + if (face.mIndices[i] >= face.mNumVertices) + { + LL_WARNS() << "Face has invalid index." << LL_ENDL; + LL_WARNS() << "face.mIndices[" << i << "]=" << face.mIndices[i] << " face.mNumVertices=" << face.mNumVertices << LL_ENDL; + return false; + } + } + + if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0) + { + LL_WARNS() << "Face has invalid number of indices." << LL_ENDL; + return false; + } + + /*const LLVector4a scale(0.5f); + + for (U32 i = 0; i < face.mNumIndices; i+=3) + { + U16 idx1 = face.mIndices[i]; + U16 idx2 = face.mIndices[i+1]; + U16 idx3 = face.mIndices[i+2]; + + LLVector4a v1; v1.setMul(face.mPositions[idx1], scale); + LLVector4a v2; v2.setMul(face.mPositions[idx2], scale); + LLVector4a v3; v3.setMul(face.mPositions[idx3], scale); + + if (ll_is_degenerate(v1,v2,v3)) + { + llwarns << "Degenerate face found!" << LL_ENDL; + return false; + } + }*/ + + return true; +} + +bool validate_model(const LLModel* mdl) +{ + if (mdl->getNumVolumeFaces() == 0) + { + LL_WARNS() << "Model has no faces!" << LL_ENDL; + return false; + } + + for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + { + if (mdl->getVolumeFace(i).mNumVertices == 0) + { + LL_WARNS() << "Face has no vertices." << LL_ENDL; + return false; + } + + if (mdl->getVolumeFace(i).mNumIndices == 0) + { + LL_WARNS() << "Face has no indices." << LL_ENDL; + return false; + } + + if (!validate_face(mdl->getVolumeFace(i))) + { + return false; + } + } + + return true; +} + +LLModelInstance::LLModelInstance(LLSD& data) + : LLModelInstanceBase() +{ + mLocalMeshID = data["mesh_id"].asInteger(); + mLabel = data["label"].asString(); + mTransform.setValue(data["transform"]); + + for (U32 i = 0; i < (U32)data["material"].size(); ++i) + { + LLImportMaterial mat(data["material"][i]); + mMaterial[mat.mBinding] = mat; + } +} + + +LLSD LLModelInstance::asLLSD() +{ + LLSD ret; + + ret["mesh_id"] = mModel->mLocalID; + ret["label"] = mLabel; + ret["transform"] = mTransform.getValue(); + + U32 i = 0; + for (std::map::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter) + { + ret["material"][i++] = iter->second.asLLSD(); + } + + return ret; +} + + +LLImportMaterial::~LLImportMaterial() +{ +} + +LLImportMaterial::LLImportMaterial(LLSD& data) +{ + mDiffuseMapFilename = data["diffuse"]["filename"].asString(); + mDiffuseMapLabel = data["diffuse"]["label"].asString(); + mDiffuseColor.setValue(data["diffuse"]["color"]); + mFullbright = data["fullbright"].asBoolean(); + mBinding = data["binding"].asString(); +} + + +LLSD LLImportMaterial::asLLSD() +{ + LLSD ret; + + ret["diffuse"]["filename"] = mDiffuseMapFilename; + ret["diffuse"]["label"] = mDiffuseMapLabel; + ret["diffuse"]["color"] = mDiffuseColor.getValue(); + ret["fullbright"] = mFullbright; + ret["binding"] = mBinding; + + return ret; +} + +bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const +{ + + if (mDiffuseMapID != rhs.mDiffuseMapID) + { + return mDiffuseMapID < rhs.mDiffuseMapID; + } + + if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) + { + return mDiffuseMapFilename < rhs.mDiffuseMapFilename; + } + + if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) + { + return mDiffuseMapLabel < rhs.mDiffuseMapLabel; + } + + if (mDiffuseColor != rhs.mDiffuseColor) + { + return mDiffuseColor < rhs.mDiffuseColor; + } + + if (mBinding != rhs.mBinding) + { + return mBinding < rhs.mBinding; + } + + return mFullbright < rhs.mFullbright; +} + diff --git a/indra/llprimitive/llmodel.h b/indra/llprimitive/llmodel.h index 33086bab9..35ab9dbd3 100644 --- a/indra/llprimitive/llmodel.h +++ b/indra/llprimitive/llmodel.h @@ -31,6 +31,7 @@ #include "llvolume.h" #include "v4math.h" #include "m4math.h" +#include class daeElement; class domMesh; @@ -138,15 +139,16 @@ public: BOOL upload_skin, BOOL upload_joints, BOOL nowrite = FALSE, - BOOL as_slm = FALSE); + BOOL as_slm = FALSE, + int submodel_id = 0); static LLSD writeModelToStream( std::ostream& ostr, LLSD& mdl, BOOL nowrite = FALSE, BOOL as_slm = FALSE); + + void ClearFacesAndMaterials() { mVolumeFaces.clear(); mMaterialList.clear(); } - static LLModel* loadModelFromDomMesh(domMesh* mesh); - static std::string getElementLabel(daeElement* element); std::string getName() const; std::string getMetric() const {return mMetric;} EModelStatus getStatus() const {return mStatus;} @@ -169,7 +171,9 @@ public: void addFace(const LLVolumeFace& face); + void sortVolumeFacesByMaterialName(); void normalizeVolumeFaces(); + void trimVolumeFacesToSize(S32 new_count = LL_SCULPT_MESH_MAX_FACES, LLVolume::face_list_t* remainder = NULL); void optimizeVolumeFaces(); void offsetMesh( const LLVector3& pivotPoint ); void getNormalizedScaleTranslation(LLVector3& scale_out, LLVector3& translation_out); @@ -280,9 +284,113 @@ public: EModelStatus mStatus ; int mSubmodelID; -protected: - void addVolumeFacesFromDomMesh(domMesh* mesh); - virtual BOOL createVolumeFacesFromDomMesh(domMesh *mesh); }; +typedef std::vector > model_list; +typedef std::queue > model_queue; + +class LLModelMaterialBase +{ +public: + std::string mDiffuseMapFilename; + std::string mDiffuseMapLabel; + std::string mBinding; + LLColor4 mDiffuseColor; + bool mFullbright; + + LLModelMaterialBase() + : mFullbright(false) + { + mDiffuseColor.set(1,1,1,1); + } +}; + +class LLImportMaterial : public LLModelMaterialBase +{ +public: + friend class LLMeshUploadThread; + friend class LLModelPreview; + + bool operator<(const LLImportMaterial ¶ms) const; + + LLImportMaterial() : LLModelMaterialBase() + { + mDiffuseColor.set(1,1,1,1); + } + + LLImportMaterial(LLSD& data); + virtual ~LLImportMaterial(); + + LLSD asLLSD(); + + const LLUUID& getDiffuseMap() const { return mDiffuseMapID; } + void setDiffuseMap(const LLUUID& texId) { mDiffuseMapID = texId; } + +protected: + + LLUUID mDiffuseMapID; + void* mOpaqueData; // allow refs to viewer/platform-specific structs for each material + // currently only stores an LLPointer< LLViewerFetchedTexture > > to + // maintain refs to textures associated with each material for free + // ref counting. +}; + +typedef std::map material_map; + +class LLModelInstanceBase +{ +public: + LLPointer mModel; + LLPointer mLOD[5]; + LLUUID mMeshID; + + LLMatrix4 mTransform; + material_map mMaterial; + + LLModelInstanceBase(LLModel* model, LLMatrix4& transform, material_map& materials) + : mModel(model), mTransform(transform), mMaterial(materials) + { + } + + LLModelInstanceBase() + : mModel(NULL) + { + } +}; + +typedef std::vector model_instance_list; + +class LLModelInstance : public LLModelInstanceBase +{ +public: + std::string mLabel; + LLUUID mMeshID; + S32 mLocalMeshID; + + LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, material_map& materials) + : LLModelInstanceBase(model, transform, materials), mLabel(label) + { + mLocalMeshID = -1; + } + + LLModelInstance(LLSD& data); + + LLSD asLLSD(); +}; + +#define LL_DEGENERACY_TOLERANCE 1e-7f + +inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b) +{ + volatile F32 p0 = a[0] * b[0]; + volatile F32 p1 = a[1] * b[1]; + volatile F32 p2 = a[2] * b[2]; + return p0 + p1 + p2; +} + +bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE); + +bool validate_face(const LLVolumeFace& face); +bool validate_model(const LLModel* mdl); + #endif //LL_LLMODEL_H diff --git a/indra/llprimitive/llmodelloader.cpp b/indra/llprimitive/llmodelloader.cpp new file mode 100644 index 000000000..91b09ad75 --- /dev/null +++ b/indra/llprimitive/llmodelloader.cpp @@ -0,0 +1,644 @@ +/** + * @file llmodelloader.cpp + * @brief LLModelLoader class implementation + * + * $LicenseInfo:firstyear=2004&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 "llmodelloader.h" +#include "llsdserialize.h" +#include "lljoint.h" +#include "llcallbacklist.h" + +#include "llmatrix4a.h" +#include +#include + +std::list LLModelLoader::sActiveLoaderList; + +void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform) +{ + LLVector4a box[] = + { + LLVector4a(-1, 1,-1), + LLVector4a(-1, 1, 1), + LLVector4a(-1,-1,-1), + LLVector4a(-1,-1, 1), + LLVector4a( 1, 1,-1), + LLVector4a( 1, 1, 1), + LLVector4a( 1,-1,-1), + LLVector4a( 1,-1, 1), + }; + + for (S32 j = 0; j < model->getNumVolumeFaces(); ++j) + { + const LLVolumeFace& face = model->getVolumeFace(j); + + LLVector4a center; + center.setAdd(face.mExtents[0], face.mExtents[1]); + center.mul(0.5f); + LLVector4a size; + size.setSub(face.mExtents[1],face.mExtents[0]); + size.mul(0.5f); + + for (U32 i = 0; i < 8; i++) + { + LLVector4a t; + t.setMul(size, box[i]); + t.add(center); + + LLVector4a v; + + mat.affineTransform(t, v); + + if (first_transform) + { + first_transform = FALSE; + min = max = v; + } + else + { + update_min_max(min, max, v); + } + } + } +} + +void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform) +{ + LLVector4a mina, maxa; + LLMatrix4a mata; + + mata.loadu(mat); + mina.load3(min.mV); + maxa.load3(max.mV); + + stretch_extents(model, mata, mina, maxa, first_transform); + + min.set(mina.getF32ptr()); + max.set(maxa.getF32ptr()); +} + +//----------------------------------------------------------------------------- +// LLModelLoader +//----------------------------------------------------------------------------- +LLModelLoader::LLModelLoader( + std::string filename, + S32 lod, + load_callback_t load_cb, + joint_lookup_func_t joint_lookup_func, + texture_load_func_t texture_load_func, + state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointMap, + JointSet& jointsFromNodes ) +: mJointList( jointMap ) +, mJointsFromNode( jointsFromNodes ) +, LLThread("Model Loader") +, mFilename(filename) +, mLod(lod) +, mTrySLM(false) +, mFirstTransform(TRUE) +, mNumOfFetchingTextures(0) +, mLoadCallback(load_cb) +, mJointLookupFunc(joint_lookup_func) +, mTextureLoadFunc(texture_load_func) +, mStateCallback(state_cb) +, mOpaqueData(opaque_userdata) +, mRigParityWithScene(false) +, mRigValidJointUpload(false) +, mLegacyRigValid(false) +, mNoNormalize(false) +, mNoOptimize(false) +, mCacheOnlyHitIfRigged(false) +{ + mJointMap["mPelvis"] = "mPelvis"; + mJointMap["mTorso"] = "mTorso"; + mJointMap["mChest"] = "mChest"; + mJointMap["mNeck"] = "mNeck"; + mJointMap["mHead"] = "mHead"; + mJointMap["mSkull"] = "mSkull"; + mJointMap["mEyeRight"] = "mEyeRight"; + mJointMap["mEyeLeft"] = "mEyeLeft"; + mJointMap["mCollarLeft"] = "mCollarLeft"; + mJointMap["mShoulderLeft"] = "mShoulderLeft"; + mJointMap["mElbowLeft"] = "mElbowLeft"; + mJointMap["mWristLeft"] = "mWristLeft"; + mJointMap["mCollarRight"] = "mCollarRight"; + mJointMap["mShoulderRight"] = "mShoulderRight"; + mJointMap["mElbowRight"] = "mElbowRight"; + mJointMap["mWristRight"] = "mWristRight"; + mJointMap["mHipRight"] = "mHipRight"; + mJointMap["mKneeRight"] = "mKneeRight"; + mJointMap["mAnkleRight"] = "mAnkleRight"; + mJointMap["mFootRight"] = "mFootRight"; + mJointMap["mToeRight"] = "mToeRight"; + mJointMap["mHipLeft"] = "mHipLeft"; + mJointMap["mKneeLeft"] = "mKneeLeft"; + mJointMap["mAnkleLeft"] = "mAnkleLeft"; + mJointMap["mFootLeft"] = "mFootLeft"; + mJointMap["mToeLeft"] = "mToeLeft"; + + mJointMap["avatar_mPelvis"] = "mPelvis"; + mJointMap["avatar_mTorso"] = "mTorso"; + mJointMap["avatar_mChest"] = "mChest"; + mJointMap["avatar_mNeck"] = "mNeck"; + mJointMap["avatar_mHead"] = "mHead"; + mJointMap["avatar_mSkull"] = "mSkull"; + mJointMap["avatar_mEyeRight"] = "mEyeRight"; + mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; + mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; + mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; + mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; + mJointMap["avatar_mWristLeft"] = "mWristLeft"; + mJointMap["avatar_mCollarRight"] = "mCollarRight"; + mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; + mJointMap["avatar_mElbowRight"] = "mElbowRight"; + mJointMap["avatar_mWristRight"] = "mWristRight"; + mJointMap["avatar_mHipRight"] = "mHipRight"; + mJointMap["avatar_mKneeRight"] = "mKneeRight"; + mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; + mJointMap["avatar_mFootRight"] = "mFootRight"; + mJointMap["avatar_mToeRight"] = "mToeRight"; + mJointMap["avatar_mHipLeft"] = "mHipLeft"; + mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; + mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; + mJointMap["avatar_mFootLeft"] = "mFootLeft"; + mJointMap["avatar_mToeLeft"] = "mToeLeft"; + + + mJointMap["hip"] = "mPelvis"; + mJointMap["abdomen"] = "mTorso"; + mJointMap["chest"] = "mChest"; + mJointMap["neck"] = "mNeck"; + mJointMap["head"] = "mHead"; + mJointMap["figureHair"] = "mSkull"; + mJointMap["lCollar"] = "mCollarLeft"; + mJointMap["lShldr"] = "mShoulderLeft"; + mJointMap["lForeArm"] = "mElbowLeft"; + mJointMap["lHand"] = "mWristLeft"; + mJointMap["rCollar"] = "mCollarRight"; + mJointMap["rShldr"] = "mShoulderRight"; + mJointMap["rForeArm"] = "mElbowRight"; + mJointMap["rHand"] = "mWristRight"; + mJointMap["rThigh"] = "mHipRight"; + mJointMap["rShin"] = "mKneeRight"; + mJointMap["rFoot"] = "mFootRight"; + mJointMap["lThigh"] = "mHipLeft"; + mJointMap["lShin"] = "mKneeLeft"; + mJointMap["lFoot"] = "mFootLeft"; + + //move into joint mapper class + //1. joints for joint offset verification + mMasterJointList.push_front("mPelvis"); + mMasterJointList.push_front("mTorso"); + mMasterJointList.push_front("mChest"); + mMasterJointList.push_front("mNeck"); + mMasterJointList.push_front("mHead"); + mMasterJointList.push_front("mCollarLeft"); + mMasterJointList.push_front("mShoulderLeft"); + mMasterJointList.push_front("mElbowLeft"); + mMasterJointList.push_front("mWristLeft"); + mMasterJointList.push_front("mCollarRight"); + mMasterJointList.push_front("mShoulderRight"); + mMasterJointList.push_front("mElbowRight"); + mMasterJointList.push_front("mWristRight"); + mMasterJointList.push_front("mHipRight"); + mMasterJointList.push_front("mKneeRight"); + mMasterJointList.push_front("mFootRight"); + mMasterJointList.push_front("mHipLeft"); + mMasterJointList.push_front("mKneeLeft"); + mMasterJointList.push_front("mFootLeft"); + + //2. legacy joint list - used to verify rigs that will not be using joint offsets + mMasterLegacyJointList.push_front("mPelvis"); + mMasterLegacyJointList.push_front("mTorso"); + mMasterLegacyJointList.push_front("mChest"); + mMasterLegacyJointList.push_front("mNeck"); + mMasterLegacyJointList.push_front("mHead"); + mMasterLegacyJointList.push_front("mHipRight"); + mMasterLegacyJointList.push_front("mKneeRight"); + mMasterLegacyJointList.push_front("mFootRight"); + mMasterLegacyJointList.push_front("mHipLeft"); + mMasterLegacyJointList.push_front("mKneeLeft"); + mMasterLegacyJointList.push_front("mFootLeft"); + + assert_main_thread(); + sActiveLoaderList.push_back(this) ; +} + +LLModelLoader::~LLModelLoader() +{ + assert_main_thread(); + sActiveLoaderList.remove(this); +} + +void LLModelLoader::run() +{ + doLoadModel(); + doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this)); +} + +bool LLModelLoader::doLoadModel() +{ + //first, look for a .slm file of the same name that was modified later + //than the .dae + + if (mTrySLM) + { + std::string filename = mFilename; + + std::string::size_type i = filename.rfind("."); + if (i != std::string::npos) + { + filename.replace(i, filename.size()-1, ".slm"); + llstat slm_status; + if (LLFile::stat(filename, &slm_status) == 0) + { //slm file exists + llstat dae_status; + if (LLFile::stat(mFilename, &dae_status) != 0 || + dae_status.st_mtime < slm_status.st_mtime) + { + if (loadFromSLM(filename)) + { //slm successfully loaded, if this fails, fall through and + //try loading from dae + + mLod = -1; //successfully loading from an slm implicitly sets all + //LoDs + return true; + } + } + } + } + } + + return OpenFile(mFilename); +} + +void LLModelLoader::setLoadState(U32 state) +{ + mStateCallback(state, mOpaqueData); +} + +bool LLModelLoader::loadFromSLM(const std::string& filename) +{ + //only need to populate mScene with data from slm + llstat stat; + + if (LLFile::stat(filename, &stat)) + { //file does not exist + return false; + } + + S32 file_size = (S32) stat.st_size; + + llifstream ifstream(filename.c_str(), std::ifstream::in | std::ifstream::binary); + LLSD data; + LLSDSerialize::fromBinary(data, ifstream, file_size); + ifstream.close(); + + //build model list for each LoD + model_list model[LLModel::NUM_LODS]; + + if (data["version"].asInteger() != SLM_SUPPORTED_VERSION) + { //unsupported version + return false; + } + + LLSD& mesh = data["mesh"]; + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + + for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + { + for (U32 i = 0; i < (U32)mesh.size(); ++i) + { + std::stringstream str(mesh[i].asString()); + LLPointer loaded_model = new LLModel(volume_params, (F32) lod); + if (loaded_model->loadModel(str)) + { + loaded_model->mLocalID = i; + model[lod].push_back(loaded_model); + + if (lod == LLModel::LOD_HIGH) + { + if (!loaded_model->mSkinInfo.mJointNames.empty()) + { + //check to see if rig is valid + critiqueRigForUploadApplicability( loaded_model->mSkinInfo.mJointNames ); + } + else if (mCacheOnlyHitIfRigged) + { + return false; + } + } + } + } + } + + if (model[LLModel::LOD_HIGH].empty()) + { //failed to load high lod + return false; + } + + //load instance list + model_instance_list instance_list; + + LLSD& instance = data["instance"]; + + for (U32 i = 0; i < (U32)instance.size(); ++i) + { + //deserialize instance list + instance_list.push_back(LLModelInstance(instance[i])); + + //match up model instance pointers + S32 idx = instance_list[i].mLocalMeshID; + std::string instance_label = instance_list[i].mLabel; + + for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + { + if (!model[lod].empty()) + { + if (idx >= model[lod].size()) + { + if (model[lod].size()) + { + instance_list[i].mLOD[lod] = model[lod][0]; + } + else + { + instance_list[i].mLOD[lod] = NULL; + } + continue; + } + + if (model[lod][idx] + && model[lod][idx]->mLabel.empty() + && !instance_label.empty()) + { + // restore model names + std::string name = instance_label; + switch (lod) + { + case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; + case LLModel::LOD_LOW: name += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + model[lod][idx]->mLabel = name; + } + + instance_list[i].mLOD[lod] = model[lod][idx]; + } + } + + if (!instance_list[i].mModel) + instance_list[i].mModel = model[LLModel::LOD_HIGH][idx]; + } + + // Set name for UI to use + std::string name = data["name"]; + if (!name.empty()) + { + model[LLModel::LOD_HIGH][0]->mRequestedLabel = name; + } + + + //convert instance_list to mScene + mFirstTransform = TRUE; + for (U32 i = 0; i < instance_list.size(); ++i) + { + LLModelInstance& cur_instance = instance_list[i]; + mScene[cur_instance.mTransform].push_back(cur_instance); + stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform); + } + + setLoadState( DONE ); + + return true; +} + +//static +bool LLModelLoader::isAlive(LLModelLoader* loader) +{ + if(!loader) + { + return false ; + } + + std::list::iterator iter = sActiveLoaderList.begin() ; + for(; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter) ; + + return *iter == loader ; +} + +void LLModelLoader::loadModelCallback() +{ + mLoadCallback(mScene,mModelList,mLod, mOpaqueData); + + while (!isStopped()) + { //wait until this thread is stopped before deleting self + boost::this_thread::sleep_for(boost::chrono::microseconds(100)); + } + + //double check if "this" is valid before deleting it, in case it is aborted during running. + if(!isAlive(this)) + { + return ; + } + + delete this; +} + +//----------------------------------------------------------------------------- +// critiqueRigForUploadApplicability() +//----------------------------------------------------------------------------- +void LLModelLoader::critiqueRigForUploadApplicability( const std::vector &jointListFromAsset ) +{ + critiqueJointToNodeMappingFromScene(); + + //Determines the following use cases for a rig: + //1. It is suitable for upload with skin weights & joint positions, or + //2. It is suitable for upload as standard av with just skin weights + + bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload( jointListFromAsset ); + bool isRigLegacyOK = isRigLegacy( jointListFromAsset ); + + //It's OK that both could end up being true, both default to false + if ( isJointPositionUploadOK ) + { + setRigValidForJointPositionUpload( true ); + } + + if ( isRigLegacyOK) + { + setLegacyRigValid( true ); + } + +} +//----------------------------------------------------------------------------- +// critiqueJointToNodeMappingFromScene() +//----------------------------------------------------------------------------- +void LLModelLoader::critiqueJointToNodeMappingFromScene( void ) +{ + //Do the actual nodes back the joint listing from the dae? + //if yes then this is a fully rigged asset, otherwise it's just a partial rig + + JointSet::iterator jointsFromNodeIt = mJointsFromNode.begin(); + JointSet::iterator jointsFromNodeEndIt = mJointsFromNode.end(); + bool result = true; + + if ( !mJointsFromNode.empty() ) + { + for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt ) + { + std::string name = *jointsFromNodeIt; + if ( mJointTransformMap.find( name ) != mJointTransformMap.end() ) + { + continue; + } + else + { + LL_INFOS() <<"critiqueJointToNodeMappingFromScene is missing a: " << name << LL_ENDL; + result = false; + } + } + } + else + { + result = false; + } + + //Determines the following use cases for a rig: + //1. Full av rig w/1-1 mapping from the scene and joint array + //2. Partial rig but w/o parity between the scene and joint array + if ( result ) + { + setRigWithSceneParity( true ); + } +} +//----------------------------------------------------------------------------- +// isRigLegacy() +//----------------------------------------------------------------------------- +bool LLModelLoader::isRigLegacy( const std::vector &jointListFromAsset ) +{ + //No joints in asset + if ( jointListFromAsset.size() == 0 ) + { + return false; + } + + bool result = false; + + JointSet :: const_iterator masterJointIt = mMasterLegacyJointList.begin(); + JointSet :: const_iterator masterJointEndIt = mMasterLegacyJointList.end(); + + std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); + std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); + + for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) + { + result = false; + modelJointIt = jointListFromAsset.begin(); + + for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) + { + if ( *masterJointIt == *modelJointIt ) + { + result = true; + break; + } + } + if ( !result ) + { + LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; + break; + } + } + return result; +} +//----------------------------------------------------------------------------- +// isRigSuitableForJointPositionUpload() +//----------------------------------------------------------------------------- +bool LLModelLoader::isRigSuitableForJointPositionUpload( const std::vector &jointListFromAsset ) +{ + bool result = false; + + JointSet :: const_iterator masterJointIt = mMasterJointList.begin(); + JointSet :: const_iterator masterJointEndIt = mMasterJointList.end(); + + std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); + std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); + + for ( ;masterJointIt!=masterJointEndIt;++masterJointIt ) + { + result = false; + modelJointIt = jointListFromAsset.begin(); + + for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt ) + { + if ( *masterJointIt == *modelJointIt ) + { + result = true; + break; + } + } + if ( !result ) + { + LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; + break; + } + } + return result; +} + + +//called in the main thread +void LLModelLoader::loadTextures() +{ + BOOL is_paused = isPaused() ; + pause() ; //pause the loader + + for(scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter) + { + for(U32 i = 0 ; i < iter->second.size(); i++) + { + for(std::map::iterator j = iter->second[i].mMaterial.begin(); + j != iter->second[i].mMaterial.end(); ++j) + { + LLImportMaterial& material = j->second; + + if(!material.mDiffuseMapFilename.empty()) + { + mNumOfFetchingTextures += mTextureLoadFunc(material, mOpaqueData); + } + } + } + } + + if(!is_paused) + { + unpause() ; + } +} diff --git a/indra/llprimitive/llmodelloader.h b/indra/llprimitive/llmodelloader.h new file mode 100644 index 000000000..bb4d06dca --- /dev/null +++ b/indra/llprimitive/llmodelloader.h @@ -0,0 +1,212 @@ +/** + * @file llmodelloader.h + * @brief LLModelLoader class definition + * + * $LicenseInfo:firstyear=2004&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_LLMODELLOADER_H +#define LL_LLMODELLOADER_H + +#include "llmodel.h" +#include "llthread.h" +#include +#include + +class LLJoint; + +typedef std::map JointTransformMap; +typedef std::map:: iterator JointTransformMapIt; +typedef std::map JointMap; +typedef std::deque JointSet; + +const S32 SLM_SUPPORTED_VERSION = 3; +const S32 NUM_LOD = 4; + +class LLModelLoader : public LLThread +{ +public: + + typedef std::map material_map; + typedef std::vector > model_list; + typedef std::vector model_instance_list; + typedef std::map scene; + + // Callback with loaded model data and loaded LoD + // + typedef boost::function load_callback_t; + + // Function to provide joint lookup by name + // (within preview avi skeleton, for example) + // + typedef boost::function joint_lookup_func_t; + + // Func to load and associate material with all it's textures, + // returned value is the number of textures loaded + // intentionally non-const so func can modify material to + // store platform-specific data + // + typedef boost::function texture_load_func_t; + + // Callback to inform client of state changes + // during loading process (errors will be reported + // as state changes here as well) + // + typedef boost::function state_callback_t; + + typedef enum + { + STARTING = 0, + READING_FILE, + CREATING_FACES, + GENERATING_VERTEX_BUFFERS, + GENERATING_LOD, + DONE, + ERROR_PARSING, //basically loading failed + ERROR_MATERIALS, + ERROR_PASSWORD_REQUIRED, + ERROR_NEED_MORE_MEMORY, + ERROR_INVALID_FILE, + ERROR_LOADER_SETUP, + ERROR_INVALID_PARAMETERS, + ERROR_OUT_OF_RANGE, + ERROR_FILE_VERSION_INVALID, + ERROR_MODEL // this error should always be last in this list, error code is passed as ERROR_MODEL+error_code + } eLoadState; + + U32 mState; + std::string mFilename; + + S32 mLod; + + LLMatrix4 mTransform; + BOOL mFirstTransform; + LLVector3 mExtents[2]; + + bool mTrySLM; + bool mCacheOnlyHitIfRigged; // ignore cached SLM if it does not contain rig info (and we want rig info) + + model_list mModelList; + scene mScene; + + typedef std::queue > model_queue; + + //queue of models that need a physics rep + model_queue mPhysicsQ; + + //map of avatar joints as named in COLLADA assets to internal joint names + JointMap mJointMap; + JointTransformMap& mJointList; + JointSet& mJointsFromNode; + + LLModelLoader( + std::string filename, + S32 lod, + LLModelLoader::load_callback_t load_cb, + LLModelLoader::joint_lookup_func_t joint_lookup_func, + LLModelLoader::texture_load_func_t texture_load_func, + LLModelLoader::state_callback_t state_cb, + void* opaque_userdata, + JointTransformMap& jointMap, + JointSet& jointsFromNodes); + virtual ~LLModelLoader() ; + + virtual void setNoNormalize() { mNoNormalize = true; } + virtual void setNoOptimize() { mNoOptimize = true; } + + virtual void run(); + + // Will try SLM or derived class OpenFile as appropriate + // + virtual bool doLoadModel(); + + // Derived classes need to provide their parsing of files here + // + virtual bool OpenFile(const std::string& filename) = 0; + + bool loadFromSLM(const std::string& filename); + + void loadModelCallback(); + void loadTextures() ; //called in the main thread. + void setLoadState(U32 state); + + + + S32 mNumOfFetchingTextures ; //updated in the main thread + bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread. + + bool verifyCount( int expected, int result ); + + //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps) + void critiqueRigForUploadApplicability( const std::vector &jointListFromAsset ); + void critiqueJointToNodeMappingFromScene( void ); + + //Determines if a rig is a legacy from the joint list + bool isRigLegacy( const std::vector &jointListFromAsset ); + + //Determines if a rig is suitable for upload + bool isRigSuitableForJointPositionUpload( const std::vector &jointListFromAsset ); + + void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; } + const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; } + + const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; } + void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; } + + const bool isLegacyRigValid( void ) const { return mLegacyRigValid; } + void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; } + + //----------------------------------------------------------------------------- + // isNodeAJoint() + //----------------------------------------------------------------------------- + bool isNodeAJoint(const char* name) + { + return mJointMap.find(name) != mJointMap.end(); + } + +protected: + + LLModelLoader::load_callback_t mLoadCallback; + LLModelLoader::joint_lookup_func_t mJointLookupFunc; + LLModelLoader::texture_load_func_t mTextureLoadFunc; + LLModelLoader::state_callback_t mStateCallback; + void* mOpaqueData; + + bool mRigParityWithScene; + bool mRigValidJointUpload; + bool mLegacyRigValid; + + bool mNoNormalize; + bool mNoOptimize; + + JointSet mMasterJointList; + JointSet mMasterLegacyJointList; + JointTransformMap mJointTransformMap; + + static std::list sActiveLoaderList; + static bool isAlive(LLModelLoader* loader) ; +}; +class LLMatrix4a; +void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform); +void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform); + +#endif // LL_LLMODELLOADER_H diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index e9c804b26..e30f49493 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -40,6 +40,7 @@ #include "llprimtexturelist.h" #include "imageids.h" #include "llmaterialid.h" +#include "llvolume.h" /** * exported constants @@ -321,6 +322,11 @@ S32 LLPrimitive::setTEMaterialParams(const U8 index, const LLMaterialPtr pMateri return mTextureList.setMaterialParams(index, pMaterialParams); } +LLMaterialPtr LLPrimitive::getTEMaterialParams(const U8 index) +{ + return mTextureList.getMaterialParams(index); +} + //=============================================================== S32 LLPrimitive::setTEBumpShinyFullbright(const U8 index, const U8 bump) { @@ -987,8 +993,6 @@ BOOL LLPrimitive::setMaterial(U8 material) } } -const F32 LL_MAX_SCALE_S = 100.0f; -const F32 LL_MAX_SCALE_T = 100.0f; S32 LLPrimitive::packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const { S32 face_index; @@ -1843,9 +1847,12 @@ BOOL LLSculptParams::pack(LLDataPacker &dp) const BOOL LLSculptParams::unpack(LLDataPacker &dp) { - dp.unpackUUID(mSculptTexture, "texture"); - dp.unpackU8(mSculptType, "type"); - + U8 type; + LLUUID id; + dp.unpackUUID(id, "texture"); + dp.unpackU8(type, "type"); + + setSculptTexture(id, type); return TRUE; } @@ -1870,8 +1877,7 @@ bool LLSculptParams::operator==(const LLNetworkData& data) const void LLSculptParams::copy(const LLNetworkData& data) { const LLSculptParams *param = (LLSculptParams*)&data; - mSculptTexture = param->mSculptTexture; - mSculptType = param->mSculptType; + setSculptTexture(param->mSculptTexture, param->mSculptType); } @@ -1889,20 +1895,38 @@ LLSD LLSculptParams::asLLSD() const bool LLSculptParams::fromLLSD(LLSD& sd) { const char *w; - w = "texture"; - if (sd.has(w)) - { - setSculptTexture( sd[w] ); - } else goto fail; + U8 type; w = "type"; if (sd.has(w)) { - setSculptType( (U8)sd[w].asInteger() ); - } else goto fail; - + type = sd[w].asInteger(); + } + else return false; + + w = "texture"; + if (sd.has(w)) + { + setSculptTexture(sd[w], type); + } + else return false; + return true; - fail: - return false; +} + +void LLSculptParams::setSculptTexture(const LLUUID& texture_id, U8 sculpt_type) +{ + U8 type = sculpt_type & LL_SCULPT_TYPE_MASK; + U8 flags = sculpt_type & LL_SCULPT_FLAG_MASK; + if (sculpt_type != (type | flags) || type > LL_SCULPT_TYPE_MAX) + { + mSculptTexture.set(SCULPT_DEFAULT_TEXTURE); + mSculptType = LL_SCULPT_TYPE_SPHERE; + } + else + { + mSculptTexture = texture_id; + mSculptType = sculpt_type; + } } //============================================================================ diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index 36680ba9b..85fb2233e 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -259,9 +259,8 @@ public: operator LLSD() const { return asLLSD(); } bool fromLLSD(LLSD& sd); - void setSculptTexture(const LLUUID& id) { mSculptTexture = id; } + void setSculptTexture(const LLUUID& texture_id, U8 sculpt_type); LLUUID getSculptTexture() const { return mSculptTexture; } - void setSculptType(U8 type) { mSculptType = type; } U8 getSculptType() const { return mSculptType; } }; @@ -389,6 +388,8 @@ public: virtual BOOL setMaterial(const U8 material); // returns TRUE if material changed virtual void setTESelected(const U8 te, bool sel); + LLMaterialPtr getTEMaterialParams(const U8 index); + void copyTEs(const LLPrimitive *primitive); S32 packTEField(U8 *cur_ptr, U8 *data_ptr, U8 data_size, U8 last_face_index, EMsgVariableType type) const; S32 unpackTEField(U8 *cur_ptr, U8 *buffer_end, U8 *data_ptr, U8 data_size, U8 face_count, EMsgVariableType type); diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index dfae9699e..854003d42 100644 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -137,7 +137,7 @@ S32 LLPrimTextureList::copyTexture(const U8 index, const LLTextureEntry& te) // we're changing an existing entry llassert(mEntryList[index]); delete (mEntryList[index]); - if (&te) + if (te != LLTextureEntry::null) { mEntryList[index] = te.newCopy(); } @@ -377,6 +377,16 @@ S32 LLPrimTextureList::setMaterialParams(const U8 index, const LLMaterialPtr pMa return TEM_CHANGE_NONE; } +LLMaterialPtr LLPrimTextureList::getMaterialParams(const U8 index) +{ + if (index < mEntryList.size()) + { + return mEntryList[index]->getMaterialParams(); + } + + return LLMaterialPtr(); +} + S32 LLPrimTextureList::size() const { return mEntryList.size(); diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index c91764e7a..ce5f6b72b 100644 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -115,6 +115,8 @@ public: S32 setMaterialID(const U8 index, const LLMaterialID& pMaterialID); S32 setMaterialParams(const U8 index, const LLMaterialPtr pMaterialParams); + LLMaterialPtr getMaterialParams(const U8 index); + S32 size() const; // void forceResize(S32 new_size); diff --git a/indra/llprimitive/lltextureentry.h b/indra/llprimitive/lltextureentry.h index 19edcaa27..a40c3988f 100644 --- a/indra/llprimitive/lltextureentry.h +++ b/indra/llprimitive/lltextureentry.h @@ -89,6 +89,10 @@ public: bool operator==(const LLTextureEntry &rhs) const; bool operator!=(const LLTextureEntry &rhs) const; + + // Added to allow use with std::map + // + bool operator <(const LLTextureEntry &rhs) const; LLSD asLLSD() const; void asLLSD(LLSD& sd) const; diff --git a/indra/llrender/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp index 4547c2f61..9b1a4b431 100644 --- a/indra/llrender/llfontfreetype.cpp +++ b/indra/llrender/llfontfreetype.cpp @@ -104,7 +104,6 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index) LLFontFreetype::LLFontFreetype() : mFontBitmapCachep(new LLFontBitmapCache), - mValid(FALSE), mAscender(0.f), mDescender(0.f), mLineHeight(0.f), @@ -112,6 +111,7 @@ LLFontFreetype::LLFontFreetype() mFTFace(NULL), mRenderGlyphCount(0), mAddGlyphCount(0), + mStyle(0), mPointSize(0) { } @@ -204,6 +204,19 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, const F32 point_size, mName = filename; mPointSize = point_size; + mStyle = LLFontGL::NORMAL; + if(mFTFace->style_flags & FT_STYLE_FLAG_BOLD) + { + mStyle |= LLFontGL::BOLD; + mStyle &= ~LLFontGL::NORMAL; + } + + if(mFTFace->style_flags & FT_STYLE_FLAG_ITALIC) + { + mStyle |= LLFontGL::ITALIC; + mStyle &= ~LLFontGL::NORMAL; + } + return TRUE; } @@ -536,6 +549,15 @@ const LLPointer LLFontFreetype::getFontBitmapCache() const return mFontBitmapCachep; } +void LLFontFreetype::setStyle(U8 style) +{ + mStyle = style; +} + +U8 LLFontFreetype::getStyle() const +{ + return mStyle; +} void LLFontFreetype::setSubImageLuminanceAlpha(const U32 x, const U32 y, const U32 bitmap_num, const U32 width, const U32 height, const U8 *data, S32 stride) const { LLImageRaw *image_raw = mFontBitmapCachep->getImageRaw(bitmap_num); diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h index 948445835..649fb254b 100644 --- a/indra/llrender/llfontfreetype.h +++ b/indra/llrender/llfontfreetype.h @@ -93,8 +93,6 @@ public: void setFallbackFonts(const font_vector_t &font); const font_vector_t &getFallbackFonts() const; - void setCharToGlyphMap(llwchar wch, U32 glyph_index) const; - // Global font metrics - in units of pixels F32 getLineHeight() const; F32 getAscenderHeight() const; @@ -140,6 +138,9 @@ public: const std::string& getName() const; const LLPointer getFontBitmapCache() const; + + void setStyle(U8 style); + U8 getStyle() const; static bool sOpenGLcrashOnRestart; @@ -154,6 +155,8 @@ private: std::string mName; + U8 mStyle; + F32 mPointSize; F32 mAscender; F32 mDescender; @@ -164,8 +167,6 @@ private: BOOL mIsFallback; font_vector_t mFallbackFonts; // A list of fallback fonts to look for glyphs in (for Unicode chars) - BOOL mValid; - typedef boost::unordered_map char_glyph_info_map_t; mutable char_glyph_info_map_t mCharGlyphInfoMap; // Information about glyph location in bitmap diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index ac425abad..7f5bfefb1 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -36,6 +36,7 @@ #include "llfontregistry.h" #include "llgl.h" #include "llrender.h" +#include "lltexture.h" #include "v4color.h" #include "llstl.h" #include "llfasttimer.h" @@ -69,20 +70,6 @@ const F32 PIXEL_CORRECTION_DISTANCE = 0.01f; const F32 PAD_UVY = 0.5f; // half of vertical padding between glyphs in the glyph texture const F32 DROP_SHADOW_SOFT_STRENGTH = 0.3f; -F32 llfont_round_x(F32 x) -{ - //return llfloor((x-LLFontGL::sCurOrigin.mX)/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleX+LLFontGL::sCurOrigin.mX; - //return llfloor(x/LLFontGL::sScaleX+0.5f)*LLFontGL::sScaleY; - return x; -} - -F32 llfont_round_y(F32 y) -{ - //return llfloor((y-LLFontGL::sCurOrigin.mY)/LLFontGL::sScaleY+0.5f)*LLFontGL::sScaleY+LLFontGL::sCurOrigin.mY; - //return llfloor(y+0.5f); - return y; -} - LLFontGL::LLFontGL() { clearEmbeddedChars(); @@ -166,8 +153,9 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons S32 scaled_max_pixels = max_pixels == S32_MAX ? S32_MAX : llceil((F32)max_pixels * sScaleX); - // Strip off any style bits that are already accounted for by the font. - style = style & (~getFontDesc().getStyle()); + // determine which style flags need to be added programmatically by stripping off the + // style bits that are drawn by the underlying Freetype font + U8 style_to_add = (style | mFontDescriptor.getStyle()) & ~mFontFreetype->getStyle(); F32 drop_shadow_strength = 0.f; if (shadow != NO_SHADOW) @@ -412,7 +400,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons glyph_count = 0; } - drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style, shadow, drop_shadow_strength); + drawGlyph(glyph_count, vertices, uvs, colors, screen_rect, uv_rect, text_color, style_to_add, shadow, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; @@ -453,7 +441,8 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons *right_x = (cur_x - origin.mV[VX]) / sScaleX; } - if (style & UNDERLINE) + //FIXME: add underline as glyph? + if (style_to_add & UNDERLINE) { F32 descender = (F32)llfloor(mFontFreetype->getDescenderHeight()); @@ -475,7 +464,7 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons (cur_x - origin.mV[VX]) / sScaleX, (F32)y, color, LEFT, valign, - style, + style_to_add, shadow, S32_MAX, max_pixels, right_x, @@ -940,7 +929,7 @@ void LLFontGL::removeEmbeddedChar( llwchar wc ) const } // static -void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector& xui_paths, bool create_gl_textures) +void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures) { sVertDPI = (F32)llfloor(screen_dpi * y_scale); sHorizDPI = (F32)llfloor(screen_dpi * x_scale); @@ -951,7 +940,7 @@ void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::st // Font registry init if (!sFontRegistry) { - sFontRegistry = new LLFontRegistry(xui_paths,create_gl_textures); + sFontRegistry = new LLFontRegistry(create_gl_textures); sFontRegistry->parseFontInfo("fonts.xml"); } else diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 6300f67ab..6d1c6a29a 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -30,7 +30,7 @@ #include "llcoord.h" #include "llfontregistry.h" -#include "lltexture.h" +#include "llimagegl.h" #include "llpointer.h" #include "llrect.h" #include "v2math.h" @@ -152,7 +152,7 @@ public: void addEmbeddedChar( llwchar wc, LLTexture* image, const LLWString& label) const; void removeEmbeddedChar( llwchar wc ) const; - static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, const std::vector& xui_paths, bool create_gl_textures = true); + static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, bool create_gl_textures = true); // Load sans-serif, sans-serif-small, etc. // Slow, requires multiple seconds to load fonts. diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 53e3a1c57..98ee83193 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -34,13 +34,15 @@ #include "llcontrol.h" #include "lldir.h" #include "llwindow.h" +#include "llxmlnode.h" extern LLControlGroup gSavedSettings; using std::string; using std::map; -bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc); +bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc); +bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node); LLFontDescriptor::LLFontDescriptor(): mStyle(0) @@ -163,14 +165,9 @@ LLFontDescriptor LLFontDescriptor::normalize() const return LLFontDescriptor(new_name,new_size,new_style,getFileNames()); } -LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths, - bool create_gl_textures) +LLFontRegistry::LLFontRegistry(bool create_gl_textures) : mCreateGLTextures(create_gl_textures) { - // Propagate this down from LLUICtrlFactory so LLRender doesn't - // need an upstream dependency on LLUI. - mXUIPaths = xui_paths; - // This is potentially a slow directory traversal, so we want to // cache the result. mUltimateFallbackList = LLWindow::getDynamicFallbackFontList(); @@ -183,23 +180,27 @@ LLFontRegistry::~LLFontRegistry() bool LLFontRegistry::parseFontInfo(const std::string& xml_filename) { - bool success = false; // Succeed if we find at least one XUI file - const string_vec_t& xml_paths = mXUIPaths; + bool success = false; // Succeed if we find and read at least one XUI file + const string_vec_t xml_paths = gDirUtilp->findSkinnedFilenames(LLDir::XUI, xml_filename); + if (xml_paths.empty()) + { + // We didn't even find one single XUI file + return false; + } + for (string_vec_t::const_iterator path_it = xml_paths.begin(); path_it != xml_paths.end(); ++path_it) { LLXMLNodePtr root; - std::string full_filename = gDirUtilp->findSkinnedFilename(*path_it, xml_filename); - bool parsed_file = LLXMLNode::parseFile(full_filename, root, NULL); + bool parsed_file = LLXMLNode::parseFile(*path_it, root, NULL); if (!parsed_file) continue; if ( root.isNull() || ! root->hasName( "fonts" ) ) { - LL_WARNS() << "Bad font info file: " - << full_filename << LL_ENDL; + LL_WARNS() << "Bad font info file: " << *path_it << LL_ENDL; continue; } @@ -208,12 +209,12 @@ bool LLFontRegistry::parseFontInfo(const std::string& xml_filename) if (root->hasName("fonts")) { // Expect a collection of children consisting of "font" or "font_size" entries - bool init_succ = initFromXML(root); + bool init_succ = init_from_xml(this, root); success = success || init_succ; } } - if (success) - dump(); + //if (success) + // dump(); return success; } @@ -231,7 +232,7 @@ std::string currentOsName() #endif } -bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc) +bool font_desc_init_from_xml(LLXMLNodePtr node, LLFontDescriptor& desc) { if (node->hasName("font")) { @@ -264,14 +265,14 @@ bool fontDescInitFromXML(LLXMLNodePtr node, LLFontDescriptor& desc) { if (child_name == currentOsName()) { - fontDescInitFromXML(child, desc); + font_desc_init_from_xml(child, desc); } } } return true; } -bool LLFontRegistry::initFromXML(LLXMLNodePtr node) +bool init_from_xml(LLFontRegistry* registry, LLXMLNodePtr node) { LLXMLNodePtr child; @@ -282,17 +283,17 @@ bool LLFontRegistry::initFromXML(LLXMLNodePtr node) if (child->hasName("font")) { LLFontDescriptor desc; - bool font_succ = fontDescInitFromXML(child, desc); + bool font_succ = font_desc_init_from_xml(child, desc); LLFontDescriptor norm_desc = desc.normalize(); if (font_succ) { // if this is the first time we've seen this font name, // create a new template map entry for it. - const LLFontDescriptor *match_desc = getMatchingFontDesc(desc); + const LLFontDescriptor *match_desc = registry->getMatchingFontDesc(desc); if (match_desc == NULL) { // Create a new entry (with no corresponding font). - mFontMap[norm_desc] = NULL; + registry->mFontMap[norm_desc] = NULL; } // otherwise, find the existing entry and combine data. else @@ -307,8 +308,8 @@ bool LLFontRegistry::initFromXML(LLXMLNodePtr node) desc.getFileNames().end()); LLFontDescriptor new_desc = *match_desc; new_desc.getFileNames() = match_file_names; - mFontMap.erase(*match_desc); - mFontMap[new_desc] = NULL; + registry->mFontMap.erase(*match_desc); + registry->mFontMap[new_desc] = NULL; } } } @@ -319,7 +320,7 @@ bool LLFontRegistry::initFromXML(LLXMLNodePtr node) if (child->getAttributeString("name",size_name) && child->getAttributeF32("size",size_value)) { - mFontSizes[size_name] = size_value; + registry->mFontSizes[size_name] = size_value; } } diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index 8b06191c5..177eb6c8a 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -28,7 +28,7 @@ #ifndef LL_LLFONTREGISTRY_H #define LL_LLFONTREGISTRY_H -#include "llxmlnode.h" +#include "llpointer.h" class LLFontGL; @@ -65,15 +65,14 @@ private: class LLFontRegistry { public: + friend bool init_from_xml(LLFontRegistry*, LLPointer); // create_gl_textures - set to false for test apps with no OpenGL window, // such as llui_libtest - LLFontRegistry(const string_vec_t& xui_paths, - bool create_gl_textures); + LLFontRegistry(bool create_gl_textures); ~LLFontRegistry(); // Load standard font info from XML file(s). bool parseFontInfo(const std::string& xml_filename); - bool initFromXML(LLXMLNodePtr node); // Clear cached glyphs for all fonts. void reset(); @@ -95,6 +94,7 @@ public: const string_vec_t& getUltimateFallbackList() const; private: + LLFontRegistry(const LLFontRegistry& other); // no-copy LLFontGL *createFont(const LLFontDescriptor& desc); typedef std::map font_reg_map_t; typedef std::map font_size_map_t; @@ -105,7 +105,6 @@ private: font_size_map_t mFontSizes; string_vec_t mUltimateFallbackList; - string_vec_t mXUIPaths; bool mCreateGLTextures; }; diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 24f7d94ce..5a0668ef3 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -223,6 +223,7 @@ PFNGLENDQUERYARBPROC glEndQueryARB = NULL; PFNGLGETQUERYIVARBPROC glGetQueryivARB = NULL; PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB = NULL; PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB = NULL; +PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64vEXT = NULL; // GL_ARB_point_parameters PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB = NULL; @@ -443,6 +444,7 @@ LLGLManager::LLGLManager() : mHasCubeMap(FALSE), mHasDebugOutput(FALSE), + mHasGpuShader5(FALSE), mHasAdaptiveVsync(FALSE), mHasTextureSwizzle(FALSE), @@ -938,6 +940,9 @@ void LLGLManager::initExtensions() mHasVertexShader = FALSE; mHasFragmentShader = FALSE; mHasTextureRectangle = FALSE; +#ifdef GL_ARB_gpu_shader5 + mHasGpuShader5 = FALSE; +#endif #else // LL_MESA_HEADLESS //important, gGLHExts.mSysExts is uninitialized until after glh_init_extensions is called mHasMultitexture = glh_init_extensions("GL_ARB_multitexture"); mHasATIMemInfo = ExtensionExists("GL_ATI_meminfo", gGLHExts.mSysExts); @@ -982,7 +987,9 @@ void LLGLManager::initExtensions() && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts)); mHasFragmentShader = ExtensionExists("GL_ARB_fragment_shader", gGLHExts.mSysExts) && (LLRender::sGLCoreProfile || ExtensionExists("GL_ARB_shading_language_100", gGLHExts.mSysExts)); #endif - +#ifdef GL_ARB_gpu_shader5 + mHasGpuShader5 = ExtensionExists("GL_ARB_gpu_shader5", gGLHExts.mSysExts);; +#endif #if LL_WINDOWS mHasAdaptiveVsync = ExtensionExists("WGL_EXT_swap_control_tear", gGLHExts.mSysExts); #elif LL_LINUX @@ -1262,6 +1269,9 @@ void LLGLManager::initExtensions() glGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectivARB"); glGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectuivARB"); } +#if !LL_DARWIN + glGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)GLH_EXT_GET_PROC_ADDRESS("glGetQueryObjectui64vEXT"); +#endif if (mHasPointParameters) { LL_INFOS() << "initExtensions() PointParameters-related procs..." << LL_ENDL; diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 1cf65c8ca..36650b442 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -112,7 +112,7 @@ public: BOOL mHasARBEnvCombine; BOOL mHasCubeMap; BOOL mHasDebugOutput; - + BOOL mHasGpuShader5; BOOL mHasAdaptiveVsync; BOOL mHasTextureSwizzle; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 3a91c50ff..fe6001fec 100644 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -620,6 +620,8 @@ extern PFNGLGETQUERYIVARBPROC glGetQueryivARB; extern PFNGLGETQUERYOBJECTIVARBPROC glGetQueryObjectivARB; extern PFNGLGETQUERYOBJECTUIVARBPROC glGetQueryObjectuivARB; +extern PFNGLGETQUERYOBJECTUI64VEXTPROC glGetQueryObjectui64vEXT; + // GL_ARB_point_parameters extern PFNGLPOINTPARAMETERFARBPROC glPointParameterfARB; extern PFNGLPOINTPARAMETERFVARBPROC glPointParameterfvARB; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 33404433f..dc8c08b99 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -38,6 +38,11 @@ #include "OpenGL/OpenGL.h" #endif +#ifdef LL_RELEASE_FOR_DOWNLOAD +#define UNIFORM_ERRS LL_WARNS_ONCE("Shader") +#else +#define UNIFORM_ERRS LL_ERRS("Shader") +#endif // Lots of STL stuff in here, using namespace std to keep things more readable using std::vector; using std::pair; @@ -48,6 +53,12 @@ GLhandleARB LLGLSLShader::sCurBoundShader = 0; LLGLSLShader* LLGLSLShader::sCurBoundShaderPtr = NULL; S32 LLGLSLShader::sIndexedTextureChannels = 0; bool LLGLSLShader::sNoFixedFunction = false; +bool LLGLSLShader::sProfileEnabled = false; +std::set LLGLSLShader::sInstances; +U64 LLGLSLShader::sTotalTimeElapsed = 0; +U32 LLGLSLShader::sTotalTrianglesDrawn = 0; +U64 LLGLSLShader::sTotalSamplesDrawn = 0; +U32 LLGLSLShader::sTotalDrawCalls = 0; //UI shader -- declared here so llui_libtest will link properly //Singu note: Not using llui_libtest... and LLViewerShaderMgr is a part of newview. So, @@ -77,13 +88,221 @@ LLShaderFeatures::LLShaderFeatures() , hasGamma(false) , mIndexedTextureChannels(0) , disableTextureIndex(false) - , hasAlphaMask(false) + , hasAlphaMask(false) + , attachNothing(false) { } //=============================== // LLGLSL Shader implementation //=============================== + +//static +void LLGLSLShader::initProfile() +{ + sProfileEnabled = true; + sTotalTimeElapsed = 0; + sTotalTrianglesDrawn = 0; + sTotalSamplesDrawn = 0; + sTotalDrawCalls = 0; + + for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + { + (*iter)->clearStats(); + } +} + + +struct LLGLSLShaderCompareTimeElapsed +{ + bool operator()(const LLGLSLShader* const& lhs, const LLGLSLShader* const& rhs) + { + return lhs->mTimeElapsed < rhs->mTimeElapsed; + } +}; + +//static +void LLGLSLShader::finishProfile(bool emit_report) +{ + sProfileEnabled = false; + + if (emit_report) + { + std::vector sorted; + + for (std::set::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) + { + sorted.push_back(*iter); + } + + std::sort(sorted.begin(), sorted.end(), LLGLSLShaderCompareTimeElapsed()); + + for (std::vector::iterator iter = sorted.begin(); iter != sorted.end(); ++iter) + { + (*iter)->dumpStats(); + } + + LL_INFOS() << "-----------------------------------" << LL_ENDL; + LL_INFOS() << "Total rendering time: " << llformat("%.4f ms", sTotalTimeElapsed/1000000.f) << LL_ENDL; + LL_INFOS() << "Total samples drawn: " << llformat("%.4f million", sTotalSamplesDrawn/1000000.f) << LL_ENDL; + LL_INFOS() << "Total triangles drawn: " << llformat("%.3f million", sTotalTrianglesDrawn/1000000.f) << LL_ENDL; + } +} + +void LLGLSLShader::clearStats() +{ + mTrianglesDrawn = 0; + mTimeElapsed = 0; + mSamplesDrawn = 0; + mDrawCalls = 0; + mTextureStateFetched = false; + mTextureMagFilter.clear(); + mTextureMinFilter.clear(); +} + +void LLGLSLShader::dumpStats() +{ + if (mDrawCalls > 0) + { + LL_INFOS() << "=============================================" << LL_ENDL; + LL_INFOS() << mName << LL_ENDL; + for (U32 i = 0; i < mShaderFiles.size(); ++i) + { + LL_INFOS() << mShaderFiles[i].first << LL_ENDL; + } + for (U32 i = 0; i < mTexture.size(); ++i) + { + GLint idx = mTexture[i]; + + if (idx >= 0) + { + GLint uniform_idx = getUniformLocation(i); + LL_INFOS() << mUniformNameMap[uniform_idx] << " - " << std::hex << mTextureMagFilter[i] << "/" << mTextureMinFilter[i] << std::dec << LL_ENDL; + } + } + LL_INFOS() << "=============================================" << LL_ENDL; + + F32 ms = mTimeElapsed/1000000.f; + F32 seconds = ms/1000.f; + + F32 pct_tris = (F32) mTrianglesDrawn/(F32)sTotalTrianglesDrawn*100.f; + F32 tris_sec = (F32) (mTrianglesDrawn/1000000.0); + tris_sec /= seconds; + + F32 pct_samples = (F32) ((F64)mSamplesDrawn/(F64)sTotalSamplesDrawn)*100.f; + F32 samples_sec = (F32) mSamplesDrawn/1000000000.0; + samples_sec /= seconds; + + F32 pct_calls = (F32) mDrawCalls/(F32)sTotalDrawCalls*100.f; + U32 avg_batch = mTrianglesDrawn/mDrawCalls; + + LL_INFOS() << "Triangles Drawn: " << mTrianglesDrawn << " " << llformat("(%.2f pct of total, %.3f million/sec)", pct_tris, tris_sec ) << LL_ENDL; + LL_INFOS() << "Draw Calls: " << mDrawCalls << " " << llformat("(%.2f pct of total, avg %d tris/call)", pct_calls, avg_batch) << LL_ENDL; + LL_INFOS() << "SamplesDrawn: " << mSamplesDrawn << " " << llformat("(%.2f pct of total, %.3f billion/sec)", pct_samples, samples_sec) << LL_ENDL; + LL_INFOS() << "Time Elapsed: " << mTimeElapsed << " " << llformat("(%.2f pct of total, %.5f ms)\n", (F32) ((F64)mTimeElapsed/(F64)sTotalTimeElapsed)*100.f, ms) << LL_ENDL; + } +} + +//static +void LLGLSLShader::startProfile() +{ + if (sProfileEnabled && sCurBoundShaderPtr) + { + sCurBoundShaderPtr->placeProfileQuery(); + } + +} + +//static +void LLGLSLShader::stopProfile(U32 count, U32 mode) +{ + if (sProfileEnabled && sCurBoundShaderPtr) + { + sCurBoundShaderPtr->readProfileQuery(count, mode); + } +} + +void LLGLSLShader::placeProfileQuery() +{ +#if !LL_DARWIN + if (mTimerQuery == 0) + { + glGenQueriesARB(1, &mSamplesQuery); + glGenQueriesARB(1, &mTimerQuery); + } + + if (!mTextureStateFetched) + { + mTextureStateFetched = true; + mTextureMagFilter.resize(mTexture.size()); + mTextureMinFilter.resize(mTexture.size()); + + U32 cur_active = gGL.getCurrentTexUnitIndex(); + + for (U32 i = 0; i < mTexture.size(); ++i) + { + GLint idx = mTexture[i]; + + if (idx >= 0) + { + gGL.getTexUnit(idx)->activate(); + + U32 mag = 0xFFFFFFFF; + U32 min = 0xFFFFFFFF; + + U32 type = LLTexUnit::getInternalType(gGL.getTexUnit(idx)->getCurrType()); + + glGetTexParameteriv(type, GL_TEXTURE_MAG_FILTER, (GLint*) &mag); + glGetTexParameteriv(type, GL_TEXTURE_MIN_FILTER, (GLint*) &min); + + mTextureMagFilter[i] = mag; + mTextureMinFilter[i] = min; + } + } + + gGL.getTexUnit(cur_active)->activate(); + } + + + glBeginQueryARB(GL_SAMPLES_PASSED, mSamplesQuery); + glBeginQueryARB(GL_TIME_ELAPSED, mTimerQuery); +#endif +} + +void LLGLSLShader::readProfileQuery(U32 count, U32 mode) +{ +#if !LL_DARWIN + glEndQueryARB(GL_TIME_ELAPSED); + glEndQueryARB(GL_SAMPLES_PASSED); + + GLuint64 time_elapsed = 0; + glGetQueryObjectui64vEXT(mTimerQuery, GL_QUERY_RESULT, &time_elapsed); + + GLuint64 samples_passed = 0; + glGetQueryObjectui64vEXT(mSamplesQuery, GL_QUERY_RESULT, &samples_passed); + + sTotalTimeElapsed += time_elapsed; + mTimeElapsed += time_elapsed; + + sTotalSamplesDrawn += samples_passed; + mSamplesDrawn += samples_passed; + + U32 tri_count = 0; + switch (mode) + { + case LLRender::TRIANGLES: tri_count = count/3; break; + case LLRender::TRIANGLE_FAN: tri_count = count-2; break; + case LLRender::TRIANGLE_STRIP: tri_count = count-2; break; + default: tri_count = count; break; //points lines etc just use primitive count + } + + mTrianglesDrawn += tri_count; + sTotalTrianglesDrawn += tri_count; + + sTotalDrawCalls++; + mDrawCalls++; +#endif +} LLGLSLShader::LLGLSLShader(S32 shader_class) : mProgramObject(0), mShaderClass(shader_class), @@ -91,20 +310,25 @@ LLGLSLShader::LLGLSLShader(S32 shader_class) mTotalUniformSize(0), mActiveTextureChannels(0), mShaderLevel(0), - mShaderGroup(SG_DEFAULT), - mUniformsDirty(FALSE) + mShaderGroup(SG_DEFAULT), + mUniformsDirty(FALSE), + mTimerQuery(0), + mSamplesQuery(0) + { LLShaderMgr::getGlobalShaderList().push_back(this); } LLGLSLShader::~LLGLSLShader() -{ - +{ } + void LLGLSLShader::unload() { - stop_glerror(); - mAttribute.clear(); + sInstances.erase(this); + + stop_glerror(); + mAttribute.clear(); mTexture.clear(); mUniform.clear(); mShaderFiles.clear(); @@ -126,10 +350,22 @@ void LLGLSLShader::unload() glDeleteObjectARB(mProgramObject); mProgramObject = 0; } - - //hack to make apple not complain - glGetError(); - + + if (mTimerQuery) + { + glDeleteQueriesARB(1, &mTimerQuery); + mTimerQuery = 0; + } + + if (mSamplesQuery) + { + glDeleteQueriesARB(1, &mSamplesQuery); + mSamplesQuery = 0; + } + + //hack to make apple not complain + glGetError(); + stop_glerror(); } @@ -138,9 +374,11 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, U32 varying_count, const char** varyings) { - //reloading, reset matrix hash values - for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) - { + sInstances.insert(this); + + //reloading, reset matrix hash values + for (U32 i = 0; i < LLRender::NUM_MATRIX_MODES; ++i) + { mMatHash[i] = 0xFFFFFFFF; } mLightHash = 0xFFFFFFFF; @@ -243,9 +481,18 @@ BOOL LLGLSLShader::createShader(std::vector * attributes, } } unbind(); - } + } - return success; + if (LLShaderMgr::instance()->mProgramObjects.find(mName) == LLShaderMgr::instance()->mProgramObjects.end()) + { + LLShaderMgr::instance()->mProgramObjects.emplace(mName, mProgramObject); + } + else + { + LL_WARNS("ShaderLoading") << "Attempting to create shader program with duplicate name: " << mName << LL_ENDL; + } + + return success; } BOOL LLGLSLShader::attachObject(std::string object) @@ -425,6 +672,7 @@ void LLGLSLShader::mapUniform(GLint index, const vector * } LLStaticHashedString hashedName(name); + mUniformNameMap[location] = name; mUniformMap[hashedName] = location; LL_DEBUGS("ShaderLoading") << "Uniform " << name << " is at location " << location << LL_ENDL; @@ -489,6 +737,7 @@ BOOL LLGLSLShader::mapUniforms(const vector * uniforms) mActiveTextureChannels = 0; mUniform.clear(); mUniformMap.clear(); + mUniformNameMap.clear(); mTexture.clear(); mValueVec4.clear(); mValueMat3.clear(); diff --git a/indra/llrender/llglslshader.h b/indra/llrender/llglslshader.h index e57ac1702..050af2a1e 100644 --- a/indra/llrender/llglslshader.h +++ b/indra/llrender/llglslshader.h @@ -56,6 +56,7 @@ public: S32 mIndexedTextureChannels; bool disableTextureIndex; bool hasAlphaMask; + bool attachNothing; // char numLights; @@ -73,6 +74,9 @@ public: SG_WATER }; + static std::set sInstances; + static bool sProfileEnabled; + LLGLSLShader(S32 shader_class); ~LLGLSLShader(); @@ -81,7 +85,18 @@ public: static S32 sIndexedTextureChannels; static bool sNoFixedFunction; + static void initProfile(); + static void finishProfile(bool emit_report = true); + + static void startProfile(); + static void stopProfile(U32 count, U32 mode); + void unload(); + void clearStats(); + void dumpStats(); + void placeProfileQuery(); + void readProfileQuery(U32 count, U32 mode); + BOOL createShader(std::vector * attributes, std::vector * uniforms, U32 varying_count = 0, @@ -379,6 +394,7 @@ public: U32 mAttributeMask; //mask of which reserved attributes are set (lines up with LLVertexBuffer::getTypeMask()) std::vector mUniform; //lookup table of uniform enum to uniform location LLStaticStringTable mUniformMap; //lookup map of uniform name to uniform location + std::map mUniformNameMap; //lookup map of uniform location to uniform name //There are less naive ways to do this than just having several vectors for the differing types, but this method is of least complexity and has some inherent type-safety. std::vector > mValueVec4; //lookup map of uniform location to last known value std::vector > mValueMat3; //lookup map of uniform location to last known value @@ -395,6 +411,23 @@ public: std::vector< std::pair< std::string, GLenum > > mShaderFiles; std::string mName; std::map mDefines; + + //statistcis for profiling shader performance + U32 mTimerQuery; + U32 mSamplesQuery; + U64 mTimeElapsed; + static U64 sTotalTimeElapsed; + U32 mTrianglesDrawn; + static U32 sTotalTrianglesDrawn; + U64 mSamplesDrawn; + static U64 sTotalSamplesDrawn; + U32 mDrawCalls; + static U32 sTotalDrawCalls; + + bool mTextureStateFetched; + std::vector mTextureMagFilter; + std::vector mTextureMinFilter; + }; //UI shader (declared here so llui_libtest will link properly) diff --git a/indra/llrender/llgltexture.cpp b/indra/llrender/llgltexture.cpp index 5154a854f..aa1e4371a 100644 --- a/indra/llrender/llgltexture.cpp +++ b/indra/llrender/llgltexture.cpp @@ -298,7 +298,7 @@ LLTexUnit::eTextureAddressMode LLGLTexture::getAddressMode(void) const return mGLTexturep->getAddressMode() ; } -S32 LLGLTexture::getTextureMemory() const +S32Bytes LLGLTexture::getTextureMemory() const { llassert(mGLTexturep.notNull()) ; diff --git a/indra/llrender/llgltexture.h b/indra/llrender/llgltexture.h index 1b6107858..a27fcb630 100644 --- a/indra/llrender/llgltexture.h +++ b/indra/llrender/llgltexture.h @@ -138,7 +138,7 @@ public: S32 getDiscardLevel() const; S8 getComponents() const; BOOL getBoundRecently() const; - S32 getTextureMemory() const ; + S32Bytes getTextureMemory() const ; LLGLenum getPrimaryFormat() const; BOOL getIsAlphaMask(const F32 max_rmse) const ; LLTexUnit::eTextureType getTarget(void) const ; diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 68ff5d6a0..4d0e0b03c 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -50,9 +50,9 @@ U32 wpo2(U32 i); U32 LLImageGL::sUniqueCount = 0; U32 LLImageGL::sBindCount = 0; -S32 LLImageGL::sGlobalTextureMemoryInBytes = 0; -S32 LLImageGL::sBoundTextureMemoryInBytes = 0; -S32 LLImageGL::sCurBoundTextureMemory = 0; +S32Bytes LLImageGL::sGlobalTextureMemory(0); +S32Bytes LLImageGL::sBoundTextureMemory(0); +S32Bytes LLImageGL::sCurBoundTextureMemory(0); S32 LLImageGL::sCount = 0; BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; @@ -78,9 +78,9 @@ S32 LLImageGL::sCurTexPickSize = -1 ; LLPointer LLImageGL::sHighlightTexturep = NULL; S32 LLImageGL::sMaxCategories = 1 ; -std::vector LLImageGL::sTextureMemByCategory; -std::vector LLImageGL::sTextureMemByCategoryBound ; -std::vector LLImageGL::sTextureCurMemByCategoryBound ; +std::vector LLImageGL::sTextureMemByCategory; +std::vector LLImageGL::sTextureMemByCategoryBound ; +std::vector LLImageGL::sTextureCurMemByCategoryBound ; //------------------------ // **************************************************************************************************** //End for texture auditing use only @@ -292,8 +292,8 @@ void LLImageGL::updateStats(F32 current_time) { LLFastTimer t(FTM_IMAGE_UPDATE_STATS); sLastFrameTime = current_time; - sBoundTextureMemoryInBytes = sCurBoundTextureMemory; - sCurBoundTextureMemory = 0; + sBoundTextureMemory = sCurBoundTextureMemory; + sCurBoundTextureMemory = S32Bytes(0); if(gAuditTexture) { @@ -305,22 +305,22 @@ void LLImageGL::updateStats(F32 current_time) for(U32 i = 0 ; i < sTextureCurMemByCategoryBound.size() ; i++) { sTextureMemByCategoryBound[i] = sTextureCurMemByCategoryBound[i] ; - sTextureCurMemByCategoryBound[i] = 0 ; + sTextureCurMemByCategoryBound[i] = (S32Bytes)0 ; } } } //static -S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) +S32 LLImageGL::updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) { if(gAuditTexture && ncomponents > 0 && category > -1) { - sTextureCurBoundCounter[getTextureCounterIndex(mem / ncomponents)]++ ; + sTextureCurBoundCounter[getTextureCounterIndex(mem.value() / ncomponents)]++ ; sTextureCurMemByCategoryBound[category] += mem ; } LLImageGL::sCurBoundTextureMemory += mem ; - return LLImageGL::sCurBoundTextureMemory; + return LLImageGL::sCurBoundTextureMemory.value(); } //---------------------------------------------------------------------------- @@ -480,7 +480,7 @@ void LLImageGL::init(BOOL usemipmaps) // so that it is obvious by visual inspection if we forgot to // init a field. - mTextureMemory = 0; + mTextureMemory = (S32Bytes)0; mLastBindTime = 0.f; mPickMask = NULL; @@ -644,7 +644,7 @@ void LLImageGL::forceUpdateBindStats(void) const mLastBindTime = sLastFrameTime; } -BOOL LLImageGL::updateBindStats(S32 tex_mem) const +BOOL LLImageGL::updateBindStats(S32Bytes tex_mem) const { if (mTexName != 0) { @@ -1677,7 +1677,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ if (old_name != 0) { - sGlobalTextureMemoryInBytes -= mTextureMemory; + sGlobalTextureMemory -= mTextureMemory; if(gAuditTexture) { @@ -1689,8 +1689,8 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ stop_glerror(); } - mTextureMemory = getMipBytes(discard_level); - sGlobalTextureMemoryInBytes += mTextureMemory; + mTextureMemory = (S32Bytes)getMipBytes(discard_level); + sGlobalTextureMemory += mTextureMemory; if(gAuditTexture) { @@ -1829,14 +1829,14 @@ void LLImageGL::destroyGLTexture() { if (mTexName != 0) { - if(mTextureMemory) + if(mTextureMemory != S32Bytes(0)) { if(gAuditTexture) { decTextureCounter(mTextureMemory, mComponents, mCategory) ; } - sGlobalTextureMemoryInBytes -= mTextureMemory; - mTextureMemory = 0; + sGlobalTextureMemory -= mTextureMemory; + mTextureMemory = (S32Bytes)0; } LLImageGL::deleteTextures(1, &mTexName); @@ -2204,26 +2204,10 @@ void LLImageGL::analyzeAlpha(const void* data_in, U32 w, U32 h) } //---------------------------------------------------------------------------- -void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) +U32 LLImageGL::createPickMask(S32 pWidth, S32 pHeight) { - if(!mNeedsAlphaAndPickMask) - { - return ; - } - - delete [] mPickMask; - mPickMask = NULL; - mPickMaskWidth = mPickMaskHeight = 0; - - if (mFormatType != GL_UNSIGNED_BYTE || - mFormatPrimary != GL_RGBA) - { - //cannot generate a pick mask for this texture - return; - } - - U32 pick_width = width/2 + 1; - U32 pick_height = height/2 + 1; + U32 pick_width = pWidth/2 + 1; + U32 pick_height = pHeight/2 + 1; U32 size = pick_width * pick_height; size = (size + 7) / 8; // pixelcount-to-bits @@ -2233,6 +2217,44 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) memset(mPickMask, 0, sizeof(U8) * size); + return size; +} + +//---------------------------------------------------------------------------- +void LLImageGL::freePickMask() +{ + // pickmask validity depends on old image size, delete it + if (mPickMask != NULL) + { + delete [] mPickMask; + } + mPickMask = NULL; + mPickMaskWidth = mPickMaskHeight = 0; +} + +//---------------------------------------------------------------------------- +void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) +{ + if(!mNeedsAlphaAndPickMask) + { + return ; + } + + freePickMask(); + + if (mFormatType != GL_UNSIGNED_BYTE || + mFormatPrimary != GL_RGBA) + { + //cannot generate a pick mask for this texture + return; + } + +#ifdef SHOW_ASSERT + const U32 pickSize = createPickMask(width, height); +#else // SHOW_ASSERT + createPickMask(width, height); +#endif // SHOW_ASSERT + U32 pick_bit = 0; for (S32 y = 0; y < height; y += 2) @@ -2245,7 +2267,7 @@ void LLImageGL::updatePickMask(S32 width, S32 height, const U8* data_in) { U32 pick_idx = pick_bit/8; U32 pick_offset = pick_bit%8; - llassert(pick_idx < size); + llassert(pick_idx < pickSize); mPickMask[pick_idx] |= 1 << pick_offset; } @@ -2356,19 +2378,19 @@ S32 LLImageGL::getTextureCounterIndex(U32 val) } //static -void LLImageGL::incTextureCounter(U32 val, S32 ncomponents, S32 category) +void LLImageGL::incTextureCounter(S32Bytes val, S32 ncomponents, S32 category) { - sTextureLoadedCounter[getTextureCounterIndex(val)]++ ; + sTextureLoadedCounter[getTextureCounterIndex(val.value())]++ ; if(category > -1) - sTextureMemByCategory[category] += (S32)val * ncomponents ; + sTextureMemByCategory[category] += (S32Bytes)val * ncomponents ; } //static -void LLImageGL::decTextureCounter(U32 val, S32 ncomponents, S32 category) +void LLImageGL::decTextureCounter(S32Bytes val, S32 ncomponents, S32 category) { - sTextureLoadedCounter[getTextureCounterIndex(val)]-- ; + sTextureLoadedCounter[getTextureCounterIndex(val.value())]-- ; if(category > -1) - sTextureMemByCategory[category] -= (S32)val * ncomponents ; + sTextureMemByCategory[category] -= (S32Bytes)val * ncomponents ; } void LLImageGL::setCurTexSizebar(S32 index, BOOL set_pick_size) diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index ecb5222de..623013678 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -34,6 +34,7 @@ #include "llpointer.h" #include "llrefcount.h" #include "v2math.h" +#include "llunits.h" #include "llrender.h" @@ -55,7 +56,7 @@ public: static S32 dataFormatBytes(S32 dataformat, S32 width, S32 height); static S32 dataFormatComponents(S32 dataformat); - BOOL updateBindStats(S32 tex_mem) const ; + BOOL updateBindStats(S32Bytes tex_mem) const ; F32 getTimePassedSinceLastBound(); void forceUpdateBindStats(void) const; @@ -68,7 +69,7 @@ public: static void dirtyTexOptions(); // Sometimes called externally for textures not using LLImageGL (should go away...) - static S32 updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) ; + static S32 updateBoundTexMem(const S32Bytes mem, const S32 ncomponents, S32 category) ; static bool checkSize(S32 width, S32 height); @@ -172,10 +173,13 @@ public: void setNeedsAlphaAndPickMask(BOOL need_mask); public: // Various GL/Rendering options - S32 mTextureMemory; + S32Bytes mTextureMemory; mutable F32 mLastBindTime; // last time this was bound, by discard level private: + U32 createPickMask(S32 pWidth, S32 pHeight); + void freePickMask(); + LLPointer mSaveData; // used for destroyGL/restoreGL S32 mSaveDiscardLevel; U8* mPickMask; //downsampled bitmap approximation of alpha channel. NULL if no alpha channel @@ -228,9 +232,9 @@ public: static F32 sLastFrameTime; // Global memory statistics - static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem - static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame - static S32 sCurBoundTextureMemory; // Tracks bound texmem for current frame + static S32Bytes sGlobalTextureMemory; // Tracks main memory texmem + static S32Bytes sBoundTextureMemory; // Tracks bound texmem for last completed frame + static S32Bytes sCurBoundTextureMemory; // Tracks bound texmem for current frame static U32 sBindCount; // Tracks number of texture binds for current frame static U32 sUniqueCount; // Tracks number of unique texture binds for current frame static BOOL sGlobalUseAnisotropic; @@ -274,8 +278,8 @@ public: static void setHighlightTexture(S32 category) ; static S32 getTextureCounterIndex(U32 val) ; - static void incTextureCounter(U32 val, S32 ncomponents, S32 category) ; - static void decTextureCounter(U32 val, S32 ncomponents, S32 category) ; + static void incTextureCounter(S32Bytes val, S32 ncomponents, S32 category) ; + static void decTextureCounter(S32Bytes val, S32 ncomponents, S32 category) ; static void setCurTexSizebar(S32 index, BOOL set_pick_size = TRUE) ; static void resetCurTexSizebar(); //---------------------------------------- @@ -283,9 +287,9 @@ public: //for debug use: show texture category distribution //---------------------------------------- - static std::vector sTextureMemByCategory; - static std::vector sTextureMemByCategoryBound ; - static std::vector sTextureCurMemByCategoryBound ; + static std::vector sTextureMemByCategory; + static std::vector sTextureMemByCategoryBound ; + static std::vector sTextureCurMemByCategoryBound ; //---------------------------------------- // **************************************************************************************************** //End of definitions for texture auditing use only diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index b8a723415..1d42d0cf5 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -56,7 +56,7 @@ bool LLRender::sGLCoreProfile = false; static const U32 LL_NUM_TEXTURE_LAYERS = 32; static const U32 LL_NUM_LIGHT_UNITS = 8; -static GLenum sGLTextureType[] = +static const GLenum sGLTextureType[] = { GL_TEXTURE_2D, GL_TEXTURE_RECTANGLE_ARB, @@ -64,14 +64,14 @@ static GLenum sGLTextureType[] = //,GL_TEXTURE_2D_MULTISAMPLE Don't use. }; -static GLint sGLAddressMode[] = +static const GLint sGLAddressMode[] = { GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_EDGE }; -static GLenum sGLCompareFunc[] = +static const GLenum sGLCompareFunc[] = { GL_NEVER, GL_ALWAYS, @@ -85,7 +85,7 @@ static GLenum sGLCompareFunc[] = const U32 immediate_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_COLOR | LLVertexBuffer::MAP_TEXCOORD0; -static GLenum sGLBlendFactor[] = +static const GLenum sGLBlendFactor[] = { GL_ONE, GL_ZERO, @@ -102,15 +102,15 @@ static GLenum sGLBlendFactor[] = }; LLTexUnit::LLTexUnit(S32 index) -: mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT), -mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT), -mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), -mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), -mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), -mHasMipMaps(false) + : mCurrTexType(TT_NONE), mCurrBlendType(TB_MULT), + mCurrColorOp(TBO_MULT), mCurrAlphaOp(TBO_MULT), + mCurrColorSrc1(TBS_TEX_COLOR), mCurrColorSrc2(TBS_PREV_COLOR), + mCurrAlphaSrc1(TBS_TEX_ALPHA), mCurrAlphaSrc2(TBS_PREV_ALPHA), + mCurrColorScale(1), mCurrAlphaScale(1), mCurrTexture(0), + mHasMipMaps(false), + mIndex(index) { llassert_always(index < (S32)LL_NUM_TEXTURE_LAYERS); - mIndex = index; } //static @@ -228,53 +228,66 @@ void LLTexUnit::disable(void) bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) { stop_glerror(); - if (mIndex < 0) return false; - - LLImageGL* gl_tex = NULL ; - if (texture == NULL || !(gl_tex = texture->getGLTexture())) + if (mIndex >= 0) { - LL_WARNS() << "NULL LLTexUnit::bind texture" << LL_ENDL; + gGL.flush(); + + LLImageGL* gl_tex = NULL ; + + if (texture != NULL && (gl_tex = texture->getGLTexture())) + { + if (gl_tex->getTexName()) //if texture exists + { + //in audit, replace the selected texture by the default one. + if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0) + { + if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize) + { + gl_tex->updateBindStats(gl_tex->mTextureMemory); + return bind(LLImageGL::sHighlightTexturep.get()); + } + } + if ((mCurrTexture != gl_tex->getTexName()) || forceBind) + { + gGL.flush(); + activate(); + enable(gl_tex->getTarget()); + mCurrTexture = gl_tex->getTexName(); + glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); + if(gl_tex->updateBindStats(gl_tex->mTextureMemory)) + { + texture->setActive() ; + texture->updateBindStatsForTester() ; + } + mHasMipMaps = gl_tex->mHasMipMaps; + if (gl_tex->mTexOptionsDirty) + { + gl_tex->mTexOptionsDirty = false; + setTextureAddressMode(gl_tex->mAddressMode); + setTextureFilteringOption(gl_tex->mFilterOption); + } + } + } + else + { + //if deleted, will re-generate it immediately + texture->forceImmediateUpdate() ; + + gl_tex->forceUpdateBindStats() ; + return texture->bindDefaultImage(mIndex); + } + } + else + { + LL_WARNS() << "NULL LLTexUnit::bind texture" << LL_ENDL; + return false; + } + } + else + { // mIndex < 0 return false; } - if (!gl_tex->getTexName()) //if texture does not exist - { - //if deleted, will re-generate it immediately - texture->forceImmediateUpdate() ; - - gl_tex->forceUpdateBindStats() ; - return texture->bindDefaultImage(mIndex); - } - - //in audit, replace the selected texture by the default one. - if(gAuditTexture && for_rendering && LLImageGL::sCurTexPickSize > 0) - { - if(texture->getWidth() * texture->getHeight() == LLImageGL::sCurTexPickSize) - { - gl_tex->updateBindStats(gl_tex->mTextureMemory); - return bind(LLImageGL::sHighlightTexturep.get()); - } - } - if ((mCurrTexture != gl_tex->getTexName()) || forceBind) - { - gGL.flush(); - activate(); - enable(gl_tex->getTarget()); - mCurrTexture = gl_tex->getTexName(); - glBindTexture(sGLTextureType[gl_tex->getTarget()], mCurrTexture); - if(gl_tex->updateBindStats(gl_tex->mTextureMemory)) - { - texture->setActive() ; - texture->updateBindStatsForTester() ; - } - mHasMipMaps = gl_tex->mHasMipMaps; - if (gl_tex->mTexOptionsDirty) - { - gl_tex->mTexOptionsDirty = false; - setTextureAddressMode(gl_tex->mAddressMode); - setTextureFilteringOption(gl_tex->mFilterOption); - } - } return true; } @@ -1763,7 +1776,7 @@ void LLRender::pushUIMatrix() { if (mUIOffset.empty()) { - mUIOffset.push_back(LLVector4a(0.f)); + mUIOffset.emplace_back(LLVector4a(0.f)); } else { @@ -1772,7 +1785,7 @@ void LLRender::pushUIMatrix() if (mUIScale.empty()) { - mUIScale.push_back(LLVector4a(1.f)); + mUIScale.emplace_back(LLVector4a(1.f)); } else { @@ -1782,9 +1795,9 @@ void LLRender::pushUIMatrix() void LLRender::popUIMatrix() { - if (mUIOffset.empty()) + if (mUIOffset.empty() || mUIScale.empty()) { - LL_ERRS() << "UI offset stack blown." << LL_ENDL; + LL_ERRS() << "UI offset or scale stack blown." << LL_ENDL; } mUIOffset.pop_back(); mUIScale.pop_back(); diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index cdadd5b03..1b1de7640 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -38,12 +38,13 @@ #include "v3math.h" #include "v4coloru.h" #include "v4math.h" -#include "llmatrix4a.h" -#include "llalignedarray.h" #include "llstrider.h" #include "llpointer.h" #include "llglheaders.h" +#include "llmatrix4a.h" #include "llrect.h" +#include "llvector4a.h" +#include class LLVertexBuffer; class LLCubeMap; @@ -200,7 +201,7 @@ public: void setHasMipMaps(bool hasMips) { mHasMipMaps = hasMips; } protected: - S32 mIndex; + const S32 mIndex; U32 mCurrTexture; eTextureType mCurrTexType; eTextureBlendType mCurrBlendType; @@ -493,8 +494,8 @@ private: F32 mMaxAnisotropy; - LLAlignedArray mUIOffset; - LLAlignedArray mUIScale; + std::vector > mUIOffset; + std::vector > mUIScale; } LL_ALIGN_POSTFIX(16); diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index cc447d870..628b3e705 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -348,6 +348,11 @@ void gl_draw_image( S32 x, S32 y, LLTexture* image, const LLColor4& color, const gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), 0.f, image, color, uv_rect ); } +void gl_draw_scaled_target(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* target, const LLColor4& color, const LLRectf& uv_rect) +{ + gl_draw_scaled_rotated_image(x, y, width, height, 0.f, NULL, color, uv_rect, target); +} + void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) { if (NULL == image) @@ -358,7 +363,7 @@ void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, gl_draw_scaled_rotated_image( x, y, width, height, 0.f, image, color, uv_rect ); } -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect) +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_rect, bool scale_inner) { if (NULL == image) { @@ -371,10 +376,10 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border F32 border_height_fraction = (F32)border_height / (F32)image->getHeight(0); LLRectf scale_rect(border_width_fraction, 1.f - border_height_fraction, 1.f - border_width_fraction, border_height_fraction); - gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect); + gl_draw_scaled_image_with_border(x, y, width, height, image, color, solid_color, uv_rect, scale_rect, scale_inner); } -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect) +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color, BOOL solid_color, const LLRectf& uv_outer_rect, const LLRectf& center_rect, bool scale_inner) { stop_glerror(); @@ -384,56 +389,6 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex return; } - // add in offset of current image to current UI translation - const LLVector3 ui_scale = gGL.getUIScale(); - const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); - - F32 uv_width = uv_outer_rect.getWidth(); - F32 uv_height = uv_outer_rect.getHeight(); - - // shrink scaling region to be proportional to clipped image region - LLRectf uv_center_rect( - uv_outer_rect.mLeft + (center_rect.mLeft * uv_width), - uv_outer_rect.mBottom + (center_rect.mTop * uv_height), - uv_outer_rect.mLeft + (center_rect.mRight * uv_width), - uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); - - F32 image_width = image->getWidth(0); - F32 image_height = image->getHeight(0); - - S32 image_natural_width = ll_round(image_width * uv_width); - S32 image_natural_height = ll_round(image_height * uv_height); - - LLRectf draw_center_rect( uv_center_rect.mLeft * image_width, - uv_center_rect.mTop * image_height, - uv_center_rect.mRight * image_width, - uv_center_rect.mBottom * image_height); - - { // scale fixed region of image to drawn region - draw_center_rect.mRight += width - image_natural_width; - draw_center_rect.mTop += height - image_natural_height; - - F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight); - F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop); - - F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth())); - F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight())); - - F32 shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); - - draw_center_rect.mLeft = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * shrink_scale * ui_scale.mV[VX]); - draw_center_rect.mTop = ll_round(ui_translation.mV[VY] + lerp((F32)height, (F32)draw_center_rect.mTop, shrink_scale) * ui_scale.mV[VY]); - draw_center_rect.mRight = ll_round(ui_translation.mV[VX] + lerp((F32)width, (F32)draw_center_rect.mRight, shrink_scale) * ui_scale.mV[VX]); - draw_center_rect.mBottom = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * shrink_scale * ui_scale.mV[VY]); - } - - LLRectf draw_outer_rect(ui_translation.mV[VX], - ui_translation.mV[VY] + height * ui_scale.mV[VY], - ui_translation.mV[VX] + width * ui_scale.mV[VX], - ui_translation.mV[VY]); - - LLGLSUIDefault gls_ui; - if (solid_color) { if (LLGLSLShader::sNoFixedFunction) @@ -447,7 +402,79 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex } } - gGL.getTexUnit(0)->bind(image, true); + if (center_rect.mLeft == 0.f + && center_rect.mRight == 1.f + && center_rect.mBottom == 0.f + && center_rect.mTop == 1.f) + { + gl_draw_scaled_image(x, y, width, height, image, color, uv_outer_rect); + } + else + { + // add in offset of current image to current UI translation + const LLVector3 ui_scale = gGL.getUIScale(); + const LLVector3 ui_translation = (gGL.getUITranslation() + LLVector3(x, y, 0.f)).scaledVec(ui_scale); + + F32 uv_width = uv_outer_rect.getWidth(); + F32 uv_height = uv_outer_rect.getHeight(); + + // shrink scaling region to be proportional to clipped image region + LLRectf uv_center_rect( uv_outer_rect.mLeft + (center_rect.mLeft * uv_width), + uv_outer_rect.mBottom + (center_rect.mTop * uv_height), + uv_outer_rect.mLeft + (center_rect.mRight * uv_width), + uv_outer_rect.mBottom + (center_rect.mBottom * uv_height)); + + F32 image_width = image->getWidth(0); + F32 image_height = image->getHeight(0); + + S32 image_natural_width = ll_round(image_width * uv_width); + S32 image_natural_height = ll_round(image_height * uv_height); + + LLRectf draw_center_rect( uv_center_rect.mLeft * image_width, + uv_center_rect.mTop * image_height, + uv_center_rect.mRight * image_width, + uv_center_rect.mBottom * image_height); + + if (scale_inner) + { + // scale center region of image to drawn region + draw_center_rect.mRight += width - image_natural_width; + draw_center_rect.mTop += height - image_natural_height; + + const F32 border_shrink_width = llmax(0.f, draw_center_rect.mLeft - draw_center_rect.mRight); + const F32 border_shrink_height = llmax(0.f, draw_center_rect.mBottom - draw_center_rect.mTop); + + const F32 shrink_width_ratio = center_rect.getWidth() == 1.f ? 0.f : border_shrink_width / ((F32)image_natural_width * (1.f - center_rect.getWidth())); + const F32 shrink_height_ratio = center_rect.getHeight() == 1.f ? 0.f : border_shrink_height / ((F32)image_natural_height * (1.f - center_rect.getHeight())); + + const F32 border_shrink_scale = 1.f - llmax(shrink_width_ratio, shrink_height_ratio); + draw_center_rect.mLeft *= border_shrink_scale; + draw_center_rect.mTop = lerp((F32)height, (F32)draw_center_rect.mTop, border_shrink_scale); + draw_center_rect.mRight = lerp((F32)width, (F32)draw_center_rect.mRight, border_shrink_scale); + draw_center_rect.mBottom *= border_shrink_scale; + } + else + { + // keep center region of image at fixed scale, but in same relative position + F32 scale_factor = llmin((F32)width / draw_center_rect.getWidth(), (F32)height / draw_center_rect.getHeight(), 1.f); + F32 scaled_width = draw_center_rect.getWidth() * scale_factor; + F32 scaled_height = draw_center_rect.getHeight() * scale_factor; + draw_center_rect.setCenterAndSize(uv_center_rect.getCenterX() * width, uv_center_rect.getCenterY() * height, scaled_width, scaled_height); + } + + draw_center_rect.mLeft = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mLeft * ui_scale.mV[VX]); + draw_center_rect.mTop = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mTop * ui_scale.mV[VY]); + draw_center_rect.mRight = ll_round(ui_translation.mV[VX] + (F32)draw_center_rect.mRight * ui_scale.mV[VX]); + draw_center_rect.mBottom = ll_round(ui_translation.mV[VY] + (F32)draw_center_rect.mBottom * ui_scale.mV[VY]); + + LLRectf draw_outer_rect(ui_translation.mV[VX], + ui_translation.mV[VY] + height * ui_scale.mV[VY], + ui_translation.mV[VX] + width * ui_scale.mV[VX], + ui_translation.mV[VY]); + + LLGLSUIDefault gls_ui; + + gGL.getTexUnit(0)->bind(image, true); gGL.color4fv(color.mV); gGL.diffuseColor4fv(color.mV); //workaround: Intel HD 4000 @@ -611,11 +638,12 @@ void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTex uv[index] = LLVector2(uv_center_rect.mRight, uv_outer_rect.mTop); pos[index].set(draw_center_rect.mRight, draw_outer_rect.mTop, 0.f); - index++; + index++; - gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); + gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); + } + gGL.end(); } - gGL.end(); if (solid_color) { @@ -635,9 +663,9 @@ void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LL gl_draw_scaled_rotated_image( x, y, image->getWidth(0), image->getHeight(0), degrees, image, color, uv_rect ); } -void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect) +void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color, const LLRectf& uv_rect, LLRenderTarget* target) { - if (NULL == image) + if (!image && !target) { LL_WARNS() << "image == NULL; aborting function" << LL_ENDL; return; @@ -645,8 +673,14 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre LLGLSUIDefault gls_ui; - - gGL.getTexUnit(0)->bind(image, true); + if(image != NULL) + { + gGL.getTexUnit(0)->bind(image, true); + } + else + { + gGL.getTexUnit(0)->bind(target); + } gGL.color4fv(color.mV); @@ -698,11 +732,18 @@ void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degre gGL.translateUI(offset_x, offset_y, 0.f); LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD); - - gGL.getTexUnit(0)->bind(image, true); + + if(image != NULL) + { + gGL.getTexUnit(0)->bind(image, true); + } + else + { + gGL.getTexUnit(0)->bind(target); + } gGL.color4fv(color.mV); - + gGL.begin(LLRender::QUADS); { LLVector3 v; @@ -1202,18 +1243,18 @@ void gl_segmented_rect_2d_tex(const S32 left, gGL.popUIMatrix(); } -//FIXME: rewrite to use scissor? -void gl_segmented_rect_2d_fragment_tex(const S32 left, - const S32 top, - const S32 right, - const S32 bottom, - const S32 texture_width, - const S32 texture_height, - const S32 border_size, - const F32 start_fragment, - const F32 end_fragment, - const U32 edges) +void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, + const S32 texture_width, + const S32 texture_height, + const S32 border_size, + const F32 start_fragment, + const F32 end_fragment, + const U32 edges) { + const S32 left = rect.mLeft; + const S32 right = rect.mRight; + const S32 top = rect.mTop; + const S32 bottom = rect.mBottom; S32 width = llabs(right - left); S32 height = llabs(top - bottom); @@ -1343,10 +1384,10 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, if (end_fragment > middle_end) { - u_min = (1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_uv_scale.mV[VX]; - u_max = (1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]; - x_min = width_vec - ((1.f - llmax(0.f, ((start_fragment - middle_end) / middle_start))) * border_width_right); - x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right); + u_min = 1.f - ((1.f - llmax(0.f, (start_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]); + u_max = 1.f - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_uv_scale.mV[VX]); + x_min = width_vec - ((1.f - llmax(0.f, (start_fragment - middle_end) / middle_start)) * border_width_right); + x_max = width_vec - ((1.f - ((end_fragment - middle_end) / middle_start)) * border_width_right); // draw bottom right gGL.texCoord2f(u_min, 0.f); @@ -1393,145 +1434,132 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, gGL.popUIMatrix(); } -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, - const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, - const U32 edges) +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, + const LLVector3& width_vec, const LLVector3& height_vec) { - LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero; - LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero; - - LLVector3 top_border_height = ((edges & (~(U32)ROUNDED_RECT_BOTTOM)) != 0) ? border_height : LLVector3::zero; - LLVector3 bottom_border_height = ((edges & (~(U32)ROUNDED_RECT_TOP)) != 0) ? border_height : LLVector3::zero; - - gGL.begin(LLRender::QUADS); { // draw bottom left - gGL.texCoord2f(0.f, 0.f); + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mBottom); gGL.vertex3f(0.f, 0.f, 0.f); - gGL.texCoord2f(border_scale.mV[VX], 0.f); - gGL.vertex3fv(left_border_width.mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(0.f, border_scale.mV[VY]); - gGL.vertex3fv(bottom_border_height.mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); // draw bottom middle - gGL.texCoord2f(border_scale.mV[VX], 0.f); - gGL.vertex3fv(left_border_width.mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); - gGL.vertex3fv((width_vec - right_border_width).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); // draw bottom right - gGL.texCoord2f(1.f - border_scale.mV[VX], 0.f); - gGL.vertex3fv((width_vec - right_border_width).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec).mV); - gGL.texCoord2f(1.f, 0.f); + gGL.texCoord2f(clip_rect.mRight, clip_rect.mBottom); gGL.vertex3fv(width_vec.mV); - gGL.texCoord2f(1.f, border_scale.mV[VY]); - gGL.vertex3fv((width_vec + bottom_border_height).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); // draw left - gGL.texCoord2f(0.f, border_scale.mV[VY]); - gGL.vertex3fv(bottom_border_height.mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); // draw middle - gGL.texCoord2f(border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); // draw right - gGL.texCoord2f(1.f - border_scale.mV[VX], border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + bottom_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f, border_scale.mV[VY]); - gGL.vertex3fv((width_vec + bottom_border_height).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mBottom); + gGL.vertex3fv((width_vec + center_draw_rect.mBottom * height_vec).mV); - gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); // draw top left - gGL.texCoord2f(0.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f); - gGL.vertex3fv((left_border_width + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); - gGL.texCoord2f(0.f, 1.f); + gGL.texCoord2f(clip_rect.mLeft, clip_rect.mTop); gGL.vertex3fv((height_vec).mV); // draw top middle - gGL.texCoord2f(border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((left_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mLeft, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); - gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); - gGL.texCoord2f(border_scale.mV[VX], 1.f); - gGL.vertex3fv((left_border_width + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mLeft, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mLeft * width_vec + height_vec).mV); // draw top right - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec - right_border_width + height_vec - top_border_height).mV); + gGL.texCoord2f(center_uv_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f, 1.f - border_scale.mV[VY]); - gGL.vertex3fv((width_vec + height_vec - top_border_height).mV); + gGL.texCoord2f(clip_rect.mRight, center_uv_rect.mTop); + gGL.vertex3fv((width_vec + center_draw_rect.mTop * height_vec).mV); - gGL.texCoord2f(1.f, 1.f); + gGL.texCoord2f(clip_rect.mRight, clip_rect.mTop); gGL.vertex3fv((width_vec + height_vec).mV); - gGL.texCoord2f(1.f - border_scale.mV[VX], 1.f); - gGL.vertex3fv((width_vec - right_border_width + height_vec).mV); + gGL.texCoord2f(center_uv_rect.mRight, clip_rect.mTop); + gGL.vertex3fv((center_draw_rect.mRight * width_vec + height_vec).mV); } gGL.end(); } -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec) -{ - gl_segmented_rect_3d_tex(border_scale, border_width, border_height, width_vec, height_vec, ROUNDED_RECT_TOP); -} - // static void LLRender2D::initClass(LLImageProviderInterface* image_provider, const LLVector2* scale_factor) diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h index 0323af6a2..1a2fbdbf4 100644 --- a/indra/llrender/llrender2dutils.h +++ b/indra/llrender/llrender2dutils.h @@ -71,11 +71,12 @@ void gl_washer_2d(F32 outer_radius, F32 inner_radius, S32 steps, const LLColor4& void gl_washer_segment_2d(F32 outer_radius, F32 inner_radius, F32 start_radians, F32 end_radians, S32 steps, const LLColor4& inner_color, const LLColor4& outer_color); void gl_washer_spokes_2d(F32 outer_radius, F32 inner_radius, S32 count, const LLColor4& inner_color, const LLColor4& outer_color); void gl_draw_image(S32 x, S32 y, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_target(S32 x, S32 y, S32 width, S32 height, LLRenderTarget* target, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); void gl_draw_scaled_image(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); void gl_draw_rotated_image(S32 x, S32 y, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees,LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); -void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f)); +void gl_draw_scaled_rotated_image(S32 x, S32 y, S32 width, S32 height, F32 degrees, LLTexture* image, const LLColor4& color = UI_VERTEX_COLOR, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), LLRenderTarget* target = NULL); +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 border_width, S32 border_height, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true); +void gl_draw_scaled_image_with_border(S32 x, S32 y, S32 width, S32 height, LLTexture* image, const LLColor4 &color, BOOL solid_color = FALSE, const LLRectf& uv_rect = LLRectf(0.f, 1.f, 1.f, 0.f), const LLRectf& scale_rect = LLRectf(0.f, 1.f, 1.f, 0.f), bool scale_inner = true); void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase = 0.f ); @@ -105,9 +106,8 @@ typedef enum e_rounded_edge void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_2d_fragment_tex(const S32 left, const S32 top, const S32 right, const S32 bottom, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, U32 edges = ROUNDED_RECT_ALL); -void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec); +void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, const S32 texture_width, const S32 texture_height, const S32 border_size, const F32 start_fragment, const F32 end_fragment, const U32 edges = ROUNDED_RECT_ALL); +void gl_segmented_rect_3d_tex(const LLRectf& clip_rect, const LLRectf& center_uv_rect, const LLRectf& center_draw_rect, const LLVector3& width_vec, const LLVector3& height_vec); inline void gl_rect_2d( const LLRect& rect, BOOL filled ) { diff --git a/indra/llrender/llshadermgr.cpp b/indra/llrender/llshadermgr.cpp index 946361e62..bfb3eb1a9 100644 --- a/indra/llrender/llshadermgr.cpp +++ b/indra/llrender/llshadermgr.cpp @@ -80,7 +80,11 @@ BOOL LLShaderMgr::attachShaderFeatures(LLGLSLShader * shader) { llassert_always(shader != NULL); LLShaderFeatures *features = & shader->mFeatures; - + + if (features->attachNothing) + { + return TRUE; + } ////////////////////////////////////// // Attach Vertex Shader Features First ////////////////////////////////////// @@ -640,11 +644,14 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade // before any non-preprocessor directives (per spec) text[count++] = strdup("#extension GL_ARB_texture_rectangle : enable\n"); text[count++] = strdup("#extension GL_ARB_shader_texture_lod : enable\n"); - - + if (minor_version == 50 && gGLManager.mHasGpuShader5) + { + text[count++] = strdup("#extension GL_ARB_gpu_shader5 : enable\n"); + } //some implementations of GLSL 1.30 require integer precision be explicitly declared text[count++] = strdup("precision mediump int;\n"); text[count++] = strdup("precision highp float;\n"); + text[count++] = strdup("#define FXAA_GLSL_130 1\n"); } else { //set version to 400 @@ -653,11 +660,11 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade // before any non-preprocessor directives (per spec) text[count++] = strdup("#extension GL_ARB_texture_rectangle : enable\n"); text[count++] = strdup("#extension GL_ARB_shader_texture_lod : enable\n"); + text[count++] = strdup("#define FXAA_GLSL_400 1\n"); } text[count++] = strdup("#define DEFINE_GL_FRAGCOLOR 1\n"); - text[count++] = strdup("#define FXAA_GLSL_130 1\n"); text[count++] = strdup("#define ATTRIBUTE in\n"); @@ -875,8 +882,7 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade { //dump every 128 lines LL_WARNS("ShaderLoading") << "\n" << ostr.str() << LL_ENDL; - ostr.clear(); - ostr.str(LLStringUtil::null); + ostr = std::stringstream(); } } @@ -943,6 +949,63 @@ GLhandleARB LLShaderMgr::loadShaderFile(const std::string& filename, S32 & shade return ret; } +void LLShaderMgr::unloadShaders() +{ + //Instead of manually unloading, shaders are now automatically accumulated in a list. + //Simply iterate and unload. + std::vector &shader_list = LLShaderMgr::getGlobalShaderList(); + for (std::vector::iterator it = shader_list.begin(); it != shader_list.end(); ++it) + (*it)->unload(); + mShaderObjects.clear(); + mProgramObjects.clear(); +} + +void LLShaderMgr::unloadShaderObjects() +{ + std::multimap::iterator it = mShaderObjects.begin(); + for (; it != mShaderObjects.end(); ++it) + if (it->second.mHandle) + glDeleteObjectARB(it->second.mHandle); + mShaderObjects.clear(); + cleanupShaderSources(); +} + +void LLShaderMgr::cleanupShaderSources() +{ + if (!mProgramObjects.empty()) + { + for (auto iter = mProgramObjects.cbegin(), + iter_end = mProgramObjects.cend(); iter != iter_end; ++iter) + { + GLuint program = iter->second; + if (program > 0) + { + GLhandleARB shaders[1024] = {}; + GLsizei count = -1; + glGetAttachedObjectsARB(program, 1024, &count, shaders); + if (count > 0) + { + for (GLsizei i = 0; i < count; ++i) + { + std::multimap::iterator it = mShaderObjects.begin(); + for (; it != LLShaderMgr::instance()->mShaderObjects.end(); it++) + { + if ((*it).second.mHandle == shaders[i]) + { + glDetachObjectARB(program, shaders[i]); + break; + } + } + } + } + } + } + + // Clear the linked program list as its no longer needed + mProgramObjects.clear(); + } +} + BOOL LLShaderMgr::linkProgramObject(GLhandleARB obj, BOOL suppress_errors) { //check for errors diff --git a/indra/llrender/llshadermgr.h b/indra/llrender/llshadermgr.h index e29f80f10..b9cff8680 100644 --- a/indra/llrender/llshadermgr.h +++ b/indra/llrender/llshadermgr.h @@ -232,6 +232,8 @@ DISPLAY_GAMMA, BOOL linkProgramObject(GLhandleARB obj, BOOL suppress_errors = FALSE); BOOL validateProgramObject(GLhandleARB obj); GLhandleARB loadShaderFile(const std::string& filename, S32 & shader_level, GLenum type, std::map* defines = NULL, S32 texture_index_channels = -1); + void unloadShaders(); + void unloadShaderObjects(); // Implemented in the application to actually point to the shader directory. virtual std::string getShaderDirPrefix(void) = 0; // Pure Virtual @@ -252,6 +254,9 @@ public: // Map of shader names to compiled std::multimap mShaderObjects; //Singu Note: Packing more info here. Doing such provides capability to skip unneeded duplicate loading.. + // Map of program names linked + std::map mProgramObjects; + //global (reserved slot) shader parameters std::vector mReservedAttribs; @@ -261,6 +266,7 @@ public: std::map mDefinitions; protected: + void cleanupShaderSources(); // our parameter manager singleton instance static LLShaderMgr * sInstance; diff --git a/indra/llrender/lluiimage.cpp b/indra/llrender/lluiimage.cpp index 00edc7610..5d8f92b2e 100644 --- a/indra/llrender/lluiimage.cpp +++ b/indra/llrender/lluiimage.cpp @@ -38,11 +38,9 @@ LLUIImage::LLUIImage(const std::string& name, LLPointer image) mImage(image), mScaleRegion(0.f, 1.f, 1.f, 0.f), mClipRegion(0.f, 1.f, 1.f, 0.f), - mUniformScaling(TRUE), - mNoClip(TRUE), - mImageLoaded(NULL) -{ -} + mImageLoaded(NULL), + mScaleStyle(SCALE_INNER) +{} LLUIImage::~LLUIImage() { @@ -52,44 +50,35 @@ LLUIImage::~LLUIImage() void LLUIImage::setClipRegion(const LLRectf& region) { mClipRegion = region; - mNoClip = mClipRegion.mLeft == 0.f - && mClipRegion.mRight == 1.f - && mClipRegion.mBottom == 0.f - && mClipRegion.mTop == 1.f; } void LLUIImage::setScaleRegion(const LLRectf& region) { mScaleRegion = region; - mUniformScaling = mScaleRegion.mLeft == 0.f - && mScaleRegion.mRight == 1.f - && mScaleRegion.mBottom == 0.f - && mScaleRegion.mTop == 1.f; +} + +void LLUIImage::setScaleStyle(LLUIImage::EScaleStyle style) +{ + mScaleStyle = style; } //TODO: move drawing implementation inside class void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const { - gl_draw_scaled_image(x, y, getWidth(), getHeight(), mImage, color, mClipRegion); + draw(x, y, getWidth(), getHeight(), color); } void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const { - if (mUniformScaling) - { - gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion); - } - else - { - gl_draw_scaled_image_with_border( - x, y, - width, height, - mImage, - color, - FALSE, - mClipRegion, - mScaleRegion); - } + gl_draw_scaled_image_with_border( + x, y, + width, height, + mImage, + color, + FALSE, + mClipRegion, + mScaleRegion, + mScaleStyle == SCALE_INNER); } void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const @@ -101,7 +90,8 @@ void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& c color, TRUE, mClipRegion, - mScaleRegion); + mScaleRegion, + mScaleStyle == SCALE_INNER); } void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const @@ -112,6 +102,50 @@ void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& drawSolid(border_rect, color); } +void LLUIImage::draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, + const LLRect& rect, const LLColor4& color) +{ + F32 border_scale = 1.f; + F32 border_height = (1.f - mScaleRegion.getHeight()) * getHeight(); + F32 border_width = (1.f - mScaleRegion.getWidth()) * getWidth(); + if (rect.getHeight() < border_height || rect.getWidth() < border_width) + { + if(border_height - rect.getHeight() > border_width - rect.getWidth()) + { + border_scale = (F32)rect.getHeight() / border_height; + } + else + { + border_scale = (F32)rect.getWidth() / border_width; + } + } + + LLRender2D::pushMatrix(); + { + LLVector3 rect_origin = origin_agent + (rect.mLeft * x_axis) + (rect.mBottom * y_axis); + LLRender2D::translate(rect_origin.mV[VX], + rect_origin.mV[VY], + rect_origin.mV[VZ]); + gGL.getTexUnit(0)->bind(getImage()); + gGL.color4fv(color.mV); + + LLRectf center_uv_rect(mClipRegion.mLeft + mScaleRegion.mLeft * mClipRegion.getWidth(), + mClipRegion.mBottom + mScaleRegion.mTop * mClipRegion.getHeight(), + mClipRegion.mLeft + mScaleRegion.mRight * mClipRegion.getWidth(), + mClipRegion.mBottom + mScaleRegion.mBottom * mClipRegion.getHeight()); + gl_segmented_rect_3d_tex(mClipRegion, + center_uv_rect, + LLRectf(border_width * border_scale * 0.5f / (F32)rect.getWidth(), + (rect.getHeight() - (border_height * border_scale * 0.5f)) / (F32)rect.getHeight(), + (rect.getWidth() - (border_width * border_scale * 0.5f)) / (F32)rect.getWidth(), + (border_height * border_scale * 0.5f) / (F32)rect.getHeight()), + rect.getWidth() * x_axis, + rect.getHeight() * y_axis); + + } LLRender2D::popMatrix(); +} + + S32 LLUIImage::getWidth() const { // return clipped dimensions of actual image area diff --git a/indra/llrender/lluiimage.h b/indra/llrender/lluiimage.h index dede4acb1..939f78d65 100644 --- a/indra/llrender/lluiimage.h +++ b/indra/llrender/lluiimage.h @@ -45,6 +45,12 @@ extern const LLColor4 UI_VERTEX_COLOR; class LLUIImage : public LLRefCount { public: + enum EScaleStyle + { + SCALE_INNER, + SCALE_OUTER + }; + typedef boost::signals2::signal image_loaded_signal_t; LLUIImage(const std::string& name, LLPointer image); @@ -52,6 +58,7 @@ public: void setClipRegion(const LLRectf& region); void setScaleRegion(const LLRectf& region); + void setScaleStyle(EScaleStyle style); LLPointer getImage() { return mImage; } const LLPointer& getImage() const { return mImage; } @@ -67,7 +74,9 @@ public: void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const; void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); } void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, getWidth(), getHeight(), color, border_width); } - + + void draw3D(const LLVector3& origin_agent, const LLVector3& x_axis, const LLVector3& y_axis, const LLRect& rect, const LLColor4& color); + const std::string& getName() const { return mName; } virtual S32 getWidth() const; @@ -84,12 +93,11 @@ public: protected: image_loaded_signal_t* mImageLoaded; - std::string mName; - LLRectf mScaleRegion; - LLRectf mClipRegion; - LLPointer mImage; - BOOL mUniformScaling; - BOOL mNoClip; + std::string mName; + LLRectf mScaleRegion; + LLRectf mClipRegion; + LLPointer mImage; + EScaleStyle mScaleStyle; }; namespace LLInitParam diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 62db38a5c..0988b0581 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -187,7 +187,7 @@ volatile U8* LLVBOPool::allocate(U32& name, U32 size, bool for_seed) if (LLVertexBuffer::sDisableVBOMapping || mUsage != GL_DYNAMIC_DRAW_ARB) { glBufferDataARB(mType, size, 0, mUsage); - ret = (U8*) ll_aligned_malloc(size, 64); + ret = (U8*) ll_aligned_malloc<64>(size); } else { //always use a true hint of static draw when allocating non-client-backed buffers @@ -240,7 +240,7 @@ void LLVBOPool::release(U32 name, volatile U8* buffer, U32 size) llassert(vbo_block_size(size) == size); deleteBuffer(name); - ll_aligned_free((U8*) buffer); + ll_aligned_free<64>((U8*) buffer); if (mType == GL_ARRAY_BUFFER_ARB) { @@ -294,7 +294,7 @@ void LLVBOPool::cleanup() if (r.mClientData) { - ll_aligned_free((void*) r.mClientData); + ll_aligned_free<64>((void*) r.mClientData); } l.pop_front(); diff --git a/indra/llui/llmultislider.cpp b/indra/llui/llmultislider.cpp index f4643fa9e..fa431d676 100644 --- a/indra/llui/llmultislider.cpp +++ b/indra/llui/llmultislider.cpp @@ -466,7 +466,7 @@ void LLMultiSlider::draw() F32 opacity = getEnabled() ? 1.f : 0.3f; // Track - LLUIImagePtr thumb_imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr thumb_imagep = LLUI::getUIImage("Rounded_Square"); S32 height_offset = (getRect().getHeight() - MULTI_TRACK_HEIGHT) / 2; LLRect track_rect(0, getRect().getHeight() - height_offset, getRect().getWidth(), height_offset ); diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 3d66d0d36..990416c9a 100644 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -415,7 +415,7 @@ LLNotification::LLNotification(const LLNotification::Params& p) : mTimestamp(p.timestamp), mSubstitutions(p.substitutions), mPayload(p.payload), - mExpiresAt(0), + mExpiresAt(F64SecondsImplicit()), mResponseFunctorName(p.functor_name), mTemporaryResponder(p.mTemporaryResponder), mRespondedTo(false), @@ -1297,14 +1297,20 @@ LLXMLNodePtr LLNotificationTemplates::checkForXMLTemplate(LLXMLNodePtr item) bool LLNotificationTemplates::loadTemplates() { - const std::string xml_filename = "notifications.xml"; + LL_INFOS() << "Reading notifications template" << LL_ENDL; + // Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it + // output all relevant pathnames instead of just the ones from the most + // specific skin. + std::vector search_paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS); + + std::string base_filename = search_paths.front(); LLXMLNodePtr root; - - BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); + BOOL success = LLXMLNode::getLayeredXMLNode(root, search_paths); if (!success || root.isNull() || !root->hasName( "notifications" )) { - LL_ERRS() << "Problem reading UI Notifications file: " << xml_filename << LL_ENDL; + LL_ERRS() << "Problem reading XML from UI Notifications file: " << base_filename << LL_ENDL; return false; } @@ -1337,7 +1343,7 @@ bool LLNotificationTemplates::loadTemplates() if (!item->hasName("notification")) { LL_WARNS() << "Unexpected entity " << item->getName()->mString << - " found in " << xml_filename << LL_ENDL; + " found in notifications.xml [language=]" << LLUI::getLanguage() << LL_ENDL; continue; } } @@ -1347,14 +1353,20 @@ bool LLNotificationTemplates::loadTemplates() bool LLNotifications::loadNotifications() { - const std::string xml_filename = "notifications.xml"; + LL_INFOS() << "Reading notifications template" << LL_ENDL; + // Passing findSkinnedFilenames(constraint=LLDir::ALL_SKINS) makes it + // output all relevant pathnames instead of just the ones from the most + // specific skin. + std::vector search_paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, "notifications.xml", LLDir::ALL_SKINS); + + std::string base_filename = search_paths.front(); LLXMLNodePtr root; - - BOOL success = LLUICtrlFactory::getLayeredXMLNode(xml_filename, root); + BOOL success = LLXMLNode::getLayeredXMLNode(root, search_paths); if (!success || root.isNull() || !root->hasName( "notifications" )) { - LL_ERRS() << "Problem reading UI Notifications file: " << xml_filename << LL_ENDL; + LL_ERRS() << "Problem reading XML from UI Notifications file: " << base_filename << LL_ENDL; return false; } diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 81611090f..26b537bbe 100644 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -92,8 +92,9 @@ #include #include #include +#include #include - +#include // we want to minimize external dependencies, but this one is important #include "llsd.h" #include "llinstancetracker.h" @@ -102,6 +103,7 @@ #include "llavatarname.h" #include "llevents.h" #include "llfunctorregistry.h" +#include "llinitparam.h" #include "llui.h" #include "llxmlnode.h" #include "llnotificationptr.h" @@ -131,6 +133,70 @@ class LLNotificationForm LOG_CLASS(LLNotificationForm); public: + struct FormElementBase : public LLInitParam::Block + { + Optional name; + Optional enabled; + + FormElementBase(); + }; + + struct FormIgnore : public LLInitParam::Block + { + Optional text; + Optional save_option; + Optional control; + Optional invert_control; + + FormIgnore(); + }; + + struct FormButton : public LLInitParam::Block + { + Mandatory index; + Mandatory text; + Optional ignore; + Optional is_default; + + Mandatory type; + + FormButton(); + }; + + struct FormInput : public LLInitParam::Block + { + Mandatory type; + Optional width; + Optional max_length_chars; + Optional text; + + Optional value; + FormInput(); + }; + + struct FormElement : public LLInitParam::ChoiceBlock + { + Alternative button; + Alternative input; + + FormElement(); + }; + + struct FormElements : public LLInitParam::Block + { + Multiple elements; + FormElements(); + }; + + struct Params : public LLInitParam::Block + { + Optional name; + Optional ignore; + Optional form_elements; + + Params(); + }; + typedef enum e_ignore_type { IGNORE_NO, diff --git a/indra/llui/llprogressbar.cpp b/indra/llui/llprogressbar.cpp index c1c842d54..9ba58039e 100644 --- a/indra/llui/llprogressbar.cpp +++ b/indra/llui/llprogressbar.cpp @@ -48,16 +48,16 @@ static LLRegisterWidget r("progress_bar"); LLProgressBar::LLProgressBar(const std::string& name, const LLRect &rect) - : LLView(name, rect, FALSE), - mImageBar( NULL ), - mImageShadow( NULL ) + : LLView(name, rect, FALSE) + //mImageBar( NULL ), + // mImageShadow( NULL ) { mPercentDone = 0.f; // Defaults: - setImageBar("rounded_square.tga"); - setImageShadow("rounded_square_soft.tga"); + setImageBar("Rounded_Square"); + setImageShadow("Rounded_Square_Soft"); mColorBackground = LLColor4(0.3254f, 0.4000f, 0.5058f, 1.0f); mColorBar = LLColor4(0.5764f, 0.6627f, 0.8352f, 1.0f); @@ -75,10 +75,8 @@ void LLProgressBar::draw() static LLTimer timer; F32 alpha = getDrawContext().mAlpha; - //LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga"); - LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("progressbar_fill.tga"); - LLUIImagePtr bar_bg_imagep = LLUI::getUIImage("progressbar_track.tga"); - //LLUIImagePtr bar_imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr bar_fg_imagep = LLUI::getUIImage("ProgressBar"); + LLUIImagePtr bar_bg_imagep = LLUI::getUIImage("ProgressTrack"); LLColor4 background_color = LLUI::sColorsGroup->getColor("LoginProgressBarBgColor"); bar_bg_imagep->draw(getLocalRect(), background_color % alpha); @@ -95,12 +93,12 @@ void LLProgressBar::setPercent(const F32 percent) void LLProgressBar::setImageBar( const std::string &bar_name ) { - mImageBar = LLUI::getUIImage(bar_name)->getImage(); + //mImageBar = LLUI::getUIImage(bar_name)->getImage(); } void LLProgressBar::setImageShadow(const std::string &shadow_name) { - mImageShadow = LLUI::getUIImage(shadow_name)->getImage(); + //mImageShadow = LLUI::getUIImage(shadow_name)->getImage(); } void LLProgressBar::setColorBar(const LLColor4 &c) @@ -140,14 +138,14 @@ LLView* LLProgressBar::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactor LLProgressBar *progress = new LLProgressBar(name, LLRect()); - std::string image_bar; + /*std::string image_bar; if (node->hasAttribute("image_bar")) node->getAttributeString("image_bar",image_bar); if (image_bar != LLStringUtil::null) progress->setImageBar(image_bar); std::string image_shadow; if (node->hasAttribute("image_shadow")) node->getAttributeString("image_shadow",image_shadow); - if (image_shadow != LLStringUtil::null) progress->setImageShadow(image_shadow); + if (image_shadow != LLStringUtil::null) progress->setImageShadow(image_shadow);*/ LLColor4 color_bar; diff --git a/indra/llui/llprogressbar.h b/indra/llui/llprogressbar.h index 8f548da66..d7af5360c 100644 --- a/indra/llui/llprogressbar.h +++ b/indra/llui/llprogressbar.h @@ -62,13 +62,13 @@ public: protected: F32 mPercentDone; - LLPointer mImageBar; + // mImageBar; //LLUUID mImageBarID; //LLString mImageBarName; LLColor4 mColorBar; LLColor4 mColorBar2; - LLPointer mImageShadow; + //LLPointer mImageShadow; //LLUUID mImageShadowID; //LLString mImageShadowName; LLColor4 mColorShadow; diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index 1b8fe5ce2..f7b4d19d3 100644 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -511,7 +511,7 @@ void LLScrollbar::draw() // Draw background and thumb. - LLUIImage* rounded_rect_imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImage* rounded_rect_imagep = LLUI::getUIImage("Rounded_Square"); if (!rounded_rect_imagep) { diff --git a/indra/llui/llscrolllistcell.cpp b/indra/llui/llscrolllistcell.cpp index 82484b0bb..24a81cf94 100644 --- a/indra/llui/llscrolllistcell.cpp +++ b/indra/llui/llscrolllistcell.cpp @@ -203,7 +203,7 @@ LLScrollListText::LLScrollListText(const LLScrollListCell::Params& p) // initialize rounded rect image if (!mRoundedRectImage) { - mRoundedRectImage = LLUI::getUIImage("rounded_square.tga"); + mRoundedRectImage = LLUI::getUIImage("Rounded_Square"); } } diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp index 59c991512..72d4b3d01 100644 --- a/indra/llui/llscrolllistcolumn.cpp +++ b/indra/llui/llscrolllistcolumn.cpp @@ -249,8 +249,8 @@ void LLScrollColumnHeader::handleReshape(const LLRect& new_rect, bool by_user) // tell scroll list to layout columns again // do immediate update to get proper feedback to resize handle // which needs to know how far the resize actually went - mColumn->mParentCtrl->dirtyColumns(); //Must flag as dirty, else updateColumns will probably be a noop. - mColumn->mParentCtrl->updateColumns(); + const bool force_update = true; + mColumn->mParentCtrl->updateColumns(force_update); } } diff --git a/indra/llui/llscrolllistctrl.cpp b/indra/llui/llscrolllistctrl.cpp index 915833bd0..ff2afae93 100644 --- a/indra/llui/llscrolllistctrl.cpp +++ b/indra/llui/llscrolllistctrl.cpp @@ -570,7 +570,6 @@ S32 LLScrollListCtrl::calcMaxContentWidth() if (mColumnWidthsDirty) { - mColumnWidthsDirty = false; // update max content width for this column, by looking at all items column->mMaxContentWidth = column->mHeader ? LLFontGL::getFontSansSerifSmall()->getWidth(column->mLabel.getWString()) + mColumnPadding + HEADING_TEXT_PADDING : 0; item_list::iterator iter; @@ -584,8 +583,8 @@ S32 LLScrollListCtrl::calcMaxContentWidth() } max_item_width += column->mMaxContentWidth; } + mColumnWidthsDirty = false; - mMaxContentWidth = max_item_width; return max_item_width; } @@ -599,7 +598,7 @@ bool LLScrollListCtrl::updateColumnWidths() if (!column) continue; // update column width - S32 new_width = column->getWidth(); + S32 new_width = 0; if (column->mRelWidth >= 0) { new_width = (S32)ll_round(column->mRelWidth*mItemListRect.getWidth()); @@ -608,6 +607,10 @@ bool LLScrollListCtrl::updateColumnWidths() { new_width = (mItemListRect.getWidth() - mTotalStaticColumnWidth - mTotalColumnPadding) / mNumDynamicWidthColumns; } + else + { + new_width = column->getWidth(); + } if (column->getWidth() != new_width) { @@ -650,9 +653,9 @@ void LLScrollListCtrl::updateLineHeightInsert(LLScrollListItem* itemp) } -void LLScrollListCtrl::updateColumns() +void LLScrollListCtrl::updateColumns(bool force_update) { - if (!mColumnsDirty) + if (!mColumnsDirty && !force_update) return; mColumnsDirty = false; @@ -706,7 +709,7 @@ void LLScrollListCtrl::updateColumns() } // propagate column widths to individual cells - if (columns_changed_width) + if (columns_changed_width || force_update) { item_list::iterator iter; for (iter = mItemList.begin(); iter != mItemList.end(); iter++) diff --git a/indra/llui/llscrolllistctrl.h b/indra/llui/llscrolllistctrl.h index 96df91b80..68905327c 100644 --- a/indra/llui/llscrolllistctrl.h +++ b/indra/llui/llscrolllistctrl.h @@ -288,7 +288,7 @@ public: static void onClickColumn(void *userdata); - virtual void updateColumns(); + virtual void updateColumns(bool force_update = false); S32 calcMaxContentWidth(); bool updateColumnWidths(); S32 getMaxContentWidth() { return mMaxContentWidth; } diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp index 14fa0cd0f..8e7e886ef 100644 --- a/indra/llui/llslider.cpp +++ b/indra/llui/llslider.cpp @@ -72,9 +72,9 @@ LLSlider::LLSlider( mMouseDownSignal( NULL ), mMouseUpSignal( NULL ) { - mThumbImage = LLUI::getUIImage("icn_slide-thumb_dark.tga"); - mTrackImage = LLUI::getUIImage("icn_slide-groove_dark.tga"); - mTrackHighlightImage = LLUI::getUIImage("icn_slide-highlight.tga"); + mThumbImage = LLUI::getUIImage("SliderThumb_Off"); + mTrackImage = LLUI::getUIImage("SliderTrack_Horiz"); + mTrackHighlightImage = LLUI::getUIImage("SliderTrack_Horiz_Highlight"); // properly handle setting the starting thumb rect // do it this way to handle both the operating-on-settings diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 42f617b21..9ede41892 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -223,32 +223,33 @@ std::string LLUI::getLanguage() //static std::string LLUI::locateSkin(const std::string& filename) { - std::string slash = gDirUtilp->getDirDelimiter(); std::string found_file = filename; - if (!gDirUtilp->fileExists(found_file)) + if (gDirUtilp->fileExists(found_file)) { - found_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); // Should be CUSTOM_SKINS? + return found_file; } - if (sConfigGroup && sConfigGroup->controlExists("Language")) + + found_file = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, filename); // Should be CUSTOM_SKINS? + if (gDirUtilp->fileExists(found_file)) { - if (!gDirUtilp->fileExists(found_file)) - { - std::string localization = getLanguage(); - std::string local_skin = "xui" + slash + localization + slash + filename; - found_file = gDirUtilp->findSkinnedFilename(local_skin); - } + return found_file; } - if (!gDirUtilp->fileExists(found_file)) + + found_file = gDirUtilp->findSkinnedFilename(LLDir::XUI, filename); + if (! found_file.empty()) { - std::string local_skin = "xui" + slash + "en-us" + slash + filename; - found_file = gDirUtilp->findSkinnedFilename(local_skin); + return found_file; } - if (!gDirUtilp->fileExists(found_file)) + + found_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename); + if (gDirUtilp->fileExists(found_file)) { - found_file = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, filename); + return found_file; } - return found_file; -} + LL_WARNS("LLUI") << "Can't find '" << filename + << "' in user settings, any skin directory or app_settings" << LL_ENDL; + return ""; +} //static LLVector2 LLUI::getWindowSize() diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp index e980ecec2..683eaab3f 100644 --- a/indra/llui/lluictrlfactory.cpp +++ b/indra/llui/lluictrlfactory.cpp @@ -174,7 +174,7 @@ const std::vector& LLUICtrlFactory::getXUIPaths() //----------------------------------------------------------------------------- bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNodePtr& root) { - std::string full_filename = gDirUtilp->findSkinnedFilename(sXUIPaths.front(), xui_filename); + std::string full_filename = gDirUtilp->findSkinnedFilenameBaseLang(LLDir::XUI, xui_filename); if (full_filename.empty()) { // try filename as passed in since sometimes we load an xml file from a user-supplied path @@ -194,29 +194,21 @@ bool LLUICtrlFactory::getLayeredXMLNode(const std::string &xui_filename, LLXMLNo LL_WARNS() << "Problem reading UI description file: " << full_filename << LL_ENDL; return false; } + + std::vector paths = + gDirUtilp->findSkinnedFilenames(LLDir::XUI, xui_filename); - LLXMLNodePtr updateRoot; - - std::vector::const_iterator itor; - - for (itor = sXUIPaths.begin(), ++itor; itor != sXUIPaths.end(); ++itor) + for ( auto& layer_filename : paths ) { - std::string nodeName; - std::string updateName; - - std::string layer_filename = gDirUtilp->findSkinnedFilename((*itor), xui_filename); - if(layer_filename.empty()) - { - // no localized version of this file, that's ok, keep looking - continue; - } - + LLXMLNodePtr updateRoot; if (!LLXMLNode::parseFile(layer_filename, updateRoot, NULL)) { - LL_WARNS() << "Problem reading localized UI description file: " << (*itor) + gDirUtilp->getDirDelimiter() + xui_filename << LL_ENDL; + LL_WARNS() << "Problem reading localized UI description file: " << layer_filename << LL_ENDL; return false; } + std::string updateName; + std::string nodeName; updateRoot->getAttributeString("name", updateName); root->getAttributeString("name", nodeName); diff --git a/indra/llvfs/lldir.cpp b/indra/llvfs/lldir.cpp index 69a89abf8..d0bb1d4c2 100644 --- a/indra/llvfs/lldir.cpp +++ b/indra/llvfs/lldir.cpp @@ -71,8 +71,15 @@ LLDir_Linux gDirUtil; LLDir *gDirUtilp = (LLDir *)&gDirUtil; +/// Values for findSkinnedFilenames(subdir) parameter +const char + *LLDir::XUI = "xui", + *LLDir::TEXTURES = "textures", + *LLDir::SKINBASE = ""; + static const char* const empty = ""; std::string LLDir::sDumpDir = ""; + LLDir::LLDir() : mAppName(""), mExecutablePathAndName(""), @@ -85,7 +92,9 @@ LLDir::LLDir() mOSCacheDir(""), mCAFile(""), mTempDir(""), - mDirDelimiter("/") // fallback to forward slash if not overridden + mDirDelimiter("/"), // fallback to forward slash if not overridden + mLanguage("en"), + mUserName("undefined") { } @@ -97,7 +106,11 @@ std::vector LLDir::getFilesInDir(const std::string &dirname) { //Returns a vector of fullpath filenames. +#if LL_WINDOWS + boost::filesystem::path p (utf8str_to_utf16str(dirname).c_str()); +#else boost::filesystem::path p (dirname); +#endif std::vector v; if (exists(p)) @@ -188,19 +201,33 @@ S32 LLDir::deleteFilesInDir(const std::string &dirname, const std::string &mask) U32 LLDir::deleteDirAndContents(const std::string& dir_name) { //Removes the directory and its contents. Returns number of files removed. - // Singu Note: boost::filesystem throws exceptions - S32 res = 0; + + U32 num_deleted = 0; - try + try { - res = boost::filesystem::remove_all(dir_name); +#if LL_WINDOWS + boost::filesystem::path dir_path(utf8str_to_utf16str(dir_name).c_str()); +#else + boost::filesystem::path dir_path(dir_name); +#endif + if (boost::filesystem::exists (dir_path)) + { + if (!boost::filesystem::is_empty (dir_path)) + { // Directory has content + num_deleted = boost::filesystem::remove_all (dir_path); + } + else + { // Directory is empty + boost::filesystem::remove (dir_path); + } + } } - catch(const boost::filesystem::filesystem_error& e) - { - LL_WARNS() << "boost::filesystem::remove_all(\"" + dir_name + "\") failed: '" + e.code().message() + "'" << LL_ENDL; - } - - return res; + catch (boost::filesystem::filesystem_error &er) + { + LL_WARNS() << "Failed to delete " << dir_name << " with error " << er.code().message() << LL_ENDL; + } + return num_deleted; } const std::string LLDir::findFile(const std::string &filename, @@ -346,6 +373,12 @@ const std::string LLDir::getCacheDir(bool get_default) const } } +#if (defined(_WIN64) || defined(__amd64__) || defined(__x86_64__)) +#define OS_CACHE_DIR "SingularityViewer64" +#else +#define OS_CACHE_DIR "Obsidian" +#endif + // Return the default cache directory std::string LLDir::buildSLOSCacheDir() const { @@ -363,11 +396,7 @@ std::string LLDir::buildSLOSCacheDir() const } else { -#if defined(_WIN64) - res = add(getOSCacheDir(), "SingularityViewer64"); -#else - res = add(getOSCacheDir(), "SingularityViewer"); -#endif + res = add(getOSCacheDir(), OS_CACHE_DIR); } return res; } @@ -390,20 +419,26 @@ const std::string &LLDir::getDirDelimiter() const return mDirDelimiter; } +const std::string& LLDir::getDefaultSkinDir() const +{ + return mDefaultSkinDir; +} + const std::string &LLDir::getSkinDir() const { return mSkinDir; } +const std::string& LLDir::getUserDefaultSkinDir() const +{ + return mUserDefaultSkinDir; +} + const std::string &LLDir::getUserSkinDir() const { return mUserSkinDir; } -const std::string& LLDir::getDefaultSkinDir() const -{ - return mDefaultSkinDir; -} const std::string LLDir::getSkinBaseDir() const { @@ -415,6 +450,11 @@ const std::string &LLDir::getLLPluginDir() const return mLLPluginDir; } +const std::string &LLDir::getUserName() const +{ + return mUserName; +} + static std::string ELLPathToString(ELLPath location) { typedef std::map ELLPathMap; @@ -602,7 +642,7 @@ std::string LLDir::getBaseFileName(const std::string& filepath, bool strip_exten std::string LLDir::getDirName(const std::string& filepath) const { std::size_t offset = filepath.find_last_of(getDirDelimiter()); - S32 len = (offset == std::string::npos) ? 0 : offset; + size_t len = (offset == std::string::npos) ? 0 : offset; std::string dirname = filepath.substr(0, len); return dirname; } @@ -618,31 +658,207 @@ std::string LLDir::getExtension(const std::string& filepath) const return exten; } -std::string LLDir::findSkinnedFilename(const std::string &filename) const +std::string LLDir::findSkinnedFilenameBaseLang(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint) const { - return findSkinnedFilename("", "", filename); + // This implementation is basically just as described in the declaration comments. + std::vector found(findSkinnedFilenames(subdir, filename, constraint)); + if (found.empty()) + { + return ""; + } + return found.front(); } -std::string LLDir::findSkinnedFilename(const std::string &subdir, const std::string &filename) const +std::string LLDir::findSkinnedFilename(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint) const { - return findSkinnedFilename("", subdir, filename); + // This implementation is basically just as described in the declaration comments. + std::vector found(findSkinnedFilenames(subdir, filename, constraint)); + if (found.empty()) + { + return ""; + } + return found.back(); } -std::string LLDir::findSkinnedFilename(const std::string &subdir1, const std::string &subdir2, const std::string &filename) const +// This method exists because the two code paths for +// findSkinnedFilenames(ALL_SKINS) and findSkinnedFilenames(CURRENT_SKIN) must +// generate the list of candidate pathnames in identical ways. The only +// difference is in the body of the inner loop. +template +void LLDir::walkSearchSkinDirs(const std::string& subdir, + const std::vector& subsubdirs, + const std::string& filename, + const FUNCTION& function) const { - // generate subdirectory path fragment, e.g. "/foo/bar", "/foo", "" - std::string subdirs = ((subdir1.empty() ? "" : mDirDelimiter) + subdir1) - + ((subdir2.empty() ? "" : mDirDelimiter) + subdir2); + BOOST_FOREACH(std::string skindir, mSearchSkinDirs) + { + std::string subdir_path(add(skindir, subdir)); + BOOST_FOREACH(std::string subsubdir, subsubdirs) + { + std::string full_path(add(add(subdir_path, subsubdir), filename)); + if (fileExists(full_path)) + { + function(subsubdir, full_path); + } + } + } +} - std::vector search_paths; - - search_paths.push_back(getUserSkinDir() + subdirs); // first look in user skin override - search_paths.push_back(getSkinDir() + subdirs); // then in current skin - search_paths.push_back(getDefaultSkinDir() + subdirs); // then default skin - search_paths.push_back(getCacheDir() + subdirs); // and last in preload directory +// ridiculous little helper function that should go away when we can use lambda +inline void push_back(std::vector& vector, const std::string& value) +{ + vector.push_back(value); +} - std::string found_file = findFile(filename, search_paths); - return found_file; +typedef std::map StringMap; +// ridiculous little helper function that should go away when we can use lambda +inline void store_in_map(StringMap& map, const std::string& key, const std::string& value) +{ + map[key] = value; +} + +std::vector LLDir::findSkinnedFilenames(const std::string& subdir, + const std::string& filename, + ESkinConstraint constraint) const +{ + // Recognize subdirs that have no localization. + static const std::set sUnlocalized = list_of + ("") // top-level directory not localized + ("textures") // textures not localized + ; + + LL_DEBUGS("LLDir") << "subdir '" << subdir << "', filename '" << filename + << "', constraint " + << ((constraint == CURRENT_SKIN)? "CURRENT_SKIN" : "ALL_SKINS") + << LL_ENDL; + + // Cache the default language directory for each subdir we've encountered. + // A cache entry whose value is the empty string means "not localized, + // don't bother checking again." + static StringMap sLocalized; + + // Check whether we've already discovered if this subdir is localized. + StringMap::const_iterator found = sLocalized.find(subdir); + if (found == sLocalized.end()) + { + // We have not yet determined that. Is it one of the subdirs "known" + // to be unlocalized? + if (sUnlocalized.find(subdir) != sUnlocalized.end()) + { + // This subdir is known to be unlocalized. Remember that. + found = sLocalized.insert(StringMap::value_type(subdir, "")).first; + } + else + { + // We do not recognize this subdir. Investigate. + std::string subdir_path(add(getDefaultSkinDir(), subdir)); + if (fileExists(add(subdir_path, "en"))) + { + // defaultSkinDir/subdir contains subdir "en". That's our + // default language; this subdir is localized. + found = sLocalized.insert(StringMap::value_type(subdir, "en")).first; + } + else if (fileExists(add(subdir_path, "en-us"))) + { + // defaultSkinDir/subdir contains subdir "en-us" but not "en". + // Set as default language; this subdir is localized. + found = sLocalized.insert(StringMap::value_type(subdir, "en-us")).first; + } + else + { + // defaultSkinDir/subdir contains neither "en" nor "en-us". + // Assume it's not localized. Remember that assumption. + found = sLocalized.insert(StringMap::value_type(subdir, "")).first; + } + } + } + // Every code path above should have resulted in 'found' becoming a valid + // iterator to an entry in sLocalized. + llassert(found != sLocalized.end()); + + // Now -- is this subdir localized, or not? The answer determines what + // subdirectories we check (under subdir) for the requested filename. + std::vector subsubdirs; + if (found->second.empty()) + { + // subdir is not localized. filename should be located directly within it. + subsubdirs.push_back(""); + } + else + { + // subdir is localized, and found->second is the default language + // directory within it. Check both the default language and the + // current language -- if it differs from the default, of course. + subsubdirs.push_back(found->second); + if (mLanguage != found->second) + { + subsubdirs.push_back(mLanguage); + } + } + + // Build results vector. + std::vector results; + // The process we use depends on 'constraint'. + if (constraint != CURRENT_SKIN) // meaning ALL_SKINS + { + // ALL_SKINS is simpler: just return every pathname generated by + // walkSearchSkinDirs(). Tricky bit: walkSearchSkinDirs() passes its + // FUNCTION the subsubdir as well as the full pathname. We just want + // the full pathname. + walkSearchSkinDirs(subdir, subsubdirs, filename, + boost::bind(push_back, boost::ref(results), _2)); + } + else // CURRENT_SKIN + { + // CURRENT_SKIN turns out to be a bit of a misnomer because we might + // still return files from two different skins. In any case, this + // value of 'constraint' means we will return at most two paths: one + // for the default language, one for the current language (supposing + // those differ). + // It is important to allow a user to override only the localization + // for a particular file, for all viewer installs, without also + // overriding the default-language file. + // It is important to allow a user to override only the default- + // language file, for all viewer installs, without also overriding the + // applicable localization of that file. + // Therefore, treat the default language and the current language as + // two separate cases. For each, capture the most-specialized file + // that exists. + // Use a map keyed by subsubdir (i.e. language code). This allows us + // to handle the case of a single subsubdirs entry with the same logic + // that handles two. For every real file path generated by + // walkSearchSkinDirs(), update the map entry for its subsubdir. + StringMap path_for; + walkSearchSkinDirs(subdir, subsubdirs, filename, + boost::bind(store_in_map, boost::ref(path_for), _1, _2)); + // Now that we have a path for each of the default language and the + // current language, copy them -- in proper order -- into results. + // Don't drive this by walking the map itself: it matters that we + // generate results in the same order as subsubdirs. + BOOST_FOREACH(std::string subsubdir, subsubdirs) + { + StringMap::const_iterator found(path_for.find(subsubdir)); + if (found != path_for.end()) + { + results.push_back(found->second); + } + } + } + + LL_DEBUGS("LLDir") << empty; + const char* comma = ""; + BOOST_FOREACH(std::string path, results) + { + LL_CONT << comma << "'" << path << "'"; + comma = ", "; + } + LL_CONT << LL_ENDL; + + return results; } std::string LLDir::getTempFilename() const @@ -657,7 +873,7 @@ std::string LLDir::getTempFilename() const } // static -std::string LLDir::getScrubbedFileName(const std::string uncleanFileName) +std::string LLDir::getScrubbedFileName(const std::string& uncleanFileName) { std::string name(uncleanFileName); std::string illegalChars(getForbiddenFileChars()); @@ -668,8 +884,8 @@ std::string LLDir::getScrubbedFileName(const std::string uncleanFileName) // replace any illegal file chars with and underscore '_' for( unsigned int i = 0; i < illegalChars.length(); i++ ) { - int j = -1; - while((j = name.find(illegalChars[i])) > -1) + size_t j = std::string::npos; + while ((j = name.find(illegalChars[i])) != std::string::npos) { name[j] = '_'; } @@ -683,6 +899,19 @@ std::string LLDir::getForbiddenFileChars() return "\\/:*?\"<>|"; } +// static +std::string LLDir::getGridSpecificDir( const std::string& in, const std::string& grid ) +{ + std::string ret; + if (!grid.empty()) + { + std::string gridlower(grid); + LLStringUtil::toLower(gridlower); + ret = in + "@" + gridlower; + } + return ret; +} + void LLDir::setLindenUserDir(const std::string &grid, const std::string &first, const std::string &last) { // if both first and last aren't set, assume we're grabbing the cached dir @@ -692,15 +921,7 @@ void LLDir::setLindenUserDir(const std::string &grid, const std::string &first, // utterly consistent with our firstname/lastname case. std::string userlower(first+"_"+last); LLStringUtil::toLower(userlower); - mLindenUserDir = add(getOSUserAppDir(), userlower); - - if (!grid.empty()) - { - std::string gridlower(grid); - LLStringUtil::toLower(gridlower); - mLindenUserDir += "@"; - mLindenUserDir += gridlower; - } + mLindenUserDir = getGridSpecificDir(grid, add(getOSUserAppDir(), userlower)); } else { @@ -737,7 +958,7 @@ void LLDir::makePortable() initAppDirs(mAppName); // This is kinda lazy, but it's probably the quickest, most uniform way. } -void LLDir::setChatLogsDir(const std::string &path) +void LLDir::setChatLogsDir( const std::string& path) { if (!path.empty() ) { @@ -749,6 +970,11 @@ void LLDir::setChatLogsDir(const std::string &path) } } +void LLDir::updatePerAccountChatLogsDir(const std::string &grid) +{ + mPerAccountChatLogsDir = getGridSpecificDir(grid, add(getChatLogsDir(), mUserName)); +} + void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string &first, const std::string &last) { // if both first and last aren't set, assume we're grabbing the cached dir @@ -758,14 +984,9 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string // utterly consistent with our firstname/lastname case. std::string userlower(first+"_"+last); LLStringUtil::toLower(userlower); - mPerAccountChatLogsDir = add(getChatLogsDir(), userlower); - if (!grid.empty()) - { - std::string gridlower(grid); - LLStringUtil::toLower(gridlower); - mPerAccountChatLogsDir += "@"; - mPerAccountChatLogsDir += gridlower; - } + + mUserName = userlower; + updatePerAccountChatLogsDir(grid); } else { @@ -773,21 +994,59 @@ void LLDir::setPerAccountChatLogsDir(const std::string &grid, const std::string } } -void LLDir::setSkinFolder(const std::string &skin_folder) +void LLDir::setSkinFolder(const std::string &skin_folder, const std::string& language) { - mSkinDir = getSkinBaseDir(); - append(mSkinDir, skin_folder); + LL_DEBUGS("LLDir") << "Setting skin '" << skin_folder << "', language '" << language << "'" + << LL_ENDL; + mSkinName = skin_folder; + mLanguage = language; - // user modifications to current skin - // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle - mUserSkinDir = getOSUserAppDir(); - append(mUserSkinDir, "skins_sg1"); - append(mUserSkinDir, skin_folder); + // This method is called multiple times during viewer initialization. Each + // time it's called, reset mSearchSkinDirs. + mSearchSkinDirs.clear(); // base skin which is used as fallback for all skinned files // e.g. c:\program files\secondlife\skins\default mDefaultSkinDir = getSkinBaseDir(); append(mDefaultSkinDir, "default"); + // This is always the most general of the search skin directories. + addSearchSkinDir(mDefaultSkinDir); + + mSkinDir = getSkinBaseDir(); + append(mSkinDir, skin_folder); + // Next level of generality is a skin installed with the viewer. + addSearchSkinDir(mSkinDir); + + // user modifications to skins, current and default + // e.g. c:\documents and settings\users\username\application data\second life\skins\dazzle + mUserSkinDir = getOSUserAppDir(); + append(mUserSkinDir, "skins_sg1"); + mUserDefaultSkinDir = mUserSkinDir; + append(mUserDefaultSkinDir, "default"); + append(mUserSkinDir, skin_folder); + // Next level of generality is user modifications to default skin... + addSearchSkinDir(mUserDefaultSkinDir); + // then user-defined skins. + addSearchSkinDir(mUserSkinDir); +} + +void LLDir::addSearchSkinDir(const std::string& skindir) +{ + if (std::find(mSearchSkinDirs.begin(), mSearchSkinDirs.end(), skindir) == mSearchSkinDirs.end()) + { + LL_DEBUGS("LLDir") << "search skin: '" << skindir << "'" << LL_ENDL; + mSearchSkinDirs.push_back(skindir); + } +} + +std::string LLDir::getSkinFolder() const +{ + return mSkinName; +} + +std::string LLDir::getLanguage() const +{ + return mLanguage; } bool LLDir::setCacheDir(const std::string &path) diff --git a/indra/llvfs/lldir.h b/indra/llvfs/lldir.h index 2be6dd3ec..34b5ebf55 100644 --- a/indra/llvfs/lldir.h +++ b/indra/llvfs/lldir.h @@ -78,7 +78,7 @@ class LLDir virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask) = 0; virtual std::string getCurPath() = 0; - virtual BOOL fileExists(const std::string &filename) const = 0; + virtual bool fileExists(const std::string &filename) const = 0; const std::string findFile(const std::string& filename, const std::vector filenames) const; const std::string findFile(const std::string& filename, const std::string& searchPath1 = "", const std::string& searchPath2 = "", const std::string& searchPath3 = "") const; @@ -103,11 +103,13 @@ class LLDir const std::string &getOSCacheDir() const; // location of OS-specific cache folder (may be empty string) const std::string &getCAFile() const; // File containing TLS certificate authorities const std::string &getDirDelimiter() const; // directory separator for platform (ie. '\' or '/' or ':') - const std::string &getSkinDir() const; // User-specified skin folder. - const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin const std::string &getDefaultSkinDir() const; // folder for default skin. e.g. c:\program files\second life\skins\default + const std::string &getSkinDir() const; // User-specified skin folder. + const std::string &getUserDefaultSkinDir() const; // dir with user modifications to default skin + const std::string &getUserSkinDir() const; // User-specified skin folder with user modifications. e.g. c:\documents and settings\username\application data\second life\skins\curskin const std::string getSkinBaseDir() const; // folder that contains all installed skins (not user modifications). e.g. c:\program files\second life\skins const std::string &getLLPluginDir() const; // Directory containing plugins and plugin shell + const std::string &getUserName() const; // Expanded filename std::string getExpandedFilename(ELLPath location, const std::string &filename) const; @@ -120,25 +122,80 @@ class LLDir std::string getExtension(const std::string& filepath) const; // Excludes '.', e.g getExtension("foo.wav") == "wav" // these methods search the various skin paths for the specified file in the following order: - // getUserSkinDir(), getSkinDir(), getDefaultSkinDir() - std::string findSkinnedFilename(const std::string &filename) const; - std::string findSkinnedFilename(const std::string &subdir, const std::string &filename) const; - std::string findSkinnedFilename(const std::string &subdir1, const std::string &subdir2, const std::string &filename) const; + // getUserSkinDir(), getUserDefaultSkinDir(), getSkinDir(), getDefaultSkinDir() + /// param value for findSkinnedFilenames(), explained below + enum ESkinConstraint { CURRENT_SKIN, ALL_SKINS }; + /** + * Given a filename within skin, return an ordered sequence of paths to + * search. Nonexistent files will be filtered out -- which means that the + * vector might be empty. + * + * @param subdir Identify top-level skin subdirectory by passing one of + * LLDir::XUI (file lives under "xui" subtree), LLDir::TEXTURES (file + * lives under "textures" subtree), LLDir::SKINBASE (file lives at top + * level of skin subdirectory). + * @param filename Desired filename within subdir within skin, e.g. + * "panel_login.xml". DO NOT prepend (e.g.) "xui" or the desired language. + * @param constraint Callers perform two different kinds of processing. + * When fetching a XUI file, for instance, the existence of @a filename in + * the specified skin completely supercedes any @a filename in the default + * skin. For that case, leave the default @a constraint=CURRENT_SKIN. The + * returned vector will contain only + * ".../current_skin/xui/en/filename", + * ".../current_skin/xui/current_language/filename". + * But for (e.g.) "strings.xml", we want a given skin to be able to + * override only specific entries from the default skin. Any string not + * defined in the specified skin will be sought in the default skin. For + * that case, pass @a constraint=ALL_SKINS. The returned vector will + * contain at least ".../default/xui/en/strings.xml", + * ".../default/xui/current_language/strings.xml", + * ".../current_skin/xui/en/strings.xml", + * ".../current_skin/xui/current_language/strings.xml". + */ + std::vector findSkinnedFilenames(const std::string& subdir, + const std::string& filename, + ESkinConstraint constraint=CURRENT_SKIN) const; + /// Values for findSkinnedFilenames(subdir) parameter + static const char *XUI, *TEXTURES, *SKINBASE; + /** + * Return the base-language pathname from findSkinnedFilenames(), or + * the empty string if no such file exists. Parameters are identical to + * findSkinnedFilenames(). This is shorthand for capturing the vector + * returned by findSkinnedFilenames(), checking for empty() and then + * returning front(). + */ + std::string findSkinnedFilenameBaseLang(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint=CURRENT_SKIN) const; + /** + * Return the "most localized" pathname from findSkinnedFilenames(), or + * the empty string if no such file exists. Parameters are identical to + * findSkinnedFilenames(). This is shorthand for capturing the vector + * returned by findSkinnedFilenames(), checking for empty() and then + * returning back(). + */ + std::string findSkinnedFilename(const std::string &subdir, + const std::string &filename, + ESkinConstraint constraint=CURRENT_SKIN) const; // random filename in common temporary directory std::string getTempFilename() const; // For producing safe download file names from potentially unsafe ones - static std::string getScrubbedFileName(const std::string uncleanFileName); + static std::string getScrubbedFileName(const std::string& uncleanFileName); static std::string getForbiddenFileChars(); + static std::string getGridSpecificDir( const std::string& in, const std::string& grid ); void setDumpDir( const std::string& path ); void makePortable(); virtual void setChatLogsDir(const std::string &path); // Set the chat logs dir to this user's dir - virtual void setPerAccountChatLogsDir(const std::string &grid, const std::string &first, const std::string &last); // Set the per user chat log directory. + virtual void setPerAccountChatLogsDir(const std::string &grid, const std::string &first, const std::string& last); // Set the per user chat log directory. virtual void setLindenUserDir(const std::string& grid, const std::string& first, const std::string& last); // Set the linden user dir to this user's dir - virtual void setSkinFolder(const std::string &skin_folder); + virtual void setSkinFolder(const std::string &skin_folder, const std::string& language); + virtual std::string getSkinFolder() const; + virtual std::string getLanguage() const; virtual bool setCacheDir(const std::string &path); + virtual void updatePerAccountChatLogsDir(const std::string &grid); virtual void dumpCurrentDirectories(); @@ -156,6 +213,16 @@ protected: // Does an add() or append() call need a directory delimiter? typedef std::pair SepOff; SepOff needSep(const std::string& path, const std::string& name) const; + // build mSearchSkinDirs without adding duplicates + void addSearchSkinDir(const std::string& skindir); + + // Internal to findSkinnedFilenames() + template + void walkSearchSkinDirs(const std::string& subdir, + const std::vector& subsubdirs, + const std::string& filename, + const FUNCTION& function) const; + std::string mAppName; // install directory under progams/ ie "SecondLife" std::string mExecutablePathAndName; // full path + Filename of .exe std::string mExecutableFilename; // Filename of .exe @@ -173,12 +240,21 @@ protected: std::string mDefaultCacheDir; // default cache diretory std::string mOSCacheDir; // operating system cache dir std::string mDirDelimiter; + std::string mSkinName; // caller-specified skin name std::string mSkinBaseDir; // Base for skins paths. - std::string mSkinDir; // Location for current skin info. std::string mDefaultSkinDir; // Location for default skin info. + std::string mSkinDir; // Location for current skin info. + std::string mUserDefaultSkinDir; // Location for default skin info. std::string mUserSkinDir; // Location for user-modified skin info. + // Skin directories to search, most general to most specific. This order + // works well for composing fine-grained files, in which an individual item + // in a specific file overrides the corresponding item in more general + // files. Of course, for a file-level search, iterate backwards. + std::vector mSearchSkinDirs; + std::string mLanguage; // Current viewer language std::string mLLPluginDir; // Location for plugins and plugin shell static std::string sDumpDir; // Per-run crash report subdir of log directory. + std::string mUserName; // Current user name }; void dir_exists_or_crash(const std::string &dir_name); diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp index d677c75a8..738508b34 100644 --- a/indra/llvfs/lldir_linux.cpp +++ b/indra/llvfs/lldir_linux.cpp @@ -257,7 +257,7 @@ std::string LLDir_Linux::getCurPath() } -BOOL LLDir_Linux::fileExists(const std::string &filename) const +bool LLDir_Linux::fileExists(const std::string &filename) const { struct stat stat_data; // Check the age of the file diff --git a/indra/llvfs/lldir_linux.h b/indra/llvfs/lldir_linux.h index 46bf91c69..58f488da6 100644 --- a/indra/llvfs/lldir_linux.h +++ b/indra/llvfs/lldir_linux.h @@ -53,7 +53,7 @@ public: virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp index 73d8b677a..29ab1a5c9 100644 --- a/indra/llvfs/lldir_mac.cpp +++ b/indra/llvfs/lldir_mac.cpp @@ -267,7 +267,7 @@ std::string LLDir_Mac::getCurPath() -BOOL LLDir_Mac::fileExists(const std::string &filename) const +bool LLDir_Mac::fileExists(const std::string &filename) const { struct stat stat_data; // Check the age of the file diff --git a/indra/llvfs/lldir_mac.h b/indra/llvfs/lldir_mac.h index d99f9e39e..5e3fab3fa 100644 --- a/indra/llvfs/lldir_mac.h +++ b/indra/llvfs/lldir_mac.h @@ -52,7 +52,7 @@ public: virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - virtual BOOL fileExists(const std::string &filename) const; + virtual bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/llvfs/lldir_solaris.cpp b/indra/llvfs/lldir_solaris.cpp index 532ba67d4..a6e1289a0 100644 --- a/indra/llvfs/lldir_solaris.cpp +++ b/indra/llvfs/lldir_solaris.cpp @@ -278,7 +278,7 @@ std::string LLDir_Solaris::getCurPath() } -BOOL LLDir_Solaris::fileExists(const std::string &filename) const +bool LLDir_Solaris::fileExists(const std::string &filename) const { struct stat stat_data; // Check the age of the file diff --git a/indra/llvfs/lldir_solaris.h b/indra/llvfs/lldir_solaris.h index 88da8500d..c2d660554 100644 --- a/indra/llvfs/lldir_solaris.h +++ b/indra/llvfs/lldir_solaris.h @@ -53,7 +53,7 @@ public: virtual std::string getCurPath(); virtual U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ bool fileExists(const std::string &filename) const; private: DIR *mDirp; diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp index 4dc078bab..810cc811b 100644 --- a/indra/llvfs/lldir_win32.cpp +++ b/indra/llvfs/lldir_win32.cpp @@ -48,60 +48,28 @@ LLDir_Win32::LLDir_Win32() WCHAR w_str[MAX_PATH]; - HRESULT (WINAPI* pSHGetKnownFolderPath)(REFKNOWNFOLDERID rfid, DWORD dwFlags, HANDLE hToken, PWSTR *ppszPath) = NULL; - HMODULE shell = LoadLibrary(L"shell32"); - if(shell) //SHGetSpecialFolderPath is deprecated from Vista an onwards. Try to use SHGetKnownFolderPath if it's available - { - pSHGetKnownFolderPath = (HRESULT (WINAPI *)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *))GetProcAddress(shell, "SHGetKnownFolderPath"); - } + WCHAR* pPath = NULL; + if(SHGetKnownFolderPath(FOLDERID_RoamingAppData, 0, NULL, &pPath) == S_OK) + wcscpy_s(w_str, pPath); - // Application Data is where user settings go - if(pSHGetKnownFolderPath) - { - WCHAR* pPath = NULL; - if((*pSHGetKnownFolderPath)(FOLDERID_RoamingAppData, 0, NULL, &pPath) == S_OK) - wcscpy_s(w_str,pPath); - else - SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str ); - if(pPath) - CoTaskMemFree(pPath); - } - else //XP doesn't support SHGetKnownFolderPath - { - SHGetFolderPath(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str ); - } + CoTaskMemFree(pPath); + pPath = NULL; mOSUserDir = utf16str_to_utf8str(llutf16string(w_str)); // We want cache files to go on the local disk, even if the // user is on a network with a "roaming profile". // - // On XP this is: - // C:\Docments and Settings\James\Local Settings\Application Data - // On Vista this is: - // C:\Users\James\AppData\Local + // On Vista and above this is: + // C:\Users\\AppData\Local // // We used to store the cache in AppData\Roaming, and the installer // cleans up that version on upgrade. JC + if(SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &pPath) == S_OK) + wcscpy_s(w_str, pPath); - - if(pSHGetKnownFolderPath) - { - WCHAR* pPath = NULL; - if((*pSHGetKnownFolderPath)(FOLDERID_LocalAppData, 0, NULL, &pPath) == S_OK) - wcscpy_s(w_str,pPath); - else - SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str ); - if(pPath) - CoTaskMemFree(pPath); - } - else //XP doesn't support SHGetKnownFolderPath - { - SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, NULL, SHGFP_TYPE_DEFAULT, w_str ); - } - - if(shell) - FreeLibrary(shell); + CoTaskMemFree(pPath); + pPath = NULL; mOSCacheDir = utf16str_to_utf8str(llutf16string(w_str)); @@ -288,7 +256,7 @@ std::string LLDir_Win32::getCurPath() } -BOOL LLDir_Win32::fileExists(const std::string &filename) const +bool LLDir_Win32::fileExists(const std::string &filename) const { llstat stat_data; // Check the age of the file diff --git a/indra/llvfs/lldir_win32.h b/indra/llvfs/lldir_win32.h index 4421b87f0..ed2f916d4 100644 --- a/indra/llvfs/lldir_win32.h +++ b/indra/llvfs/lldir_win32.h @@ -50,7 +50,7 @@ public: /*virtual*/ std::string getCurPath(); /*virtual*/ U32 countFilesInDir(const std::string &dirname, const std::string &mask); - /*virtual*/ BOOL fileExists(const std::string &filename) const; + /*virtual*/ bool fileExists(const std::string &filename) const; /*virtual*/ std::string getLLPluginLauncher(); /*virtual*/ std::string getLLPluginFilename(std::string base_name); diff --git a/indra/llvfs/lldiriterator.cpp b/indra/llvfs/lldiriterator.cpp index 471d956e9..0cdf45623 100644 --- a/indra/llvfs/lldiriterator.cpp +++ b/indra/llvfs/lldiriterator.cpp @@ -49,7 +49,11 @@ private: LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) : mIsValid(false) { +#if LL_WINDOWS + fs::path dir_path(utf8str_to_utf16str(dirname).c_str()); +#else fs::path dir_path(dirname); +#endif bool is_dir = false; @@ -58,11 +62,7 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) { is_dir = fs::is_directory(dir_path); } -#if BOOST_FILESYSTEM_VERSION >= 3 - catch (fs::filesystem_error& e) -#else - catch (fs::basic_filesystem_error& e) -#endif + catch (const fs::filesystem_error& e) { LL_WARNS() << e.what() << LL_ENDL; return; @@ -79,13 +79,9 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) { mIter = fs::directory_iterator(dir_path); } -#if BOOST_FILESYSTEM_VERSION >= 3 - catch (fs::filesystem_error& e) -#else - catch (fs::basic_filesystem_error& e) -#endif + catch (const fs::filesystem_error& e) { - LL_ERRS() << e.what() << LL_ENDL; + LL_WARNS() << e.what() << LL_ENDL; return; } @@ -101,7 +97,7 @@ LLDirIterator::Impl::Impl(const std::string &dirname, const std::string &mask) } catch (boost::regex_error& e) { - LL_ERRS() << "\"" << exp << "\" is not a valid regular expression: " + LL_WARNS() << "\"" << exp << "\" is not a valid regular expression: " << e.what() << LL_ENDL; return; } @@ -125,20 +121,26 @@ bool LLDirIterator::Impl::next(std::string &fname) fs::directory_iterator end_itr; // default construction yields past-the-end bool found = false; - while (mIter != end_itr && !found) - { - boost::smatch match; -#if BOOST_FILESYSTEM_VERSION >= 3 - std::string name = mIter->path().filename().string(); -#else - std::string name = mIter->path().filename(); -#endif - if ((found = boost::regex_match(name, match, mFilterExp))) - { - fname = name; - } - ++mIter; + // Check if path is a directory. + try + { + while (mIter != end_itr && !found) + { + boost::smatch match; + std::string name = mIter->path().filename().string(); + found = boost::regex_match(name, match, mFilterExp); + if (found) + { + fname = name; + } + + ++mIter; + } + } + catch (const fs::filesystem_error& e) + { + LL_WARNS() << e.what() << LL_ENDL; } return found; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index b605cbb2e..a29a49481 100644 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -657,7 +657,6 @@ set(viewer_HEADER_FILES llavatarpropertiesprocessor.h llavatarrenderinfoaccountant.h llbox.h - llcallbacklist.h llcallingcard.h llcapabilitylistener.h llcaphttpsender.h @@ -1644,6 +1643,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ${Boost_REGEX_LIBRARY} ${Boost_SYSTEM_LIBRARY} ${Boost_DATE_TIME_LIBRARY} + ${Boost_CHRONO_LIBRARY} ${DBUSGLIB_LIBRARIES} ${OPENGL_LIBRARIES} ${FMOD_LIBRARY} # must come after LLAudio @@ -1662,7 +1662,7 @@ target_link_libraries(${VIEWER_BINARY_NAME} ) if (LINUX) - set(product Singularity-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}) + set(product ${VIEWER_CHANNEL_NOSPACE}-${ARCH}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}) # These are the generated targets that are copied to package/ set(COPY_INPUT_DEPENDENCIES @@ -1810,11 +1810,11 @@ if (INSTALL) endif (INSTALL) if (PACKAGE) - set(SYMBOL_NAME ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/Singularity-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}-symbols) + set(SYMBOL_NAME ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/${VIEWER_CHANNEL_NOSPACE}-${VIEWER_SHORT_VERSION}.${VIEWER_VERSION_REVISION}-symbols) set(SYMBOL_SEARCH_DIRS "") if (WINDOWS) list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}") - set(VIEWER_SYMBOL_FILE "${SYMBOL_NAME}-${PREBUILT_TYPE}.tar.bz2") + set(VIEWER_SYMBOL_FILE "${SYMBOL_NAME}-${AUTOBUILD_PLATFORM_NAME}.tar.bz2") # slplugin.exe failing symbols dump - need to debug, might have to do with updated version of google breakpad # set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX} slplugin.exe") set(VIEWER_EXE_GLOBS "${VIEWER_BINARY_NAME}${CMAKE_EXECUTABLE_SUFFIX}") @@ -1834,7 +1834,7 @@ if (PACKAGE) endif (DARWIN) if (LINUX) list(APPEND SYMBOL_SEARCH_DIRS "${CMAKE_CURRENT_BINARY_DIR}/packaged") - set(VIEWER_SYMBOL_FILE "${SYMBOL_NAME}-linux-${ARCH}.tar.bz2") + set(VIEWER_SYMBOL_FILE "${SYMBOL_NAME}-${AUTOBUILD_PLATFORM_NAME}.tar.bz2") set(VIEWER_EXE_GLOBS "${VIEWER_BRANDING_ID}-do-not-run-directly SLPlugin") set(VIEWER_LIB_GLOB "*${CMAKE_SHARED_MODULE_SUFFIX}*") set(VIEWER_COPY_MANIFEST copy_l_viewer_manifest) diff --git a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl index 13409832a..09dff0e12 100644 --- a/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl +++ b/indra/newview/app_settings/shaders/class1/deferred/fxaaF.glsl @@ -258,6 +258,10 @@ A. Or use FXAA_GREEN_AS_LUMA. #define FXAA_GLSL_130 0 #endif /*--------------------------------------------------------------------------*/ +#ifndef FXAA_GLSL_400 + #define FXAA_GLSL_400 0 +#endif +/*--------------------------------------------------------------------------*/ #ifndef FXAA_HLSL_3 #define FXAA_HLSL_3 0 #endif @@ -344,8 +348,8 @@ A. Or use FXAA_GREEN_AS_LUMA. // 1 = API supports gather4 on alpha channel. // 0 = API does not support gather4 on alpha channel. // - #if (FXAA_GLSL_130 == 0) - #define FXAA_GATHER4_ALPHA 0 + #if (FXAA_GLSL_400 == 1) + #define FXAA_GATHER4_ALPHA 1 #endif #if (FXAA_HLSL_5 == 1) #define FXAA_GATHER4_ALPHA 1 @@ -654,7 +658,7 @@ NOTE the other tuning knobs are now in the shader function inputs! API PORTING ============================================================================*/ -#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) +#if (FXAA_GLSL_120 == 1) || (FXAA_GLSL_130 == 1) || (FXAA_GLSL_400 == 1) #define FxaaBool bool #define FxaaDiscard discard #define FxaaFloat float @@ -716,6 +720,16 @@ NOTE the other tuning knobs are now in the shader function inputs! #endif #endif /*--------------------------------------------------------------------------*/ +#if (FXAA_GLSL_400 == 1) + // Requires "#version 400" or better + #define FxaaTexTop(t, p) textureLod(t, p, 0.0) + #define FxaaTexOff(t, p, o, r) textureLodOffset(t, p, 0.0, o) + #define FxaaTexAlpha4(t, p) textureGather(t, p, 3) + #define FxaaTexOffAlpha4(t, p, o) textureGatherOffset(t, p, o, 3) + #define FxaaTexGreen4(t, p) textureGather(t, p, 1) + #define FxaaTexOffGreen4(t, p, o) textureGatherOffset(t, p, o, 1) +#endif +/*--------------------------------------------------------------------------*/ #if (FXAA_HLSL_3 == 1) || (FXAA_360 == 1) || (FXAA_PS3 == 1) #define FxaaInt2 float2 #define FxaaTex sampler2D diff --git a/indra/newview/floaterlocalassetbrowse.cpp b/indra/newview/floaterlocalassetbrowse.cpp index b7a404e2f..c53705cf9 100644 --- a/indra/newview/floaterlocalassetbrowse.cpp +++ b/indra/newview/floaterlocalassetbrowse.cpp @@ -131,7 +131,7 @@ LocalBitmap::LocalBitmap(std::string fullpath) if (decodeSelf(raw_image)) { /* creating a shell LLViewerTexture and fusing raw image into it */ - LLViewerFetchedTexture* viewer_image = new LLViewerFetchedTexture( "file://"+filename, id, LOCAL_USE_MIPMAPS ); + LLViewerFetchedTexture* viewer_image = new LLViewerFetchedTexture( "file://"+filename, FTT_LOCAL_FILE, id, LOCAL_USE_MIPMAPS ); viewer_image->createGLTexture( LOCAL_DISCARD_LEVEL, raw_image ); viewer_image->setCachedRawImage(-1,raw_image); diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 72fcc6b89..e2a360c76 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -280,7 +280,7 @@ BOOL gUseWireframe = FALSE; LLVFS* gStaticVFS = NULL; LLMemoryInfo gSysMemory; -U64 gMemoryAllocated = 0; // updated in display_stats() in llviewerdisplay.cpp +U64Bytes gMemoryAllocated(0); // updated in display_stats() in llviewerdisplay.cpp std::string gLastVersionChannel; @@ -653,7 +653,7 @@ bool LLAppViewer::init() // set skin search path to default, will be overridden later // this allows simple skinned file lookups to work - gDirUtilp->setSkinFolder("default"); + gDirUtilp->setSkinFolder("default", "en-us"); initLogging(); @@ -726,16 +726,20 @@ bool LLAppViewer::init() LL_INFOS("InitInfo") << "Threads initialized." << LL_ENDL ; // Load art UUID information, don't require these strings to be declared in code. - std::string colors_base_filename = gDirUtilp->findSkinnedFilename("colors_base.xml"); - LL_DEBUGS("InitInfo") << "Loading base colors from " << colors_base_filename << LL_ENDL; - gColors.loadFromFileLegacy(colors_base_filename, FALSE, TYPE_COL4U); - - // Load overrides from user colors file - std::string user_colors_filename = gDirUtilp->findSkinnedFilename("colors.xml"); - LL_DEBUGS("InitInfo") << "Loading user colors from " << user_colors_filename << LL_ENDL; - if (gColors.loadFromFileLegacy(user_colors_filename, FALSE, TYPE_COL4U) == 0) + for(auto& colors_base_filename : gDirUtilp->findSkinnedFilenames(LLDir::SKINBASE, "colors_base.xml", LLDir::ALL_SKINS)) { - LL_DEBUGS("InitInfo") << "Cannot load user colors from " << user_colors_filename << LL_ENDL; + LL_DEBUGS("InitInfo") << "Loading colors from " << colors_base_filename << LL_ENDL; + gColors.loadFromFileLegacy(colors_base_filename, FALSE, TYPE_COL4U); + } + // Load overrides from user colors file + for (auto& colors_base_filename : gDirUtilp->findSkinnedFilenames(LLDir::SKINBASE, "colors.xml", LLDir::ALL_SKINS)) + { + gColors.loadFromFileLegacy(colors_base_filename, FALSE, TYPE_COL4U); + LL_DEBUGS("InitInfo") << "Loading user colors from " << colors_base_filename << LL_ENDL; + if (gColors.loadFromFileLegacy(colors_base_filename, FALSE, TYPE_COL4U) == 0) + { + LL_DEBUGS("InitInfo") << "Cannot load user colors from " << colors_base_filename << LL_ENDL; + } } // Widget construction depends on LLUI being initialized @@ -748,6 +752,11 @@ bool LLAppViewer::init() &LLUI::getScaleFactor()); LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ; + // NOW LLUI::getLanguage() should work. gDirUtilp must know the language + // for this session ASAP so all the file-loading commands that follow, + // that use findSkinnedFilenames(), will include the localized files. + gDirUtilp->setSkinFolder(gDirUtilp->getSkinFolder(), LLUI::getLanguage()); + LLUICtrlFactory::getInstance()->setupPaths(); // update paths with correct language set // Setup LLTrans after LLUI::initClass has been called. @@ -956,9 +965,8 @@ bool LLAppViewer::init() // get RAM data from XML std::stringstream minRAMString(LLNotificationTemplates::instance().getGlobalString("UnsupportedRAMAmount")); - U64 minRAM = 0; + U64Bytes minRAM; minRAMString >> minRAM; - minRAM = minRAM * 1024 * 1024; if(!LLFeatureManager::getInstance()->isGPUSupported() && LLFeatureManager::getInstance()->getGPUClass() != GPU_CLASS_UNKNOWN) { @@ -1038,7 +1046,7 @@ void LLAppViewer::initMaxHeapSize() //F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ; - F32 max_heap_size_gb = gSavedSettings.getF32("MaxHeapSize") ; + F32Gigabytes max_heap_size_gb = (F32Gigabytes)gSavedSettings.getF32("MaxHeapSize") ; //This is all a bunch of CRAP. We run LAA on windows. 64bit windows supports LAA out of the box. 32bit does not, unless PAE is on. #if LL_WINDOWS @@ -1052,7 +1060,7 @@ void LLAppViewer::initMaxHeapSize() if(fnIsWow64Process && fnIsWow64Process(GetCurrentProcess(), &bWow64Process) && bWow64Process) { - max_heap_size_gb = 3.7f; + max_heap_size_gb = F32Gigabytes(3.7f); } else if(ERROR_SUCCESS == RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Memory Management"), &hKey)) { @@ -1061,7 +1069,7 @@ void LLAppViewer::initMaxHeapSize() if(ERROR_SUCCESS == RegQueryValueEx(hKey, TEXT("PhysicalAddressExtension"), NULL, NULL, (LPBYTE)&dwResult, &dwSize)) { if(dwResult) - max_heap_size_gb = 3.7f; + max_heap_size_gb = F32Gigabytes(3.7f); } RegCloseKey(hKey); } @@ -1325,7 +1333,7 @@ bool LLAppViewer::mainLoop() // yield cooperatively when not running as foreground window if ( gNoRender || (gViewerWindow && !gViewerWindow->getWindow()->getVisible()) - || !gFocusMgr.getAppHasFocus()) + || (!gFocusMgr.getAppHasFocus() && !AIFilePicker::activePicker) ) { // Sleep if we're not rendering, or the window is minimized. S32 milliseconds_to_sleep = llclamp(gSavedSettings.getS32("BackgroundYieldTime"), 0, 1000); @@ -2413,7 +2421,11 @@ bool LLAppViewer::initConfiguration() const LLControlVariable* skinfolder = gSavedSettings.getControl("SkinCurrent"); if(skinfolder && LLStringUtil::null != skinfolder->getValue().asString()) { - gDirUtilp->setSkinFolder(skinfolder->getValue().asString()); + // Examining "Language" may not suffice -- see LLUI::getLanguage() + // logic. Unfortunately LLUI::getLanguage() doesn't yet do us much + // good because we haven't yet called LLUI::initClass(). + gDirUtilp->setSkinFolder(skinfolder->getValue().asString(), + gSavedSettings.getString("Language")); } // XUI:translate @@ -2695,8 +2707,8 @@ void LLAppViewer::writeSystemInfo() gDebugInfo["CPUInfo"]["CPUSSE"] = gSysCPU.hasSSE(); gDebugInfo["CPUInfo"]["CPUSSE2"] = gSysCPU.hasSSE2(); - gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB()); - gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated>>10); // MB -> KB + gDebugInfo["RAMInfo"]["Physical"] = (LLSD::Integer)(gSysMemory.getPhysicalMemoryKB().value()); + gDebugInfo["RAMInfo"]["Allocated"] = (LLSD::Integer)(gMemoryAllocated.valueInUnits()); gDebugInfo["OSInfo"] = getOSInfo().getOSStringSimple(); // The user is not logged on yet, but record the current grid choice login url diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index f461c259b..777f06207 100644 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -333,7 +333,7 @@ extern BOOL gUseWireframe; extern LLVFS *gStaticVFS; extern LLMemoryInfo gSysMemory; -extern U64 gMemoryAllocated; +extern U64Bytes gMemoryAllocated; extern std::string gLastVersionChannel; diff --git a/indra/newview/llcallbacklist.cpp b/indra/newview/llcallbacklist.cpp index 59ecbdd0e..cdc664381 100644 --- a/indra/newview/llcallbacklist.cpp +++ b/indra/newview/llcallbacklist.cpp @@ -70,7 +70,7 @@ void LLCallbackList::addFunction( callback_t func, void *data) } -BOOL LLCallbackList::containsFunction( callback_t func, void *data) +bool LLCallbackList::containsFunction( callback_t func, void *data) { callback_pair_t t(func, data); callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); @@ -85,7 +85,7 @@ BOOL LLCallbackList::containsFunction( callback_t func, void *data) } -BOOL LLCallbackList::deleteFunction( callback_t func, void *data) +bool LLCallbackList::deleteFunction( callback_t func, void *data) { callback_pair_t t(func, data); callback_list_t::iterator iter = std::find(mCallbackList.begin(), mCallbackList.end(), t); diff --git a/indra/newview/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp index 61fcd5d7b..3efba0c99 100644 --- a/indra/newview/llcolorswatch.cpp +++ b/indra/newview/llcolorswatch.cpp @@ -213,7 +213,7 @@ void LLColorSwatchCtrl::draw() { if (!mFallbackImageName.empty()) { - LLPointer fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE, + LLPointer fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if( fallback_image->getComponents() == 4 ) { diff --git a/indra/newview/llconsole.cpp b/indra/newview/llconsole.cpp index dc72314fe..e4e365cef 100644 --- a/indra/newview/llconsole.cpp +++ b/indra/newview/llconsole.cpp @@ -194,7 +194,7 @@ void LLConsole::draw() // draw remaining lines F32 y_pos = 0.f; - LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); static const LLCachedControl console_background_opacity("ConsoleBackgroundOpacity"); F32 console_opacity = llclamp(console_background_opacity.get(), 0.f, 1.f); diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 99aa79f52..fdd6fae3a 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -1080,20 +1080,27 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() retval = gPipeline.getSpatialPartition((LLViewerObject*) mVObjp); } else if (isRoot()) - { //must be an active volume + { + if (mSpatialBridge && (mSpatialBridge->asPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD) != mVObjp->isHUDAttachment()) + { + // remove obsolete bridge + mSpatialBridge->markDead(); + setSpatialBridge(NULL); + } + //must be an active volume if (!mSpatialBridge) { if (mVObjp->isHUDAttachment()) { - setSpatialBridge(new LLHUDBridge(this)); + setSpatialBridge(new LLHUDBridge(this, getRegion())); } else if (mVObjp->isAttachment()) { - setSpatialBridge(new LLAttachmentBridge(this)); + setSpatialBridge(new LLAttachmentBridge(this, getRegion())); } else { - setSpatialBridge(new LLVolumeBridge(this)); + setSpatialBridge(new LLVolumeBridge(this, getRegion())); } } return mSpatialBridge->asPartition(); @@ -1116,9 +1123,9 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() // Spatial Partition Bridging Drawable //======================================= -LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask) : +LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask, LLViewerRegion* regionp) : LLDrawable(root->getVObj()), - LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB) + LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB, regionp) { mBridge = this; mDrawable = root; @@ -1627,8 +1634,8 @@ void LLDrawable::updateFaceSize(S32 idx) } } -LLBridgePartition::LLBridgePartition() -: LLSpatialPartition(0, FALSE, 0) +LLBridgePartition::LLBridgePartition(LLViewerRegion* regionp) +: LLSpatialPartition(0, FALSE, 0, regionp) { mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; mPartitionType = LLViewerRegion::PARTITION_BRIDGE; @@ -1636,14 +1643,14 @@ LLBridgePartition::LLBridgePartition() mSlopRatio = 0.25f; } -LLAttachmentPartition::LLAttachmentPartition() -: LLBridgePartition() +LLAttachmentPartition::LLAttachmentPartition(LLViewerRegion* regionp) +: LLBridgePartition(regionp) { mDrawableType = LLPipeline::RENDER_TYPE_AVATAR; } -LLHUDBridge::LLHUDBridge(LLDrawable* drawablep) -: LLVolumeBridge(drawablep) +LLHUDBridge::LLHUDBridge(LLDrawable* drawablep, LLViewerRegion* regionp) +: LLVolumeBridge(drawablep, regionp) { mDrawableType = LLPipeline::RENDER_TYPE_HUD; mPartitionType = LLViewerRegion::PARTITION_HUD; diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp index b4f7f8838..45b144ba3 100644 --- a/indra/newview/lldrawpoolterrain.cpp +++ b/indra/newview/lldrawpoolterrain.cpp @@ -76,6 +76,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) : sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c", + FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, int_format, format); diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index ff04959a0..d2d2bae7c 100644 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -73,11 +73,11 @@ LLVector3 LLDrawPoolWater::sLightDir; LLDrawPoolWater::LLDrawPoolWater() : LLFacePool(POOL_WATER) { - mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLGLTexture::BOOST_UI); + mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); gGL.getTexUnit(0)->bind(mHBTex[0]) ; mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP); - mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLGLTexture::BOOST_UI); + mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); gGL.getTexUnit(0)->bind(mHBTex[1]); mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 11dc74b82..3b070f3c7 100644 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -339,6 +339,34 @@ void LLFace::dirtyTexture() gPipeline.markTextured(drawablep); } +void LLFace::notifyAboutCreatingTexture(LLViewerTexture *texture) +{ + LLDrawable* drawablep = getDrawable(); + if(mVObjp.notNull() && mVObjp->getVolume()) + { + LLVOVolume *vobj = drawablep->getVOVolume(); + if(vobj && vobj->notifyAboutCreatingTexture(texture)) + { + gPipeline.markTextured(drawablep); + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME); + } + } +} + +void LLFace::notifyAboutMissingAsset(LLViewerTexture *texture) +{ + LLDrawable* drawablep = getDrawable(); + if(mVObjp.notNull() && mVObjp->getVolume()) + { + LLVOVolume *vobj = drawablep->getVOVolume(); + if(vobj && vobj->notifyAboutMissingAsset(texture)) + { + gPipeline.markTextured(drawablep); + gPipeline.markRebuild(drawablep, LLDrawable::REBUILD_VOLUME); + } + } +} + void LLFace::switchTexture(U32 ch, LLViewerTexture* new_texture) { llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); @@ -989,6 +1017,10 @@ void LLFace::getPlanarProjectedParams(LLQuaternion* face_rot, LLVector3* face_po const LLVolumeFace& vf = getViewerObject()->getVolume()->getVolumeFace(mTEOffset); const LLVector4a& normal = vf.mNormals[0]; const LLVector4a& tangent = vf.mTangents[0]; + if (!&tangent) + { + return; + } LLVector4a binormal; binormal.setCross3(normal, tangent); @@ -1648,7 +1680,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume, do_xform = false; } - if (getVirtualSize() >= MIN_TEX_ANIM_SIZE) + if (getVirtualSize() >= MIN_TEX_ANIM_SIZE || isState(LLFace::RIGGED)) { //don't override texture transform during tc bake tex_mode = 0; } diff --git a/indra/newview/llface.h b/indra/newview/llface.h index ebd8bb6df..e0e478df6 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -237,6 +237,9 @@ public: static U32 getRiggedDataMask(U32 type); + void notifyAboutCreatingTexture(LLViewerTexture *texture); + void notifyAboutMissingAsset(LLViewerTexture *texture); + public: //aligned members LL_ALIGN_16(LLVector4a mExtents[2]); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index efb981f79..079b98d8b 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -421,7 +421,7 @@ void LLFastTimerView::draw() S32 left, top, right, bottom; S32 x, y, barw, barh, dx, dy; S32 texth; - LLPointer box_imagep = LLUI::getUIImage("rounded_square.tga"); + LLPointer box_imagep = LLUI::getUIImage("Rounded_Square"); // Draw the window background gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); @@ -884,7 +884,8 @@ void LLFastTimerView::draw() gGL.color4fv(color.mV); F32 start_fragment = llclamp((F32)(left - sublevel_left[level]) / (F32)sublevel_dx[level], 0.f, 1.f); F32 end_fragment = llclamp((F32)(right - sublevel_left[level]) / (F32)sublevel_dx[level], 0.f, 1.f); - gl_segmented_rect_2d_fragment_tex(sublevel_left[level], top - level + scale_offset, sublevel_right[level], bottom + level - scale_offset, box_imagep->getTextureWidth(), box_imagep->getTextureHeight(), 16, start_fragment, end_fragment); + LLRect rect(sublevel_left[level], top - level + scale_offset, sublevel_right[level], bottom + level - scale_offset); + gl_segmented_rect_2d_fragment_tex(rect, box_imagep->getTextureWidth(), box_imagep->getTextureHeight(), 16, start_fragment, end_fragment); } diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp index aedcd47b2..42f46fb2e 100644 --- a/indra/newview/llfeaturemanager.cpp +++ b/indra/newview/llfeaturemanager.cpp @@ -676,7 +676,7 @@ void LLFeatureManager::applyBaseMasks() maskFeatures(gpustr); // now mask cpu type ones - if (gSysMemory.getPhysicalMemoryClamped() <= 256*1024*1024) + if (gSysMemory.getPhysicalMemoryClamped() <= U32Megabytes(256)) { maskFeatures("RAM256MB"); } diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index d05ff2a1e..cd2cfdb17 100644 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -233,7 +233,7 @@ LLFloaterAbout::LLFloaterAbout() else support.append(" None\n"); */ - U32 memory = gSysMemory.getPhysicalMemoryKB() / 1024; + U32Megabytes memory = gSysMemory.getPhysicalMemoryKB(); // Moved hack adjustment to Windows memory size into llsys.cpp std::string mem_text = llformat("Memory: %u MB\n", memory ); diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index b9539444d..da516ca54 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -32,10 +32,8 @@ #include "llviewerprecompiledheaders.h" -#include "dae.h" -#include "dom/domCOLLADA.h" -#include "dom/domConstants.h" -#include "dom/domProfile_COMMON.h" +#include "llmodelloader.h" +#include "lldaeloader.h" #include "llfloatermodelpreview.h" @@ -82,12 +80,11 @@ #include "hippogridmanager.h" #include "hippolimits.h" -const S32 SLM_SUPPORTED_VERSION = 3; - //static S32 LLFloaterModelPreview::sUploadAmount = 10; LLFloaterModelPreview* LLFloaterModelPreview::sInstance = NULL; -std::list LLModelLoader::sActiveLoaderList; + +bool LLModelPreview::sIgnoreLoadedCallback = false; // "Retain%" decomp parameter has values from 0.0 to 1.0 by 0.01 // But according to the UI spec for upload model floater, this parameter @@ -104,240 +101,131 @@ const S32 SMOOTH_VALUES_NUMBER = 10; void drawBoxOutline(const LLVector3& pos, const LLVector3& size); -std::string lod_name[NUM_LOD] = + +std::string lod_name[NUM_LOD+1] = { "lowest", "low", "medium", "high", + "I went off the end of the lod_name array. Me so smart." }; -std::string lod_triangles_name[NUM_LOD] = +std::string lod_triangles_name[NUM_LOD+1] = { "lowest_triangles", "low_triangles", "medium_triangles", "high_triangles", + "I went off the end of the lod_triangles_name array. Me so smart." }; -std::string lod_vertices_name[NUM_LOD] = +std::string lod_vertices_name[NUM_LOD+1] = { "lowest_vertices", "low_vertices", "medium_vertices", "high_vertices", + "I went off the end of the lod_vertices_name array. Me so smart." }; -std::string lod_status_name[NUM_LOD] = +std::string lod_status_name[NUM_LOD+1] = { "lowest_status", "low_status", "medium_status", "high_status", + "I went off the end of the lod_status_name array. Me so smart." }; -std::string lod_icon_name[NUM_LOD] = +std::string lod_icon_name[NUM_LOD+1] = { "status_icon_lowest", "status_icon_low", "status_icon_medium", "status_icon_high", + "I went off the end of the lod_status_name array. Me so smart." }; -std::string lod_status_image[NUM_LOD] = +std::string lod_status_image[] = { "green_checkmark.png", "lag_status_warning.tga", "red_x.png", + "I went off the end of the lod_status_image array. Me so smart." }; -std::string lod_label_name[NUM_LOD] = +std::string lod_label_name[NUM_LOD+1] = { "lowest_label", "low_label", "medium_label", "high_label", + "I went off the end of the lod_label_name array. Me so smart." }; -std::string colladaVersion[VERSIONTYPE_COUNT + 1] = -{ - "1.4.0", - "1.4.1", - "Unsupported" -}; - -#define LL_DEGENERACY_TOLERANCE 1e-7f - -inline F32 dot3fpu(const LLVector4a& a, const LLVector4a& b) -{ - volatile F32 p0 = a[0] * b[0]; - volatile F32 p1 = a[1] * b[1]; - volatile F32 p2 = a[2] * b[2]; - return p0 + p1 + p2; -} - -bool ll_is_degenerate(const LLVector4a& a, const LLVector4a& b, const LLVector4a& c, F32 tolerance = LL_DEGENERACY_TOLERANCE) -{ - // small area check - { - LLVector4a edge1; edge1.setSub(a, b); - LLVector4a edge2; edge2.setSub(a, c); - ////////////////////////////////////////////////////////////////////////// - /// Linden Modified - ////////////////////////////////////////////////////////////////////////// - - // If no one edge is more than 10x longer than any other edge, we weaken - // the tolerance by a factor of 1e-4f. - - LLVector4a edge3; edge3.setSub(c, b); - const F32 len1sq = edge1.dot3(edge1).getF32(); - const F32 len2sq = edge2.dot3(edge2).getF32(); - const F32 len3sq = edge3.dot3(edge3).getF32(); - bool abOK = (len1sq <= 100.f * len2sq) && (len1sq <= 100.f * len3sq); - bool acOK = (len2sq <= 100.f * len1sq) && (len1sq <= 100.f * len3sq); - bool cbOK = (len3sq <= 100.f * len1sq) && (len1sq <= 100.f * len2sq); - if (abOK && acOK && cbOK) - { - tolerance *= 1e-4f; - } - - ////////////////////////////////////////////////////////////////////////// - /// End Modified - ////////////////////////////////////////////////////////////////////////// - - LLVector4a cross; cross.setCross3(edge1, edge2); - - LLVector4a edge1b; edge1b.setSub(b, a); - LLVector4a edge2b; edge2b.setSub(b, c); - LLVector4a crossb; crossb.setCross3(edge1b, edge2b); - - if ((cross.dot3(cross).getF32() < tolerance) || (crossb.dot3(crossb).getF32() < tolerance)) - { - return true; - } - } - - // point triangle distance check - { - LLVector4a Q; Q.setSub(a, b); - LLVector4a R; R.setSub(c, b); - - const F32 QQ = dot3fpu(Q, Q); - const F32 RR = dot3fpu(R, R); - const F32 QR = dot3fpu(R, Q); - - volatile F32 QQRR = QQ * RR; - volatile F32 QRQR = QR * QR; - F32 Det = (QQRR - QRQR); - - if (Det == 0.0f) - { - return true; - } - } - - return false; -} - -bool validate_face(const LLVolumeFace& face) -{ - - for (S32 v = 0; v < face.mNumVertices; v++) - { - if(face.mPositions && !face.mPositions[v].isFinite3()) - { - LL_WARNS() << "NaN position data in face found!" << LL_ENDL; - return false; - } - - if(face.mNormals && !face.mNormals[v].isFinite3()) - { - LL_WARNS() << "NaN normal data in face found!" << LL_ENDL; - return false; - } - } - - for (S32 i = 0; i < face.mNumIndices; ++i) - { - if (face.mIndices[i] >= face.mNumVertices) - { - LL_WARNS() << "Face has invalid index." << LL_ENDL; - return false; - } - } - - if (face.mNumIndices % 3 != 0 || face.mNumIndices == 0) - { - LL_WARNS() << "Face has invalid number of indices." << LL_ENDL; - return false; - } - - /*const LLVector4a scale(0.5f); - - for (U32 i = 0; i < face.mNumIndices; i+=3) - { - U16 idx1 = face.mIndices[i]; - U16 idx2 = face.mIndices[i + 1]; - U16 idx3 = face.mIndices[i+2]; - - LLVector4a v1; v1.setMul(face.mPositions[idx1], scale); - LLVector4a v2; v2.setMul(face.mPositions[idx2], scale); - LLVector4a v3; v3.setMul(face.mPositions[idx3], scale); - - if (ll_is_degenerate(v1,v2,v3)) - { - LL_WARNS() << "Degenerate face found!" << LL_ENDL; - return false; - } - }*/ - - return true; -} - -bool validate_model(const LLModel* mdl) -{ - if (mdl->getNumVolumeFaces() == 0) - { - LL_WARNS() << "Model has no faces!" << LL_ENDL; - return false; - } - - for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) - { - if (mdl->getVolumeFace(i).mNumVertices == 0) - { - LL_WARNS() << "Face has no vertices." << LL_ENDL; - return false; - } - - if (mdl->getVolumeFace(i).mNumIndices == 0) - { - LL_WARNS() << "Face has no indices." << LL_ENDL; - return false; - } - - if (!validate_face(mdl->getVolumeFace(i))) - { - return false; - } - } - - return true; -} - BOOL stop_gloderror() { GLuint error = glodGetError(); if (error != GLOD_NO_ERROR) { - LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << std::dec << LL_ENDL; + LL_WARNS() << "GLOD error detected, cannot generate LOD: " << std::hex << error << LL_ENDL; return TRUE; } return FALSE; } +LLViewerFetchedTexture* bindMaterialDiffuseTexture(const LLImportMaterial& material) +{ + LLViewerFetchedTexture *texture = LLViewerTextureManager::getFetchedTexture(material.getDiffuseMap(), FTT_DEFAULT, TRUE, LLGLTexture::BOOST_PREVIEW); + + if (texture) + { + if (texture->getDiscardLevel() > -1) + { + gGL.getTexUnit(0)->bind(texture, true); + return texture; + } + } + + return NULL; +} + +std::string stripSuffix(std::string name) +{ + if ((name.find("_LOD") != std::string::npos) || (name.find("_PHYS") != std::string::npos)) + { + return name.substr(0, name.rfind('_')); + } + return name; +} + +void FindModel(LLModelLoader::scene& scene, const std::string& name_to_match, LLModel*& baseModelOut, LLMatrix4& matOut) +{ + LLModelLoader::scene::iterator base_iter = scene.begin(); + bool found = false; + while (!found && (base_iter != scene.end())) + { + matOut = base_iter->first; + + LLModelLoader::model_instance_list::iterator base_instance_iter = base_iter->second.begin(); + while (!found && (base_instance_iter != base_iter->second.end())) + { + LLModelInstance& base_instance = *base_instance_iter++; + LLModel* base_model = base_instance.mModel; + + if (base_model && (base_model->mLabel == name_to_match)) + { + baseModelOut = base_model; + return; + } + } + base_iter++; + } +} + //----------------------------------------------------------------------------- // LLFloaterModelPreview() //----------------------------------------------------------------------------- @@ -475,9 +363,16 @@ BOOL LLFloaterModelPreview::postBuild() mUploadBtn = getChild("ok_btn"); mCalculateBtn = getChild("calculate_btn"); + if (LLConvexDecomposition::getInstance() != NULL) + { mCalculateBtn->setClickedCallback(boost::bind(&LLFloaterModelPreview::onClickCalculateBtn, this)); toggleCalculateButton(true); + } + else + { + mCalculateBtn->setEnabled(false); + } return TRUE; } @@ -566,6 +461,23 @@ void LLFloaterModelPreview::loadModel_continued(AIFilePicker* filepicker, S32 lo if (filepicker->hasFilename()) // User did not click Cancel? { filename = filepicker->getFilename(); + + const U32 lod_high = LLModel::LOD_HIGH; + for (S32 lod = 0; lod <= lod_high; ++lod) + { + std::string message = "status_reading_file"; + + mModelPreview->mFMP->childSetText(lod_triangles_name[lod], LLStringExplicit("?")); + mModelPreview->mFMP->childSetText(lod_vertices_name[lod], LLStringExplicit("?")); + LLIconCtrl* icon = mModelPreview->mFMP->getChild(lod_icon_name[lod]); + icon->setVisible(false); + } + } + + if (lod == LLModel::LOD_PHYSICS) + { + // loading physics from file + mModelPreview->mPhysicsSearchLOD = lod; } mModelPreview->loadModel(filename, lod); // Pass an empty filename if the user clicked Cancel. } @@ -686,6 +598,11 @@ void LLFloaterModelPreview::toggleGenerateNormals() { bool enabled = childGetValue("gen_normals").asBoolean(); childSetEnabled("crease_angle", enabled); + if(enabled) { + mModelPreview->generateNormals(); + } else { + mModelPreview->restoreNormals(); + } } //static @@ -701,12 +618,26 @@ void LLFloaterModelPreview::onAutoFillCommit(LLUICtrl* ctrl, void* userdata) { LLFloaterModelPreview* fp = (LLFloaterModelPreview*) userdata; - fp->mModelPreview->genLODs(); + fp->mModelPreview->queryLODs(); } void LLFloaterModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit) { mModelPreview->onLODParamCommit(lod, enforce_tri_limit); + + //refresh LoDs that reference this one + for (S32 i = lod - 1; i >= 0; --i) + { + LLComboBox* lod_source_combo = getChild("lod_source_" + lod_name[i]); + if (lod_source_combo->getCurrentIndex() == LLModelPreview::USE_LOD_ABOVE) + { + onLoDSourceCommit(i); + } + else + { + break; + } + } } @@ -726,12 +657,12 @@ void LLFloaterModelPreview::draw() childSetTextArg("status", "[STATUS]", getString("status_material_mismatch")); } else - if (mModelPreview->getLoadState() > LLModelLoader::ERROR_PARSING) + if ( mModelPreview->getLoadState() > LLModelLoader::ERROR_MODEL ) { - childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_PARSING))); + childSetTextArg("status", "[STATUS]", getString(LLModel::getStatusString(mModelPreview->getLoadState() - LLModelLoader::ERROR_MODEL))); } else - if (mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING) + if ( mModelPreview->getLoadState() == LLModelLoader::ERROR_PARSING ) { childSetTextArg("status", "[STATUS]", getString("status_parse_error")); toggleCalculateButton(false); @@ -747,12 +678,13 @@ void LLFloaterModelPreview::draw() childSetTextArg("description_label", "[TEXTURES]", llformat("%d", mModelPreview->mTextureSet.size())); */ - if (mModelPreview) + if (mModelPreview->lodsReady()) { gGL.color3f(1.f, 1.f, 1.f); gGL.getTexUnit(0)->bind(mModelPreview); + LLView* preview_panel = getChild("preview_panel"); LLRect rect = preview_panel->getRect(); @@ -878,11 +810,19 @@ BOOL LLFloaterModelPreview::handleScrollWheel(S32 x, S32 y, S32 clicks) } /*virtual*/ -void LLFloaterModelPreview::onOpen(/*const LLSD& key*/) +void LLFloaterModelPreview::onOpen() { + LLModelPreview::sIgnoreLoadedCallback = false; requestAgentUploadPermissions(); } +/*virtual*/ +void LLFloaterModelPreview::onClose(bool app_quitting) +{ + LLModelPreview::sIgnoreLoadedCallback = true; + LLFloater::onClose(app_quitting); +} + //static void LLFloaterModelPreview::onPhysicsParamCommit(LLUICtrl* ctrl, void* data) { @@ -1237,1825 +1177,19 @@ void LLFloaterModelPreview::onMouseCaptureLostModelPreview(LLMouseHandler* handl gViewerWindow->showCursor(); } -//----------------------------------------------------------------------------- -// LLModelLoader -//----------------------------------------------------------------------------- -LLModelLoader::LLModelLoader( std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, - std::deque& jointsFromNodes) -: mJointList( jointMap ) -, mJointsFromNode( jointsFromNodes ) -, LLThread("Model Loader"), mFilename(filename), mLod(lod), mPreview(preview), mFirstTransform(TRUE), mNumOfFetchingTextures(0) -{ - mJointMap["mPelvis"] = "mPelvis"; - mJointMap["mTorso"] = "mTorso"; - mJointMap["mChest"] = "mChest"; - mJointMap["mNeck"] = "mNeck"; - mJointMap["mHead"] = "mHead"; - mJointMap["mSkull"] = "mSkull"; - mJointMap["mEyeRight"] = "mEyeRight"; - mJointMap["mEyeLeft"] = "mEyeLeft"; - mJointMap["mCollarLeft"] = "mCollarLeft"; - mJointMap["mShoulderLeft"] = "mShoulderLeft"; - mJointMap["mElbowLeft"] = "mElbowLeft"; - mJointMap["mWristLeft"] = "mWristLeft"; - mJointMap["mCollarRight"] = "mCollarRight"; - mJointMap["mShoulderRight"] = "mShoulderRight"; - mJointMap["mElbowRight"] = "mElbowRight"; - mJointMap["mWristRight"] = "mWristRight"; - mJointMap["mHipRight"] = "mHipRight"; - mJointMap["mKneeRight"] = "mKneeRight"; - mJointMap["mAnkleRight"] = "mAnkleRight"; - mJointMap["mFootRight"] = "mFootRight"; - mJointMap["mToeRight"] = "mToeRight"; - mJointMap["mHipLeft"] = "mHipLeft"; - mJointMap["mKneeLeft"] = "mKneeLeft"; - mJointMap["mAnkleLeft"] = "mAnkleLeft"; - mJointMap["mFootLeft"] = "mFootLeft"; - mJointMap["mToeLeft"] = "mToeLeft"; - - mJointMap["avatar_mPelvis"] = "mPelvis"; - mJointMap["avatar_mTorso"] = "mTorso"; - mJointMap["avatar_mChest"] = "mChest"; - mJointMap["avatar_mNeck"] = "mNeck"; - mJointMap["avatar_mHead"] = "mHead"; - mJointMap["avatar_mSkull"] = "mSkull"; - mJointMap["avatar_mEyeRight"] = "mEyeRight"; - mJointMap["avatar_mEyeLeft"] = "mEyeLeft"; - mJointMap["avatar_mCollarLeft"] = "mCollarLeft"; - mJointMap["avatar_mShoulderLeft"] = "mShoulderLeft"; - mJointMap["avatar_mElbowLeft"] = "mElbowLeft"; - mJointMap["avatar_mWristLeft"] = "mWristLeft"; - mJointMap["avatar_mCollarRight"] = "mCollarRight"; - mJointMap["avatar_mShoulderRight"] = "mShoulderRight"; - mJointMap["avatar_mElbowRight"] = "mElbowRight"; - mJointMap["avatar_mWristRight"] = "mWristRight"; - mJointMap["avatar_mHipRight"] = "mHipRight"; - mJointMap["avatar_mKneeRight"] = "mKneeRight"; - mJointMap["avatar_mAnkleRight"] = "mAnkleRight"; - mJointMap["avatar_mFootRight"] = "mFootRight"; - mJointMap["avatar_mToeRight"] = "mToeRight"; - mJointMap["avatar_mHipLeft"] = "mHipLeft"; - mJointMap["avatar_mKneeLeft"] = "mKneeLeft"; - mJointMap["avatar_mAnkleLeft"] = "mAnkleLeft"; - mJointMap["avatar_mFootLeft"] = "mFootLeft"; - mJointMap["avatar_mToeLeft"] = "mToeLeft"; - - mJointMap["hip"] = "mPelvis"; - mJointMap["abdomen"] = "mTorso"; - mJointMap["chest"] = "mChest"; - mJointMap["neck"] = "mNeck"; - mJointMap["head"] = "mHead"; - mJointMap["figureHair"] = "mSkull"; - mJointMap["lCollar"] = "mCollarLeft"; - mJointMap["lShldr"] = "mShoulderLeft"; - mJointMap["lForeArm"] = "mElbowLeft"; - mJointMap["lHand"] = "mWristLeft"; - mJointMap["rCollar"] = "mCollarRight"; - mJointMap["rShldr"] = "mShoulderRight"; - mJointMap["rForeArm"] = "mElbowRight"; - mJointMap["rHand"] = "mWristRight"; - mJointMap["rThigh"] = "mHipRight"; - mJointMap["rShin"] = "mKneeRight"; - mJointMap["rFoot"] = "mFootRight"; - mJointMap["lThigh"] = "mHipLeft"; - mJointMap["lShin"] = "mKneeLeft"; - mJointMap["lFoot"] = "mFootLeft"; - - if (mPreview) - { - //only try to load from slm if viewer is configured to do so and this is the - //initial model load (not an LoD or physics shape) - mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mPreview->mUploadData.empty(); - mPreview->setLoadState(STARTING); - } - else - { - mTrySLM = false; - } - - assert_main_thread(); - sActiveLoaderList.push_back(this); -} - -LLModelLoader::~LLModelLoader() -{ - assert_main_thread(); - sActiveLoaderList.remove(this); -} - -void stretch_extents(LLModel* model, LLMatrix4a& mat, LLVector4a& min, LLVector4a& max, BOOL& first_transform) -{ - LLVector4a box[] = - { - LLVector4a(-1, 1,-1), - LLVector4a(-1, 1, 1), - LLVector4a(-1,-1,-1), - LLVector4a(-1,-1, 1), - LLVector4a( 1, 1,-1), - LLVector4a( 1, 1, 1), - LLVector4a( 1,-1,-1), - LLVector4a( 1,-1, 1), - }; - - for (S32 j = 0; j < model->getNumVolumeFaces(); ++j) - { - const LLVolumeFace& face = model->getVolumeFace(j); - - LLVector4a center; - center.setAdd(face.mExtents[0], face.mExtents[1]); - center.mul(0.5f); - LLVector4a size; - size.setSub(face.mExtents[1],face.mExtents[0]); - size.mul(0.5f); - - for (U32 i = 0; i < 8; i++) - { - LLVector4a t; - t.setMul(size, box[i]); - t.add(center); - - LLVector4a v; - - mat.affineTransform(t, v); - - if (first_transform) - { - first_transform = FALSE; - min = max = v; - } - else - { - update_min_max(min, max, v); - } - } - } -} - -void stretch_extents(LLModel* model, LLMatrix4& mat, LLVector3& min, LLVector3& max, BOOL& first_transform) -{ - LLVector4a mina, maxa; - LLMatrix4a mata; - - mata.loadu(mat); - mina.load3(min.mV); - maxa.load3(max.mV); - - stretch_extents(model, mata, mina, maxa, first_transform); - - min.set(mina.getF32ptr()); - max.set(maxa.getF32ptr()); -} - -void LLModelLoader::run() -{ - doLoadModel(); - doOnIdleOneTime(boost::bind(&LLModelLoader::loadModelCallback,this)); -} - -bool LLModelLoader::doLoadModel() -{ - //first, look for a .slm file of the same name that was modified later - //than the .dae - - if (mTrySLM) - { - std::string filename = mFilename; - - std::string::size_type i = filename.rfind("."); - if (i != std::string::npos) - { - filename.replace(i, filename.size() - 1, ".slm"); - llstat slm_status; - if (LLFile::stat(filename, &slm_status) == 0) - { //slm file exists - llstat dae_status; - if (LLFile::stat(mFilename, &dae_status) != 0 || - dae_status.st_mtime < slm_status.st_mtime) - { - if (loadFromSLM(filename)) - { //slm successfully loaded, if this fails, fall through and - //try loading from dae - - mLod = -1; //successfully loading from an slm implicitly sets all - //LoDs - return true; - } - } - } - } - } - - //no suitable slm exists, load from the .dae file - //replace illegal # in path as collada's escapser is broken - std::string tmp_file = mFilename; - boost::replace_all(tmp_file, "#", "%23"); - DAE dae; - domCOLLADA* dom = dae.open(tmp_file); - - if (!dom) - { - LL_INFOS() <<" Error with dae - traditionally indicates a corrupt file."<getVersion(); - //0=1.4 - //1=1.4.1 - //2=Currently unsupported, however may work - if (docVersion > 1) - { - docVersion = VERSIONTYPE_COUNT; - } - LL_INFOS() <<"Dae version "<getElementCount(NULL, COLLADA_TYPE_MESH); - - daeDocument* doc = dae.getDoc(tmp_file); - if (!doc) - { - LL_WARNS() << "can't find internal doc" << LL_ENDL; - return false; - } - - daeElement* root = doc->getDomRoot(); - if (!root) - { - LL_WARNS() << "document has no root" << LL_ENDL; - return false; - } - - //Verify some basic properties of the dae - //1. Basic validity check on controller - U32 controllerCount = (int) db->getElementCount(NULL, "controller"); - bool result = false; - for (U32 i = 0; i < controllerCount; ++i) - { - domController* pController = NULL; - db->getElement((daeElement**) &pController, i , NULL, "controller"); - result = mPreview->verifyController(pController); - if (!result) - { - setLoadState(ERROR_PARSING); - return true; - } - } - - //get unit scale - mTransform.setIdentity(); - - domAsset::domUnit* unit = daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUnit::ID()))); - - if (unit) - { - F32 meter = unit->getMeter(); - mTransform.mMatrix[0][0] = meter; - mTransform.mMatrix[1][1] = meter; - mTransform.mMatrix[2][2] = meter; - } - - //get up axis rotation - LLMatrix4 rotation; - - domUpAxisType up = UPAXISTYPE_Y_UP; // default is Y_UP - domAsset::domUp_axis* up_axis = - daeSafeCast(root->getDescendant(daeElement::matchType(domAsset::domUp_axis::ID()))); - - if (up_axis) - { - up = up_axis->getValue(); - } - - if (up == UPAXISTYPE_X_UP) - { - rotation.initRotation(0.0f, 90.0f * DEG_TO_RAD, 0.0f); - } - else if (up == UPAXISTYPE_Y_UP) - { - rotation.initRotation(90.0f * DEG_TO_RAD, 0.0f, 0.0f); - } - - rotation *= mTransform; - mTransform = rotation; - - for (daeInt idx = 0; idx < count; ++idx) - { //build map of domEntities to LLModel - domMesh* mesh = NULL; - db->getElement((daeElement**) &mesh, idx, NULL, COLLADA_TYPE_MESH); - - if (mesh) - { - LLPointer model = LLModel::loadModelFromDomMesh(mesh); - - if (model->getStatus() != LLModel::NO_ERRORS) - { - setLoadState(ERROR_PARSING + model->getStatus()); - return false; //abort - } - - if (model.notNull() && validate_model(model)) - { - mModelList.push_back(model); - mModel[mesh] = model; - } - } - } - - count = db->getElementCount(NULL, COLLADA_TYPE_SKIN); - for (daeInt idx = 0; idx < count; ++idx) - { //add skinned meshes as instances - domSkin* skin = NULL; - db->getElement((daeElement**) &skin, idx, NULL, COLLADA_TYPE_SKIN); - - if (skin) - { - domGeometry* geom = daeSafeCast(skin->getSource().getElement()); - - if (geom) - { - domMesh* mesh = geom->getMesh(); - if (mesh) - { - LLModel* model = mModel[mesh]; - if (model) - { - LLVector3 mesh_scale_vector; - LLVector3 mesh_translation_vector; - model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); - - LLMatrix4 normalized_transformation; - normalized_transformation.setTranslation(mesh_translation_vector); - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= normalized_transformation; - normalized_transformation = mesh_scale; - - LLMatrix4a inv_mat; - inv_mat.loadu(normalized_transformation); - inv_mat.invert(); - - LLMatrix4 inverse_normalized_transformation(inv_mat.getF32ptr()); - - domSkin::domBind_shape_matrix* bind_mat = skin->getBind_shape_matrix(); - - if (bind_mat) - { //get bind shape matrix - domFloat4x4& dom_value = bind_mat->getValue(); - - LLMeshSkinInfo& skin_info = model->mSkinInfo; - - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - skin_info.mBindShapeMatrix.mMatrix[i][j] = dom_value[i + j*4]; - } - } - - LLMatrix4 trans = normalized_transformation; - trans *= skin_info.mBindShapeMatrix; - skin_info.mBindShapeMatrix = trans; - } - - //Some collada setup for accessing the skeleton - daeElement* pElement = 0; - dae.getDatabase()->getElement(&pElement, 0, 0, "skeleton"); - - //Try to get at the skeletal instance controller - domInstance_controller::domSkeleton* pSkeleton = daeSafeCast(pElement); - bool missingSkeletonOrScene = false; - - //If no skeleton, do a breadth-first search to get at specific joints - bool rootNode = false; - - //Need to test for a skeleton that does not have a root node - //This occurs when your instance controller does not have an associated scene - if (pSkeleton) - { - daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); - if (pSkeletonRootNode) - { - rootNode = true; - } - - } - if (!pSkeleton || !rootNode) - { - daeElement* pScene = root->getDescendant("visual_scene"); - if (!pScene) - { - LL_WARNS()<<"No visual scene - unable to parse bone offsets "< > children = pScene->getChildren(); - S32 childCount = children.getCount(); - - //Process any children that are joints - //Not all children are joints, some code be ambient lights, cameras, geometry etc.. - for (S32 i = 0; i < childCount; ++i) - { - domNode* pNode = daeSafeCast(children[i]); - if (isNodeAJoint(pNode)) - { - processJointNode(pNode, mJointList); - } - } - } - } - else - //Has Skeleton - { - //Get the root node of the skeleton - daeElement* pSkeletonRootNode = pSkeleton->getValue().getElement(); - if (pSkeletonRootNode) - { - //Once we have the root node - start acccessing it's joint components - const int jointCnt = mJointMap.size(); - std::map :: const_iterator jointIt = mJointMap.begin(); - - //Loop over all the possible joints within the .dae - using the allowed joint list in the ctor. - for (int i = 0; i < jointCnt; ++i, ++jointIt) - { - //Build a joint for the resolver to work with - char str[64]={0}; - sprintf(str,"./%s",(*jointIt).first.c_str()); - //llwarns<<"Joint "<< str <(resolver.getElement()); - if (pJoint) - { - //Pull out the translate id and store it in the jointTranslations map - daeSIDResolver jointResolverA(pJoint, "./translate"); - domTranslate* pTranslateA = daeSafeCast(jointResolverA.getElement()); - daeSIDResolver jointResolverB(pJoint, "./location"); - domTranslate* pTranslateB = daeSafeCast(jointResolverB.getElement()); - - LLMatrix4 workingTransform; - - //Translation via SID - if (pTranslateA) - { - extractTranslation(pTranslateA, workingTransform); - } - else - if (pTranslateB) - { - extractTranslation(pTranslateB, workingTransform); - } - else - { - //Translation via child from element - daeElement* pTranslateElement = getChildFromElement(pJoint, "translate"); - if (pTranslateElement && pTranslateElement->typeID() != domTranslate::ID()) - { - LL_WARNS() << "The found element is not a translate node" << LL_ENDL; - missingSkeletonOrScene = true; - } - else - if (pTranslateElement) - { - extractTranslationViaElement(pTranslateElement, workingTransform); - } - else - { - extractTranslationViaSID(pJoint, workingTransform); - } - - } - - //Store the joint transform w/respect to it's name. - mJointList[(*jointIt).second.c_str()] = workingTransform; - } - } - - //If anything failed in regards to extracting the skeleton, joints or translation id, - //mention it - if (missingSkeletonOrScene) - { - LL_WARNS() << "Partial jointmap found in asset - did you mean to just have a partial map?" << LL_ENDL; - } - } //got skeleton? - } - - domSkin::domJoints* joints = skin->getJoints(); - - domInputLocal_Array& joint_input = joints->getInput_array(); - - for (size_t i = 0; i < joint_input.getCount(); ++i) - { - domInputLocal* input = joint_input.get(i); - xsNMTOKEN semantic = input->getSemantic(); - - if (strcmp(semantic, COMMON_PROFILE_INPUT_JOINT) == 0) - { //found joint source, fill model->mJointMap and model->mSkinInfo.mJointNames - daeElement* elem = input->getSource().getElement(); - - domSource* source = daeSafeCast(elem); - if (source) - { - domName_array* names_source = source->getName_array(); - - if (names_source) - { - domListOfNames &names = names_source->getValue(); - - for (size_t j = 0; j < names.getCount(); ++j) - { - std::string name(names.get(j)); - if (mJointMap.find(name) != mJointMap.end()) - { - name = mJointMap[name]; - } - model->mSkinInfo.mJointNames.push_back(name); - model->mSkinInfo.mJointMap[name] = j; - } - } - else - { - domIDREF_array* names_source = source->getIDREF_array(); - if (names_source) - { - xsIDREFS& names = names_source->getValue(); - - for (size_t j = 0; j < names.getCount(); ++j) - { - std::string name(names.get(j).getID()); - if (mJointMap.find(name) != mJointMap.end()) - { - name = mJointMap[name]; - } - model->mSkinInfo.mJointNames.push_back(name); - model->mSkinInfo.mJointMap[name] = j; - } - } - } - } - } - else if (strcmp(semantic, COMMON_PROFILE_INPUT_INV_BIND_MATRIX) == 0) - { //found inv_bind_matrix array, fill model->mInvBindMatrix - domSource* source = daeSafeCast(input->getSource().getElement()); - if (source) - { - domFloat_array* t = source->getFloat_array(); - if (t) - { - domListOfFloats& transform = t->getValue(); - S32 count = transform.getCount()/16; - - for (S32 k = 0; k < count; ++k) - { - LLMatrix4 mat; - - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - mat.mMatrix[i][j] = transform[k*16 + i + j*4]; - } - } - - model->mSkinInfo.mInvBindMatrix.push_back(mat); - } - } - } - } - } - - //Now that we've parsed the joint array, let's determine if we have a full rig - //(which means we have all the joint sthat are required for an avatar versus - //a skinned asset attached to a node in a file that contains an entire skeleton, - //but does not use the skeleton). - buildJointToNodeMappingFromScene(root); - mPreview->critiqueRigForUploadApplicability(model->mSkinInfo.mJointNames); - - if (!missingSkeletonOrScene) - { - //Set the joint translations on the avatar - if it's a full mapping - //The joints are reset in the dtor - if (mPreview->getRigWithSceneParity()) - { - std::map :: const_iterator masterJointIt = mJointMap.begin(); - std::map :: const_iterator masterJointItEnd = mJointMap.end(); - for ( ;masterJointIt!=masterJointItEnd;++masterJointIt) - { - std::string lookingForJoint = (*masterJointIt).first.c_str(); - - if (mJointList.find(lookingForJoint) != mJointList.end()) - { - //LL_INFOS() <<"joint "<getPreviewAvatar()->getJoint(lookingForJoint); - if (pJoint) - { - pJoint->storeCurrentXform(jointTransform.getTranslation()); - } - else - { - //Most likely an error in the asset. - LL_WARNS() << "Tried to apply joint position from .dae, but it did not exist in the avatar rig." << LL_ENDL; - } - } - } - } - } //missingSkeletonOrScene - - //We need to construct the alternate bind matrix (which contains the new joint positions) - //in the same order as they were stored in the joint buffer. The joints associated - //with the skeleton are not stored in the same order as they are in the exported joint buffer. - //This remaps the skeletal joints to be in the same order as the joints stored in the model. - std::vector :: const_iterator jointIt = model->mSkinInfo.mJointNames.begin(); - const int jointCnt = model->mSkinInfo.mJointNames.size(); - for (int i = 0; i < jointCnt; ++i, ++jointIt) - { - std::string lookingForJoint = (*jointIt).c_str(); - //Look for the joint xform that we extracted from the skeleton, using the jointIt as the key - //and store it in the alternate bind matrix - if (mJointList.find(lookingForJoint) != mJointList.end()) - { - LLMatrix4 jointTransform = mJointList[lookingForJoint]; - LLMatrix4 newInverse = model->mSkinInfo.mInvBindMatrix[i]; - newInverse.setTranslation(mJointList[lookingForJoint].getTranslation()); - model->mSkinInfo.mAlternateBindMatrix.push_back(newInverse); - } - else - { - LL_WARNS() << "Possibly misnamed/missing joint [" << lookingForJoint.c_str() << " ] " << LL_ENDL; - } - } - - //grab raw position array - - domVertices* verts = mesh->getVertices(); - if (verts) - { - domInputLocal_Array& inputs = verts->getInput_array(); - for (size_t i = 0; i < inputs.getCount() && model->mPosition.empty(); ++i) - { - if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_POSITION) == 0) - { - domSource* pos_source = daeSafeCast(inputs[i]->getSource().getElement()); - if (pos_source) - { - domFloat_array* pos_array = pos_source->getFloat_array(); - if (pos_array) - { - domListOfFloats& pos = pos_array->getValue(); - - for (size_t j = 0; j < pos.getCount(); j += 3) - { - if (pos.getCount() <= j+2) - { - LL_ERRS() << "Invalid position array size." << LL_ENDL; - } - - LLVector3 v(pos[j], pos[j + 1], pos[j+2]); - - //transform from COLLADA space to volume space - v = v * inverse_normalized_transformation; - - model->mPosition.push_back(v); - } - } - } - } - } - } - - //grab skin weights array - domSkin::domVertex_weights* weights = skin->getVertex_weights(); - if (weights) - { - domInputLocalOffset_Array& inputs = weights->getInput_array(); - domFloat_array* vertex_weights = NULL; - for (size_t i = 0; i < inputs.getCount(); ++i) - { - if (strcmp(inputs[i]->getSemantic(), COMMON_PROFILE_INPUT_WEIGHT) == 0) - { - domSource* weight_source = daeSafeCast(inputs[i]->getSource().getElement()); - if (weight_source) - { - vertex_weights = weight_source->getFloat_array(); - } - } - } - - if (vertex_weights) - { - domListOfFloats& w = vertex_weights->getValue(); - domListOfUInts& vcount = weights->getVcount()->getValue(); - domListOfInts& v = weights->getV()->getValue(); - - U32 c_idx = 0; - for (size_t vc_idx = 0; vc_idx < vcount.getCount(); ++vc_idx) - { //for each vertex - daeUInt count = vcount[vc_idx]; - - //create list of weights that influence this vertex - LLModel::weight_list weight_list; - - for (daeUInt i = 0; i < count; ++i) - { //for each weight - daeInt joint_idx = v[c_idx++]; - daeInt weight_idx = v[c_idx++]; - - if (joint_idx == -1) - { - //ignore bindings to bind_shape_matrix - continue; - } - - F32 weight_value = w[weight_idx]; - - weight_list.push_back(LLModel::JointWeight(joint_idx, weight_value)); - } - - //sort by joint weight - std::sort(weight_list.begin(), weight_list.end(), LLModel::CompareWeightGreater()); - - std::vector wght; - - F32 total = 0.f; - - for (U32 i = 0; i < llmin((U32) 4, (U32) weight_list.size()); ++i) - { //take up to 4 most significant weights - if (weight_list[i].mWeight > 0.f) - { - wght.push_back(weight_list[i]); - total += weight_list[i].mWeight; - } - } - - F32 scale = 1.f/total; - if (scale != 1.f) - { //normalize weights - for (U32 i = 0; i < wght.size(); ++i) - { - wght[i].mWeight *= scale; - } - } - - model->mSkinWeights[model->mPosition[vc_idx]] = wght; - } - - //add instance to scene for this model - - LLMatrix4 transformation = mTransform; - // adjust the transformation to compensate for mesh normalization - - LLMatrix4 mesh_translation; - mesh_translation.setTranslation(mesh_translation_vector); - mesh_translation *= transformation; - transformation = mesh_translation; - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= transformation; - transformation = mesh_scale; - - std::map materials; - for (U32 i = 0; i < model->mMaterialList.size(); ++i) - { - materials[model->mMaterialList[i]] = LLImportMaterial(); - } - mScene[transformation].push_back(LLModelInstance(model, model->mLabel, transformation, materials)); - stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); - } - } - } - } - } - } - } - - daeElement* scene = root->getDescendant("visual_scene"); - - if (!scene) - { - LL_WARNS() << "document has no visual_scene" << LL_ENDL; - setLoadState(ERROR_PARSING); - return true; - } - - setLoadState(DONE); - - bool badElement = false; - - processElement(scene, badElement); - - if (badElement) - { - setLoadState(ERROR_PARSING); - } - - return true; -} - -void LLModelLoader::setLoadState(U32 state) -{ - if (mPreview) - { - mPreview->setLoadState(state); - } -} - -bool LLModelLoader::loadFromSLM(const std::string& filename) -{ - //only need to populate mScene with data from slm - llstat stat; - - if (LLFile::stat(filename, &stat)) - { //file does not exist - return false; - } - - S32 file_size = (S32) stat.st_size; - - llifstream ifstream(filename, std::ifstream::in | std::ifstream::binary); - LLSD data; - LLSDSerialize::fromBinary(data, ifstream, file_size); - ifstream.close(); - - //build model list for each LoD - model_list model[LLModel::NUM_LODS]; - - if (data["version"].asInteger() != SLM_SUPPORTED_VERSION) - { //unsupported version - return false; - } - - LLSD& mesh = data["mesh"]; - - LLVolumeParams volume_params; - volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); - - for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) - { - for (int i = 0; i < mesh.size(); ++i) - { - std::stringstream str(mesh[i].asString()); - LLPointer loaded_model = new LLModel(volume_params, (F32) lod); - if (loaded_model->loadModel(str)) - { - loaded_model->mLocalID = i; - model[lod].push_back(loaded_model); - - if (lod == LLModel::LOD_HIGH && !loaded_model->mSkinInfo.mJointNames.empty()) - { - //check to see if rig is valid - mPreview->critiqueRigForUploadApplicability(loaded_model->mSkinInfo.mJointNames); - } - } - } - } - - if (model[LLModel::LOD_HIGH].empty()) - { //failed to load high lod - return false; - } - - // Set name. - std::string name = data["name"]; - if (!name.empty()) - { - model[LLModel::LOD_HIGH][0]->mLabel = name; - } - - //load instance list - model_instance_list instance_list; - - LLSD& instance = data["instance"]; - - for (int i = 0; i < instance.size(); ++i) - { - //deserialize instance list - instance_list.push_back(LLModelInstance(instance[i])); - - //match up model instance pointers - S32 idx = instance_list[i].mLocalMeshID; - - for (U32 lod = 0; lod < LLModel::NUM_LODS; ++lod) - { - if (!model[lod].empty()) - { - instance_list[i].mLOD[lod] = model[lod][idx]; - } - } - - instance_list[i].mModel = model[LLModel::LOD_HIGH][idx]; - } - - //convert instance_list to mScene - mFirstTransform = TRUE; - for (U32 i = 0; i < instance_list.size(); ++i) - { - LLModelInstance& cur_instance = instance_list[i]; - mScene[cur_instance.mTransform].push_back(cur_instance); - stretch_extents(cur_instance.mModel, cur_instance.mTransform, mExtents[0], mExtents[1], mFirstTransform); - } - - setLoadState(DONE); - - return true; -} - -//static -bool LLModelLoader::isAlive(LLModelLoader* loader) -{ - if (!loader) - { - return false; - } - - std::list::iterator iter = sActiveLoaderList.begin(); - for ( ; iter != sActiveLoaderList.end() && (*iter) != loader; ++iter); - - return *iter == loader; -} - -void LLModelLoader::loadModelCallback() -{ - assert_main_thread(); - - if (mPreview) - { - mPreview->loadModelCallback(mLod); - } - - while (!isStopped()) - { //wait until this thread is stopped before deleting self - apr_sleep(100); - } - - //double check if "this" is valid before deleting it, in case it is aborted during running. - if (!isAlive(this)) - { - return; - } - - //cleanup model loader - if (mPreview) - { - mPreview->mModelLoader = NULL; - } - - delete this; -} - -//----------------------------------------------------------------------------- -// buildJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelLoader::buildJointToNodeMappingFromScene(daeElement* pRoot) -{ - daeElement* pScene = pRoot->getDescendant("visual_scene"); - if (pScene) - { - daeTArray< daeSmartRef > children = pScene->getChildren(); - S32 childCount = children.getCount(); - for (S32 i = 0; i < childCount; ++i) - { - domNode* pNode = daeSafeCast(children[i]); - processJointToNodeMapping(pNode); - } - } -} - -//----------------------------------------------------------------------------- -// processJointToNodeMapping() -//----------------------------------------------------------------------------- -void LLModelLoader::processJointToNodeMapping(domNode* pNode) -{ - if (isNodeAJoint(pNode)) - { - //1.Store the parent - std::string nodeName = pNode->getName(); - if (!nodeName.empty()) - { - mJointsFromNode.push_front(pNode->getName()); - } - //2. Handle the kiddo's - processChildJoints(pNode); - } - else - { - //Determine if the're any children wrt to this failed node. - //This occurs when an armature is exported and ends up being what essentially amounts to - //as the root for the visual_scene - if (pNode) - { - processChildJoints(pNode); - } - else - { - LL_INFOS() <<"Node is NULL"< > childOfChild = pParentNode->getChildren(); - S32 childOfChildCount = childOfChild.getCount(); - for (S32 i = 0; i < childOfChildCount; ++i) - { - domNode* pChildNode = daeSafeCast(childOfChild[i]); - if (pChildNode) - { - processJointToNodeMapping(pChildNode); - } - } -} - -//----------------------------------------------------------------------------- -// critiqueRigForUploadApplicability() -//----------------------------------------------------------------------------- -void LLModelPreview::critiqueRigForUploadApplicability(const std::vector &jointListFromAsset) -{ - critiqueJointToNodeMappingFromScene(); - - //Determines the following use cases for a rig: - //1. It is suitable for upload with skin weights & joint positions, or - //2. It is suitable for upload as standard av with just skin weights - - bool isJointPositionUploadOK = isRigSuitableForJointPositionUpload(jointListFromAsset); - bool isRigLegacyOK = isRigLegacy(jointListFromAsset); - - //It's OK that both could end up being true, both default to false - if (isJointPositionUploadOK) - { - setRigValidForJointPositionUpload(true); - } - - if (isRigLegacyOK) - { - setLegacyRigValid(true); - } - -} - -//----------------------------------------------------------------------------- -// critiqueJointToNodeMappingFromScene() -//----------------------------------------------------------------------------- -void LLModelPreview::critiqueJointToNodeMappingFromScene(void) -{ - //Do the actual nodes back the joint listing from the dae? - //if yes then this is a fully rigged asset, otherwise it's just a partial rig - - std::deque::iterator jointsFromNodeIt = mJointsFromNode.begin(); - std::deque::iterator jointsFromNodeEndIt = mJointsFromNode.end(); - bool result = true; - - if (!mJointsFromNode.empty()) - { - for ( ;jointsFromNodeIt!=jointsFromNodeEndIt;++jointsFromNodeIt) - { - std::string name = *jointsFromNodeIt; - if (mJointTransformMap.find(name) != mJointTransformMap.end()) - { - continue; - } - else - { - LL_INFOS() <<"critiqueJointToNodeMappingFromScene is missing a: "< &jointListFromAsset) -{ - //No joints in asset - if (jointListFromAsset.size() == 0) - { - return false; - } - - bool result = false; - - std::deque :: const_iterator masterJointIt = mMasterLegacyJointList.begin(); - std::deque :: const_iterator masterJointEndIt = mMasterLegacyJointList.end(); - - std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); - std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); - - for ( ;masterJointIt!=masterJointEndIt;++masterJointIt) - { - result = false; - modelJointIt = jointListFromAsset.begin(); - - for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt) - { - if (*masterJointIt == *modelJointIt) - { - result = true; - break; - } - } - if (!result) - { - LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; - break; - } - } - return result; -} - -//----------------------------------------------------------------------------- -// isRigSuitableForJointPositionUpload() -//----------------------------------------------------------------------------- -bool LLModelPreview::isRigSuitableForJointPositionUpload(const std::vector &jointListFromAsset) -{ - bool result = false; - - std::deque :: const_iterator masterJointIt = mMasterJointList.begin(); - std::deque :: const_iterator masterJointEndIt = mMasterJointList.end(); - - std::vector :: const_iterator modelJointIt = jointListFromAsset.begin(); - std::vector :: const_iterator modelJointItEnd = jointListFromAsset.end(); - - for ( ;masterJointIt!=masterJointEndIt;++masterJointIt) - { - result = false; - modelJointIt = jointListFromAsset.begin(); - - for ( ;modelJointIt!=modelJointItEnd; ++modelJointIt) - { - if (*masterJointIt == *modelJointIt) - { - result = true; - break; - } - } - if (!result) - { - LL_INFOS() <<" Asset did not contain the joint (if you're u/l a fully rigged asset w/joint positions - it is required)." << *masterJointIt<< LL_ENDL; - break; - } - } - return result; -} - -//called in the main thread -void LLModelLoader::loadTextures() -{ - BOOL is_paused = isPaused(); - pause(); //pause the loader - - for (scene::iterator iter = mScene.begin(); iter != mScene.end(); ++iter) - { - for (U32 i = 0; i < iter->second.size(); i++) - { - for (std::map::iterator j = iter->second[i].mMaterial.begin(); - j != iter->second[i].mMaterial.end(); ++j) - { - LLImportMaterial& material = j->second; - - if (!material.mDiffuseMapFilename.empty()) - { - material.mDiffuseMap = - LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, TRUE, LLGLTexture::BOOST_PREVIEW); - material.mDiffuseMap->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, mPreview, NULL, FALSE); - material.mDiffuseMap->forceToSaveRawImage(0, F32_MAX); - mNumOfFetchingTextures++; - } - } - } - } - - if (!is_paused) - { - unpause(); - } -} - -//----------------------------------------------------------------------------- -// isNodeAJoint() -//----------------------------------------------------------------------------- -bool LLModelLoader::isNodeAJoint(domNode* pNode) -{ - if (!pNode) - { - LL_INFOS() <<"Created node is NULL"<getName() == NULL) - { - LL_INFOS() <<"Parsed node has no name "<getId()) - { - LL_INFOS() <<"Parsed node ID: "<getId()<getName()) != mJointMap.end()) - { - return true; - } - - return false; -} - -//----------------------------------------------------------------------------- -// verifyCount -//----------------------------------------------------------------------------- -bool LLModelPreview::verifyCount(int expected, int result) -{ - if (expected != result) - { - LL_INFOS() << "Error: (expected/got)"<getSkin(); - - if (pSkin) - { - xsAnyURI & uri = pSkin->getSource(); - domElement* pElement = uri.getElement(); - - if (!pElement) - { - LL_INFOS() <<"Can't resolve skin source"<getTypeName(); - if (stricmp(type_str, "geometry") == 0) - { - //Skin is reference directly by geometry and get the vertex count from skin - domSkin::domVertex_weights* pVertexWeights = pSkin->getVertex_weights(); - U32 vertexWeightsCount = pVertexWeights->getCount(); - domGeometry* pGeometry = (domGeometry*) (domElement*) uri.getElement(); - domMesh* pMesh = pGeometry->getMesh(); - - if (pMesh) - { - //Get vertex count from geometry - domVertices* pVertices = pMesh->getVertices(); - if (!pVertices) - { - LL_INFOS() <<"No vertices!"<getInput_array()[0]->getSource(); - domSource* pSource = (domSource*) (domElement*) src.getElement(); - U32 verticesCount = pSource->getTechnique_common()->getAccessor()->getCount(); - result = verifyCount(verticesCount, vertexWeightsCount); - if (!result) - { - return result; - } - } - } - - U32 vcountCount = (U32) pVertexWeights->getVcount()->getValue().getCount(); - result = verifyCount(vcountCount, vertexWeightsCount); - if (!result) - { - return result; - } - - domInputLocalOffset_Array& inputs = pVertexWeights->getInput_array(); - U32 sum = 0; - for (size_t i = 0; i < vcountCount; i++) - { - sum += pVertexWeights->getVcount()->getValue()[i]; - } - result = verifyCount(sum * inputs.getCount(), (domInt) pVertexWeights->getV()->getValue().getCount()); - } - } - - return result; -} - -//----------------------------------------------------------------------------- -// extractTranslation() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslation(domTranslate* pTranslate, LLMatrix4& transform) -{ - domFloat3 jointTrans = pTranslate->getValue(); - LLVector3 singleJointTranslation(jointTrans[0], jointTrans[1], jointTrans[2]); - transform.setTranslation(singleJointTranslation); -} - -//----------------------------------------------------------------------------- -// extractTranslationViaElement() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslationViaElement(daeElement* pTranslateElement, LLMatrix4& transform) -{ - if (pTranslateElement) - { - domTranslate* pTranslateChild = dynamic_cast(pTranslateElement); - domFloat3 translateChild = pTranslateChild->getValue(); - LLVector3 singleJointTranslation(translateChild[0], translateChild[1], translateChild[2]); - transform.setTranslation(singleJointTranslation); - } -} - -//----------------------------------------------------------------------------- -// extractTranslationViaSID() -//----------------------------------------------------------------------------- -void LLModelLoader::extractTranslationViaSID(daeElement* pElement, LLMatrix4& transform) -{ - if (pElement) - { - daeSIDResolver resolver(pElement, "./transform"); - domMatrix* pMatrix = daeSafeCast(resolver.getElement()); - //We are only extracting out the translational component atm - LLMatrix4 workingTransform; - if (pMatrix) - { - domFloat4x4 domArray = pMatrix->getValue(); - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - workingTransform.mMatrix[i][j] = domArray[i + j*4]; - } - } - LLVector3 trans = workingTransform.getTranslation(); - transform.setTranslation(trans); - } - } - else - { - LL_WARNS() << "Element is nonexistent - empty/unsupported node." << LL_ENDL; - } -} - -//----------------------------------------------------------------------------- -// processJointNode() -//----------------------------------------------------------------------------- -void LLModelLoader::processJointNode(domNode* pNode, JointTransformMap& jointTransforms) -{ - if (pNode->getName() == NULL) - { - LL_WARNS() << "nameless node, can't process" << LL_ENDL; - return; - } - - //llwarns<<"ProcessJointNode# Node:" <getName()<(jointResolverA.getElement()); - daeSIDResolver jointResolverB(pNode, "./location"); - domTranslate* pTranslateB = daeSafeCast(jointResolverB.getElement()); - - //Translation via SID was successful - if (pTranslateA) - { - extractTranslation(pTranslateA, workingTransform); - } - else - if (pTranslateB) - { - extractTranslation(pTranslateB, workingTransform); - } - else - { - //Translation via child from element - daeElement* pTranslateElement = getChildFromElement(pNode, "translate"); - if (!pTranslateElement || pTranslateElement->typeID() != domTranslate::ID()) - { - //llwarns<< "The found element is not a translate node" <(jointResolver.getElement()); - if (pMatrix) - { - //LL_INFOS() <<"A matrix SID was however found!"<getValue(); - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - workingTransform.mMatrix[i][j] = domArray[i + j*4]; - } - } - } - else - { - LL_WARNS() << "The found element is not translate or matrix node - most likely a corrupt export!" << LL_ENDL; - } - } - else - { - extractTranslationViaElement(pTranslateElement, workingTransform); - } - } - - //Store the working transform relative to the nodes name. - jointTransforms[ pNode->getName() ] = workingTransform; - - //2. handle the nodes children - - //Gather and handle the incoming nodes children - daeTArray< daeSmartRef > childOfChild = pNode->getChildren(); - S32 childOfChildCount = childOfChild.getCount(); - - for (S32 i = 0; i < childOfChildCount; ++i) - { - domNode* pChildNode = daeSafeCast(childOfChild[i]); - if (pChildNode) - { - processJointNode(pChildNode, jointTransforms); - } - } -} - -//----------------------------------------------------------------------------- -// getChildFromElement() -//----------------------------------------------------------------------------- -daeElement* LLModelLoader::getChildFromElement(daeElement* pElement, std::string const & name) -{ - daeElement* pChildOfElement = pElement->getChild(name.c_str()); - if (pChildOfElement) - { - return pChildOfElement; - } - LL_WARNS() << "Could not find a child [" << name << "] for the element: \"" << pElement->getAttribute("id") << "\"" << LL_ENDL; - return NULL; -} - -void LLModelLoader::processElement(daeElement* element, bool& badElement) -{ - LLMatrix4 saved_transform = mTransform; - - domTranslate* translate = daeSafeCast(element); - if (translate) - { - domFloat3 dom_value = translate->getValue(); - - LLMatrix4 translation; - translation.setTranslation(LLVector3(dom_value[0], dom_value[1], dom_value[2])); - - translation *= mTransform; - mTransform = translation; - } - - domRotate* rotate = daeSafeCast(element); - if (rotate) - { - domFloat4 dom_value = rotate->getValue(); - - LLMatrix4 rotation; - rotation.initRotTrans(dom_value[3] * DEG_TO_RAD, LLVector3(dom_value[0], dom_value[1], dom_value[2]), LLVector3(0, 0, 0)); - - rotation *= mTransform; - mTransform = rotation; - } - - domScale* scale = daeSafeCast(element); - if (scale) - { - domFloat3 dom_value = scale->getValue(); - - LLVector3 scale_vector = LLVector3(dom_value[0], dom_value[1], dom_value[2]); - scale_vector.abs(); // Set all values positive, since we don't currently support mirrored meshes - LLMatrix4 scaling; - scaling.initScale(scale_vector); - - scaling *= mTransform; - mTransform = scaling; - } - - domMatrix* matrix = daeSafeCast(element); - if (matrix) - { - domFloat4x4 dom_value = matrix->getValue(); - - LLMatrix4 matrix_transform; - - for (int i = 0; i < 4; i++) - { - for (int j = 0; j < 4; j++) - { - matrix_transform.mMatrix[i][j] = dom_value[i + j*4]; - } - } - - matrix_transform *= mTransform; - mTransform = matrix_transform; - } - - domInstance_geometry* instance_geo = daeSafeCast(element); - if (instance_geo) - { - domGeometry* geo = daeSafeCast(instance_geo->getUrl().getElement()); - if (geo) - { - domMesh* mesh = daeSafeCast(geo->getDescendant(daeElement::matchType(domMesh::ID()))); - if (mesh) - { - LLModel* model = mModel[mesh]; - if (model) - { - LLMatrix4 transformation = mTransform; - - if (mTransform.determinant() < 0) - { //negative scales are not supported - LL_INFOS() << "Negative scale detected, unsupported transform. domInstance_geometry: " << LLModel::getElementLabel(instance_geo) << LL_ENDL; - badElement = true; - } - - std::map materials = getMaterials(model, instance_geo); - - // adjust the transformation to compensate for mesh normalization - LLVector3 mesh_scale_vector; - LLVector3 mesh_translation_vector; - model->getNormalizedScaleTranslation(mesh_scale_vector, mesh_translation_vector); - - LLMatrix4 mesh_translation; - mesh_translation.setTranslation(mesh_translation_vector); - mesh_translation *= transformation; - transformation = mesh_translation; - - LLMatrix4 mesh_scale; - mesh_scale.initScale(mesh_scale_vector); - mesh_scale *= transformation; - transformation = mesh_scale; - - std::string label = getElementLabel(instance_geo); - mScene[transformation].push_back(LLModelInstance(model, label, transformation, materials)); - - stretch_extents(model, transformation, mExtents[0], mExtents[1], mFirstTransform); - } - } - } - else - { - LL_INFOS() <<"Unable to resolve geometry URL."<(element); - if (instance_node) - { - daeElement* instance = instance_node->getUrl().getElement(); - if (instance) - { - processElement(instance,badElement); - } - } - - //process children - daeTArray< daeSmartRef > children = element->getChildren(); - int childCount = children.getCount(); - for (S32 i = 0; i < childCount; i++) - { - processElement(children[i],badElement); - } - - domNode* node = daeSafeCast(element); - if (node) - { //this element was a node, restore transform before processiing siblings - mTransform = saved_transform; - } -} - -std::map LLModelLoader::getMaterials(LLModel* model, domInstance_geometry* instance_geo) -{ - std::map materials; - for (U32 i = 0; i < model->mMaterialList.size(); i++) - { - LLImportMaterial import_material; - - domInstance_material* instance_mat = NULL; - - domBind_material::domTechnique_common* technique = - daeSafeCast(instance_geo->getDescendant(daeElement::matchType(domBind_material::domTechnique_common::ID()))); - - if (technique) - { - daeTArray< daeSmartRef > inst_materials = technique->getChildrenByType(); - for (U32 j = 0; j < inst_materials.getCount(); j++) - { - std::string symbol(inst_materials[j]->getSymbol()); - - if (symbol == model->mMaterialList[i]) // found the binding - { - instance_mat = inst_materials[j]; - } - } - } - - if (instance_mat) - { - domMaterial* material = daeSafeCast(instance_mat->getTarget().getElement()); - if (material) - { - domInstance_effect* instance_effect = - daeSafeCast(material->getDescendant(daeElement::matchType(domInstance_effect::ID()))); - if (instance_effect) - { - domEffect* effect = daeSafeCast(instance_effect->getUrl().getElement()); - if (effect) - { - domProfile_COMMON* profile = - daeSafeCast(effect->getDescendant(daeElement::matchType(domProfile_COMMON::ID()))); - if (profile) - { - import_material = profileToMaterial(profile); - } - } - } - } - } - - import_material.mBinding = model->mMaterialList[i]; - materials[model->mMaterialList[i]] = import_material; - } - - return materials; -} - -LLImportMaterial LLModelLoader::profileToMaterial(domProfile_COMMON* material) -{ - LLImportMaterial mat; - mat.mFullbright = FALSE; - - daeElement* diffuse = material->getDescendant("diffuse"); - if (diffuse) - { - domCommon_color_or_texture_type_complexType::domTexture* texture = - daeSafeCast(diffuse->getDescendant("texture")); - if (texture) - { - domCommon_newparam_type_Array newparams = material->getNewparam_array(); - for (U32 i = 0; i < newparams.getCount(); i++) - { - domFx_surface_common* surface = newparams[i]->getSurface(); - if (surface) - { - domFx_surface_init_common* init = surface->getFx_surface_init_common(); - if (init) - { - domFx_surface_init_from_common_Array init_from = init->getInit_from_array(); - - if (init_from.getCount() > i) - { - domImage* image = daeSafeCast(init_from[i]->getValue().getElement()); - if (image) - { - // we only support init_from now - embedded data will come later - domImage::domInit_from* init = image->getInit_from(); - if (init) - { - mat.mDiffuseMapFilename = cdom::uriToNativePath(init->getValue().str()); - mat.mDiffuseMapLabel = getElementLabel(material); - } - } - } - } - } - } - } - - domCommon_color_or_texture_type_complexType::domColor* color = - daeSafeCast(diffuse->getDescendant("color")); - if (color) - { - domFx_color_common domfx_color = color->getValue(); - LLColor4 value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); - mat.mDiffuseColor = value; - } - } - - daeElement* emission = material->getDescendant("emission"); - if (emission) - { - LLColor4 emission_color = getDaeColor(emission); - if (((emission_color[0] + emission_color[1] + emission_color[2]) / 3.0) > 0.25) - { - mat.mFullbright = TRUE; - } - } - - return mat; -} - -// try to get a decent label for this element -std::string LLModelLoader::getElementLabel(daeElement *element) -{ - // if we have a name attribute, use it - std::string name = element->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if we have an ID attribute, use it - if (element->getID()) - { - return std::string(element->getID()); - } - - // if we have a parent, use it - daeElement* parent = element->getParent(); - if (parent) - { - // if parent has a name, use it - std::string name = parent->getAttribute("name"); - if (name.length()) - { - return name; - } - - // if parent has an ID, use it - if (parent->getID()) - { - return std::string(parent->getID()); - } - } - - // try to use our type - daeString element_name = element->getElementName(); - if (element_name) - { - return std::string(element_name); - } - - // if all else fails, use "object" - return std::string("object"); -} - -LLColor4 LLModelLoader::getDaeColor(daeElement* element) -{ - LLColor4 value; - domCommon_color_or_texture_type_complexType::domColor* color = - daeSafeCast(element->getDescendant("color")); - if (color) - { - domFx_color_common domfx_color = color->getValue(); - value = LLColor4(domfx_color[0], domfx_color[1], domfx_color[2], domfx_color[3]); - } - - return value; -} - //----------------------------------------------------------------------------- // LLModelPreview //----------------------------------------------------------------------------- LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) : LLViewerDynamicTexture(width, height, 3, ORDER_MIDDLE, FALSE), LLMutex() +, mLodsQuery() , mPelvisZOffset( 0.0f ) , mLegacyRigValid( false ) , mRigValidJointUpload( false ) +, mPhysicsSearchLOD( LLModel::LOD_PHYSICS ) , mResetJoints( false ) +, mModelNoErrors( true ) , mRigParityWithScene( false ) , mLastJointUpdate( false ) { @@ -3100,51 +1234,20 @@ LLModelPreview::LLModelPreview(S32 width, S32 height, LLFloater* fmp) glodInit(); - //move into joint mapper class - //1. joints for joint offset verification - mMasterJointList.push_front("mPelvis"); - mMasterJointList.push_front("mTorso"); - mMasterJointList.push_front("mChest"); - mMasterJointList.push_front("mNeck"); - mMasterJointList.push_front("mHead"); - mMasterJointList.push_front("mCollarLeft"); - mMasterJointList.push_front("mShoulderLeft"); - mMasterJointList.push_front("mElbowLeft"); - mMasterJointList.push_front("mWristLeft"); - mMasterJointList.push_front("mCollarRight"); - mMasterJointList.push_front("mShoulderRight"); - mMasterJointList.push_front("mElbowRight"); - mMasterJointList.push_front("mWristRight"); - mMasterJointList.push_front("mHipRight"); - mMasterJointList.push_front("mKneeRight"); - mMasterJointList.push_front("mFootRight"); - mMasterJointList.push_front("mHipLeft"); - mMasterJointList.push_front("mKneeLeft"); - mMasterJointList.push_front("mFootLeft"); - //2. legacy joint list - used to verify rigs that will not be using joint offsets - mMasterLegacyJointList.push_front("mPelvis"); - mMasterLegacyJointList.push_front("mTorso"); - mMasterLegacyJointList.push_front("mChest"); - mMasterLegacyJointList.push_front("mNeck"); - mMasterLegacyJointList.push_front("mHead"); - mMasterLegacyJointList.push_front("mHipRight"); - mMasterLegacyJointList.push_front("mKneeRight"); - mMasterLegacyJointList.push_front("mFootRight"); - mMasterLegacyJointList.push_front("mHipLeft"); - mMasterLegacyJointList.push_front("mKneeLeft"); - mMasterLegacyJointList.push_front("mFootLeft"); - createPreviewAvatar(); } LLModelPreview::~LLModelPreview() { - if (mModelLoader) - { - mModelLoader->mPreview = NULL; - mModelLoader = NULL; - } - // *HACK : *TODO : turn this back on when we understand why this crashes + // glod apparently has internal mem alignment issues that are angering + // the heap-check code in windows, these should be hunted down in that + // TP code, if possible + // + // kernel32.dll!HeapFree() + 0x14 bytes + // msvcr100.dll!free(void * pBlock) Line 51 C + // glod.dll!glodGetGroupParameteriv() + 0x119 bytes + // glod.dll!glodShutdown() + 0x77 bytes + // //glodShutdown(); } @@ -3173,7 +1276,11 @@ U32 LLModelPreview::calcResourceCost() if (mFMP && mFMP->childGetValue("upload_joints").asBoolean()) { - getPreviewAvatar()->setPelvisOffset(mPelvisZOffset); + // FIXME if preview avatar ever gets reused, this fake mesh ID stuff will fail. + // see also call to addAttachmentPosOverride. + LLUUID fake_mesh_id; + fake_mesh_id.generate(); + getPreviewAvatar()->addPelvisFixup( mPelvisZOffset, fake_mesh_id ); } F32 streaming_cost = 0.f; @@ -3210,8 +1317,10 @@ U32 LLModelPreview::calcResourceCost() decomp, mFMP->childGetValue("upload_skin").asBoolean(), mFMP->childGetValue("upload_joints").asBoolean(), - TRUE); - + TRUE, + FALSE, + instance.mModel->mSubmodelID); + num_hulls += decomp.mHull.size(); for (U32 i = 0; i < decomp.mHull.size(); ++i) { @@ -3276,29 +1385,12 @@ void LLModelPreview::rebuildUploadData() F32 max_scale = 0.f; - //reorder materials to match mBaseModel - for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) - { - if (mBaseModel.size() == mModel[i].size()) - { - for (U32 j = 0; j < mBaseModel.size(); ++j) - { - - int refFaceCnt = 0; - int modelFaceCnt = 0; - - if (!mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt)) - { - setLoadState( LLModelLoader::ERROR_MATERIALS ); - mFMP->childDisable("calculate_btn"); - } - } - } - } + BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug"); + BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching"); for (LLModelLoader::scene::iterator iter = mBaseScene.begin(); iter != mBaseScene.end(); ++iter) - { //for each transform in scene - LLMatrix4 mat = iter->first; + { //for each transform in scene + LLMatrix4 mat = iter->first; // compute position LLVector3 position = LLVector3(0, 0, 0) * mat; @@ -3320,33 +1412,175 @@ void LLModelPreview::rebuildUploadData() LLModelInstance instance = *model_iter; LLModel* base_model = instance.mModel; - - if (base_model) + + if (base_model && !requested_name.empty()) { base_model->mRequestedLabel = requested_name; base_model->mMetric = metric; } - U32 idx = 0; - for (idx = 0; idx < mBaseModel.size(); ++idx) - { //find reference instance for this model - if (mBaseModel[idx] == base_model) - { - break; - } - } - - if (idx < mBaseModel.size()) + for (int i = LLModel::NUM_LODS - 1; i >= LLModel::LOD_IMPOSTOR; i--) { - for (U32 i = 0; i < LLModel::NUM_LODS; i++) - { //fill LOD slots based on reference model index - if (mModel[i].size() > idx) + LLModel* lod_model = NULL; + if (!legacyMatching) + { + // Fill LOD slots by finding matching meshes by label with name extensions + // in the appropriate scene for each LOD. This fixes all kinds of issues + // where the indexed method below fails in spectacular fashion. + // If you don't take the time to name your LOD and PHYS meshes + // with the name of their corresponding mesh in the HIGH LOD, + // then the indexed method will be attempted below. + + LLMatrix4 transform; + + std::string name_to_match = instance.mLabel; + llassert(!name_to_match.empty()); + + int extensionLOD; + if (i != LLModel::LOD_PHYSICS || mModel[LLModel::LOD_PHYSICS].empty()) { - instance.mLOD[i] = mModel[i][idx]; + extensionLOD = i; } else { - instance.mLOD[i] = NULL; + //Physics can be inherited from other LODs or loaded, so we need to adjust what extension we are searching for + extensionLOD = mPhysicsSearchLOD; + } + + std::string toAdd; + switch (extensionLOD) + { + case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break; + case LLModel::LOD_LOW: toAdd = "_LOD1"; break; + case LLModel::LOD_MEDIUM: toAdd = "_LOD2"; break; + case LLModel::LOD_PHYSICS: toAdd = "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + if (name_to_match.find(toAdd) == std::string::npos) + { + name_to_match += toAdd; + } + + FindModel(mScene[i], name_to_match, lod_model, transform); + + if (!lod_model && i != LLModel::LOD_PHYSICS) + { + if (importerDebug) + { + LL_INFOS() << "Search of" << name_to_match << " in LOD" << i << " list failed. Searching for alternative among LOD lists." << LL_ENDL; + } + + int searchLOD = (i > LLModel::LOD_HIGH) ? LLModel::LOD_HIGH : i; + while ((searchLOD <= LLModel::LOD_HIGH) && !lod_model) + { + std::string name_to_match = instance.mLabel; + llassert(!name_to_match.empty()); + + std::string toAdd; + switch (searchLOD) + { + case LLModel::LOD_IMPOSTOR: toAdd = "_LOD0"; break; + case LLModel::LOD_LOW: toAdd = "_LOD1"; break; + case LLModel::LOD_MEDIUM: toAdd = "_LOD2"; break; + case LLModel::LOD_PHYSICS: toAdd = "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + if (name_to_match.find(toAdd) == std::string::npos) + { + name_to_match += toAdd; + } + + // See if we can find an appropriately named model in LOD 'searchLOD' + // + FindModel(mScene[searchLOD], name_to_match, lod_model, transform); + searchLOD++; + } + } + } + else + { + // Use old method of index-based association + U32 idx = 0; + for (idx = 0; idx < mBaseModel.size(); ++idx) + { + // find reference instance for this model + if (mBaseModel[idx] == base_model) + { + if (importerDebug) + { + LL_INFOS() << "Attempting to use model index " << idx << " for LOD " << i << " of " << instance.mLabel << LL_ENDL; + } + break; + } + } + + // If the model list for the current LOD includes that index... + // + if (mModel[i].size() > idx) + { + // Assign that index from the model list for our LOD as the LOD model for this instance + // + lod_model = mModel[i][idx]; + if (importerDebug) + { + LL_INFOS() << "Indexed match of model index " << idx << " at LOD " << i << " to model named " << lod_model->mLabel << LL_ENDL; + } + } + else if (importerDebug) + { + LL_INFOS() << "List of models does not include index " << idx << LL_ENDL; + } + } + + if (lod_model) + { + if (importerDebug) + { + if (i == LLModel::LOD_PHYSICS) + { + LL_INFOS() << "Assigning collision for " << instance.mLabel << " to match " << lod_model->mLabel << LL_ENDL; + } + else + { + LL_INFOS() << "Assigning LOD" << i << " for " << instance.mLabel << " to found match " << lod_model->mLabel << LL_ENDL; + } + } + instance.mLOD[i] = lod_model; + } + else + { + if (i < LLModel::LOD_HIGH && !lodsReady()) + { + // assign a placeholder from previous LOD until lod generation is complete. + // Note: we might need to assign it regardless of conditions like named search does, to prevent crashes. + instance.mLOD[i] = instance.mLOD[i + 1]; + } + if (importerDebug) + { + LL_INFOS() << "List of models does not include " << instance.mLabel << LL_ENDL; + } + } + } + + LLModel* high_lod_model = instance.mLOD[LLModel::LOD_HIGH]; + if (!high_lod_model) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + else + { + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + int refFaceCnt = 0; + int modelFaceCnt = 0; + llassert(instance.mLOD[i]); + if (instance.mLOD[i] && !instance.mLOD[i]->matchMaterialOrder(high_lod_model, refFaceCnt, modelFaceCnt ) ) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); } } } @@ -3355,7 +1589,33 @@ void LLModelPreview::rebuildUploadData() } } - + for (U32 lod = 0; lod < LLModel::NUM_LODS-1; lod++) + { + // Search for models that are not included into upload data + // If we found any, that means something we loaded is not a sub-model. + for (U32 model_ind = 0; model_ind < mModel[lod].size(); ++model_ind) + { + bool found_model = false; + for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) + { + LLModelInstance& instance = *iter; + if (instance.mLOD[lod] == mModel[lod][model_ind]) + { + found_model = true; + break; + } + } + if (!found_model && mModel[lod][model_ind] && !mModel[lod][model_ind]->mSubmodelID) + { + if (importerDebug) + { + LL_INFOS() << "Model " << mModel[lod][model_ind]->mLabel << " was not used - mismatching lod models." << LL_ENDL; + } + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + } + } const F32 DEFAULT_MAX_PRIM_SCALE(gHippoLimits->getMaxPrimScale()); F32 max_import_scale = (DEFAULT_MAX_PRIM_SCALE-0.1f)/max_scale; @@ -3436,15 +1696,16 @@ void LLModelPreview::saveUploadData(const std::string& filename, bool save_skinw instance.mLOD[LLModel::LOD_LOW], instance.mLOD[LLModel::LOD_IMPOSTOR], decomp, - save_skinweights, save_joint_positions, FALSE, TRUE); - + save_skinweights, save_joint_positions, + FALSE, TRUE, instance.mModel->mSubmodelID); + data["mesh"][instance.mModel->mLocalID] = str.str(); } data["instance"][i] = instance.asLLSD(); } - llofstream out(filename, std::ios_base::out | std::ios_base::binary); + llofstream out(filename.c_str(), std::ios_base::out | std::ios_base::binary); LLSDSerialize::toBinary(data, out); out.flush(); out.close(); @@ -3504,13 +1765,29 @@ void LLModelPreview::loadModel(std::string filename, S32 lod, bool force_disable clearGLODGroup(); } - mModelLoader = new LLModelLoader(filename, lod, this, mJointTransformMap, mJointsFromNode); + mModelLoader = new LLDAELoader( + filename, + lod, + &LLModelPreview::loadedCallback, + &LLModelPreview::lookupJointByName, + &LLModelPreview::loadTextures, + &LLModelPreview::stateChangedCallback, + this, + mJointTransformMap, + mJointsFromNode, + gSavedSettings.getU32("ImporterModelLimit"), + gSavedSettings.getBOOL("ImporterPreprocessDAE")); if (force_disable_slm) { mModelLoader->mTrySLM = false; } - + else + { + //only try to load from slm if viewer is configured to do so and this is the + //initial model load (not an LoD or physics shape) + mModelLoader->mTrySLM = gSavedSettings.getBOOL("MeshImportUseSLM") && mUploadData.empty(); + } mModelLoader->start(); mFMP->childSetTextArg("status", "[STATUS]", mFMP->getString("status_reading_file")); @@ -3541,6 +1818,7 @@ void LLModelPreview::setPhysicsFromLOD(S32 lod) if (lod >= 0 && lod <= 3) { + mPhysicsSearchLOD = lod; mModel[LLModel::LOD_PHYSICS] = mModel[lod]; mScene[LLModel::LOD_PHYSICS] = mScene[lod]; mLODFile[LLModel::LOD_PHYSICS].clear(); @@ -3560,11 +1838,14 @@ void LLModelPreview::clearIncompatible(S32 lod) return; } + // at this point we don't care about sub-models, + // different amount of sub-models means face count mismatch, not incompatibility + U32 lod_size = countRootModels(mModel[lod]); for (U32 i = 0; i <= LLModel::LOD_HIGH; i++) - { //clear out any entries that aren't compatible with this model + { //clear out any entries that aren't compatible with this model if (i != lod) { - if (mModel[i].size() != mModel[lod].size()) + if (countRootModels(mModel[i]) != lod_size) { mModel[i].clear(); mScene[i].clear(); @@ -3599,7 +1880,7 @@ void LLModelPreview::clearGLODGroup() } } -void LLModelPreview::loadModelCallback(S32 lod) +void LLModelPreview::loadModelCallback(S32 loaded_lod) { assert_main_thread(); @@ -3612,12 +1893,18 @@ void LLModelPreview::loadModelCallback(S32 lod) if (getLoadState() >= LLModelLoader::ERROR_PARSING) { mLoading = false; + mModelLoader = NULL; return; } - mModelLoader->loadTextures(); + // Copy determinations about rig so UI will reflect them + // + setRigValidForJointPositionUpload(mModelLoader->isRigValidForJointPositionUpload()); + setLegacyRigValid(mModelLoader->isLegacyRigValid()); - if (lod == -1) + mModelLoader->loadTextures() ; + + if (loaded_lod == -1) { //populate all LoDs from model loader scene mBaseModel.clear(); mBaseScene.clear(); @@ -3649,8 +1936,13 @@ void LLModelPreview::loadModelCallback(S32 lod) //override displayed model with current LoD list_iter->mModel = list_iter->mLOD[lod]; + if (!list_iter->mModel) + { + continue; + } + //add current model to current LoD's model list (LLModel::mLocalID makes a good vector index) - U32 idx = list_iter->mModel->mLocalID; + S32 idx = list_iter->mModel->mLocalID; if (mModel[lod].size() <= idx) { //stretch model list to fit model at given index @@ -3699,32 +1991,109 @@ void LLModelPreview::loadModelCallback(S32 lod) resetPreviewTarget(); } else - { //only replace given LoD - mModel[lod] = mModelLoader->mModelList; - mScene[lod] = mModelLoader->mScene; - mVertexBuffer[lod].clear(); + { //only replace given LoD + mModel[loaded_lod] = mModelLoader->mModelList; + mScene[loaded_lod] = mModelLoader->mScene; + mVertexBuffer[loaded_lod].clear(); - setPreviewLOD(lod); + setPreviewLOD(loaded_lod); - if (lod == LLModel::LOD_HIGH) - { //save a copy of the highest LOD for automatic LOD manipulation + if (loaded_lod == LLModel::LOD_HIGH) + { //save a copy of the highest LOD for automatic LOD manipulation if (mBaseModel.empty()) - { //first time we've loaded a model, auto-gen LoD + { //first time we've loaded a model, auto-gen LoD mGenLOD = true; } - mBaseModel = mModel[lod]; + mBaseModel = mModel[loaded_lod]; clearGLODGroup(); - mBaseScene = mScene[lod]; + mBaseScene = mScene[loaded_lod]; mVertexBuffer[5].clear(); } + else + { + BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug"); + BOOL legacyMatching = gSavedSettings.getBOOL("ImporterLegacyMatching"); + if (!legacyMatching) + { + if (!mBaseModel.empty()) + { + BOOL name_based = FALSE; + BOOL has_submodels = FALSE; + for (U32 idx = 0; idx < mBaseModel.size(); ++idx) + { + if (mBaseModel[idx]->mSubmodelID) + { // don't do index-based renaming when the base model has submodels + has_submodels = TRUE; + if (importerDebug) + { + LL_INFOS() << "High LOD has submodels" << LL_ENDL; + } + break; + } + } - clearIncompatible(lod); + for (U32 idx = 0; idx < mModel[loaded_lod].size(); ++idx) + { + std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel); + + LLModel* found_model = NULL; + LLMatrix4 transform; + FindModel(mBaseScene, loaded_name, found_model, transform); + if (found_model) + { // don't rename correctly named models (even if they are placed in a wrong order) + name_based = TRUE; + } + + if (mModel[loaded_lod][idx]->mSubmodelID) + { // don't rename the models when loaded LOD model has submodels + has_submodels = TRUE; + } + } + + if (importerDebug) + { + LL_INFOS() << "Loaded LOD " << loaded_lod << ": correct names" << (name_based ? "" : "NOT ") << "found; submodels " << (has_submodels ? "" : "NOT ") << "found" << LL_ENDL; + } + + if (!name_based && !has_submodels) + { // replace the name of the model loaded for any non-HIGH LOD to match the others (MAINT-5601) + // this actually works like "ImporterLegacyMatching" for this particular LOD + for (U32 idx = 0; idx < mModel[loaded_lod].size() && idx < mBaseModel.size(); ++idx) + { + std::string name = mBaseModel[idx]->mLabel; + std::string loaded_name = stripSuffix(mModel[loaded_lod][idx]->mLabel); + + if (loaded_name != name) + { + switch (loaded_lod) + { + case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; + case LLModel::LOD_LOW: name += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + if (importerDebug) + { + LL_WARNS() << "Loded model name " << mModel[loaded_lod][idx]->mLabel << " for LOD " << loaded_lod << " doesn't match the base model. Renaming to " << name << LL_ENDL; + } + + mModel[loaded_lod][idx]->mLabel = name; + } + } + } + } + } + } + + clearIncompatible(loaded_lod); mDirty = true; - if (lod == LLModel::LOD_HIGH) + if (loaded_lod == LLModel::LOD_HIGH) { resetPreviewTarget(); } @@ -3733,18 +2102,18 @@ void LLModelPreview::loadModelCallback(S32 lod) mLoading = false; if (mFMP) { + mFMP->getChild("confirm_checkbox")->set(FALSE); if (!mBaseModel.empty()) { - if (mFMP->getChild("description_form")->getValue().asString().empty()) - { - const std::string& model_name = mBaseModel[0]->getName(); - mFMP->getChild("description_form")->setValue(model_name); - } + const std::string& model_name = mBaseModel[0]->getName(); + mFMP->getChild("description_form")->setValue(model_name); } } refresh(); mModelLoadedSignal(); + + mModelLoader = NULL; } void LLModelPreview::resetPreviewTarget() @@ -3764,7 +2133,8 @@ void LLModelPreview::generateNormals() S32 which_lod = mPreviewLOD; - if (which_lod > 4 || which_lod < 0 || mModel[which_lod].empty()) + if (which_lod > 4 || which_lod < 0 || + mModel[which_lod].empty()) { return; } @@ -3777,19 +2147,81 @@ void LLModelPreview::generateNormals() if (which_lod == 3 && !mBaseModel.empty()) { - for (LLModelLoader::model_list::iterator iter = mBaseModel.begin(); iter != mBaseModel.end(); ++iter) + if(mBaseModelFacesCopy.empty()) { - (*iter)->generateNormals(angle_cutoff); + mBaseModelFacesCopy.reserve(mBaseModel.size()); + for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it) + { + v_LLVolumeFace_t faces; + (*it)->copyFacesTo(faces); + mBaseModelFacesCopy.push_back(faces); + } + } + + for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it) + { + (*it)->generateNormals(angle_cutoff); } mVertexBuffer[5].clear(); } - for (LLModelLoader::model_list::iterator iter = mModel[which_lod].begin(); iter != mModel[which_lod].end(); ++iter) - { - (*iter)->generateNormals(angle_cutoff); + bool perform_copy = mModelFacesCopy[which_lod].empty(); + if(perform_copy) { + mModelFacesCopy[which_lod].reserve(mModel[which_lod].size()); } + for (LLModelLoader::model_list::iterator it = mModel[which_lod].begin(), itE = mModel[which_lod].end(); it != itE; ++it) + { + if(perform_copy) + { + v_LLVolumeFace_t faces; + (*it)->copyFacesTo(faces); + mModelFacesCopy[which_lod].push_back(faces); + } + + (*it)->generateNormals(angle_cutoff); + } + + mVertexBuffer[which_lod].clear(); + refresh(); + updateStatusMessages(); +} + +void LLModelPreview::restoreNormals() +{ + S32 which_lod = mPreviewLOD; + + if (which_lod > 4 || which_lod < 0 || + mModel[which_lod].empty()) + { + return; + } + + if(!mBaseModelFacesCopy.empty()) + { + llassert(mBaseModelFacesCopy.size() == mBaseModel.size()); + + vv_LLVolumeFace_t::const_iterator itF = mBaseModelFacesCopy.begin(); + for (LLModelLoader::model_list::iterator it = mBaseModel.begin(), itE = mBaseModel.end(); it != itE; ++it, ++itF) + { + (*it)->copyFacesFrom((*itF)); + } + + mBaseModelFacesCopy.clear(); + } + + if(!mModelFacesCopy[which_lod].empty()) + { + vv_LLVolumeFace_t::const_iterator itF = mModelFacesCopy[which_lod].begin(); + for (LLModelLoader::model_list::iterator it = mModel[which_lod].begin(), itE = mModel[which_lod].end(); it != itE; ++it, ++itF) + { + (*it)->copyFacesFrom((*itF)); + } + + mModelFacesCopy[which_lod].clear(); + } + mVertexBuffer[which_lod].clear(); refresh(); updateStatusMessages(); @@ -4029,6 +2461,20 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); mModel[lod][mdl_idx] = new LLModel(volume_params, 0.f); + std::string name = base->mLabel; + + switch (lod) + { + case LLModel::LOD_IMPOSTOR: name += "_LOD0"; break; + case LLModel::LOD_LOW: name += "_LOD1"; break; + case LLModel::LOD_MEDIUM: name += "_LOD2"; break; + case LLModel::LOD_PHYSICS: name += "_PHYS"; break; + case LLModel::LOD_HIGH: break; + } + + mModel[lod][mdl_idx]->mLabel = name; + mModel[lod][mdl_idx]->mSubmodelID = base->mSubmodelID; + GLint* sizes = new GLint[patch_count*2]; glodGetObjectParameteriv(mObject[base], GLOD_PATCH_SIZES, sizes); stop_gloderror(); @@ -4141,17 +2587,112 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim { shader->bind(); } +} +void LLModelPreview::genModelBBox() +{ + LLVector3 min, max; + min = this->mModelLoader->mExtents[0]; + max = this->mModelLoader->mExtents[1]; + std::vector v_list; + v_list.resize(4); + std::map > face_list; - /*if (which_lod == -1 && mScene[LLModel::LOD_PHYSICS].empty()) - { //build physics scene - mScene[LLModel::LOD_PHYSICS] = mScene[LLModel::LOD_LOW]; - mModel[LLModel::LOD_PHYSICS] = mModel[LLModel::LOD_LOW]; + // Face 0 + v_list[0] = LLVector3(min.mV[VX], max.mV[VY], max.mV[VZ]); + v_list[1] = LLVector3(min.mV[VX], min.mV[VY], max.mV[VZ]); + v_list[2] = LLVector3(max.mV[VX], min.mV[VY], max.mV[VZ]); + v_list[3] = LLVector3(max.mV[VX], max.mV[VY], max.mV[VZ]); + face_list.insert(std::pair >(0, v_list)); - for (U32 i = 1; i < mModel[LLModel::LOD_PHYSICS].size(); ++i) - { - mPhysicsQ.push(mModel[LLModel::LOD_PHYSICS][i]); - } - }*/ + // Face 1 + v_list[0] = LLVector3(max.mV[VX], min.mV[VY], max.mV[VZ]); + v_list[1] = LLVector3(max.mV[VX], min.mV[VY], min.mV[VZ]); + v_list[2] = LLVector3(max.mV[VX], max.mV[VY], min.mV[VZ]); + v_list[3] = LLVector3(max.mV[VX], max.mV[VY], max.mV[VZ]); + face_list.insert(std::pair >(1, v_list)); + + // Face 2 + v_list[0] = LLVector3(min.mV[VX], max.mV[VY], min.mV[VZ]); + v_list[1] = LLVector3(min.mV[VX], max.mV[VY], max.mV[VZ]); + v_list[2] = LLVector3(max.mV[VX], max.mV[VY], max.mV[VZ]); + v_list[3] = LLVector3(max.mV[VX], max.mV[VY], min.mV[VZ]); + face_list.insert(std::pair >(2, v_list)); + + // Face 3 + v_list[0] = LLVector3(min.mV[VX], max.mV[VY], max.mV[VZ]); + v_list[1] = LLVector3(min.mV[VX], max.mV[VY], min.mV[VZ]); + v_list[2] = LLVector3(min.mV[VX], min.mV[VY], min.mV[VZ]); + v_list[3] = LLVector3(min.mV[VX], min.mV[VY], max.mV[VZ]); + face_list.insert(std::pair >(3, v_list)); + + // Face 4 + v_list[0] = LLVector3(min.mV[VX], min.mV[VY], max.mV[VZ]); + v_list[1] = LLVector3(min.mV[VX], min.mV[VY], min.mV[VZ]); + v_list[2] = LLVector3(max.mV[VX], min.mV[VY], min.mV[VZ]); + v_list[3] = LLVector3(max.mV[VX], min.mV[VY], max.mV[VZ]); + face_list.insert(std::pair >(4, v_list)); + + // Face 5 + v_list[0] = LLVector3(min.mV[VX], min.mV[VY], min.mV[VZ]); + v_list[1] = LLVector3(min.mV[VX], max.mV[VY], min.mV[VZ]); + v_list[2] = LLVector3(max.mV[VX], max.mV[VY], min.mV[VZ]); + v_list[3] = LLVector3(max.mV[VX], min.mV[VY], min.mV[VZ]); + face_list.insert(std::pair >(5, v_list)); + + U16 Idx[] = { 0, 1, 2, 3, 0, 2, }; + + U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; + LLPointer buff = new LLVertexBuffer(type_mask, 0); + buff->allocateBuffer(4, 6, true); + + LLStrider pos; + LLStrider idx; + LLStrider norm; + LLStrider tc; + + buff->getVertexStrider(pos); + buff->getIndexStrider(idx); + + buff->getNormalStrider(norm); + buff->getTexCoord0Strider(tc); + + for (U32 i = 0; i < 6; ++i) + { + idx[i] = Idx[i]; + } + + LLVolumeParams volume_params; + volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE); + LLModel* mdl = new LLModel(volume_params, 0.f); + mdl->mLabel = "BBOX"; // please adopt name from high LOD (mBaseModel) or from original model otherwise it breaks search mechanics which is name based + + mdl->setNumVolumeFaces(6); + for (U8 i = 0; i < 6; ++i) + { + for (U8 j = 0; j < 4; ++j) + { + pos[j] = face_list[i][j]; + } + + mdl->setVolumeFaceData(i, pos, norm, tc, idx, buff->getNumVerts(), buff->getNumIndices()); + } + + if (validate_model(mdl)) + { + LLMatrix4 mat; + std::map materials; + std::vector instance_list; + instance_list.push_back(LLModelInstance(mdl, mdl->mLabel, mat, materials)); + + for (S32 i = LLModel::LOD_HIGH - 1; i >= 0; i--) + { + mModel[i].clear(); + mModel[i].push_back(mdl); + + mScene[i].clear(); + mScene[i].insert(std::pair >(mat, instance_list)); + } + } } void LLModelPreview::updateStatusMessages() @@ -4168,48 +2709,89 @@ void LLModelPreview::updateStatusMessages() S32 total_verts[LLModel::NUM_LODS]; S32 total_submeshes[LLModel::NUM_LODS]; - for (S32 lod = 0; lod < LLModel::NUM_LODS; ++lod) + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + total_tris[i] = 0; + total_verts[i] = 0; + total_submeshes[i] = 0; + } + + for (LLMeshUploadThread::instance_list::iterator iter = mUploadData.begin(); iter != mUploadData.end(); ++iter) { - //initialize total for this lod to 0 - total_tris[lod] = total_verts[lod] = total_submeshes[lod] = 0; + LLModelInstance& instance = *iter; - for (LLModelLoader::scene::iterator iter = mScene[lod].begin(), endIter = mScene[lod].end(); iter != endIter; ++iter) + LLModel* model_high_lod = instance.mLOD[LLModel::LOD_HIGH]; + if (!model_high_lod) { - for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance) + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + continue; + } + + for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) + { + LLModel* lod_model = instance.mLOD[i]; + if (!lod_model) + { + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } + + int refFaceCnt = 0; + int modelFaceCnt = 0; + + if (!lod_model->matchMaterialOrder(model_high_lod, refFaceCnt, modelFaceCnt ) ) { - LLModel* lod_model = instance->mModel; - if (lod_model) - { - //for each model in the lod - S32 cur_tris = 0; - S32 cur_verts = 0; - S32 cur_submeshes = lod_model->getNumVolumeFaces(); + setLoadState( LLModelLoader::ERROR_MATERIALS ); + mFMP->childDisable( "calculate_btn" ); + } - for (S32 j = 0; j < cur_submeshes; ++j) - { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = lod_model->getVolumeFace(j); - cur_tris += face.mNumIndices/3; - cur_verts += face.mNumVertices; - } + if (lod_model) + { + //for each model in the lod + S32 cur_tris = 0; + S32 cur_verts = 0; + S32 cur_submeshes = lod_model->getNumVolumeFaces(); - //add this model to the lod total - total_tris[lod] += cur_tris; - total_verts[lod] += cur_verts; - total_submeshes[lod] += cur_submeshes; - - //store this model's counts to asset data - tris[lod].push_back(cur_tris); - verts[lod].push_back(cur_verts); - submeshes[lod].push_back(cur_submeshes); - } - else // !lod_model - { - setLoadState( LLModelLoader::ERROR_MATERIALS ); - mFMP->childDisable( "calculate_btn" ); + for (S32 j = 0; j < cur_submeshes; ++j) + { //for each submesh (face), add triangles and vertices to current total + const LLVolumeFace& face = lod_model->getVolumeFace(j); + cur_tris += face.mNumIndices/3; + cur_verts += face.mNumVertices; } + + std::string instance_name = instance.mLabel; + + BOOL importerDebug = gSavedSettings.getBOOL("ImporterDebug"); + if (importerDebug) + { + // Useful for debugging generalized complaints below about total submeshes which don't have enough + // context to address exactly what needs to be fixed to move towards compliance with the rules. + // + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Verts: " << cur_verts << LL_ENDL; + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Tris: " << cur_tris << LL_ENDL; + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Faces: " << cur_submeshes << LL_ENDL; + + LLModel::material_list::iterator mat_iter = lod_model->mMaterialList.begin(); + while (mat_iter != lod_model->mMaterialList.end()) + { + LL_INFOS() << "Instance " << lod_model->mLabel << " LOD " << i << " Material " << *(mat_iter) << LL_ENDL; + mat_iter++; + } + } + + //add this model to the lod total + total_tris[i] += cur_tris; + total_verts[i] += cur_verts; + total_submeshes[i] += cur_submeshes; + + //store this model's counts to asset data + tris[i].push_back(cur_tris); + verts[i].push_back(cur_verts); + submeshes[i].push_back(cur_submeshes); } } - } + } if (mMaxTriangleLimit == 0) { @@ -4222,29 +2804,36 @@ void LLModelPreview::updateStatusMessages() U32 lod = LLModel::LOD_PHYSICS; const LLVector4a scale(0.5f); for (U32 i = 0; i < mModel[lod].size() && !has_degenerate; ++i) - { //for each model in the lod - if (mModel[lod][i]->mPhysics.mHull.empty()) - { //no decomp exists + { //for each model in the lod + if (mModel[lod][i] && mModel[lod][i]->mPhysics.mHull.empty()) + { //no decomp exists S32 cur_submeshes = mModel[lod][i]->getNumVolumeFaces(); for (S32 j = 0; j < cur_submeshes && !has_degenerate; ++j) - { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); - for (S32 k = 0; k < face.mNumIndices && !has_degenerate; ) + { //for each submesh (face), add triangles and vertices to current total + LLVolumeFace& face = mModel[lod][i]->getVolumeFace(j); + for (S32 k = 0; (k < face.mNumIndices) && !has_degenerate; ) { - LLVector4a v1; v1.setMul(face.mPositions[face.mIndices[k++]], scale); - LLVector4a v2; v2.setMul(face.mPositions[face.mIndices[k++]], scale); - LLVector4a v3; v3.setMul(face.mPositions[face.mIndices[k++]], scale); + U16 index_a = face.mIndices[k+0]; + U16 index_b = face.mIndices[k+1]; + U16 index_c = face.mIndices[k+2]; - if (ll_is_degenerate(v1, v2, v3)) + LLVector4a v1; v1.setMul(face.mPositions[index_a], scale); + LLVector4a v2; v2.setMul(face.mPositions[index_b], scale); + LLVector4a v3; v3.setMul(face.mPositions[index_c], scale); + + if (ll_is_degenerate(v1,v2,v3)) { has_degenerate = true; } + else + { + k += 3; + } } } } } } - /* Singu Note: Dummy views and what for? mFMP->childSetTextArg("submeshes_info", "[SUBMESHES]", llformat("%d", total_submeshes[LLModel::LOD_HIGH])); */ @@ -4253,9 +2842,12 @@ void LLModelPreview::updateStatusMessages() S32 upload_status[LLModel::LOD_HIGH + 1]; - bool upload_ok = true; + mModelNoErrors = true; - for (S32 lod = 0; lod <= LLModel::LOD_HIGH; ++lod) + const U32 lod_high = LLModel::LOD_HIGH; + U32 high_submodel_count = mModel[lod_high].size() - countRootModels(mModel[lod_high]); + + for (S32 lod = 0; lod <= lod_high; ++lod) { upload_status[lod] = 0; @@ -4268,7 +2860,7 @@ void LLModelPreview::updateStatusMessages() } else { - if (lod == LLModel::LOD_HIGH) + if (lod == lod_high) { upload_status[lod] = 2; message = "mesh_status_missing_lod"; @@ -4289,8 +2881,6 @@ void LLModelPreview::updateStatusMessages() mFMP->childSetText(lod_vertices_name[lod], mesh_status_na); } - const U32 lod_high = LLModel::LOD_HIGH; - if (lod != lod_high) { if (total_submeshes[lod] && total_submeshes[lod] != total_submeshes[lod_high]) @@ -4298,6 +2888,13 @@ void LLModelPreview::updateStatusMessages() message = "mesh_status_submesh_mismatch"; upload_status[lod] = 2; } + else if (mModel[lod].size() - countRootModels(mModel[lod]) != high_submodel_count) + {//number of submodels is different, not all faces are matched correctly. + message = "mesh_status_submesh_mismatch"; + upload_status[lod] = 2; + // Note: Submodels in instance were loaded from higher LOD and as result face count + // returns same value and total_submeshes[lod] is identical to high_lod one. + } else if (!tris[lod].empty() && tris[lod].size() != tris[lod_high].size()) { //number of meshes is different message = "mesh_status_mesh_mismatch"; @@ -4318,68 +2915,91 @@ void LLModelPreview::updateStatusMessages() { //too many vertices in this lod message = "mesh_status_too_many_vertices"; - upload_status[lod] = 2; + upload_status[lod] = 1; } } } - std::string img = lod_status_image[upload_status[lod]]; LLIconCtrl* icon = mFMP->getChild(lod_icon_name[lod]); - icon->setVisible(true); - icon->setValue(img); + LLUIImagePtr img = LLUI::getUIImage(lod_status_image[upload_status[lod]]); + icon->setVisible(lodsReady()); + icon->setImage(img); if (upload_status[lod] >= 2) { - upload_ok = false; + mModelNoErrors = false; } if (lod == mPreviewLOD) { mFMP->childSetText("lod_status_message_text", mFMP->getString(message)); icon = mFMP->getChild("lod_status_message_icon"); - icon->setValue(img); + icon->setImage(img); } updateLodControls(lod); } - //make sure no hulls have more than 256 points in them - for (U32 i = 0; upload_ok && i < mModel[LLModel::LOD_PHYSICS].size(); ++i) + + //warn if hulls have more than 256 points in them + BOOL physExceededVertexLimit = FALSE; + for (U32 i = 0; mModelNoErrors && i < mModel[LLModel::LOD_PHYSICS].size(); ++i) { LLModel* mdl = mModel[LLModel::LOD_PHYSICS][i]; - for (U32 j = 0; upload_ok && j < mdl->mPhysics.mHull.size(); ++j) + if (mdl) { - if (mdl->mPhysics.mHull[j].size() > 256) + for (U32 j = 0; j < mdl->mPhysics.mHull.size(); ++j) { - upload_ok = false; + if (mdl->mPhysics.mHull[j].size() > 256) + { + physExceededVertexLimit = TRUE; + LL_INFOS() << "Physical model " << mdl->mLabel << " exceeds vertex per hull limitations." << LL_ENDL; + break; + } } } } + mFMP->childSetVisible("physics_status_message_text", physExceededVertexLimit); + LLIconCtrl* physStatusIcon = mFMP->getChild("physics_status_message_icon"); + physStatusIcon->setVisible(physExceededVertexLimit); + if (physExceededVertexLimit) + { + mFMP->childSetValue("physics_status_message_text", mFMP->getString("phys_status_vertex_limit_exceeded")); + LLUIImagePtr img = LLUI::getUIImage("ModelImport_Status_Warning"); + physStatusIcon->setImage(img); + } - bool errorStateFromLoader = getLoadState() >= LLModelLoader::ERROR_PARSING ? true : false; + if (getLoadState() >= LLModelLoader::ERROR_PARSING) + { + mModelNoErrors = false; + LL_INFOS() << "Loader returned errors, model can't be uploaded" << LL_ENDL; + } - bool skinAndRigOk = true; bool uploadingSkin = mFMP->childGetValue("upload_skin").asBoolean(); bool uploadingJointPositions = mFMP->childGetValue("upload_joints").asBoolean(); - if (uploadingSkin) + if ( uploadingSkin ) { - if (uploadingJointPositions && !isRigValidForJointPositionUpload()) + if ( uploadingJointPositions && !isRigValidForJointPositionUpload() ) { - skinAndRigOk = false; + mModelNoErrors = false; + LL_INFOS() << "Invalid rig, there might be issues with uploading Joint positions" << LL_ENDL; } } - if (upload_ok && mModelLoader) + if(mModelNoErrors && mModelLoader) { - if (!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean()) + if(!mModelLoader->areTexturesReady() && mFMP->childGetValue("upload_textures").asBoolean()) { - upload_ok = false; + // Some textures are still loading, prevent upload until they are done + mModelNoErrors = false; } } - if (!upload_ok || errorStateFromLoader || !skinAndRigOk || has_degenerate) + // Todo: investigate use of has_degenerate and include into mModelNoErrors upload blocking mechanics + // current use of has_degenerate won't block upload permanently - later checks will restore the button + if (!mModelNoErrors || has_degenerate) { mFMP->childDisable("ok_btn"); } @@ -4697,11 +3317,6 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) model = &(mModel[lod]); } - if (!mVertexBuffer[lod].empty()) - { - mVertexBuffer[lod].clear(); - } - mVertexBuffer[lod].clear(); LLModelLoader::model_list::iterator base_iter = mBaseModel.begin(); @@ -4717,7 +3332,8 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) LLModel* base_mdl = *base_iter; base_iter++; - for (S32 i = 0; i < mdl->getNumVolumeFaces(); ++i) + S32 num_faces = mdl->getNumVolumeFaces(); + for (S32 i = 0; i < num_faces; ++i) { const LLVolumeFace &vf = mdl->getVolumeFace(i); U32 num_vertices = vf.mNumVertices; @@ -4811,21 +3427,32 @@ void LLModelPreview::genBuffers(S32 lod, bool include_skin_weights) void LLModelPreview::update() { - if (mDirty) + if (mGenLOD) + { + bool subscribe_for_generation = mLodsQuery.empty(); + mGenLOD = false; + mDirty = true; + mLodsQuery.clear(); + + for (S32 lod = LLModel::LOD_HIGH; lod >= 0; --lod) + { + // adding all lods into query for generation + mLodsQuery.push_back(lod); + } + + if (subscribe_for_generation) + { + doOnIdleRepeating(lodQueryCallback); + } + } + + if (mDirty && mLodsQuery.empty()) { mDirty = false; mResourceCost = calcResourceCost(); refresh(); updateStatusMessages(); } - - if (mGenLOD) - { - mGenLOD = false; - genLODs(); - refresh(); - updateStatusMessages(); - } } //----------------------------------------------------------------------------- @@ -4866,7 +3493,76 @@ void LLModelPreview::createPreviewAvatar(void) } } -void LLModelPreview::addEmptyFace(LLModel* pTarget) +//static +U32 LLModelPreview::countRootModels(LLModelLoader::model_list models) +{ + U32 root_models = 0; + model_list::iterator model_iter = models.begin(); + while (model_iter != models.end()) + { + LLModel* mdl = *model_iter; + if (mdl && mdl->mSubmodelID == 0) + { + root_models++; + } + model_iter++; + } + return root_models; +} + +void LLModelPreview::loadedCallback( + LLModelLoader::scene& scene, + LLModelLoader::model_list& model_list, + S32 lod, + void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview && !LLModelPreview::sIgnoreLoadedCallback) + { + pPreview->loadModelCallback(lod); + } +} + +void LLModelPreview::stateChangedCallback(U32 state,void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview) + { + pPreview->setLoadState(state); + } +} + +LLJoint* LLModelPreview::lookupJointByName(const std::string& str, void* opaque) +{ + LLModelPreview* pPreview = static_cast< LLModelPreview* >(opaque); + if (pPreview) + { + return pPreview->getPreviewAvatar()->getJoint(str); + } + return NULL; +} + +U32 LLModelPreview::loadTextures(LLImportMaterial& material,void* opaque) +{ + (void)opaque; + + if (material.mDiffuseMapFilename.size()) + { + material.mOpaqueData = new LLPointer< LLViewerFetchedTexture >; + LLPointer< LLViewerFetchedTexture >& tex = (*reinterpret_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData)); + + tex = LLViewerTextureManager::getFetchedTextureFromUrl("file://" + material.mDiffuseMapFilename, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_PREVIEW); + tex->setLoadedCallback(LLModelPreview::textureLoadedCallback, 0, TRUE, FALSE, opaque, NULL, FALSE); + tex->forceToSaveRawImage(0, F32_MAX); + material.setDiffuseMap(tex->getID()); // record tex ID + return 1; + } + + material.mOpaqueData = NULL; + return 0; +} + +void LLModelPreview::addEmptyFace( LLModel* pTarget ) { U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; @@ -4989,8 +3685,9 @@ BOOL LLModelPreview::render() if (fmp && isLegacyRigValid()) { fmp->enableViewOption("show_skin_weight"); - fmp->setViewOptionEnabled("show_joint_positions", skin_weight); + fmp->setViewOptionEnabled("show_joint_positions", skin_weight); mFMP->childEnable("upload_skin"); + mFMP->childSetValue("show_skin_weight", skin_weight); } } else @@ -5001,8 +3698,11 @@ BOOL LLModelPreview::render() mViewOption["show_skin_weight"] = false; fmp->disableViewOption("show_skin_weight"); fmp->disableViewOption("show_joint_positions"); + + skin_weight = false; + mFMP->childSetValue("show_skin_weight", false); + fmp->setViewOptionEnabled("show_skin_weight", skin_weight); } - skin_weight = false; } if (upload_skin && !has_skin_weights) @@ -5106,29 +3806,20 @@ BOOL LLModelPreview::render() const LLVertexBuffer* buff = vb_vec[0]; regen = buff->hasDataType(LLVertexBuffer::TYPE_WEIGHT4) != skin_weight; } - } - - //make sure material lists all match - for (U32 i = 0; i < LLModel::NUM_LODS-1; i++) - { - if (mBaseModel.size() == mModel[i].size()) + else { - for (U32 j = 0; j < mBaseModel.size(); ++j) - { - int refFaceCnt = 0; - int modelFaceCnt = 0; - - if (!mModel[i][j]->matchMaterialOrder(mBaseModel[j], refFaceCnt, modelFaceCnt)) - { - mFMP->childDisable("calculate_btn"); - } - } + LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL; + regen = TRUE; } } if (regen) { genBuffers(mPreviewLOD, skin_weight); + { + LL_INFOS() << "Vertex Buffer[" << mPreviewLOD << "]" << " is EMPTY!!!" << LL_ENDL; + regen = TRUE; + } } if (!skin_weight) @@ -5144,39 +3835,40 @@ BOOL LLModelPreview::render() continue; } - gGL.pushMatrix(); - LLMatrix4a mat; - mat.loadu((F32*)instance.mTransform.mMatrix); + gGL.pushMatrix(); - gGL.multMatrix(mat); + LLMatrix4a transform; + transform.loadu(instance.mTransform); + gGL.multMatrix(transform); - for (U32 i = 0; i < mVertexBuffer[mPreviewLOD][model].size(); ++i) - { - LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; - buffer->setBuffer(type_mask & buffer->getTypeMask()); - - if (textures) + U32 num_models = mVertexBuffer[mPreviewLOD][model].size(); + for (U32 i = 0; i < num_models; ++i) { - U32 materialCnt = instance.mModel->mMaterialList.size(); - if (i < materialCnt) + LLVertexBuffer* buffer = mVertexBuffer[mPreviewLOD][model][i]; + + buffer->setBuffer(type_mask & buffer->getTypeMask()); + + if (textures) { - const std::string& binding = instance.mModel->mMaterialList[i]; - const LLImportMaterial& material = instance.mMaterial[binding]; - - gGL.diffuseColor4fv(material.mDiffuseColor.mV); - - if (material.mDiffuseMap.notNull()) + U32 materialCnt = instance.mModel->mMaterialList.size(); + if ( i < materialCnt ) { - if (material.mDiffuseMap->getDiscardLevel() > -1) + const std::string& binding = instance.mModel->mMaterialList[i]; + const LLImportMaterial& material = instance.mMaterial[binding]; + + gGL.diffuseColor4fv(material.mDiffuseColor.mV); + + // Find the tex for this material, bind it, and add it to our set + // + LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material); + if (tex) { - gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); - mTextureSet.insert(material.mDiffuseMap.get()); + mTextureSet.insert(tex); } } } - } - else + else { gGL.diffuseColor4f(1,1,1,1); } @@ -5291,12 +3983,14 @@ BOOL LLModelPreview::render() if (mVertexBuffer[LLModel::LOD_PHYSICS].empty()) { genBuffers(LLModel::LOD_PHYSICS, false); - } - for (U32 i = 0; i < mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); ++i) - { - LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; + } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + U32 num_models = mVertexBuffer[LLModel::LOD_PHYSICS][model].size(); + for (U32 i = 0; i < num_models; ++i) + { + LLVertexBuffer* buffer = mVertexBuffer[LLModel::LOD_PHYSICS][model][i]; + + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.diffuseColor4f(0.4f, 0.4f, 0.0f, 0.4f); buffer->setBuffer(type_mask & buffer->getTypeMask()); @@ -5442,15 +4136,15 @@ BOOL LLModelPreview::render() buffer->setBuffer(type_mask & buffer->getTypeMask()); gGL.diffuseColor4fv(material.mDiffuseColor.mV); gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - if (material.mDiffuseMap.notNull()) - { - if (material.mDiffuseMap->getDiscardLevel() > -1) - { - gGL.getTexUnit(0)->bind(material.mDiffuseMap, true); - mTextureSet.insert(material.mDiffuseMap.get()); - } - } + // Find the tex for this material, bind it, and add it to our set + // + LLViewerFetchedTexture* tex = bindMaterialDiffuseTexture(material); + if (tex) + { + mTextureSet.insert(tex); + } + buffer->draw(LLRender::TRIANGLES, buffer->getNumIndices(), 0); gGL.diffuseColor3f(0.4f, 0.4f, 0.4f); @@ -5525,6 +4219,12 @@ void LLModelPreview::setPreviewLOD(S32 lod) combo_box->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order mFMP->childSetText("lod_file_" + lod_name[mPreviewLOD], mLODFile[mPreviewLOD]); + LLComboBox* combo_box2 = mFMP->getChild("preview_lod_combo2"); + combo_box2->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order + + LLComboBox* combo_box3 = mFMP->getChild("preview_lod_combo3"); + combo_box3->setCurrentByIndex((NUM_LOD-1)-mPreviewLOD); // combo box list of lods is in reverse order + LLColor4 highlight_color = LLUI::sColorsGroup->getColor("MeshImportTableHighlightColor"); LLColor4 normal_color = LLUI::sColorsGroup->getColor("MeshImportTableNormalColor"); @@ -5557,14 +4257,14 @@ void LLFloaterModelPreview::onReset(void* user_data) LLFloaterModelPreview* fmp = (LLFloaterModelPreview*) user_data; fmp->childDisable("reset_btn"); LLModelPreview* mp = fmp->mModelPreview; - std::string filename = mp->mLODFile[3]; + std::string filename = mp->mLODFile[LLModel::LOD_HIGH]; fmp->resetDisplayOptions(); //reset model preview fmp->initModelPreview(); mp = fmp->mModelPreview; - mp->loadModel(filename,3,true); + mp->loadModel(filename,LLModel::LOD_HIGH,true); } //static @@ -5609,6 +4309,36 @@ void LLModelPreview::textureLoadedCallback( BOOL success, LLViewerFetchedTexture } } +// static +bool LLModelPreview::lodQueryCallback() +{ + // not the best solution, but model preview belongs to floater + // so it is an easy way to check that preview still exists. + LLFloaterModelPreview* fmp = LLFloaterModelPreview::sInstance; + if (fmp && fmp->mModelPreview) + { + LLModelPreview* preview = fmp->mModelPreview; + if (preview->mLodsQuery.size() > 0) + { + S32 lod = preview->mLodsQuery.back(); + preview->mLodsQuery.pop_back(); + preview->genLODs(lod); + + // return false to continue cycle + return false; + } + } + + for (U32 lod = 0; lod < NUM_LOD; ++lod) + { + LLIconCtrl* icon = fmp->getChild(lod_icon_name[lod]); + icon->setVisible(true); + } + + // nothing to process + return true; +} + void LLModelPreview::onLODParamCommit(S32 lod, bool enforce_tri_limit) { if (!mLODFrozen) @@ -5657,7 +4387,7 @@ void LLFloaterModelPreview::toggleCalculateButton(bool visible) } mUploadBtn->setVisible(!visible); - mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); + mUploadBtn->setEnabled(isModelUploadAllowed()); if (visible) { @@ -5679,6 +4409,12 @@ void LLFloaterModelPreview::onLoDSourceCommit(S32 lod) { mModelPreview->updateLodControls(lod); refresh(); + + LLComboBox* lod_source_combo = getChild("lod_source_" + lod_name[lod]); + if (lod_source_combo->getCurrentIndex() == LLModelPreview::GENERATE) + { //rebuild LoD to update triangle counts + onLODParamCommit(lod, true); + } } void LLFloaterModelPreview::resetDisplayOptions() @@ -5717,7 +4453,7 @@ void LLFloaterModelPreview::handleModelPhysicsFeeReceived() childSetTextArg("price_breakdown", "[MODEL]", llformat("%d", result["upload_price_breakdown"]["model"].asInteger())); childSetVisible("upload_fee", true); childSetVisible("price_breakdown", true); - mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); + mUploadBtn->setEnabled(isModelUploadAllowed()); } void LLFloaterModelPreview::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason) @@ -5741,6 +4477,16 @@ void LLFloaterModelPreview::onModelUploadFailure() mUploadBtn->setEnabled(true); } +bool LLFloaterModelPreview::isModelUploadAllowed() +{ + bool allow_upload = mHasUploadPerm && !mUploadModelUrl.empty(); + if (mModelPreview) + { + allow_upload &= mModelPreview->mModelNoErrors; + } + return allow_upload; +} + S32 LLFloaterModelPreview::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2) { if (mContinue) @@ -5790,8 +4536,17 @@ void LLFloaterModelPreview::onPermissionsReceived(const LLSD& result) // BAP HACK: handle "" for case that MeshUploadFlag cap is broken. mHasUploadPerm = (("" == upload_status) || ("valid" == upload_status)); - //mUploadBtn->setEnabled(mHasUploadPerm); - mUploadBtn->setEnabled(mHasUploadPerm && !mUploadModelUrl.empty()); + if (!mHasUploadPerm) + { + LL_WARNS() << "Upload permission set to false because upload_status=\"" << upload_status << "\"" << LL_ENDL; + } + else if (mHasUploadPerm && mUploadModelUrl.empty()) + { + LL_WARNS() << "Upload permission set to true but uploadModelUrl is empty!" << LL_ENDL; + } + + // isModelUploadAllowed() includes mHasUploadPerm + mUploadBtn->setEnabled(isModelUploadAllowed()); getChild("warning_title")->setVisible(!mHasUploadPerm); getChild("warning_message")->setVisible(!mHasUploadPerm); } diff --git a/indra/newview/llfloatermodelpreview.h b/indra/newview/llfloatermodelpreview.h index 46e290dcb..8bc1a5714 100644 --- a/indra/newview/llfloatermodelpreview.h +++ b/indra/newview/llfloatermodelpreview.h @@ -2,31 +2,25 @@ * @file llfloatermodelpreview.h * @brief LLFloaterModelPreview class definition * - * $LicenseInfo:firstyear=2004&license=viewergpl$ - * - * Copyright (c) 2010, 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$ */ @@ -42,105 +36,24 @@ #include "llviewermenufile.h" #include "llfloatermodeluploadbase.h" +#include "lldaeloader.h" + class LLComboBox; +class LLJoint; +class LLViewerJointMesh; class LLVOAvatar; class LLVertexBuffer; class LLModelPreview; class LLFloaterModelPreview; +class DAE; class daeElement; class domProfile_COMMON; class domInstance_geometry; class domNode; class domTranslate; class domController; - -typedef std::map JointTransformMap; -typedef std::map:: iterator JointTransformMapIt; - -const S32 NUM_LOD = 4; - -class LLModelLoader : public LLThread -{ -public: - typedef enum - { - STARTING = 0, - READING_FILE, - CREATING_FACES, - GENERATING_VERTEX_BUFFERS, - GENERATING_LOD, - DONE, - ERROR_PARSING, //basically loading failed - ERROR_MATERIALS, - } eLoadState; - - U32 mState; - std::string mFilename; - S32 mLod; - LLModelPreview* mPreview; - LLMatrix4 mTransform; - BOOL mFirstTransform; - LLVector3 mExtents[2]; - bool mTrySLM; - - std::map > mModel; - - typedef std::vector > model_list; - model_list mModelList; - - typedef std::vector model_instance_list; - - typedef std::map scene; - - scene mScene; - - typedef std::queue > model_queue; - - //queue of models that need a physics rep - model_queue mPhysicsQ; - - LLModelLoader(std::string filename, S32 lod, LLModelPreview* preview, JointTransformMap& jointMap, - std::deque& jointsFromNodes); - ~LLModelLoader() ; - - virtual void run(); - bool doLoadModel(); - bool loadFromSLM(const std::string& filename); - void loadModelCallback(); - - void loadTextures() ; //called in the main thread. - void processElement(daeElement* element, bool& badElement); - std::map getMaterials(LLModel* model, domInstance_geometry* instance_geo); - LLImportMaterial profileToMaterial(domProfile_COMMON* material); - std::string getElementLabel(daeElement *element); - LLColor4 getDaeColor(daeElement* element); - - daeElement* getChildFromElement(daeElement* pElement, std::string const & name); - - bool isNodeAJoint(domNode* pNode); - void processJointNode(domNode* pNode, std::map& jointTransforms); - void extractTranslation(domTranslate* pTranslate, LLMatrix4& transform); - void extractTranslationViaElement(daeElement* pTranslateElement, LLMatrix4& transform); - void extractTranslationViaSID(daeElement* pElement, LLMatrix4& transform); - - void setLoadState(U32 state); - - void buildJointToNodeMappingFromScene(daeElement* pRoot); - void processJointToNodeMapping(domNode* pNode); - void processChildJoints(domNode* pParentNode); - - //map of avatar joints as named in COLLADA assets to internal joint names - std::map mJointMap; - JointTransformMap& mJointList; - std::deque& mJointsFromNode; - - S32 mNumOfFetchingTextures ; //updated in the main thread - bool areTexturesReady() { return !mNumOfFetchingTextures; } //called in the main thread. - -private: - static std::list sActiveLoaderList; - static bool isAlive(LLModelLoader* loader) ; -}; +class domSkin; +class domMesh; class LLFloaterModelPreview : public LLFloaterModelUploadBase { @@ -171,7 +84,8 @@ public: BOOL handleHover(S32 x, S32 y, MASK mask); BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - /*virtual*/ void onOpen(/*const LLSD& key*/); + /*virtual*/ void onOpen(); + /*virtual*/ void onClose(bool app_quitting); static void onMouseCaptureLostModelPreview(LLMouseHandler*); static void setUploadAmount(S32 amount) { sUploadAmount = amount; } @@ -211,6 +125,8 @@ public: /*virtual*/ void onModelUploadFailure(); + bool isModelUploadAllowed(); + protected: friend class LLModelPreview; friend class LLPhysicsDecomp; @@ -339,8 +255,12 @@ public: void clearModel(S32 lod); void loadModel(std::string filename, S32 lod, bool force_disable_slm = false); void loadModelCallback(S32 lod); + bool lodsReady() { return !mGenLOD && mLodsQuery.empty(); } + void queryLODs() { mGenLOD = true; }; void genLODs(S32 which_lod = -1, U32 decimation = 3, bool enforce_tri_limit = false); + void genModelBBox(); // Generate just a model BBox if we can't generate proper LOD void generateNormals(); + void restoreNormals(); U32 calcResourceCost(); void rebuildUploadData(); void saveUploadData(bool save_skinweights, bool save_joint_poisitions); @@ -354,44 +274,51 @@ public: const bool getModelPivot(void) const { return mHasPivot; } void setHasPivot(bool val) { mHasPivot = val; } - void setModelPivot(const LLVector3& pivot) { mModelPivot = pivot; } + void setModelPivot( const LLVector3& pivot ) { mModelPivot = pivot; } - //Determines the viability of an asset to be used as an avatar rig (w or w/o joint upload caps) - void critiqueRigForUploadApplicability(const std::vector &jointListFromAsset); - void critiqueJointToNodeMappingFromScene(void); //Is a rig valid so that it can be used as a criteria for allowing for uploading of joint positions //Accessors for joint position upload friendly rigs - const bool isRigValidForJointPositionUpload(void) const { return mRigValidJointUpload; } - void setRigValidForJointPositionUpload(bool rigValid) { mRigValidJointUpload = rigValid; } - bool isRigSuitableForJointPositionUpload(const std::vector &jointListFromAsset); - //Determines if a rig is a legacy from the joint list - bool isRigLegacy(const std::vector &jointListFromAsset); + const bool isRigValidForJointPositionUpload( void ) const { return mRigValidJointUpload; } + void setRigValidForJointPositionUpload( bool rigValid ) { mRigValidJointUpload = rigValid; } + //Accessors for the legacy rigs - const bool isLegacyRigValid(void) const { return mLegacyRigValid; } - void setLegacyRigValid(bool rigValid) { mLegacyRigValid = rigValid; } - //Verify that a controller matches vertex counts - bool verifyController(domController* pController); + const bool isLegacyRigValid( void ) const { return mLegacyRigValid; } + void setLegacyRigValid( bool rigValid ) { mLegacyRigValid = rigValid; } - static void textureLoadedCallback(BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata); - - boost::signals2::connection setDetailsCallback(const details_signal_t::slot_type& cb){ return mDetailsSignal.connect(cb); } - boost::signals2::connection setModelLoadedCallback(const model_loaded_signal_t::slot_type& cb){ return mModelLoadedSignal.connect(cb); } - boost::signals2::connection setModelUpdatedCallback(const model_updated_signal_t::slot_type& cb){ return mModelUpdatedSignal.connect(cb); } - - void setLoadState(U32 state) { mLoadState = state; } + static void textureLoadedCallback( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); + static bool lodQueryCallback(); + + boost::signals2::connection setDetailsCallback( const details_signal_t::slot_type& cb ){ return mDetailsSignal.connect(cb); } + boost::signals2::connection setModelLoadedCallback( const model_loaded_signal_t::slot_type& cb ){ return mModelLoadedSignal.connect(cb); } + boost::signals2::connection setModelUpdatedCallback( const model_updated_signal_t::slot_type& cb ){ return mModelUpdatedSignal.connect(cb); } + + void setLoadState( U32 state ) { mLoadState = state; } U32 getLoadState() { return mLoadState; } - void setRigWithSceneParity(bool state) { mRigParityWithScene = state; } - const bool getRigWithSceneParity(void) const { return mRigParityWithScene; } + void setRigWithSceneParity( bool state ) { mRigParityWithScene = state; } + const bool getRigWithSceneParity( void ) const { return mRigParityWithScene; } + + LLVector3 getTranslationForJointOffset( std::string joint ); - LLVector3 getTranslationForJointOffset(std::string joint); + static bool sIgnoreLoadedCallback; + std::vector mLodsQuery; + +protected: + + static void loadedCallback(LLModelLoader::scene& scene,LLModelLoader::model_list& model_list, S32 lod, void* opaque); + static void stateChangedCallback(U32 state, void* opaque); + + static LLJoint* lookupJointByName(const std::string&, void* opaque); + static U32 loadTextures(LLImportMaterial& material, void* opaque); private: //Utility function for controller vertex compare - bool verifyCount(int expected, int result); + bool verifyCount( int expected, int result ); //Creates the dummy avatar for the preview window - void createPreviewAvatar(void); + void createPreviewAvatar( void ); //Accessor for the dummy avatar - LLVOAvatar* getPreviewAvatar(void) { return mPreviewAvatar; } + LLVOAvatar* getPreviewAvatar( void ) { return mPreviewAvatar; } + // Count amount of original models, excluding sub-models + static U32 countRootModels(LLModelLoader::model_list models); protected: friend class LLModelLoader; @@ -413,12 +340,14 @@ private: LLVector3 mPreviewTarget; LLVector3 mPreviewScale; S32 mPreviewLOD; + S32 mPhysicsSearchLOD; U32 mResourceCost; std::string mLODFile[LLModel::NUM_LODS]; bool mLoading; U32 mLoadState; bool mResetJoints; bool mRigParityWithScene; + bool mModelNoErrors; std::map mViewOption; @@ -445,6 +374,12 @@ private: LLModelLoader::model_list mModel[LLModel::NUM_LODS]; LLModelLoader::model_list mBaseModel; + typedef std::vector v_LLVolumeFace_t; + typedef std::vector vv_LLVolumeFace_t; + + vv_LLVolumeFace_t mModelFacesCopy[LLModel::NUM_LODS]; + vv_LLVolumeFace_t mBaseModelFacesCopy; + U32 mGroup; std::map, U32> mObject; U32 mMaxTriangleLimit; @@ -463,16 +398,15 @@ private: bool mHasPivot; float mPelvisZOffset; - + bool mRigValidJointUpload; bool mLegacyRigValid; bool mLastJointUpdate; - std::deque mMasterJointList; - std::deque mMasterLegacyJointList; - std::deque mJointsFromNode; - JointTransformMap mJointTransformMap; + JointSet mJointsFromNode; + JointTransformMap mJointTransformMap; + LLPointer mPreviewAvatar; }; diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp index be5ff68b1..0c303fd17 100644 --- a/indra/newview/llfloaterreporter.cpp +++ b/indra/newview/llfloaterreporter.cpp @@ -802,7 +802,7 @@ void LLFloaterReporter::takeScreenshot() // store in the image list so it doesn't try to fetch from the server LLPointer image_in_list = - LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE); + LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE); image_in_list->createGLTexture(0, raw, 0, TRUE, LLViewerTexture::OTHER); // the texture picker then uses that texture diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp index 7fe24895c..83404d746 100644 --- a/indra/newview/llfloaterscriptdebug.cpp +++ b/indra/newview/llfloaterscriptdebug.cpp @@ -129,7 +129,7 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std: if (objectp) { - objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", TRUE, LLGLTexture::BOOST_UI)); + objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("script_error.j2c", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); floater_label = llformat("%s(%.2f, %.2f)", user_name.c_str(), objectp->getPositionRegion().mV[VX], objectp->getPositionRegion().mV[VY]); } else diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp index 1605f8174..df6c03ddb 100644 --- a/indra/newview/llfolderviewitem.cpp +++ b/indra/newview/llfolderviewitem.cpp @@ -75,7 +75,7 @@ LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style) void LLFolderViewItem::initClass() { sArrowImage = LLUI::getUIImage("folder_arrow.tga"); - sBoxImage = LLUI::getUIImage("rounded_square.tga"); + sBoxImage = LLUI::getUIImage("Rounded_Square"); } //static diff --git a/indra/newview/llhoverview.cpp b/indra/newview/llhoverview.cpp index b6821d601..1d5293035 100644 --- a/indra/newview/llhoverview.cpp +++ b/indra/newview/llhoverview.cpp @@ -803,8 +803,8 @@ void LLHoverView::draw() return; } - LLUIImagePtr box_imagep = LLUI::getUIImage("rounded_square.tga"); - LLUIImagePtr shadow_imagep = LLUI::getUIImage("rounded_square_soft.tga"); + LLUIImagePtr box_imagep = LLUI::getUIImage("Rounded_Square"); + LLUIImagePtr shadow_imagep = LLUI::getUIImage("Rounded_Square_Soft"); const LLFontGL* fontp = LLResMgr::getInstance()->getRes(LLFONT_SANSSERIF_SMALL); diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index d870a2b7f..abb031627 100644 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -112,7 +112,7 @@ LLHUDNameTag::LLHUDNameTag(const U8 type) { LLPointer ptr(this); sTextObjects.insert(ptr); - mBubbleImage = LLUI::getUIImage("Rounded_Rect.png"); + mBubbleImage = LLUI::getUIImage("Rounded_Rect"); } LLHUDNameTag::~LLHUDNameTag() @@ -304,29 +304,14 @@ void LLHUDNameTag::renderText(BOOL for_select) mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f)); + LLUIImagePtr imagep = mBubbleImage; + // *TODO: make this a per-text setting static const LLCachedControl background_chat_color("BackgroundChatColor", LLColor4(0,0,0,1.f)); static const LLCachedControl chat_bubble_opacity("ChatBubbleOpacity", .5); LLColor4 bg_color = background_chat_color; bg_color.setAlpha(chat_bubble_opacity.get() * alpha_factor); - // maybe a no-op? - //const S32 border_height = 16; - //const S32 border_width = 16; - const S32 border_height = 8; - const S32 border_width = 8; - - // *TODO move this into helper function - F32 border_scale = 1.f; - - if (border_height * 2 > mHeight) - { - border_scale = (F32)mHeight / ((F32)border_height * 2.f); - } - if (border_width * 2 > mWidth) - { - border_scale = llmin(border_scale, (F32)mWidth / ((F32)border_width * 2.f)); - } // scale screen size of borders down //RN: for now, text on hud objects is never occluded @@ -336,34 +321,42 @@ void LLHUDNameTag::renderText(BOOL for_select) LLViewerCamera::getInstance()->getPixelVectors(mPositionAgent, y_pixel_vec, x_pixel_vec); - LLVector2 border_scale_vec((F32)border_width / (F32)mBubbleImage->getTextureWidth(), (F32)border_height / (F32)mBubbleImage->getTextureHeight()); LLVector3 width_vec = mWidth * x_pixel_vec; LLVector3 height_vec = mHeight * y_pixel_vec; - LLVector3 scaled_border_width = (F32)llfloor(border_scale * (F32)border_width) * x_pixel_vec; - LLVector3 scaled_border_height = (F32)llfloor(border_scale * (F32)border_height) * y_pixel_vec; mRadius = (width_vec + height_vec).magVec() * 0.5f; LLCoordGL screen_pos; LLViewerCamera::getInstance()->projectPosAgentToScreen(mPositionAgent, screen_pos, FALSE); - LLVector2 screen_offset; -// if (!mUseBubble) -// { -// screen_offset = mPositionOffset; -// } -// else -// { - screen_offset = updateScreenPos(mPositionOffset); -// } + LLVector2 screen_offset = updateScreenPos(mPositionOffset); LLVector3 render_position = mPositionAgent + (x_pixel_vec * screen_offset.mV[VX]) + (y_pixel_vec * screen_offset.mV[VY]); -// if (mUseBubble) + LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + LLRect screen_rect; + screen_rect.setCenterAndSize(0, static_cast(lltrunc(-mHeight / 2 + mOffsetY)), static_cast(lltrunc(mWidth)), static_cast(lltrunc(mHeight))); + imagep->draw3D(render_position, x_pixel_vec, y_pixel_vec, screen_rect, bg_color); + if (mLabelSegments.size()) + { + LLUIImagePtr rect_top_image = LLUI::getUIImage("Rounded_Rect_Top"); + LLRect label_top_rect = screen_rect; + const S32 label_height = ll_round((mFontp->getLineHeight() * (F32)mLabelSegments.size() + (VERTICAL_PADDING / 3.f))); + label_top_rect.mBottom = label_top_rect.mTop - label_height; + LLColor4 label_top_color = text_color; + label_top_color.mV[VALPHA] = chat_bubble_opacity * alpha_factor; + + rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); + } + + BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f; + BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f); + + // draw line segments pointing to parent object + if (!mOffscreen && (outside_width || outside_height)) { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); LLUI::pushMatrix(); { LLVector3 bg_pos = render_position @@ -371,46 +364,9 @@ void LLHUDNameTag::renderText(BOOL for_select) - (width_vec / 2.f) - (height_vec); LLUI::translate(bg_pos.mV[VX], bg_pos.mV[VY], bg_pos.mV[VZ]); - - if (for_select) + + /*LLUI::pushMatrix(); { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - S32 name = mSourceObject->mGLName; - LLColor4U coloru((U8)(name >> 16), (U8)(name >> 8), (U8)name); - gGL.color4ubv(coloru.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - LLUI::popMatrix(); - return; - } - else - { - gGL.getTexUnit(0)->bind(mBubbleImage->getImage()); - - gGL.color4fv(bg_color.mV); - gl_segmented_rect_3d_tex(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, height_vec); - - if ( mLabelSegments.size()) - { - LLUI::pushMatrix(); - { - gGL.color4f(text_color.mV[VX], text_color.mV[VY], text_color.mV[VZ], chat_bubble_opacity * alpha_factor); - LLVector3 label_height = (mFontp->getLineHeight() * mLabelSegments.size() + (VERTICAL_PADDING / 3.f)) * y_pixel_vec; - LLVector3 label_offset = height_vec - label_height; - LLUI::translate(label_offset.mV[VX], label_offset.mV[VY], label_offset.mV[VZ]); - gl_segmented_rect_3d_tex_top(border_scale_vec, scaled_border_width, scaled_border_height, width_vec, label_height); - } - LLUI::popMatrix(); - } - } - - BOOL outside_width = llabs(mPositionOffset.mV[VX]) > mWidth * 0.5f; - BOOL outside_height = llabs(mPositionOffset.mV[VY] + (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.5f : 0.f)) > mHeight * (mVertAlignment == ALIGN_VERT_TOP ? mHeight * 0.75f : 0.5f); - - // draw line segments pointing to parent object - if (!mOffscreen && (outside_width || outside_height)) - { - LLUI::pushMatrix(); - { gGL.color4fv(bg_color.mV); LLVector3 target_pos = -1.f * (mPositionOffset.mV[VX] * x_pixel_vec + mPositionOffset.mV[VY] * y_pixel_vec); target_pos += (width_vec / 2.f); @@ -419,67 +375,65 @@ void LLHUDNameTag::renderText(BOOL for_select) target_pos -= 6.f * y_pixel_vec; LLUI::translate(target_pos.mV[VX], target_pos.mV[VY], target_pos.mV[VZ]); gl_segmented_rect_3d_tex(border_scale_vec, 3.f * x_pixel_vec, 3.f * y_pixel_vec, 6.f * x_pixel_vec, 6.f * y_pixel_vec); - } - LLUI::popMatrix(); + } + LLUI::popMatrix();*/ - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE); - - LLVector3 box_center_offset; - box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f); - LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]); - gGL.color4fv(bg_color.mV); - LLUI::setLineWidth(2.0); - gGL.begin(LLRender::LINES); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLGLDepthTest gls_depth(mZCompare ? GL_TRUE : GL_FALSE, GL_FALSE); + + LLVector3 box_center_offset; + box_center_offset = (width_vec * 0.5f) + (height_vec * 0.5f); + LLUI::translate(box_center_offset.mV[VX], box_center_offset.mV[VY], box_center_offset.mV[VZ]); + gGL.color4fv(bg_color.mV); + LLUI::setLineWidth(2.0); + gGL.begin(LLRender::LINES); + { + if (outside_width) { - if (outside_width) + LLVector3 vert; + // draw line in x then y + if (mPositionOffset.mV[VX] < 0.f) { - LLVector3 vert; - // draw line in x then y - if (mPositionOffset.mV[VX] < 0.f) - { - // start at right edge - vert = width_vec * 0.5f; - gGL.vertex3fv(vert.mV); - } - else - { - // start at left edge - vert = width_vec * -0.5f; - gGL.vertex3fv(vert.mV); - } - vert = -mPositionOffset.mV[VX] * x_pixel_vec; - gGL.vertex3fv(vert.mV); - gGL.vertex3fv(vert.mV); - vert -= mPositionOffset.mV[VY] * y_pixel_vec; - vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); + // start at right edge + vert = width_vec * 0.5f; gGL.vertex3fv(vert.mV); } else { - LLVector3 vert; - // draw line in y then x - if (mPositionOffset.mV[VY] < 0.f) - { - // start at top edge - vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); - gGL.vertex3fv(vert.mV); - } - else - { - // start at bottom edge - vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); - gGL.vertex3fv(vert.mV); - } - vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec; - vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); + // start at left edge + vert = width_vec * -0.5f; gGL.vertex3fv(vert.mV); } + vert = -mPositionOffset.mV[VX] * x_pixel_vec; + gGL.vertex3fv(vert.mV); + gGL.vertex3fv(vert.mV); + vert -= mPositionOffset.mV[VY] * y_pixel_vec; + vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); + gGL.vertex3fv(vert.mV); + } + else + { + LLVector3 vert; + // draw line in y then x + if (mPositionOffset.mV[VY] < 0.f) + { + // start at top edge + vert = (height_vec * 0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); + gGL.vertex3fv(vert.mV); + } + else + { + // start at bottom edge + vert = (height_vec * -0.5f) - (mPositionOffset.mV[VX] * x_pixel_vec); + gGL.vertex3fv(vert.mV); + } + vert = -mPositionOffset.mV[VY] * y_pixel_vec - mPositionOffset.mV[VX] * x_pixel_vec; + vert -= ((mVertAlignment == ALIGN_VERT_TOP) ? (height_vec * 0.5f) : LLVector3::zero); + gGL.vertex3fv(vert.mV); } - gGL.end(); - LLUI::setLineWidth(1.0); - } + gGL.end(); + LLUI::setLineWidth(1.0); } LLUI::popMatrix(); } diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp index 2cba0a759..3227f7d85 100644 --- a/indra/newview/llhudtext.cpp +++ b/indra/newview/llhudtext.cpp @@ -158,7 +158,7 @@ void LLHUDText::renderText() mOffsetY = lltrunc(mHeight * ((mVertAlignment == ALIGN_VERT_CENTER) ? 0.5f : 1.f)); // *TODO: cache this image - LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); // *TODO: make this a per-text setting static const LLCachedControl background_chat_color("BackgroundChatColor", LLColor4(0,0,0,1.f)); diff --git a/indra/newview/llmanip.cpp b/indra/newview/llmanip.cpp index d4c607dd8..fc4e2a46d 100644 --- a/indra/newview/llmanip.cpp +++ b/indra/newview/llmanip.cpp @@ -456,7 +456,7 @@ void LLManip::renderXYZ(const LLVector3 &vec) gGL.pushMatrix(); { - LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga"); + LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square"); gViewerWindow->setup2DRender(); const LLVector2& display_scale = gViewerWindow->getDisplayScale(); gGL.scalef(display_scale.mV[VX], display_scale.mV[VY], 1.f); diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index f4d4d877a..c345691b1 100644 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -595,15 +595,9 @@ void LLMediaCtrl::navigateTo( std::string url_in, std::string mime_type) // void LLMediaCtrl::navigateToLocalPage( const std::string& subdir, const std::string& filename_in ) { - std::string language = LLUI::getLanguage(); std::string filename(gDirUtilp->add(subdir, filename_in)); + std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", filename); - std::string expanded_filename = gDirUtilp->findSkinnedFilename("html", language, filename); - - if (expanded_filename.empty() && language != "en-us") - { - expanded_filename = gDirUtilp->findSkinnedFilename("html", "en-us", filename); - } if(expanded_filename.empty()) { LL_WARNS() << "File " << filename << "not found" << LL_ENDL; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index 3b7dadf17..e186b1c02 100644 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -124,6 +124,7 @@ std::string header_lod[] = "medium_lod", "high_lod" }; +const char * const LOG_MESH = "Mesh"; //get the number of bytes resident in memory for given volume @@ -206,6 +207,12 @@ void get_vertex_buffer_from_mesh(LLCDMeshData& mesh, LLModel::PhysicsMesh& res, } } +LLViewerFetchedTexture* LLMeshUploadThread::FindViewerTexture(const LLImportMaterial& material) +{ + LLPointer< LLViewerFetchedTexture > * ppTex = static_cast< LLPointer< LLViewerFetchedTexture > * >(material.mOpaqueData); + return ppTex ? (*ppTex).get() : NULL; +} + S32 LLMeshRepoThread::sActiveHeaderRequests = 0; S32 LLMeshRepoThread::sActiveLODRequests = 0; U32 LLMeshRepoThread::sMaxConcurrentRequests = 1; @@ -1429,6 +1436,13 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) { LLMeshUploadData data; data.mBaseModel = iter->first; + + if (data.mBaseModel->mSubmodelID) + { + // These are handled below to insure correct parenting order on creation + // due to map walking being based on model address (aka random) + continue; + } LLModelInstance& first_instance = *(iter->second.begin()); for (S32 i = 0; i < 5; i++) { @@ -1466,7 +1480,10 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) data.mModel[LLModel::LOD_IMPOSTOR], decomp, mUploadSkin, - mUploadJoints); + mUploadJoints, + FALSE, + FALSE, + data.mBaseModel->mSubmodelID); data.mAssetData = ostr.str(); std::string str = ostr.str(); @@ -1500,17 +1517,26 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) instance_entry["scale"] = ll_sd_from_vector3(scale); instance_entry["material"] = LL_MCODE_WOOD; - instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); + instance_entry["physics_shape_type"] = data.mModel[LLModel::LOD_PHYSICS].notNull() ? (U8)(LLViewerObject::PHYSICS_SHAPE_PRIM) : (U8)(LLViewerObject::PHYSICS_SHAPE_CONVEX_HULL); instance_entry["mesh"] = mesh_index[data.mBaseModel]; instance_entry["face_list"] = LLSD::emptyArray(); - S32 end = llmin((S32)data.mBaseModel->mMaterialList.size(), data.mBaseModel->getNumVolumeFaces()) ; + // We want to be able to allow more than 8 materials... + // + S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ; + for (S32 face_num = 0; face_num < end; face_num++) { LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]]; LLSD face_entry = LLSD::emptyMap(); - LLViewerFetchedTexture *texture = material.mDiffuseMap.get(); + + LLViewerFetchedTexture *texture = NULL; + + if (material.mDiffuseMapFilename.size()) + { + texture = FindViewerTexture(material); + } if ((texture != NULL) && (textures.find(texture) == textures.end())) @@ -1525,9 +1551,171 @@ void LLMeshUploadThread::wholeModelToLLSD(LLSD& dest, bool include_textures) { LLPointer upload_file = LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + + if (!upload_file.isNull() && upload_file->getDataSize()) + { texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); } } + } + + if (texture != NULL && + mUploadTextures && + texture_index.find(texture) == texture_index.end()) + { + texture_index[texture] = texture_num; + std::string str = texture_str.str(); + res["texture_list"][texture_num] = LLSD::Binary(str.begin(),str.end()); + texture_num++; + } + + // Subset of TextureEntry fields. + if (texture != NULL && mUploadTextures) + { + face_entry["image"] = texture_index[texture]; + face_entry["scales"] = 1.0; + face_entry["scalet"] = 1.0; + face_entry["offsets"] = 0.0; + face_entry["offsett"] = 0.0; + face_entry["imagerot"] = 0.0; + } + face_entry["diffuse_color"] = ll_sd_from_color4(material.mDiffuseColor); + face_entry["fullbright"] = material.mFullbright; + instance_entry["face_list"][face_num] = face_entry; + } + + res["instance_list"][instance_num] = instance_entry; + instance_num++; + } + } + + for (instance_map::iterator iter = mInstance.begin(); iter != mInstance.end(); ++iter) + { + LLMeshUploadData data; + data.mBaseModel = iter->first; + + if (!data.mBaseModel->mSubmodelID) + { + // These were handled above already... + // + continue; + } + + LLModelInstance& first_instance = *(iter->second.begin()); + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = first_instance.mLOD[i]; + } + + if (mesh_index.find(data.mBaseModel) == mesh_index.end()) + { + // Have not seen this model before - create a new mesh_list entry for it. + if (model_name.empty()) + { + model_name = data.mBaseModel->getName(); + } + + if (model_metric.empty()) + { + model_metric = data.mBaseModel->getMetric(); + } + + std::stringstream ostr; + + LLModel::Decomposition& decomp = + data.mModel[LLModel::LOD_PHYSICS].notNull() ? + data.mModel[LLModel::LOD_PHYSICS]->mPhysics : + data.mBaseModel->mPhysics; + + decomp.mBaseHull = mHullMap[data.mBaseModel]; + + LLSD mesh_header = LLModel::writeModel( + ostr, + data.mModel[LLModel::LOD_PHYSICS], + data.mModel[LLModel::LOD_HIGH], + data.mModel[LLModel::LOD_MEDIUM], + data.mModel[LLModel::LOD_LOW], + data.mModel[LLModel::LOD_IMPOSTOR], + decomp, + mUploadSkin, + mUploadJoints, + FALSE, + FALSE, + data.mBaseModel->mSubmodelID); + + data.mAssetData = ostr.str(); + std::string str = ostr.str(); + + res["mesh_list"][mesh_num] = LLSD::Binary(str.begin(),str.end()); + mesh_index[data.mBaseModel] = mesh_num; + mesh_num++; + } + + // For all instances that use this model + for (instance_list::iterator instance_iter = iter->second.begin(); + instance_iter != iter->second.end(); + ++instance_iter) + { + + LLModelInstance& instance = *instance_iter; + + LLSD instance_entry; + + for (S32 i = 0; i < 5; i++) + { + data.mModel[i] = instance.mLOD[i]; + } + + LLVector3 pos, scale; + LLQuaternion rot; + LLMatrix4 transformation = instance.mTransform; + decomposeMeshMatrix(transformation,pos,rot,scale); + instance_entry["position"] = ll_sd_from_vector3(pos); + instance_entry["rotation"] = ll_sd_from_quaternion(rot); + instance_entry["scale"] = ll_sd_from_vector3(scale); + + instance_entry["material"] = LL_MCODE_WOOD; + instance_entry["physics_shape_type"] = (U8)(LLViewerObject::PHYSICS_SHAPE_NONE); + instance_entry["mesh"] = mesh_index[data.mBaseModel]; + + instance_entry["face_list"] = LLSD::emptyArray(); + + // We want to be able to allow more than 8 materials... + // + S32 end = llmin((S32)instance.mMaterial.size(), instance.mModel->getNumVolumeFaces()) ; + + for (S32 face_num = 0; face_num < end; face_num++) + { + LLImportMaterial& material = instance.mMaterial[data.mBaseModel->mMaterialList[face_num]]; + LLSD face_entry = LLSD::emptyMap(); + + LLViewerFetchedTexture *texture = NULL; + + if (material.mDiffuseMapFilename.size()) + { + texture = FindViewerTexture(material); + } + + if ((texture != NULL) && + (textures.find(texture) == textures.end())) + { + textures.insert(texture); + } + + std::stringstream texture_str; + if (texture != NULL && include_textures && mUploadTextures) + { + if(texture->hasSavedRawImage()) + { + LLPointer upload_file = + LLViewerTextureList::convertToUploadFile(texture->getSavedRawImage()); + + if (!upload_file.isNull() && upload_file->getDataSize()) + { + texture_str.write((const char*) upload_file->getData(), upload_file->getDataSize()); + } + } + } if (texture != NULL && mUploadTextures && @@ -2165,7 +2353,7 @@ void LLMeshRepository::init() void LLMeshRepository::shutdown() { - LL_INFOS() << "Shutting down mesh repository." << LL_ENDL; + LL_INFOS(LOG_MESH) << "Shutting down mesh repository." << LL_ENDL; mThread->mSignal->signal(); @@ -2179,7 +2367,7 @@ void LLMeshRepository::shutdown() delete mMeshMutex; mMeshMutex = NULL; - LL_INFOS() << "Shutting down decomposition system." << LL_ENDL; + LL_INFOS(LOG_MESH) << "Shutting down decomposition system." << LL_ENDL; if (mDecompThread) { @@ -2407,7 +2595,8 @@ void LLMeshRepository::notifyLoadedMeshes() } //sort by "score" - std::sort(mPendingRequests.begin(), mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater()); + std::partial_sort(mPendingRequests.begin(), mPendingRequests.begin() + push_count, + mPendingRequests.end(), LLMeshRepoThread::CompareScoreGreater()); while (!mPendingRequests.empty() && push_count > 0) { @@ -2461,9 +2650,8 @@ void LLMeshRepository::notifySkinInfoReceived(LLMeshSkinInfo& info) vobj->notifyMeshLoaded(); } } + mLoadingSkins.erase(info.mMeshID); } - - mLoadingSkins.erase(info.mMeshID); } void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decomp) @@ -2472,18 +2660,18 @@ void LLMeshRepository::notifyDecompositionReceived(LLModel::Decomposition* decom if (iter == mDecompositionMap.end()) { //just insert decomp into map mDecompositionMap[decomp->mMeshID] = decomp; + mLoadingDecompositions.erase(decomp->mMeshID); } else - { //merge decomp with existing entry + { //merge decomp with existing entry iter->second->merge(decomp); + mLoadingDecompositions.erase(decomp->mMeshID); delete decomp; } - - mLoadingDecompositions.erase(decomp->mMeshID); } void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVolume* volume) -{ //called from main thread +{ //called from main thread S32 detail = LLVolumeLODGroup::getVolumeDetailFromScale(volume->getDetail()); //get list of objects waiting to be notified this mesh is loaded @@ -2494,7 +2682,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol //make sure target volume is still valid if (volume->getNumVolumeFaces() <= 0) { - LL_WARNS() << "Mesh loading returned empty volume." << LL_ENDL; + LL_WARNS(LOG_MESH) << "Mesh loading returned empty volume. ID: " << mesh_params.getSculptID() + << LL_ENDL; } { //update system volume @@ -2507,7 +2696,8 @@ void LLMeshRepository::notifyMeshLoaded(const LLVolumeParams& mesh_params, LLVol } else { - LL_WARNS() << "Couldn't find system volume for given mesh." << LL_ENDL; + LL_WARNS(LOG_MESH) << "Couldn't find system volume for mesh " << mesh_params.getSculptID() + << LL_ENDL; } } @@ -2774,37 +2964,6 @@ void LLMeshUploadThread::decomposeMeshMatrix(LLMatrix4& transformation, result_rot = quat_rotation; } -bool LLImportMaterial::operator<(const LLImportMaterial &rhs) const -{ - if (mDiffuseMap != rhs.mDiffuseMap) - { - return mDiffuseMap < rhs.mDiffuseMap; - } - - if (mDiffuseMapFilename != rhs.mDiffuseMapFilename) - { - return mDiffuseMapFilename < rhs.mDiffuseMapFilename; - } - - if (mDiffuseMapLabel != rhs.mDiffuseMapLabel) - { - return mDiffuseMapLabel < rhs.mDiffuseMapLabel; - } - - if (mDiffuseColor != rhs.mDiffuseColor) - { - return mDiffuseColor < rhs.mDiffuseColor; - } - - if (mBinding != rhs.mBinding) - { - return mBinding < rhs.mBinding; - } - - return mFullbright < rhs.mFullbright; -} - - void LLMeshRepository::updateInventory(inventory_data data) { LLMutexLock lock(mMeshMutex); @@ -3036,7 +3195,7 @@ void LLPhysicsDecomp::setMeshData(LLCDMeshData& mesh, bool vertex_based) if (ret) { - LL_ERRS() << "Convex Decomposition thread valid but could not set mesh data" << LL_ENDL; + LL_ERRS(LOG_MESH) << "Convex Decomposition thread valid but could not set mesh data." << LL_ENDL; } } } @@ -3112,7 +3271,8 @@ void LLPhysicsDecomp::doDecomposition() if (ret) { - LL_WARNS() << "Convex Decomposition thread valid but could not execute stage " << stage << LL_ENDL; + LL_WARNS(LOG_MESH) << "Convex Decomposition thread valid but could not execute stage " << stage << "." + << LL_ENDL; LLMutexLock lock(mMutex); mCurRequest->mHull.clear(); @@ -3243,7 +3403,7 @@ void LLPhysicsDecomp::doDecompositionSingleHull() LLCDResult ret = decomp->buildSingleHull() ; if(ret) { - LL_WARNS() << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL; + LL_WARNS(LOG_MESH) << "Could not execute decomposition stage when attempting to create single hull." << LL_ENDL; make_box(mCurRequest); } else @@ -3491,60 +3651,6 @@ void LLPhysicsDecomp::Request::setStatusMessage(const std::string& msg) mStatusMessage = msg; } -LLModelInstance::LLModelInstance(LLSD& data) -{ - mLocalMeshID = data["mesh_id"].asInteger(); - mLabel = data["label"].asString(); - mTransform.setValue(data["transform"]); - - for (U32 i = 0; i < (U32)data["material"].size(); ++i) - { - LLImportMaterial mat(data["material"][i]); - mMaterial[mat.mBinding] = mat; - } -} - - -LLSD LLModelInstance::asLLSD() -{ - LLSD ret; - - ret["mesh_id"] = mModel->mLocalID; - ret["label"] = mLabel; - ret["transform"] = mTransform.getValue(); - - U32 i = 0; - for (std::map::iterator iter = mMaterial.begin(); iter != mMaterial.end(); ++iter) - { - ret["material"][i++] = iter->second.asLLSD(); - } - - return ret; -} - -LLImportMaterial::LLImportMaterial(LLSD& data) -{ - mDiffuseMapFilename = data["diffuse"]["filename"].asString(); - mDiffuseMapLabel = data["diffuse"]["label"].asString(); - mDiffuseColor.setValue(data["diffuse"]["color"]); - mFullbright = data["fullbright"].asBoolean(); - mBinding = data["binding"].asString(); -} - - -LLSD LLImportMaterial::asLLSD() -{ - LLSD ret; - - ret["diffuse"]["filename"] = mDiffuseMapFilename; - ret["diffuse"]["label"] = mDiffuseMapLabel; - ret["diffuse"]["color"] = mDiffuseColor.getValue(); - ret["fullbright"] = mFullbright; - ret["binding"] = mBinding; - - return ret; -} - void LLMeshRepository::buildPhysicsMesh(LLModel::Decomposition& decomp) { decomp.mMesh.resize(decomp.mHull.size()); diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h index c6ccd68cd..4aba15b7f 100644 --- a/indra/newview/llmeshrepository.h +++ b/indra/newview/llmeshrepository.h @@ -92,54 +92,6 @@ public: } }; -class LLImportMaterial -{ -public: - LLPointer mDiffuseMap; - std::string mDiffuseMapFilename; - std::string mDiffuseMapLabel; - std::string mBinding; - LLColor4 mDiffuseColor; - bool mFullbright; - - bool operator<(const LLImportMaterial ¶ms) const; - - LLImportMaterial() - : mFullbright(false) - { - mDiffuseColor.set(1, 1, 1, 1); - } - - LLImportMaterial(LLSD& data); - - LLSD asLLSD(); -}; - -class LLModelInstance -{ -public: - LLPointer mModel; - LLPointer mLOD[5]; - - std::string mLabel; - - LLUUID mMeshID; - S32 mLocalMeshID; - - LLMatrix4 mTransform; - std::map mMaterial; - - LLModelInstance(LLModel* model, const std::string& label, LLMatrix4& transform, std::map& materials) - : mModel(model), mLabel(label), mTransform(transform), mMaterial(materials) - { - mLocalMeshID = -1; - } - - LLModelInstance(LLSD& data); - - LLSD asLLSD(); -}; - class LLPhysicsDecomp : public LLThread { public: @@ -441,6 +393,7 @@ public: void setFeeObserverHandle(LLHandle observer_handle) { mFeeObserverHandle = observer_handle; } void setUploadObserverHandle(LLHandle observer_handle) { mUploadObserverHandle = observer_handle; } + LLViewerFetchedTexture* FindViewerTexture(const LLImportMaterial& material); private: LLHandle mFeeObserverHandle; LLHandle mUploadObserverHandle; diff --git a/indra/newview/llnotify.cpp b/indra/newview/llnotify.cpp index 3a4e8f2ed..3a81ac69a 100644 --- a/indra/newview/llnotify.cpp +++ b/indra/newview/llnotify.cpp @@ -497,7 +497,7 @@ void LLNotifyBox::draw() void LLNotifyBox::drawBackground() const { - if (LLUIImagePtr imagep = LLUI::getUIImage("rounded_square.tga")) + if (LLUIImagePtr imagep = LLUI::getUIImage("Rounded_Square")) { gGL.getTexUnit(0)->bind(imagep->getImage()); // set proper background color depending on whether notify box is a caution or not diff --git a/indra/newview/llpaneldisplay.cpp b/indra/newview/llpaneldisplay.cpp index 688c03f6c..715d59f70 100644 --- a/indra/newview/llpaneldisplay.cpp +++ b/indra/newview/llpaneldisplay.cpp @@ -472,9 +472,13 @@ void LLPanelDisplay::refreshEnabledState() mWindowSizeLabel->setVisible(!isFullScreen); mCtrlWindowSize->setVisible(!isFullScreen); + F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); + S32Megabytes min_tex_mem = LLViewerTextureList::getMinVideoRamSetting(); + S32Megabytes max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting(false, mem_multiplier); + // Hardware tab - getChild("GrapicsCardTextureMemory")->setMinValue(LLViewerTextureList::getMinVideoRamSetting()); - getChild("GrapicsCardTextureMemory")->setMaxValue(LLViewerTextureList::getMaxVideoRamSetting()); + getChild("GrapicsCardTextureMemory")->setMinValue(min_tex_mem.value()); + getChild("GrapicsCardTextureMemory")->setMaxValue(max_tex_mem.value()); if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") || !gGLManager.mHasVertexBufferObject) diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index e7fef5ebf..f838f7d8f 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -2141,17 +2141,17 @@ void LLPanelObject::sendSculpt() return; LLSculptParams sculpt_params; + LLUUID sculpt_id = LLUUID::null; if (mCtrlSculptTexture) - sculpt_params.setSculptTexture(mCtrlSculptTexture->getImageAssetID()); + sculpt_id = mCtrlSculptTexture->getImageAssetID(); U8 sculpt_type = 0; if (mCtrlSculptType) sculpt_type |= mCtrlSculptType->getCurrentIndex(); - bool enabled = true; - enabled = sculpt_type != LL_SCULPT_TYPE_MESH; + bool enabled = sculpt_type != LL_SCULPT_TYPE_MESH; if (mCtrlSculptMirror) { @@ -2168,7 +2168,7 @@ void LLPanelObject::sendSculpt() if ((mCtrlSculptInvert) && (mCtrlSculptInvert->get())) sculpt_type |= LL_SCULPT_FLAG_INVERT; - sculpt_params.setSculptType(sculpt_type); + sculpt_params.setSculptTexture(sculpt_id, sculpt_type); mObject->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); } diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp index c5e6a987c..bdd363757 100644 --- a/indra/newview/llpreviewtexture.cpp +++ b/indra/newview/llpreviewtexture.cpp @@ -685,7 +685,7 @@ void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata) void LLPreviewTexture::loadAsset() { - mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mImage = LLViewerTextureManager::getFetchedTexture(mImageID, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mImageOldBoostLevel = mImage->getBoostLevel(); mImage->setBoostLevel(LLGLTexture::BOOST_PREVIEW); mImage->forceToSaveRawImage(0) ; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 674418489..1acfc9617 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -5408,7 +5408,7 @@ void LLSelectMgr::updateSilhouettes() if (!mSilhouetteImagep) { - mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, LLGLTexture::BOOST_UI); + mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI); } mHighlightedObjects->cleanupNodes(); diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index c8aed5346..c5040826a 100644 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -815,9 +815,10 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion) //============================================== -LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage) +LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 buffer_usage, LLViewerRegion* regionp) : mRenderByGroup(render_by_group), mBridge(NULL) { + mRegionp = regionp; mPartitionType = LLViewerRegion::PARTITION_NONE; mVertexDataMask = data_mask; mBufferUsage = buffer_usage; diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index 2dc2031bd..ea6c156a7 100644 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -384,7 +384,7 @@ class LLSpatialPartition: public LLViewerOctreePartition, public LLGeometryManag { public: //static BOOL sFreezeState; //if true, no spatialgroup state updates will be made - LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage); + LLSpatialPartition(U32 data_mask, BOOL render_by_group, U32 mBufferUsage, LLViewerRegion* regionp); virtual ~LLSpatialPartition(); LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE); @@ -449,7 +449,7 @@ protected: public: typedef std::vector > bridge_vector_t; - LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask); + LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask, LLViewerRegion* regionp); void destroyTree(); @@ -538,7 +538,7 @@ private: class LLWaterPartition : public LLSpatialPartition { public: - LLWaterPartition(); + LLWaterPartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group) { } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } }; @@ -547,14 +547,14 @@ public: class LLVoidWaterPartition : public LLWaterPartition { public: - LLVoidWaterPartition(); + LLVoidWaterPartition(LLViewerRegion* regionp); }; //spatial partition for terrain (impelmented in LLVOSurfacePatch.cpp) class LLTerrainPartition : public LLSpatialPartition { public: - LLTerrainPartition(); + LLTerrainPartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group); virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage); }; @@ -563,7 +563,7 @@ public: class LLTreePartition : public LLSpatialPartition { public: - LLTreePartition(); + LLTreePartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group) { } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } @@ -573,7 +573,7 @@ public: class LLParticlePartition : public LLSpatialPartition { public: - LLParticlePartition(); + LLParticlePartition(LLViewerRegion* regionp); virtual void rebuildGeom(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); @@ -585,14 +585,14 @@ protected: class LLHUDParticlePartition : public LLParticlePartition { public: - LLHUDParticlePartition(); + LLHUDParticlePartition(LLViewerRegion* regionp); }; //spatial partition for grass (implemented in LLVOGrass.cpp) class LLGrassPartition : public LLSpatialPartition { public: - LLGrassPartition(); + LLGrassPartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group); virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); protected: @@ -604,7 +604,7 @@ protected: class LLCloudPartition : public LLParticlePartition { public: - LLCloudPartition(); + LLCloudPartition(LLViewerRegion* regionp); }; #endif @@ -619,18 +619,32 @@ class LLVolumeGeometryManager: public LLGeometryManager DISTANCE_SORT } eSortType; + LLVolumeGeometryManager(); + virtual ~LLVolumeGeometryManager(); virtual void rebuildGeom(LLSpatialGroup* group); virtual void rebuildMesh(LLSpatialGroup* group); virtual void getGeometry(LLSpatialGroup* group); void genDrawInfo(LLSpatialGroup* group, U32 mask, LLFace** faces, U32 face_count, BOOL distance_sort = FALSE, BOOL batch_textures = FALSE); void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); +private: + void allocateFaces(U32 pMaxFaceCount); + void freeFaces(); + + static int32_t sInstanceCount; + static LLFace** sFullbrightFaces; + static LLFace** sBumpFaces; + static LLFace** sSimpleFaces; + static LLFace** sNormFaces; + static LLFace** sSpecFaces; + static LLFace** sNormSpecFaces; + static LLFace** sAlphaFaces; }; //spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp) class LLVolumePartition : public LLSpatialPartition, public LLVolumeGeometryManager { public: - LLVolumePartition(); + LLVolumePartition(LLViewerRegion* regionp); virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); } @@ -641,7 +655,7 @@ public: class LLVolumeBridge : public LLSpatialBridge, public LLVolumeGeometryManager { public: - LLVolumeBridge(LLDrawable* drawable); + LLVolumeBridge(LLDrawable* drawable, LLViewerRegion* regionp); virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } virtual void rebuildMesh(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildMesh(group); } @@ -651,13 +665,13 @@ public: class LLAttachmentBridge : public LLVolumeBridge { public: - LLAttachmentBridge(LLDrawable* drawable); + LLAttachmentBridge(LLDrawable* drawable, LLViewerRegion* regionp); }; class LLHUDBridge : public LLVolumeBridge { public: - LLHUDBridge(LLDrawable* drawablep); + LLHUDBridge(LLDrawable* drawablep, LLViewerRegion* regionp); virtual void shiftPos(const LLVector4a& vec); virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); }; @@ -666,7 +680,7 @@ public: class LLBridgePartition : public LLSpatialPartition { public: - LLBridgePartition(); + LLBridgePartition(LLViewerRegion* regionp); virtual void getGeometry(LLSpatialGroup* group) { } virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } }; @@ -675,13 +689,13 @@ public: class LLAttachmentPartition : public LLBridgePartition { public: - LLAttachmentPartition(); + LLAttachmentPartition(LLViewerRegion* regionp); }; class LLHUDPartition : public LLBridgePartition { public: - LLHUDPartition(); + LLHUDPartition(LLViewerRegion* regionp); virtual void shift(const LLVector4a &offset) { } //HUD objects don't shift with region crossing. That would be silly. }; diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 4198a5247..abf6b4fd8 100644 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -1968,7 +1968,7 @@ bool idle_startup() gFirstSim, MAX_TIMEOUT_COUNT, FALSE, - TIMEOUT_SECONDS, + F32Seconds(TIMEOUT_SECONDS), use_circuit_callback, NULL); diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index 0a35767ec..6aeea41a4 100644 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -129,8 +129,8 @@ public: // debug S32 getNumReads() { return mReaders.size(); } S32 getNumWrites() { return mWriters.size(); } - S64 getUsage() { return mTexturesSizeTotal; } - S64 getMaxUsage() { return sCacheMaxTexturesSize; } + S64Bytes getUsage() { return S64Bytes(mTexturesSizeTotal); } + S64Bytes getMaxUsage() { return S64Bytes(sCacheMaxTexturesSize); } U32 getEntries() { return mHeaderEntriesInfo.mEntries; } U32 getMaxEntries() { return sCacheMaxEntries; }; BOOL isInCache(const LLUUID& id) ; @@ -202,7 +202,7 @@ private: typedef std::map size_map_t; size_map_t mTexturesSizeMap; S64 mTexturesSizeTotal; - LLAtomic32 mDoPurge; + LLAtomic32 mDoPurge; typedef std::map idx_entry_map_t; idx_entry_map_t mUpdatedEntryMap; diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index 7dfc7f68d..c6c154ce3 100644 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -637,11 +637,11 @@ void LLFloaterTexturePicker::draw() mTexturep = NULL; if(mImageAssetID.notNull()) { - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES, LLGLTexture::BOOST_PREVIEW); + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_PREVIEW); } else if (!mFallbackImageName.empty()) { - mTexturep = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, MIPMAP_YES, LLGLTexture::BOOST_PREVIEW); + mTexturep = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, FTT_LOCAL_FILE, MIPMAP_YES, LLGLTexture::BOOST_PREVIEW); } if (mTentativeLabel) @@ -1619,13 +1619,13 @@ void LLTextureCtrl::draw() } else if (!mImageAssetID.isNull()) { - mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES,LLGLTexture::BOOST_PREVIEW, LLViewerTexture::LOD_TEXTURE); + mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES,LLGLTexture::BOOST_PREVIEW, LLViewerTexture::LOD_TEXTURE); mTexturep->forceToSaveRawImage(0) ; } else if (!mFallbackImageName.empty()) { // Show fallback image. - mTexturep = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, MIPMAP_YES,LLGLTexture::BOOST_PREVIEW, LLViewerTexture::LOD_TEXTURE); + mTexturep = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, FTT_LOCAL_FILE, MIPMAP_YES,LLGLTexture::BOOST_PREVIEW, LLViewerTexture::LOD_TEXTURE); } else // mImageAssetID == LLUUID::null { diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 432d34ec8..1c970d57a 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -60,6 +60,7 @@ #include "llstartup.h" #include "llsdserialize.h" #include "llbuffer.h" +#include "llhttpretrypolicy.h" #include "hippogridmanager.h" #include @@ -74,6 +75,9 @@ LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128); LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128); ////////////////////////////////////////////////////////////////////////////// +// Log scope +static const char * const LOG_TXT = "Texture"; + class LLTextureFetchWorker : public LLWorkerClass { friend class LLTextureFetch; @@ -190,7 +194,8 @@ public: LLTextureFetch & getFetcher() { return *mFetcher; } protected: - LLTextureFetchWorker(LLTextureFetch* fetcher, const std::string& url, const LLUUID& id, const LLHost& host, + LLTextureFetchWorker(LLTextureFetch* fetcher, FTType f_type, + const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 discard, S32 size); private: @@ -256,8 +261,9 @@ private: e_write_to_cache_state mWriteToCacheState; LLTextureFetch* mFetcher; LLPointer mFormattedImage; - LLPointer mRawImage; - LLPointer mAuxImage; + LLPointer mRawImage, + mAuxImage; + FTType mFTType; LLUUID mID; LLHost mHost; std::string mUrl; @@ -266,23 +272,23 @@ private: F32 mImagePriority; U32 mWorkPriority; F32 mRequestedPriority; - S32 mDesiredDiscard; - S32 mSimRequestedDiscard; - S32 mRequestedDiscard; - S32 mLoadedDiscard; - S32 mDecodedDiscard; - LLFrameTimer mRequestedTimer; - LLFrameTimer mFetchTimer; + S32 mDesiredDiscard, + mSimRequestedDiscard, + mRequestedDiscard, + mLoadedDiscard, + mDecodedDiscard; + LLFrameTimer mRequestedTimer, + mFetchTimer; LLTimer mCacheReadTimer; F32 mCacheReadTime; - LLTextureCache::handle_t mCacheReadHandle; - LLTextureCache::handle_t mCacheWriteHandle; + LLTextureCache::handle_t mCacheReadHandle, + mCacheWriteHandle; std::vector mHttpBuffer; - S32 mRequestedSize; - S32 mRequestedOffset; - S32 mDesiredSize; - S32 mFileSize; - S32 mCachedSize; + S32 mRequestedSize, + mRequestedOffset, + mDesiredSize, + mFileSize, + mCachedSize; e_request_state mSentRequest; handle_t mDecodeHandle; BOOL mLoaded; @@ -291,8 +297,8 @@ private: BOOL mNeedsAux; BOOL mHaveAllData; BOOL mInLocalCache; - bool mCanUseHTTP ; - bool mCanUseNET ; //can get from asset server. + bool mCanUseHTTP, + mCanUseNET ; //can get from asset server. S32 mHTTPFailCount; S32 mRetryAttempt; S32 mActiveCount; @@ -303,9 +309,12 @@ private: LLMutex mWorkMutex; struct PacketData { - PacketData(U8* data, S32 size) { mData = data; mSize = size; } + PacketData(U8* data, S32 size) + : mData(data), mSize(size) + {} ~PacketData() { clearData(); } void clearData() { delete[] mData; mData = NULL; } + U8* mData; U32 mSize; }; @@ -316,11 +325,11 @@ private: U8 mImageCodec; LLViewerAssetStats::duration_t mMetricsStartTime; - unsigned int mHttpReplySize; // Actual received data size - unsigned int mHttpReplyOffset; // Actual received data offset + U32 mHttpReplySize, // Actual received data size + mHttpReplyOffset; // Actual received data offset // State history - U32 mCacheReadCount; - U32 mCacheWriteCount; + U32 mCacheReadCount, + mCacheWriteCount; }; ////////////////////////////////////////////////////////////////////////////// @@ -328,7 +337,7 @@ class HTTPGetResponder : public LLHTTPClient::ResponderWithCompleted { LOG_CLASS(HTTPGetResponder); public: - HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id, U64 startTime, S32 requestedSize, U32 offset) + HTTPGetResponder( FTType f_type, LLTextureFetch* fetcher, const LLUUID& id, U64 startTime, S32 requestedSize, U32 offset) : mFetcher(fetcher) , mID(id) , mMetricsStartTime(startTime) @@ -337,7 +346,9 @@ public: , mReplyOffset(0) , mReplyLength(0) , mReplyFullLength(0) + , mFTType(f_type) { + mFetchRetryPolicy = new LLAdaptiveRetryPolicy(10.0,3600.0,2.0,10); } ~HTTPGetResponder() { @@ -396,13 +407,11 @@ public: if (log_to_viewer_log || log_to_sim) { - - U64 timeNow = LLTimer::getTotalTime(); mFetcher->mTextureInfo.setRequestStartTime(mID, mMetricsStartTime); mFetcher->mTextureInfo.setRequestType(mID, LLTextureInfoDetails::REQUEST_TYPE_HTTP); mFetcher->mTextureInfo.setRequestSize(mID, mRequestedSize); mFetcher->mTextureInfo.setRequestOffset(mID, mRequestedOffset); - mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, timeNow); + mFetcher->mTextureInfo.setRequestCompleteTimeAndLog(mID, LLTimer::getTotalTime()); } LL_DEBUGS("Texture") << "HTTP COMPLETE: " << mID << LL_ENDL; @@ -414,6 +423,7 @@ public: bool partial = false; if (HTTP_OK <= mStatus && mStatus < HTTP_MULTIPLE_CHOICES) { + mFetchRetryPolicy->onSuccess(); success = true; if (HTTP_PARTIAL_CONTENT == mStatus) // partial information { @@ -422,10 +432,28 @@ public: } if (!success) { + if(mFTType == FTT_SERVER_BAKE) + { + mFetchRetryPolicy->onFailure(getStatus(), getResponseHeaders()); + F32 retry_after; + if (mFetchRetryPolicy->shouldRetry(retry_after)) + { + LL_INFOS(LOG_TXT) << mID << " will retry after " << retry_after << " seconds, resetting state to LOAD_FROM_NETWORK" << LL_ENDL; + mFetcher->removeFromHTTPQueue(mID, 0); + worker->setGetStatus(mStatus, mReason); + worker->setState(LLTextureFetchWorker::LOAD_FROM_NETWORK); + worker->unlockWorkMutex(); + return; + } + } worker->setGetStatus(mStatus, mReason); - LL_WARNS() << "CURL GET FAILED, status:" << mStatus << " reason:" << mReason << LL_ENDL; + if (mFTType != FTT_MAP_TILE) // missing map tiles are normal, don't complain about them. + { + LL_WARNS(LOG_TXT) << "CURL GET FAILED, status:" << mStatus + << " reason: " << mReason << LL_ENDL; + } } - S32 data_size = worker->callbackHttpGet(mReplyOffset, mReplyLength, channels, buffer, partial, success); + S32BytesImplicit data_size = worker->callbackHttpGet(mReplyOffset, mReplyLength, channels, buffer, partial, success); if(log_texture_traffic && data_size > 0) { @@ -455,12 +483,15 @@ private: LLTextureFetch* mFetcher; LLUUID mID; + FTType mFTType; + LLPointer mFetchRetryPolicy; U64 mMetricsStartTime; S32 mRequestedSize; U32 mRequestedOffset; U32 mReplyOffset; U32 mReplyLength; U32 mReplyFullLength; + }; ////////////////////////////////////////////////////////////////////////////// @@ -780,6 +811,7 @@ volatile bool LLTextureFetch::svMetricsDataBreak(true); // Start with a data bre // called from MAIN THREAD LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, + FTType f_type, // Fetched image type const std::string& url, // Optional URL const LLUUID& id, // Image UUID const LLHost& host, // Simulator host @@ -790,6 +822,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mState(INIT), mWriteToCacheState(NOT_WRITE), mFetcher(fetcher), + mFTType(f_type), mID(id), mHost(host), mUrl(url), @@ -901,7 +934,7 @@ void LLTextureFetchWorker::setupPacketData() mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1; if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size) { - LL_WARNS() << "Bad CACHED TEXTURE size: " << data_size << " removing." << LL_ENDL; + LL_WARNS(LOG_TXT) << "Bad CACHED TEXTURE size: " << data_size << " removing." << LL_ENDL; removeFromCache(); resetFormattedData(); clearPackets(); @@ -1013,14 +1046,14 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (mState == INIT || mState == LOAD_FROM_NETWORK/* || mState == LOAD_FROM_SIMULATOR*/) //If we've already sent out requests.. might as well continue. { - LL_WARNS("Texture") << mID << " abort: mImagePriority < F_ALMOST_ZERO" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " abort: mImagePriority < F_ALMOST_ZERO" << LL_ENDL; return true; // abort } } if(mState > CACHE_POST && !mCanUseNET && !mCanUseHTTP) { //nowhere to get data, abort. - LL_WARNS("Texture") << mID << " abort, nowhere to get data" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " abort, nowhere to get data" << LL_ENDL; return true ; } @@ -1069,7 +1102,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mCacheWriteHandle = LLTextureCache::nullHandle(); setState(LOAD_FROM_TEXTURE_CACHE); mDesiredSize = llmax(mDesiredSize, TEXTURE_CACHE_ENTRY_SIZE); // min desired size is TEXTURE_CACHE_ENTRY_SIZE - LL_DEBUGS("Texture") << mID << ": Priority: " << llformat("%8.0f",mImagePriority) + LL_DEBUGS(LOG_TXT) << mID << ": Priority: " << llformat("%8.0f",mImagePriority) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; // fall through } @@ -1101,7 +1134,7 @@ bool LLTextureFetchWorker::doWork(S32 param) offset, size, responder); mCacheReadTimer.reset(); } - else if (mUrl.empty()) + else if ((mUrl.empty() || mFTType==FTT_SERVER_BAKE)) { setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it @@ -1142,7 +1175,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // //This should never happen // - LL_WARNS("Texture") << mID << " this should never happen" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " this should never happen" << LL_ENDL; return false; } } @@ -1163,12 +1196,12 @@ bool LLTextureFetchWorker::doWork(S32 param) mLoadedDiscard = mDesiredDiscard; if (mLoadedDiscard < 0) { - LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard << ", should be >=0" << LL_ENDL; } setState(DECODE_IMAGE); mWriteToCacheState = NOT_WRITE ; - LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize() + LL_DEBUGS(LOG_TXT) << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize() << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight()) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; LLTextureFetch::sCacheHitRate.addValue(100.f); @@ -1178,13 +1211,13 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mUrl.compare(0, 7, "file://") == 0) { // failed to load local file, we're done. - LL_WARNS("Texture") << mID << ": abort, failed to load local file " << mUrl << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << ": abort, failed to load local file " << mUrl << LL_ENDL; return true; } // need more data else { - LL_DEBUGS("Texture") << mID << ": Not in Cache" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << ": Not in Cache" << LL_ENDL; setState(LOAD_FROM_NETWORK); } @@ -1211,22 +1244,33 @@ bool LLTextureFetchWorker::doWork(S32 param) std::string http_url = region->getHttpUrl() ; if (!http_url.empty()) { + if (mFTType != FTT_DEFAULT) + { + LL_WARNS(LOG_TXT) << "trying to seek a non-default texture on the sim. Bad!" << LL_ENDL; + } mUrl = http_url + "/?texture_id=" + mID.asString().c_str(); + LL_DEBUGS(LOG_TXT) << "Texture URL: " << mUrl << LL_ENDL; mWriteToCacheState = CAN_WRITE ; //because this texture has a fixed texture id. mPerServicePtr = AIPerService::instance(AIPerService::extract_canonical_servicename(http_url)); } else { mCanUseHTTP = false ; + LL_DEBUGS(LOG_TXT) << "Texture not available via HTTP: empty URL." << LL_ENDL; } } else { // This will happen if not logged in or if a region does not have HTTP Texture enabled //LL_WARNS() << "Region not found for host: " << mHost << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "Texture not available via HTTP: no region " << mUrl << LL_ENDL; mCanUseHTTP = false; } } + else if (mFTType == FTT_SERVER_BAKE) + { + mWriteToCacheState = CAN_WRITE; + } if (!mUrl.empty() && SGHostBlackList::isBlacklisted(mUrl)){ mCanUseHTTP = false; } @@ -1272,19 +1316,19 @@ bool LLTextureFetchWorker::doWork(S32 param) } if (processSimulatorPackets()) { - LL_DEBUGS("Texture") << mID << ": Loaded from Sim. Bytes: " << mFormattedImage->getDataSize() << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << ": Loaded from Sim. Bytes: " << mFormattedImage->getDataSize() << LL_ENDL; mFetcher->removeFromNetworkQueue(this, false); if (mFormattedImage.isNull() || !mFormattedImage->getDataSize()) { // processSimulatorPackets() failed // LL_WARNS() << "processSimulatorPackets() failed to load buffer" << LL_ENDL; - LL_WARNS("Texture") << mID << " processSimulatorPackets() failed to load buffer" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " processSimulatorPackets() failed to load buffer" << LL_ENDL; return true; // failed } setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if (mLoadedDiscard < 0) { - LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard << ", should be >=0" << LL_ENDL; } setState(DECODE_IMAGE); @@ -1337,7 +1381,7 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (! mCanUseHTTP) { - LL_WARNS("Texture") << mID << " abort: SEND_HTTP_REQ but !mCanUseHTTP" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " abort: SEND_HTTP_REQ but !mCanUseHTTP" << LL_ENDL; return true ; //abort } S32 cur_size = 0; @@ -1355,7 +1399,7 @@ bool LLTextureFetchWorker::doWork(S32 param) setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if (mLoadedDiscard < 0) { - LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard << ", should be >=0" << LL_ENDL; } setState(DECODE_IMAGE); @@ -1363,7 +1407,7 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { - LL_WARNS("Texture") << mID << " SEND_HTTP_REQ abort: cur_size " << cur_size << " <=0" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " SEND_HTTP_REQ abort: cur_size " << cur_size << " <=0" << LL_ENDL; return true ; //abort. } } @@ -1401,35 +1445,33 @@ bool LLTextureFetchWorker::doWork(S32 param) mRequestedSize += 1; } - if (!mUrl.empty()) - { - mRequestedTimer.reset(); - mLoaded = FALSE; - mGetStatus = 0; - mGetReason.clear(); - LL_DEBUGS("Texture") << "HTTP GET: " << mID << " Offset: " << mRequestedOffset - << " Bytes: " << mRequestedSize - << LL_ENDL; - // Will call callbackHttpGet when curl request completes - AIHTTPHeaders headers("Accept", "image/x-j2c"); - // Call LLHTTPClient::request directly instead of LLHTTPClient::getByteRange, because we want to pass a NULL AIEngine. - if (mRequestedOffset > 0 || mRequestedSize > 0) - { - int const range_end = mRequestedOffset + mRequestedSize - 1; - char const* const range_format = (range_end >= HTTP_REQUESTS_RANGE_END_MAX) ? "bytes=%d-" : "bytes=%d-%d"; - headers.addHeader("Range", llformat(range_format, mRequestedOffset, range_end)); - } - LLHTTPClient::request(mUrl, LLHTTPClient::HTTP_GET, NULL, - new HTTPGetResponder(mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, mRequestedOffset), - headers, approved/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, no_does_authentication, allow_compressed_reply, NULL, 0, NULL); - } - else + if (mUrl.empty()) { LL_WARNS() << "HTTP GET request failed for " << mID << LL_ENDL; resetFormattedData(); ++mHTTPFailCount; return true; // failed } + + mRequestedTimer.reset(); + mLoaded = FALSE; + mGetStatus = 0; + mGetReason.clear(); + LL_DEBUGS(LOG_TXT) << "HTTP GET: " << mID << " Offset: " << mRequestedOffset + << " Bytes: " << mRequestedSize + << LL_ENDL; + // Will call callbackHttpGet when curl request completes + AIHTTPHeaders headers("Accept", "image/x-j2c"); + // Call LLHTTPClient::request directly instead of LLHTTPClient::getByteRange, because we want to pass a NULL AIEngine. + if (mRequestedOffset > 0 || mRequestedSize > 0) + { + int const range_end = mRequestedOffset + mRequestedSize - 1; + char const* const range_format = (range_end >= HTTP_REQUESTS_RANGE_END_MAX) ? "bytes=%d-" : "bytes=%d-%d"; + headers.addHeader("Range", llformat(range_format, mRequestedOffset, range_end)); + } + LLHTTPClient::request(mUrl, LLHTTPClient::HTTP_GET, NULL, + new HTTPGetResponder( mFTType, mFetcher, mID, LLTimer::getTotalTime(), mRequestedSize, mRequestedOffset), + headers, approved/*,*/ DEBUG_CURLIO_PARAM(debug_off), keep_alive, no_does_authentication, allow_compressed_reply, NULL, 0, NULL); mFetcher->addToHTTPQueue(mID); recordTextureStart(true); @@ -1505,14 +1547,21 @@ bool LLTextureFetchWorker::doWork(S32 param) mHTTPFailCount = max_attempts = 1; // Don't retry if(mGetStatus == HTTP_NOT_FOUND) { + if (mFTType != FTT_MAP_TILE) + { + LL_WARNS(LOG_TXT) << "Texture missing from server (404): " << mUrl << LL_ENDL; + } + if(mWriteToCacheState == NOT_WRITE) //map tiles { resetFormattedData(); setState(DONE); - //LL_INFOS("Texture") << mID << " abort: WAIT_HTTP_REQ not found" << LL_ENDL; + if (mFTType != FTT_MAP_TILE) + { + LL_WARNS(LOG_TXT) << mID << " abort: WAIT_HTTP_REQ not found" << LL_ENDL; + } return true; // failed, means no map tile on the empty region. } - LL_WARNS() << "Texture missing from server (404): " << mUrl << LL_ENDL; } else if (mGetStatus == HTTP_INTERNAL_ERROR_CURL_TIMEOUT || mGetStatus == HTTP_INTERNAL_ERROR_LOW_SPEED) { @@ -1573,6 +1622,10 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mHTTPFailCount >= max_attempts) { + if (mFTType != FTT_SERVER_BAKE) + { + mUrl.clear(); + } // Make max_attempts attempt at decoding what data we have, // then bail forever on this image if (cur_size > 0 && (mHTTPFailCount < (max_attempts+1)) ) @@ -1582,8 +1635,8 @@ bool LLTextureFetchWorker::doWork(S32 param) setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); if (mLoadedDiscard < 0) { - LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard - << ", should be >=0" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard + << ", should be >=0" << LL_ENDL; } setState(DECODE_IMAGE); return false; @@ -1605,7 +1658,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // UDP is not an option, we are dead resetFormattedData(); setState(DONE); - LL_INFOS("Texture") << mID << " abort: fail harder" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " abort: fail harder" << LL_ENDL; return true; // failed } } @@ -1620,7 +1673,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // Clear the url since we're done with the fetch // Note: mUrl is used to check is fetching is required so failure to clear it will force an http fetch // next time the texture is requested, even if the data have already been fetched. - if(mWriteToCacheState != NOT_WRITE) + if(mWriteToCacheState != NOT_WRITE && mFTType != FTT_SERVER_BAKE) { // Why do we want to keep url if NOT_WRITE - is this a proxy for map tiles? mUrl.clear(); @@ -1630,7 +1683,7 @@ bool LLTextureFetchWorker::doWork(S32 param) { //abort. setState(DONE); - LL_WARNS("Texture") << mID << " abort: no data received" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << " abort: no data received" << LL_ENDL; return true; } @@ -1645,7 +1698,7 @@ bool LLTextureFetchWorker::doWork(S32 param) // Get back into alignment. if ((S32)mHttpReplyOffset > cur_size) { - LL_WARNS("Texture") << "Partial HTTP response produces break in image data for texture " + LL_WARNS(LOG_TXT) << "Partial HTTP response produces break in image data for texture " << mID << ". Aborting load." << LL_ENDL; setState(DONE); return true; @@ -1697,7 +1750,7 @@ bool LLTextureFetchWorker::doWork(S32 param) mLoadedDiscard = mRequestedDiscard; if (mLoadedDiscard < 0) { - LL_WARNS("Texture") << mID << " mLoadedDiscard is " << mLoadedDiscard + LL_WARNS(LOG_TXT) << mID << " mLoadedDiscard is " << mLoadedDiscard << ", should be >=0" << LL_ENDL; } setState(DECODE_IMAGE); @@ -1731,26 +1784,26 @@ bool LLTextureFetchWorker::doWork(S32 param) { // We aborted, don't decode setState(DONE); - LL_WARNS("Texture") << mID << " DECODE_IMAGE abort: desired discard " << mDesiredDiscard << "<0" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: desired discard " << mDesiredDiscard << "<0" << LL_ENDL; return true; } if (mFormattedImage->getDataSize() <= 0) { - LL_WARNS() << "Decode entered with invalid mFormattedImage. ID = " << mID << LL_ENDL; + LL_WARNS(LOG_TXT) << "Decode entered with invalid mFormattedImage. ID = " << mID << LL_ENDL; //abort, don't decode setState(DONE); - LL_WARNS("Texture") << mID << " DECODE_IMAGE abort: (mFormattedImage->getDataSize() <= 0)" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: (mFormattedImage->getDataSize() <= 0)" << LL_ENDL; return true; } if (mLoadedDiscard < 0) { - LL_WARNS() << "Decode entered with invalid mLoadedDiscard. ID = " << mID << LL_ENDL; + LL_WARNS(LOG_TXT) << "Decode entered with invalid mLoadedDiscard. ID = " << mID << LL_ENDL; //abort, don't decode setState(DONE); - LL_WARNS("Texture") << mID << " DECODE_IMAGE abort: mLoadedDiscard < 0" << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " DECODE_IMAGE abort: mLoadedDiscard < 0" << LL_ENDL; return true; } @@ -1761,7 +1814,7 @@ bool LLTextureFetchWorker::doWork(S32 param) U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority; mDecoded = FALSE; setState(DECODE_IMAGE_UPDATE); - LL_DEBUGS("Texture") << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard + LL_DEBUGS(LOG_TXT) << mID << ": Decoding. Bytes: " << mFormattedImage->getDataSize() << " Discard: " << discard << " All Data: " << mHaveAllData << LL_ENDL; mDecodeHandle = mFetcher->mImageDecodeThread->decodeImage(mFormattedImage, image_priority, discard, mNeedsAux, new DecodeResponder(mFetcher, mID, this)); @@ -1774,11 +1827,11 @@ bool LLTextureFetchWorker::doWork(S32 param) { if (mDecodedDiscard < 0) { - LL_WARNS("Texture") << mID << ": Failed to Decode." << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << ": Failed to Decode." << LL_ENDL; if (mCachedSize > 0 && !mInLocalCache && mRetryAttempt == 0) { // Cache file should be deleted, try again -// LL_WARNS() << mID << ": Decode of cached file failed (removed), retrying" << LL_ENDL; + LL_WARNS(LOG_TXT) << mID << ": Decode of cached file failed (removed), retrying" << LL_ENDL; llassert_always(mDecodeHandle == 0); mFormattedImage = NULL; ++mRetryAttempt; @@ -1795,7 +1848,7 @@ bool LLTextureFetchWorker::doWork(S32 param) else { llassert_always(mRawImage.notNull()); - LL_DEBUGS("Texture") << mID << ": Decoded. Discard: " << mDecodedDiscard + LL_DEBUGS(LOG_TXT) << mID << ": Decoded. Discard: " << mDecodedDiscard << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); setState(WRITE_TO_CACHE); @@ -1868,9 +1921,9 @@ bool LLTextureFetchWorker::doWork(S32 param) { // More data was requested, return to INIT setState(INIT); - LL_WARNS("Texture") << mID << " more data requested, returning to INIT: " - << " mDecodedDiscard " << mDecodedDiscard << ">= 0 && mDesiredDiscard " << mDesiredDiscard - << "<" << " mDecodedDiscard " << mDecodedDiscard << LL_ENDL; + LL_DEBUGS(LOG_TXT) << mID << " more data requested, returning to INIT: " + << " mDecodedDiscard " << mDecodedDiscard << ">= 0 && mDesiredDiscard " << mDesiredDiscard + << "<" << " mDecodedDiscard " << mDecodedDiscard << LL_ENDL; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); return false; } @@ -2031,13 +2084,13 @@ S32 LLTextureFetchWorker::callbackHttpGet(U32 offset, U32 length, if (mState != WAIT_HTTP_REQ) { - LL_WARNS() << "callbackHttpGet for unrequested fetch worker: " << mID + LL_WARNS(LOG_TXT) << "callbackHttpGet for unrequested fetch worker: " << mID << " req=" << mSentRequest << " state= " << mState << LL_ENDL; return data_size; } if (mLoaded) { - LL_WARNS() << "Duplicate callback for " << mID.asString() << LL_ENDL; + LL_WARNS(LOG_TXT) << "Duplicate callback for " << mID.asString() << LL_ENDL; return data_size; // ignore duplicate callback } if (success) @@ -2045,7 +2098,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(U32 offset, U32 length, // get length of stream: data_size = buffer->countAfter(channels.in(), NULL); - LL_DEBUGS("Texture") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL; if (data_size > 0) { LLViewerStatsRecorder::instance().textureFetch(data_size); @@ -2081,7 +2134,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(U32 offset, U32 length, // response body becomes the entire dataset. if (data_size <= mRequestedOffset) { - LL_WARNS("Texture") << "Fetched entire texture " << mID + LL_WARNS(LOG_TXT) << "Fetched entire texture " << mID << " when it was expected to be marked complete. mImageSize: " << mFileSize << " datasize: " << mFormattedImage->getDataSize() << LL_ENDL; @@ -2097,7 +2150,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(U32 offset, U32 length, else if (data_size > mRequestedSize) { // *TODO: This shouldn't be happening any more - LL_WARNS() << "data_size = " << data_size << " > requested: " << mRequestedSize << LL_ENDL; + LL_WARNS(LOG_TXT) << "data_size = " << data_size << " > requested: " << mRequestedSize << LL_ENDL; mHaveAllData = TRUE; llassert_always(mDecodeHandle == 0); mFormattedImage = NULL; // discard any previous data we had @@ -2185,18 +2238,18 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag mRawImage = raw; mAuxImage = aux; mDecodedDiscard = mFormattedImage->getDiscardLevel(); - LL_DEBUGS("Texture") << mID << ": Decode Finished. Discard: " << mDecodedDiscard + LL_DEBUGS(LOG_TXT) << mID << ": Decode Finished. Discard: " << mDecodedDiscard << " Raw Image: " << llformat("%dx%d",mRawImage->getWidth(),mRawImage->getHeight()) << LL_ENDL; } else { if (mFormattedImage.notNull()) { - LL_WARNS("Texture") << "DECODE FAILED: id = " << mID << ", Discard = " << (S32)mFormattedImage->getDiscardLevel() << LL_ENDL; + LL_WARNS(LOG_TXT) << "DECODE FAILED: id = " << mID << ", Discard = " << (S32)mFormattedImage->getDiscardLevel() << LL_ENDL; } else { - LL_WARNS("Texture") << "DECODE FAILED: id = " << mID << ", mFormattedImage is Null!" << LL_ENDL; + LL_WARNS(LOG_TXT) << "DECODE FAILED: id = " << mID << ", mFormattedImage is Null!" << LL_ENDL; } removeFromCache(); mDecodedDiscard = -1; // Redundant, here for clarity and paranoia @@ -2234,7 +2287,7 @@ bool LLTextureFetchWorker::writeToCacheComplete() // Threads: Ttf void LLTextureFetchWorker::recordTextureStart(bool is_http) { - if (! mMetricsStartTime) + if (! mMetricsStartTime.value()) { mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); } @@ -2247,13 +2300,13 @@ void LLTextureFetchWorker::recordTextureStart(bool is_http) // Threads: Ttf void LLTextureFetchWorker::recordTextureDone(bool is_http) { - if (mMetricsStartTime) + if (mMetricsStartTime.value()) { LLViewerAssetStatsFF::record_response_thread1(LLViewerAssetType::AT_TEXTURE, is_http, LLImageBase::TYPE_AVATAR_BAKE == mType, LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime); - mMetricsStartTime = 0; + mMetricsStartTime = (U32Seconds)0; } LLViewerAssetStatsFF::record_dequeue_thread1(LLViewerAssetType::AT_TEXTURE, is_http, @@ -2277,7 +2330,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mTotalCacheReadCount(0U), mTotalCacheWriteCount(0U) { - mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold")); + mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), U32Bytes(gSavedSettings.getU32("TextureLoggingThreshold"))); } LLTextureFetch::~LLTextureFetch() @@ -2294,20 +2347,23 @@ LLTextureFetch::~LLTextureFetch() // ~LLQueuedThread() called here } -bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, +bool LLTextureFetch::createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 desired_discard, bool needs_aux, bool can_use_http) { if (mDebugPause) { return false; } - - LLTextureFetchWorker* worker = getWorker(id); + if (f_type == FTT_SERVER_BAKE) + { + LL_DEBUGS("Avatar") << " requesting " << id << " " << w << "x" << h << " discard " << desired_discard << " type " << f_type << LL_ENDL; + } + LLTextureFetchWorker* worker = getWorker(id) ; if (worker) { if (worker->mHost != host) { - LL_WARNS() << "LLTextureFetch::createRequest " << id << " called with multiple hosts: " + LL_WARNS(LOG_TXT) << "LLTextureFetch::createRequest " << id << " called with multiple hosts: " << host << " != " << worker->mHost << LL_ENDL; removeRequest(worker, true); worker = NULL; @@ -2317,9 +2373,21 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con S32 desired_size; std::string exten = gDirUtilp->getExtension(url); - if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)) + //if (f_type == FTT_SERVER_BAKE) + if ((f_type == FTT_SERVER_BAKE) && !url.empty() && !exten.empty() && (LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)) { - LL_DEBUGS("Texture") << "full request for " << id << " exten is not J2C: " << exten << LL_ENDL; + // SH-4030: This case should be redundant with the following one, just + // breaking it out here to clarify that it's intended behavior. + llassert(!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)); + + // Do full requests for baked textures to reduce interim blurring. + LL_DEBUGS(LOG_TXT) << "full request for " << id << " texture is FTT_SERVER_BAKE" << LL_ENDL; + desired_size = MAX_IMAGE_DATA_SIZE; + desired_discard = 0; + } + else if (!url.empty() && (!exten.empty() && LLImageBase::getCodecFromExtension(exten) != IMG_CODEC_J2C)) + { + LL_DEBUGS(LOG_TXT) << "full request for " << id << " exten is not J2C: " << exten << LL_ENDL; // Only do partial requests for J2C at the moment //LL_INFOS() << "Merov : LLTextureFetch::createRequest(), blocking fetch on " << url << LL_ENDL; desired_size = MAX_IMAGE_DATA_SIZE; @@ -2372,7 +2440,7 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con } else { - worker = new LLTextureFetchWorker(this, url, id, host, priority, desired_discard, desired_size); + worker = new LLTextureFetchWorker(this, f_type, url, id, host, priority, desired_discard, desired_size); lockQueue() ; mRequestMap[id] = worker; unlockQueue() ; @@ -2384,7 +2452,8 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con worker->unlockWorkMutex(); } - LL_DEBUGS("Texture") << "REQUESTED: " << id << " Discard: " << desired_discard << " size " << desired_size << LL_ENDL; + LL_DEBUGS(LOG_TXT) << "REQUESTED: " << id << " f_type " << fttype_to_string(f_type) + << " Discard: " << desired_discard << " size " << desired_size << LL_ENDL; return true; } @@ -2703,10 +2772,10 @@ void LLTextureFetch::startThread() // Threads: Ttf void LLTextureFetch::endThread() { - LL_INFOS("Texture") << "CacheReads: " << mTotalCacheReadCount - << ", CacheWrites: " << mTotalCacheWriteCount - << ", TotalHTTPReq: " << getTotalNumHTTPRequests() - << LL_ENDL; + LL_INFOS(LOG_TXT) << "CacheReads: " << mTotalCacheReadCount + << ", CacheWrites: " << mTotalCacheWriteCount + << ", TotalHTTPReq: " << getTotalNumHTTPRequests() + << LL_ENDL; } // Threads: Ttf @@ -2731,7 +2800,7 @@ void LLTextureFetch::threadedUpdate() S32 q = mCurlGetRequest->getQueued(); if (q > 0) { - LL_INFOS() << "Queued gets: " << q << LL_ENDL; + LL_INFOS(LOG_TXT) << "Queued gets: " << q << LL_ENDL; info_timer.reset(); } } @@ -2783,7 +2852,7 @@ void LLTextureFetch::sendRequestListToSimulators() (req->mState != LLTextureFetchWorker::LOAD_FROM_SIMULATOR)) { // We already received our URL, remove from the queue - LL_WARNS() << "Worker: " << req->mID << " in mNetworkQueue but in wrong state: " << req->mState << LL_ENDL; + LL_WARNS(LOG_TXT) << "Worker: " << req->mID << " in mNetworkQueue but in wrong state: " << req->mState << LL_ENDL; mNetworkQueue.erase(curiter); continue; } @@ -3118,7 +3187,7 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 if (log_to_viewer_log || log_to_sim) { - U64 timeNow = LLTimer::getTotalTime(); + U64Microseconds timeNow = LLTimer::getTotalTime(); mTextureInfo.setRequestSize(id, worker->mFileSize); mTextureInfo.setRequestCompleteTimeAndLog(id, timeNow); } @@ -3196,25 +3265,25 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r void LLTextureFetch::dump() { - LL_INFOS() << "LLTextureFetch REQUESTS:" << LL_ENDL; + LL_INFOS(LOG_TXT) << "LLTextureFetch REQUESTS:" << LL_ENDL; for (request_queue_t::iterator iter = mRequestQueue.begin(); iter != mRequestQueue.end(); ++iter) { LLQueuedThread::QueuedRequest* qreq = *iter; LLWorkerThread::WorkRequest* wreq = (LLWorkerThread::WorkRequest*)qreq; LLTextureFetchWorker* worker = (LLTextureFetchWorker*)wreq->getWorkerClass(); - LL_INFOS() << " ID: " << worker->mID + LL_INFOS(LOG_TXT) << " ID: " << worker->mID << " PRI: " << llformat("0x%08x",wreq->getPriority()) << " STATE: " << worker->sStateDescs[worker->mState] << LL_ENDL; } - LL_INFOS() << "LLTextureFetch ACTIVE_HTTP:" << LL_ENDL; + LL_INFOS(LOG_TXT) << "LLTextureFetch ACTIVE_HTTP:" << LL_ENDL; for (queue_t::const_iterator iter(mHTTPTextureQueue.begin()); mHTTPTextureQueue.end() != iter; ++iter) { - LL_INFOS() << " ID: " << (*iter) << LL_ENDL; + LL_INFOS(LOG_TXT) << " ID: " << (*iter) << LL_ENDL; } } diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index adabfcf91..5de76de4d 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -43,6 +43,7 @@ #include "lltextureinfo.h" #include "llapr.h" #include "llstat.h" +#include "llviewertexture.h" class LLViewerTexture; class LLTextureFetchWorker; @@ -68,7 +69,7 @@ public: void shutDownTextureCacheThread() ; //called in the main thread after the TextureCacheThread shuts down. void shutDownImageDecodeThread() ; //called in the main thread after the ImageDecodeThread shuts down. - bool createRequest(const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, + bool createRequest(FTType f_type, const std::string& url, const LLUUID& id, const LLHost& host, F32 priority, S32 w, S32 h, S32 c, S32 discard, bool needs_aux, bool can_use_http); void deleteRequest(const LLUUID& id, bool cancel); void deleteAllRequests(); diff --git a/indra/newview/lltextureinfo.cpp b/indra/newview/lltextureinfo.cpp index d24ca3341..e115021d3 100644 --- a/indra/newview/lltextureinfo.cpp +++ b/indra/newview/lltextureinfo.cpp @@ -44,17 +44,17 @@ LLTextureInfo::LLTextureInfo() : mTextureDownloadsStarted(0), mTextureDownloadsCompleted(0), mTextureDownloadProtocol("NONE"), - mTextureLogThreshold(100 * 1024), + mTextureLogThreshold(LLUnits::Kilobytes::fromValue(100)), mCurrentStatsBundleStartTime(0) { mTextures.clear(); } -void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold) +void LLTextureInfo::setUpLogging(bool writeToViewerLog, bool sendToSim, U32Bytes textureLogThreshold) { mLogTextureDownloadsToViewerLog = writeToViewerLog; mLogTextureDownloadsToSimulator = sendToSim; - mTextureLogThreshold = textureLogThreshold; + mTextureLogThreshold = U32Bytes(textureLogThreshold); } LLTextureInfo::~LLTextureInfo() @@ -82,15 +82,7 @@ U32 LLTextureInfo::getTextureInfoMapSize() bool LLTextureInfo::has(const LLUUID& id) { - std::map::iterator iterator = mTextures.find(id); - if (iterator == mTextures.end()) - { - return false; - } - else - { - return true; - } + return mTextures.end() != mTextures.find(id); } void LLTextureInfo::setRequestStartTime(const LLUUID& id, U64 startTime) @@ -99,7 +91,7 @@ void LLTextureInfo::setRequestStartTime(const LLUUID& id, U64 startTime) { addRequest(id); } - mTextures[id]->mStartTime = startTime; + mTextures[id]->mStartTime = (U64Microseconds)startTime; mTextureDownloadsStarted++; } @@ -109,7 +101,7 @@ void LLTextureInfo::setRequestSize(const LLUUID& id, U32 size) { addRequest(id); } - mTextures[id]->mSize = size; + mTextures[id]->mSize = (U32Bytes)size; } void LLTextureInfo::setRequestOffset(const LLUUID& id, U32 offset) @@ -130,16 +122,19 @@ void LLTextureInfo::setRequestType(const LLUUID& id, LLTextureInfoDetails::LLReq mTextures[id]->mType = type; } -void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime) +void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64Microseconds completeTime) { if (!has(id)) { addRequest(id); } - mTextures[id]->mCompleteTime = completeTime; + + LLTextureInfoDetails& details = *mTextures[id]; + + details.mCompleteTime = completeTime; std::string protocol = "NONE"; - switch(mTextures[id]->mType) + switch(details.mType) { case LLTextureInfoDetails::REQUEST_TYPE_HTTP: protocol = "HTTP"; @@ -156,21 +151,21 @@ void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeT if (mLogTextureDownloadsToViewerLog) { - LL_INFOS() << "texture=" << id - << " start=" << mTextures[id]->mStartTime - << " end=" << mTextures[id]->mCompleteTime - << " size=" << mTextures[id]->mSize - << " offset=" << mTextures[id]->mOffset - << " length_in_ms=" << (mTextures[id]->mCompleteTime - mTextures[id]->mStartTime) / 1000 - << " protocol=" << protocol - << LL_ENDL; + LL_INFOS() << "texture=" << id + << " start=" << details.mStartTime + << " end=" << details.mCompleteTime + << " size=" << details.mSize + << " offset=" << details.mOffset + << " length=" << U32Milliseconds(details.mCompleteTime - details.mStartTime) + << " protocol=" << protocol + << LL_ENDL; } if(mLogTextureDownloadsToSimulator) { - S32 texture_stats_upload_threshold = mTextureLogThreshold; - mTotalBytes += mTextures[id]->mSize; - mTotalMilliseconds += mTextures[id]->mCompleteTime - mTextures[id]->mStartTime; + U32Bytes texture_stats_upload_threshold = mTextureLogThreshold; + mTotalBytes += details.mSize; + mTotalMilliseconds += details.mCompleteTime - details.mStartTime; mTextureDownloadsCompleted++; mTextureDownloadProtocol = protocol; if (mTotalBytes >= texture_stats_upload_threshold) @@ -194,18 +189,15 @@ void LLTextureInfo::setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeT LLSD LLTextureInfo::getAverages() { LLSD averagedTextureData; - S32 averageDownloadRate; - if(mTotalMilliseconds == 0) + S32 averageDownloadRate = 0; + unsigned int download_time = mTotalMilliseconds.valueInUnits(); + if (0 != download_time) { - averageDownloadRate = 0; - } - else - { - averageDownloadRate = (mTotalBytes * 8) / mTotalMilliseconds; + averageDownloadRate = mTotalBytes.valueInUnits() / download_time; } averagedTextureData["bits_per_second"] = averageDownloadRate; - averagedTextureData["bytes_downloaded"] = mTotalBytes; + averagedTextureData["bytes_downloaded"] = (LLSD::Integer)mTotalBytes.valueInUnits(); averagedTextureData["texture_downloads_started"] = mTextureDownloadsStarted; averagedTextureData["texture_downloads_completed"] = mTextureDownloadsCompleted; averagedTextureData["transport"] = mTextureDownloadProtocol; @@ -215,19 +207,19 @@ LLSD LLTextureInfo::getAverages() void LLTextureInfo::resetTextureStatistics() { - mTotalMilliseconds = 0; - mTotalBytes = 0; + mTotalMilliseconds = U32Milliseconds(0); + mTotalBytes = U32Bytes(0); mTextureDownloadsStarted = 0; mTextureDownloadsCompleted = 0; mTextureDownloadProtocol = "NONE"; mCurrentStatsBundleStartTime = LLTimer::getTotalTime(); } -U32 LLTextureInfo::getRequestStartTime(const LLUUID& id) +U32Microseconds LLTextureInfo::getRequestStartTime(const LLUUID& id) { if (!has(id)) { - return 0; + return U32Microseconds(0); } else { @@ -236,11 +228,11 @@ U32 LLTextureInfo::getRequestStartTime(const LLUUID& id) } } -U32 LLTextureInfo::getRequestSize(const LLUUID& id) +U32Bytes LLTextureInfo::getRequestSize(const LLUUID& id) { if (!has(id)) { - return 0; + return U32Bytes(0); } else { @@ -275,11 +267,11 @@ LLTextureInfoDetails::LLRequestType LLTextureInfo::getRequestType(const LLUUID& } } -U32 LLTextureInfo::getRequestCompleteTime(const LLUUID& id) +U32Microseconds LLTextureInfo::getRequestCompleteTime(const LLUUID& id) { if (!has(id)) { - return 0; + return U32Microseconds(0); } else { diff --git a/indra/newview/lltextureinfo.h b/indra/newview/lltextureinfo.h index 71b0ea431..2c9c494c0 100644 --- a/indra/newview/lltextureinfo.h +++ b/indra/newview/lltextureinfo.h @@ -43,18 +43,18 @@ public: LLTextureInfo(); ~LLTextureInfo(); - void setUpLogging(bool writeToViewerLog, bool sendToSim, U32 textureLogThreshold); + void setUpLogging(bool writeToViewerLog, bool sendToSim, U32Bytes textureLogThreshold); bool has(const LLUUID& id); void setRequestStartTime(const LLUUID& id, U64 startTime); void setRequestSize(const LLUUID& id, U32 size); void setRequestOffset(const LLUUID& id, U32 offset); void setRequestType(const LLUUID& id, LLTextureInfoDetails::LLRequestType type); - void setRequestCompleteTimeAndLog(const LLUUID& id, U64 completeTime); - U32 getRequestStartTime(const LLUUID& id); - U32 getRequestSize(const LLUUID& id); + void setRequestCompleteTimeAndLog(const LLUUID& id, U64Microseconds completeTime); + U32Microseconds getRequestStartTime(const LLUUID& id); + U32Bytes getRequestSize(const LLUUID& id); U32 getRequestOffset(const LLUUID& id); LLTextureInfoDetails::LLRequestType getRequestType(const LLUUID& id); - U32 getRequestCompleteTime(const LLUUID& id); + U32Microseconds getRequestCompleteTime(const LLUUID& id); void resetTextureStatistics(); U32 getTextureInfoMapSize(); LLSD getAverages(); @@ -66,15 +66,15 @@ private: LLSD mAverages; - bool mLogTextureDownloadsToViewerLog; - bool mLogTextureDownloadsToSimulator; - S32 mTotalBytes; - S32 mTotalMilliseconds; + bool mLogTextureDownloadsToViewerLog, + mLogTextureDownloadsToSimulator; + U32Bytes mTotalBytes; + U32Milliseconds mTotalMilliseconds; S32 mTextureDownloadsStarted; S32 mTextureDownloadsCompleted; std::string mTextureDownloadProtocol; - U32 mTextureLogThreshold; // in bytes - U64 mCurrentStatsBundleStartTime; + U32Bytes mTextureLogThreshold; // in bytes + U64Microseconds mCurrentStatsBundleStartTime; }; #endif // LL_LLTEXTUREINFO_H diff --git a/indra/newview/lltextureinfodetails.cpp b/indra/newview/lltextureinfodetails.cpp index f6ef47a2e..d0c5f1e3a 100644 --- a/indra/newview/lltextureinfodetails.cpp +++ b/indra/newview/lltextureinfodetails.cpp @@ -34,7 +34,9 @@ #include "lltextureinfodetails.h" -LLTextureInfoDetails::LLTextureInfoDetails() : mStartTime(0), mCompleteTime(0), mSize(0), mType(REQUEST_TYPE_NONE), mOffset(0) +LLTextureInfoDetails::LLTextureInfoDetails() +: mType(REQUEST_TYPE_NONE), + mOffset(0) { } diff --git a/indra/newview/lltextureinfodetails.h b/indra/newview/lltextureinfodetails.h index 091fa01a3..ef8f74ae8 100644 --- a/indra/newview/lltextureinfodetails.h +++ b/indra/newview/lltextureinfodetails.h @@ -34,10 +34,10 @@ #define LL_LLTEXTUREINFODETAILS_H #include "lluuid.h" +#include "llunits.h" -class LLTextureInfoDetails +struct LLTextureInfoDetails { -public: enum LLRequestType { REQUEST_TYPE_NONE, @@ -45,11 +45,11 @@ public: REQUEST_TYPE_UDP }; - U32 mStartTime; - U32 mCompleteTime; - U32 mOffset; - U32 mSize; - LLRequestType mType; + U32Microseconds mStartTime, + mCompleteTime; + U32 mOffset; + U32Bytes mSize; + LLRequestType mType; LLTextureInfoDetails(); }; diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index b201bfcca..14ee16c5c 100644 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -407,7 +407,7 @@ void LLTextureBar::draw() default:; }; std::string num_str = llformat("%4dx%4d (%+d) %7d %s", mImagep->getWidth(), mImagep->getHeight(), - mImagep->getDiscardLevel(), mImagep->hasGLTexture() ? mImagep->getTextureMemory() : 0, boost_lvl.c_str()); + mImagep->getDiscardLevel(), mImagep->hasGLTexture() ? mImagep->getTextureMemory().value() : 0, boost_lvl.c_str()); LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, title_x4, getRect().getHeight(), color, LLFontGL::LEFT, LLFontGL::TOP); } @@ -564,18 +564,18 @@ private: void LLGLTexMemBar::draw() { - S32 bound_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sBoundTextureMemoryInBytes); - S32 max_bound_mem = LLViewerTexture::sMaxBoundTextureMemInMegaBytes; - S32 total_mem = BYTES_TO_MEGA_BYTES(LLViewerTexture::sTotalTextureMemoryInBytes); - S32 max_total_mem = LLViewerTexture::sMaxTotalTextureMemInMegaBytes; + S32Megabytes bound_mem = LLViewerTexture::sBoundTextureMemory; + S32Megabytes max_bound_mem = LLViewerTexture::sMaxBoundTextureMemory; + S32Megabytes total_mem = LLViewerTexture::sTotalTextureMemory; + S32Megabytes max_total_mem = LLViewerTexture::sMaxTotalTextureMem; F32 discard_bias = LLViewerTexture::sDesiredDiscardBias; - F32 cache_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getUsage()) ; - F32 cache_max_usage = (F32)BYTES_TO_MEGA_BYTES(LLAppViewer::getTextureCache()->getMaxUsage()) ; - S32 line_height = (S32)(LLFontGL::getFontMonospace()->getLineHeight() + .5f); - S32 v_offset = 0; - F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024); - F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024); - U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ; + F32 cache_usage = LLAppViewer::getTextureCache()->getUsage().valueInUnits(); + F32 cache_max_usage = LLAppViewer::getTextureCache()->getMaxUsage().valueInUnits(); + S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); + S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f); + F32Bytes total_texture_downloaded = gTotalTextureData; + F32Bytes total_object_downloaded = gTotalObjectData; + U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests(); //---------------------------------------------------------------------------- LLGLSUIDefault gls_ui; LLColor4 text_color(1.f, 1.f, 1.f, 0.75f); @@ -588,10 +588,10 @@ void LLGLTexMemBar::draw() global_raw_memory = *AIAccess(LLImageRaw::sGlobalRawMemory); } text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d", - total_mem, - max_total_mem, - bound_mem, - max_bound_mem, + total_mem.value(), + max_total_mem.value(), + bound_mem.value(), + max_bound_mem.value(), LLRenderTarget::sBytesAllocated/(1024*1024), global_raw_memory >> 20, discard_bias, cache_usage, cache_max_usage, total_texture_downloaded, total_object_downloaded, total_http_requests); @@ -890,7 +890,7 @@ void LLTextureView::draw() if (mPrintList) { - S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory() : 0 ; + S32 tex_mem = imagep->hasGLTexture() ? imagep->getTextureMemory().value() : 0 ; LL_INFOS() << imagep->getID() << "\t" << tex_mem << "\t" << imagep->getBoostLevel() @@ -1317,7 +1317,7 @@ void LLTextureSizeView::drawTextureCategoryGraph() for(U32 i = 0 ; i < mTextureSizeBar.size() ; i++) { U32 k = LLViewerTexture::getIndexFromCategory(i) ; - mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k] >> 20, LLImageGL::sTextureMemByCategoryBound[k] >> 20, size_bar_scale) ; + mTextureSizeBar[i]->setTop(LLImageGL::sTextureMemByCategory[k].value() >> 20, LLImageGL::sTextureMemByCategoryBound[k].value() >> 20, size_bar_scale) ; mTextureSizeBar[i]->draw() ; } LLImageGL::resetCurTexSizebar(); @@ -1335,7 +1335,7 @@ F32 LLTextureSizeView::drawTextureCategoryDistributionGraph() S32 count = 0 ; for(U32 i = 0 ; i < LLImageGL::sTextureMemByCategory.size() ; i++) { - S32 tmp = LLImageGL::sTextureMemByCategory[i] >> 20 ; + S32 tmp = LLImageGL::sTextureMemByCategory[i].value() >> 20 ; if(tmp > count) { count = tmp ; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 4f5bb691e..29dfeba7a 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1119,8 +1119,7 @@ void LLToolDragAndDrop::dropMesh(LLViewerObject* hit_obj, } LLSculptParams sculpt_params; - sculpt_params.setSculptTexture(asset_id); - sculpt_params.setSculptType(LL_SCULPT_TYPE_MESH); + sculpt_params.setSculptTexture(asset_id, LL_SCULPT_TYPE_MESH); hit_obj->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); dialog_refresh_all(); diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index ed768eb09..90260ed6f 100644 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -110,7 +110,7 @@ LLViewerAssetStats::PerRegionStats::reset() } mFPS.reset(); - mTotalTime = 0; + mTotalTime = U64Microseconds(0); mStartTimestamp = LLViewerAssetStatsFF::get_timestamp(); } @@ -315,9 +315,9 @@ LLViewerAssetStats::asLLSD(bool compact_output) slot[enq_tag] = LLSD(S32(stats.mRequests[i].mEnqueued.getCount())); slot[deq_tag] = LLSD(S32(stats.mRequests[i].mDequeued.getCount())); slot[rcnt_tag] = LLSD(S32(stats.mRequests[i].mResponse.getCount())); - slot[rmin_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMin() * 1.0e-6)); - slot[rmax_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMax() * 1.0e-6)); - slot[rmean_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMean() * 1.0e-6)); + slot[rmin_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMin().valueInUnits())); + slot[rmax_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMax().valueInUnits())); + slot[rmean_tag] = LLSD(F64(stats.mRequests[i].mResponse.getMean().valueInUnits())); } } @@ -334,13 +334,13 @@ LLViewerAssetStats::asLLSD(bool compact_output) grid_from_region_handle(it->first, &grid_x, &grid_y); reg_stat["grid_x"] = LLSD::Integer(grid_x); reg_stat["grid_y"] = LLSD::Integer(grid_y); - reg_stat["duration"] = LLSD::Real(stats.mTotalTime * 1.0e-6); + reg_stat["duration"] = LLSD::Real(stats.mTotalTime.valueInUnits()); regions.append(reg_stat); } LLSD ret = LLSD::emptyMap(); ret["regions"] = regions; - ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6); + ret["duration"] = LLSD::Real((now - mResetTimestamp).valueInUnits()); return ret; } diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index 3381c01ed..a1091daa1 100644 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -94,7 +94,7 @@ public: * for compatibility with the pre-existing timestamp on the texture * fetcher class, LLTextureFetch. */ - typedef U64 duration_t; +typedef U64Microseconds duration_t; /** * Type for the region identifier used in stats. Currently uses diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index c2c23891c..5d184a037 100644 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -69,7 +69,7 @@ public: protected: void recordMetrics() { - if (mMetricsStartTime) + if (mMetricsStartTime.value()) { // Okay, it appears this request was used for useful things. Record // the expected dequeue and duration of request processing. @@ -77,7 +77,7 @@ protected: LLViewerAssetStatsFF::record_response_main(mType, false, false, (LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime)); - mMetricsStartTime = 0; + mMetricsStartTime = (U32Seconds)0; } } @@ -113,7 +113,7 @@ void LLViewerAssetStorage::storeAssetData( bool is_priority, bool store_local, bool user_waiting, - F64 timeout) + F64Seconds timeout) { LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); LL_DEBUGS("AssetStorage") << "LLViewerAssetStorage::storeAssetData (legacy) " << tid << ":" << LLAssetType::lookup(asset_type) @@ -238,7 +238,7 @@ void LLViewerAssetStorage::storeAssetData( bool temp_file, bool is_priority, bool user_waiting, - F64 timeout) + F64Seconds timeout) { if(filename.empty()) { @@ -302,6 +302,7 @@ void LLViewerAssetStorage::storeAssetData( { // LLAssetStorage metric: Zero size reportMetric( asset_id, asset_type, filename, LLUUID::null, 0, MR_ZERO_SIZE, __FILE__, __LINE__, "The file was zero length" ); + fclose(fp); } else { diff --git a/indra/newview/llviewerassetstorage.h b/indra/newview/llviewerassetstorage.h index ca9b9943f..6baec647e 100644 --- a/indra/newview/llviewerassetstorage.h +++ b/indra/newview/llviewerassetstorage.h @@ -51,7 +51,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); virtual void storeAssetData( const std::string& filename, @@ -62,7 +62,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); protected: using LLAssetStorage::_queueDataRequest; diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp index 4ac560651..9ef5a9859 100644 --- a/indra/newview/llviewercontrol.cpp +++ b/indra/newview/llviewercontrol.cpp @@ -325,7 +325,7 @@ static bool handleMaxPartCountChanged(const LLSD& newvalue) static bool handleVideoMemoryChanged(const LLSD& newvalue) { - gTextureList.updateMaxResidentTexMem(newvalue.asInteger()); + gTextureList.updateMaxResidentTexMem(S32Megabytes(newvalue.asInteger())); return true; } diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index 562605b19..4a600728f 100644 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -236,9 +236,9 @@ void display_stats() F32 mem_log_freq = gSavedSettings.getF32("MemoryLogFrequency"); if (mem_log_freq > 0.f && gRecentMemoryTime.getElapsedTimeF32() >= mem_log_freq) { - gMemoryAllocated = LLMemory::getCurrentRSS(); - U32 memory = (U32)(gMemoryAllocated / (1024*1024)); - LL_INFOS() << llformat("MEMORY: %d MB", memory) << LL_ENDL; + gMemoryAllocated = (U64Bytes)LLMemory::getCurrentRSS(); + U32Megabytes memory = gMemoryAllocated; + LL_INFOS() << llformat("MEMORY: %d MB", memory.value()) << LL_ENDL; LL_INFOS() << "THREADS: "<< LLThread::getCount() << LL_ENDL; LL_INFOS() << "MALLOC: " << SGMemStat::getPrintableStat() <getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize(); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += (U32Bytes)mesgsys->getReceiveSize(); } // Update the object... @@ -5188,11 +5189,11 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize(); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += (U32Bytes)mesgsys->getReceiveSize(); } // Update the object... @@ -5204,11 +5205,11 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize(); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += (U32Bytes)mesgsys->getReceiveSize(); } // Update the object... @@ -5220,11 +5221,11 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_ { if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += (U32Bytes)mesgsys->getReceiveCompressedSize(); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += (U32Bytes)mesgsys->getReceiveSize(); } gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 331fe0c51..fc517cf30 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -119,8 +119,8 @@ BOOL LLViewerObject::sPulseEnabled(FALSE); BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE // sMaxUpdateInterpolationTime must be greater than sPhaseOutUpdateInterpolationTime -F64 LLViewerObject::sMaxUpdateInterpolationTime = 3.0; // For motion interpolation: after X seconds with no updates, don't predict object motion -F64 LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0; // For motion interpolation: after Y seconds with no updates, taper off motion prediction +F64Seconds LLViewerObject::sMaxUpdateInterpolationTime(3.0); // For motion interpolation: after X seconds with no updates, don't predict object motion +F64Seconds LLViewerObject::sPhaseOutUpdateInterpolationTime(2.0); // For motion interpolation: after Y seconds with no updates, taper off motion prediction static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object"); @@ -244,7 +244,6 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mOnMap(FALSE), mStatic(FALSE), mNumFaces(0), - mTimeDilation(1.f), mRotTime(0.f), mAngularVelocityRot(), mPreviousRotation(), @@ -373,10 +372,17 @@ void LLViewerObject::markDead() // // Root object of this hierarchy unlinks itself. + LLVOAvatar *av = getAvatarAncestor(); if (getParent()) { ((LLViewerObject *)getParent())->removeChild(this); } + LLUUID mesh_id; + if (av && LLVOAvatar::getRiggedMeshID(this,mesh_id)) + { + // This case is needed for indirectly attached mesh objects. + av->resetJointPositionsOnDetach(mesh_id); + } // Mark itself as dead mDead = TRUE; @@ -975,11 +981,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, return retval; } + F32 time_dilation = 1.f; + if(mesgsys != NULL) + { U16 time_dilation16; mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16); - F32 time_dilation = ((F32) time_dilation16) / 65535.f; - mTimeDilation = time_dilation; + time_dilation = ((F32) time_dilation16) / 65535.f; mRegionp->setTimeDilation(time_dilation); + } // this will be used to determine if we've really changed position // Use getPosition, not getPositionRegion, since this is what we're comparing directly against. @@ -1770,7 +1779,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender()); if (cdp) { - F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped); + F32 ping_delay = 0.5f * time_dilation * ( ((F32)cdp->getPingDelay().valueInUnits()) + gFrameDTClamped); LLVector3 diff = getVelocity() * ping_delay; new_pos_parent += diff; } @@ -2168,39 +2177,38 @@ BOOL LLViewerObject::isActive() const void LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - //static LLFastTimer::DeclareTimer ftm("Viewer Object"); - //LLFastTimer t(ftm); + //static LLTrace::BlockTimerStatHandle ftm("Viewer Object"); + //LL_RECORD_BLOCK_TIME(ftm); if (!mDead) { - // CRO - don't velocity interp linked objects! - // Leviathan - but DO velocity interp joints - if (!mStatic && sVelocityInterpolate && !isSelected()) - { - // calculate dt from last update - F32 dt_raw = (F32)(time - mLastInterpUpdateSecs); - F32 dt = mTimeDilation * dt_raw; + if (!mStatic && sVelocityInterpolate && !isSelected()) + { + // calculate dt from last update + F32 time_dilation = mRegionp ? mRegionp->getTimeDilation() : 1.0f; + F32 dt_raw = ((F64Seconds)time - mLastInterpUpdateSecs).value(); + F32 dt = time_dilation * dt_raw; applyAngularVelocity(dt); if (isAttachment()) - { - mLastInterpUpdateSecs = time; + { + mLastInterpUpdateSecs = (F64Seconds)time; return; + } + else + { // Move object based on it's velocity and rotation + interpolateLinearMotion(time, dt); + } } - else - { // Move object based on it's velocity and rotation - interpolateLinearMotion(time, dt); - } + + updateDrawable(FALSE); } - - updateDrawable(FALSE); -} } -// Move an object due to idle-time viewer side updates by iterpolating motion -void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) +// Move an object due to idle-time viewer side updates by interpolating motion +void LLViewerObject::interpolateLinearMotion(const F64SecondsImplicit& time, const F32SecondsImplicit& dt_seconds) { // linear motion // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object @@ -2211,8 +2219,9 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) // to see if object is selected, instead of explicitly // zeroing it out - F64 time_since_last_update = time - mLastMessageUpdateSecs; - if (time_since_last_update <= 0.0 || dt <= 0.f) + F32 dt = dt_seconds; + F64Seconds time_since_last_update = time - mLastMessageUpdateSecs; + if (time_since_last_update <= (F64Seconds)0.0 || dt <= 0.f) { return; } @@ -2220,7 +2229,7 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) LLVector3 accel = getAcceleration(); LLVector3 vel = getVelocity(); - if (sMaxUpdateInterpolationTime <= 0.0) + if (sMaxUpdateInterpolationTime <= (F64Seconds)0.0) { // Old code path ... unbounded, simple interpolation if (!(accel.isExactlyZero() && vel.isExactlyZero())) { @@ -2242,8 +2251,8 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) LLVector3 new_v = accel * dt; if (time_since_last_update > sPhaseOutUpdateInterpolationTime && - sPhaseOutUpdateInterpolationTime > 0.0) - { // Haven't seen a viewer update in a while, check to see if the ciruit is still active + sPhaseOutUpdateInterpolationTime > (F64Seconds)0.0) + { // Haven't seen a viewer update in a while, check to see if the circuit is still active if (mRegionp) { // The simulator will NOT send updates if the object continues normally on the path // predicted by the velocity and the acceleration (often gravity) sent to the viewer @@ -2252,14 +2261,14 @@ void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) if (cdp) { // Find out how many seconds since last packet arrived on the circuit - F64 time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime(); + F64Seconds time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime(); if (!cdp->isAlive() || // Circuit is dead or blocked cdp->isBlocked() || // or doesn't seem to be getting any packets (time_since_last_packet > sPhaseOutUpdateInterpolationTime)) { // Start to reduce motion interpolation since we haven't seen a server update in a while - F64 time_since_last_interpolation = time - mLastInterpUpdateSecs; + F64Seconds time_since_last_interpolation = time - mLastInterpUpdateSecs; F64 phase_out = 1.0; if (time_since_last_update > sMaxUpdateInterpolationTime) { // Past the time limit, so stop the object @@ -3305,7 +3314,7 @@ void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); LLUUID sculpt_id = sculpt_params->getSculptTexture(); - LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); + LLViewerTextureManager::getFetchedTexture(sculpt_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); } if (boost_children) @@ -4072,15 +4081,15 @@ void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) LLPrimitive::setTE(te, texture_entry); const LLUUID& image_id = getTE(te)->getID(); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (getTE(te)->getMaterialParams().notNull()) { const LLUUID& norm_id = getTE(te)->getMaterialParams()->getNormalID(); - mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTENormalMaps[te] = LLViewerTextureManager::getFetchedTexture(norm_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); const LLUUID& spec_id = getTE(te)->getMaterialParams()->getSpecularID(); - mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTESpecularMaps[te] = LLViewerTextureManager::getFetchedTexture(spec_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); } } @@ -4195,21 +4204,21 @@ S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) { // Invalid host == get from the agent's sim LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture( - uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); return setTETextureCore(te,image); } S32 LLViewerObject::setTENormalMap(const U8 te, const LLUUID& uuid) { LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( - uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); return setTENormalMapCore(te, image); } S32 LLViewerObject::setTESpecularMap(const U8 te, const LLUUID& uuid) { LLViewerFetchedTexture *image = (uuid == LLUUID::null) ? NULL : LLViewerTextureManager::getFetchedTexture( - uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); + uuid, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, LLHost::invalid); return setTESpecularMapCore(te, image); } @@ -4796,6 +4805,22 @@ LLVOAvatar* LLViewerObject::asAvatar() return NULL; } +// If this object is directly or indirectly parented by an avatar, return it. +LLVOAvatar* LLViewerObject::getAvatarAncestor() +{ + LLViewerObject *pobj = (LLViewerObject*) getParent(); + while (pobj) + { + LLVOAvatar *av = pobj->asAvatar(); + if (av) + { + return av; + } + pobj = (LLViewerObject*) pobj->getParent(); + } + return NULL; +} + BOOL LLViewerObject::isParticleSource() const { return !mPartSourcep.isNull() && !mPartSourcep->isDead(); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index ff5734a19..675ff1f8f 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -141,6 +141,8 @@ public: virtual LLVOAvatar* asAvatar(); + LLVOAvatar* getAvatarAncestor(); + static void initVOClasses(); static void cleanupVOClasses(); @@ -591,7 +593,7 @@ private: U32 checkMediaURL(const std::string &media_url); // Motion prediction between updates - void interpolateLinearMotion(const F64 & time, const F32 & dt); + void interpolateLinearMotion(const F64SecondsImplicit & time, const F32SecondsImplicit & dt); public: // @@ -710,8 +712,6 @@ protected: void deleteParticleSource(); void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id); -public: - private: void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string void deleteTEImages(); // correctly deletes list of images @@ -722,8 +722,8 @@ protected: child_list_t mChildList; - F64 mLastInterpUpdateSecs; // Last update for purposes of interpolation - F64 mLastMessageUpdateSecs; // Last update from a message from the simulator + F64Seconds mLastInterpUpdateSecs; // Last update for purposes of interpolation + F64Seconds mLastMessageUpdateSecs; // Last update from a message from the simulator TPACKETID mLatestRecvPacketID; // Latest time stamp on message from simulator // extra data sent from the sim...currently only used for tree species info @@ -765,7 +765,6 @@ protected: BOOL mStatic; // Object doesn't move. S32 mNumFaces; - F32 mTimeDilation; // Time dilation sent with the object. F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega) LLQuaternion mAngularVelocityRot; // accumulated rotation from the angular velocity computations LLQuaternion mPreviousRotation; @@ -791,12 +790,13 @@ protected: static S32 sAxisArrowLength; + // These two caches are only correct for non-parented objects right now! mutable LLVector3 mPositionRegion; mutable LLVector3 mPositionAgent; - static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64) value; } - static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64) value; } + static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64Seconds) value; } + static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64Seconds) value; } static void setVelocityInterpolate(BOOL value) { sVelocityInterpolate = value; } static void setPingInterpolate(BOOL value) { sPingInterpolate = value; } @@ -804,8 +804,8 @@ protected: private: static S32 sNumObjects; - static F64 sPhaseOutUpdateInterpolationTime; // For motion interpolation - static F64 sMaxUpdateInterpolationTime; // For motion interpolation + static F64Seconds sPhaseOutUpdateInterpolationTime; // For motion interpolation + static F64Seconds sMaxUpdateInterpolationTime; // For motion interpolation static BOOL sVelocityInterpolate; static BOOL sPingInterpolate; diff --git a/indra/newview/llviewerobjectbackup.cpp b/indra/newview/llviewerobjectbackup.cpp index 9b0f97d97..292a4cae1 100644 --- a/indra/newview/llviewerobjectbackup.cpp +++ b/indra/newview/llviewerobjectbackup.cpp @@ -1370,7 +1370,7 @@ void LLObjectBackup::xmlToPrim(LLSD prim_llsd, LLViewerObject* object) LLUUID t_id = sculpt.getSculptTexture(); if (mAssetMap.count(t_id)) { - sculpt.setSculptTexture(mAssetMap[t_id]); + sculpt.setSculptTexture(mAssetMap[t_id], sculpt.getSculptType()); } object->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt, true); diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp index 94199d1f5..74c4fc6b1 100644 --- a/indra/newview/llvieweroctree.cpp +++ b/indra/newview/llvieweroctree.cpp @@ -455,6 +455,7 @@ LLViewerOctreeGroup::~LLViewerOctreeGroup() LLViewerOctreeGroup::LLViewerOctreeGroup(OctreeNode* node) : mOctreeNode(node), + mAnyVisible(0), mState(CLEAN) { LLVector4a tmp; @@ -760,6 +761,11 @@ BOOL LLViewerOctreeGroup::isRecentlyVisible() const void LLViewerOctreeGroup::setVisible() { mVisible[LLViewerCamera::sCurCameraID] = LLViewerOctreeEntryData::getCurrentFrame(); + + if(LLViewerCamera::sCurCameraID < LLViewerCamera::CAMERA_WATER0) + { + mAnyVisible = LLViewerOctreeEntryData::getCurrentFrame(); + } } void LLViewerOctreeGroup::checkStates() @@ -882,6 +888,12 @@ BOOL LLOcclusionCullingGroup::isRecentlyVisible() const return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < MIN_VIS_FRAME_RANGE ; } +BOOL LLOcclusionCullingGroup::isAnyRecentlyVisible() const +{ + const S32 MIN_VIS_FRAME_RANGE = 2; + return (LLDrawable::getCurrentFrame() - mAnyVisible) < MIN_VIS_FRAME_RANGE ; +} + //virtual void LLOcclusionCullingGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) { @@ -1293,7 +1305,8 @@ void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera, const LLVector4a* sh //----------------------------------------------------------------------------------- //class LLViewerOctreePartition definitions //----------------------------------------------------------------------------------- -LLViewerOctreePartition::LLViewerOctreePartition() : +LLViewerOctreePartition::LLViewerOctreePartition() : + mRegionp(NULL), mOcclusionEnabled(TRUE), mDrawableType(0), mLODSeed(0), @@ -1453,21 +1466,21 @@ bool LLViewerOctreeCull::checkProjectionArea(const LLVector4a& center, const LLV //virtual bool LLViewerOctreeCull::checkObjects(const OctreeNode* branch, const LLViewerOctreeGroup* group) { - if (branch->getElementCount() == 0) //no elements - { - return false; - } - else if (branch->getChildCount() == 0) //leaf state, already checked tightest bounding box - { - return true; - } - else if (mRes == 1 && !frustumCheckObjects(group)) //no objects in frustum - { - return false; - } - + if (branch->getElementCount() == 0) //no elements + { + return false; + } + else if (branch->getChildCount() == 0) //leaf state, already checked tightest bounding box + { return true; } + else if (mRes == 1 && !frustumCheckObjects(group)) //no objects in frustum + { + return false; + } + + return true; +} //virtual void LLViewerOctreeCull::preprocess(LLViewerOctreeGroup* group) diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h index 73749edaf..78eca7b33 100644 --- a/indra/newview/llvieweroctree.h +++ b/indra/newview/llvieweroctree.h @@ -77,6 +77,7 @@ public: typedef enum { LLDRAWABLE = 0, + LLVOCACHEENTRY, NUM_DATA_TYPE }eEntryDataType_t; @@ -92,6 +93,9 @@ public: LLViewerOctreeEntryData* getDrawable() const {return mData[LLDRAWABLE];} bool hasDrawable() const {return mData[LLDRAWABLE] != NULL;} + LLViewerOctreeEntryData* getVOCacheEntry() const {return mData[LLVOCACHEENTRY];} + bool hasVOCacheEntry() const {return mData[LLVOCACHEENTRY] != NULL;} + const LLVector4a* getSpatialExtents() const {return mExtents;} const LLVector4a& getPositionGroup() const {return mPositionGroup;} LLViewerOctreeGroup* getGroup()const {return mGroup;} @@ -208,6 +212,7 @@ public: BOOL isVisible() const; virtual BOOL isRecentlyVisible() const; S32 getVisible(LLViewerCamera::eCameraID id) const {return mVisible[id];} + S32 getAnyVisible() const {return mAnyVisible;} bool isEmpty() const { return mOctreeNode->isEmpty(); } U32 getState() {return mState; } @@ -233,7 +238,7 @@ public: const LLVector4a* getObjectExtents() const {return mObjectExtents;} //octree wrappers to make code more readable - //element_list& getData() { return mOctreeNode->getData(); } //unused + //element_list& getData() { return mOctreeNode->getData(); } element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } U32 getElementCount() const { return mOctreeNode->getElementCount(); } @@ -253,6 +258,7 @@ protected: LL_ALIGN_16(LLVector4a mExtents[2]); // extents (min, max) of this node and all its children LL_ALIGN_16(LLVector4a mObjectExtents[2]); // extents (min, max) of objects in this node + S32 mAnyVisible; //latest visible to any camera S32 mVisible[LLViewerCamera::NUM_CAMERAS]; }; @@ -307,6 +313,7 @@ public: //virtual BOOL isRecentlyVisible() const; LLViewerOctreePartition* getSpatialPartition()const {return mSpatialPartition;} + BOOL isAnyRecentlyVisible() const; static U32 getNewOcclusionQueryObjectName(); static void releaseOcclusionQueryObjectName(U32 name); @@ -342,11 +349,12 @@ public: public: U32 mPartitionType; - U32 mDrawableType; - OctreeNode* mOctree; - BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed - U32 mLODSeed; - U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed) + U32 mDrawableType; + OctreeNode* mOctree; + LLViewerRegion* mRegionp; // the region this partition belongs to. + BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed + U32 mLODSeed; + U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed) }; class LLViewerOctreeCull : public OctreeTraveler diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index 937d91acb..1a389ab05 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -476,20 +476,20 @@ void LLViewerRegion::initPartitions() { //create object partitions //MUST MATCH declaration of eObjectPartitions - mImpl->mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD - mImpl->mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN - mImpl->mObjectPartition.push_back(new LLVoidWaterPartition()); //PARTITION_VOIDWATER - mImpl->mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER - mImpl->mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE - mImpl->mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE + mImpl->mObjectPartition.push_back(new LLHUDPartition(this)); //PARTITION_HUD + mImpl->mObjectPartition.push_back(new LLTerrainPartition(this)); //PARTITION_TERRAIN + mImpl->mObjectPartition.push_back(new LLVoidWaterPartition(this)); //PARTITION_VOIDWATER + mImpl->mObjectPartition.push_back(new LLWaterPartition(this)); //PARTITION_WATER + mImpl->mObjectPartition.push_back(new LLTreePartition(this)); //PARTITION_TREE + mImpl->mObjectPartition.push_back(new LLParticlePartition(this)); //PARTITION_PARTICLE #if ENABLE_CLASSIC_CLOUDS - mImpl->mObjectPartition.push_back(new LLCloudPartition()); //PARTITION_CLOUD + mImpl->mObjectPartition.push_back(new LLCloudPartition(this)); //PARTITION_CLOUD #endif - mImpl->mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS - mImpl->mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME - mImpl->mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE - mImpl->mObjectPartition.push_back(new LLAttachmentPartition()); //PARTITION_ATTACHMENT - mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_PARTICLE + mImpl->mObjectPartition.push_back(new LLGrassPartition(this)); //PARTITION_GRASS + mImpl->mObjectPartition.push_back(new LLVolumePartition(this)); //PARTITION_VOLUME + mImpl->mObjectPartition.push_back(new LLBridgePartition(this)); //PARTITION_BRIDGE + mImpl->mObjectPartition.push_back(new LLAttachmentPartition(this)); //PARTITION_ATTACHMENT + mImpl->mObjectPartition.push_back(new LLHUDParticlePartition(this));//PARTITION_HUD_PARTICLE mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE mRenderInfoRequestTimer.resetWithExpiry(0.f); // Set timer to be expired @@ -507,14 +507,14 @@ void LLViewerRegion::initStats() { mImpl->mLastNetUpdate.reset(); mPacketsIn = 0; - mBitsIn = 0; - mLastBitsIn = 0; + mBitsIn = (U32Bits)0; + mLastBitsIn = (U32Bits)0; mLastPacketsIn = 0; mPacketsOut = 0; mLastPacketsOut = 0; mPacketsLost = 0; mLastPacketsLost = 0; - mPingDelay = 0; + mPingDelay = (U32Seconds)0; mAlive = false; // can become false if circuit disconnects } @@ -1134,7 +1134,7 @@ void LLViewerRegion::updateNetStats() mPacketsLost = cdp->getPacketsLost(); mPingDelay = cdp->getPingDelay(); - mBitStat.addValue(mBitsIn - mLastBitsIn); + mBitStat.addValue((mBitsIn - mLastBitsIn).value()); mPacketsStat.addValue(mPacketsIn - mLastPacketsIn); mPacketsLostStat.addValue(mPacketsLost); } @@ -1234,7 +1234,7 @@ const LLViewerRegion::tex_matrix_t& LLViewerRegion::getWorldMapTiles() const for (U32 x = 0; x != totalX; ++x) for (U32 y = 0; y != totalY; ++y) { - LLPointer tex(LLViewerTextureManager::getFetchedTextureFromUrl(strImgURL+llformat("%d-%d-objects.jpg", gridX + x, gridY + y), TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + LLPointer tex(LLViewerTextureManager::getFetchedTextureFromUrl(strImgURL+llformat("%d-%d-objects.jpg", gridX + x, gridY + y), FTT_MAP_TILE, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); mWorldMapTiles.push_back(tex); tex->setBoostLevel(LLViewerTexture::BOOST_MAP); } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index 869c4aad2..1de1fe645 100644 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -447,14 +447,14 @@ private: BOOL mIsEstateManager; U32 mPacketsIn; - U32 mBitsIn; - U32 mLastBitsIn; + U32Bits mBitsIn, + mLastBitsIn; U32 mLastPacketsIn; U32 mPacketsOut; U32 mLastPacketsOut; S32 mPacketsLost; S32 mLastPacketsLost; - U32 mPingDelay; + U32Milliseconds mPingDelay; F32 mDeltaTime; // Time since last measurement of lastPackets, Bits, etc U64 mRegionFlags; // includes damage flags diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index cd27ce011..6ab7207b9 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -495,6 +495,7 @@ void LLViewerShaderMgr::setShaders() //Flag base shader objects for deletion //Don't worry-- they won't be deleted until no programs refrence them. unloadShaderObjects(); + cleanupShaderSources(); } if (gViewerWindow) @@ -513,11 +514,7 @@ void LLViewerShaderMgr::setShaders() void LLViewerShaderMgr::unloadShaders() { - //Instead of manually unloading, shaders are now automatically accumulated in a list. - //Simply iterate and unload. - std::vector &shader_list = LLShaderMgr::getGlobalShaderList(); - for(std::vector::iterator it=shader_list.begin();it!=shader_list.end();++it) - (*it)->unload(); + LLShaderMgr::unloadShaders(); for (S32 i = 0; i < SHADER_COUNT; i++) mVertexShaderLevel[i] = 0; @@ -530,15 +527,6 @@ void LLViewerShaderMgr::unloadShaders() LLPipeline::sRenderGlow = FALSE; } -void LLViewerShaderMgr::unloadShaderObjects() -{ - std::multimap::iterator it = mShaderObjects.begin(); - for (; it != mShaderObjects.end(); ++it) - if (it->second.mHandle) - glDeleteObjectARB(it->second.mHandle); - mShaderObjects.clear(); -} - BOOL LLViewerShaderMgr::loadBasicShaders() { // Load basic dependency shaders first diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index fe7d4d64c..ef142095e 100644 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -57,7 +57,6 @@ public: void initAttribsAndUniforms(void); void setShaders(); void unloadShaders(); - void unloadShaderObjects(); S32 getVertexShaderLevel(S32 type); BOOL loadBasicShaders(); BOOL loadShadersEffects(); diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 41cf0f276..ea6e98d23 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -451,8 +451,8 @@ void output_statistics(void*) LL_INFOS() << "Number of orphans: " << gObjectList.getOrphanCount() << LL_ENDL; LL_INFOS() << "Number of dead objects: " << gObjectList.mNumDeadObjects << LL_ENDL; LL_INFOS() << "Num images: " << gTextureList.getNumImages() << LL_ENDL; - LL_INFOS() << "Texture usage: " << LLImageGL::sGlobalTextureMemoryInBytes << LL_ENDL; - LL_INFOS() << "Texture working set: " << LLImageGL::sBoundTextureMemoryInBytes << LL_ENDL; + LL_INFOS() << "Texture usage: " << LLImageGL::sGlobalTextureMemory.value() << LL_ENDL; + LL_INFOS() << "Texture working set: " << LLImageGL::sBoundTextureMemory.value() << LL_ENDL; LL_INFOS() << "Raw usage: " << global_raw_memory << LL_ENDL; LL_INFOS() << "Formatted usage: " << LLImageFormatted::sGlobalFormattedMemory << LL_ENDL; LL_INFOS() << "Zombie Viewer Objects: " << LLViewerObject::getNumZombieObjects() << LL_ENDL; @@ -536,7 +536,6 @@ void output_statistics(void*) LL_INFOS() << "--------------------------------" << LL_ENDL; LL_INFOS() << "Avatar Memory (partly overlaps with above stats):" << LL_ENDL; LLTexLayerStaticImageList::getInstance()->dumpByteCount(); - LLVOAvatarSelf::dumpScratchTextureByteCount(); LLViewerTexLayerSetBuffer::dumpTotalByteCount(); LLVOAvatarSelf::dumpTotalLocalTextureByteCount(); LLTexLayerParamAlpha::dumpCacheByteCount(); @@ -570,19 +569,25 @@ void output_statistics(void*) } -U32 gTotalLandIn = 0, gTotalLandOut = 0; -U32 gTotalWaterIn = 0, gTotalWaterOut = 0; +U32 gTotalLandIn = 0, + gTotalLandOut = 0, + gTotalWaterIn = 0, + gTotalWaterOut = 0; -F32 gAveLandCompression = 0.f, gAveWaterCompression = 0.f; -F32 gBestLandCompression = 1.f, gBestWaterCompression = 1.f; -F32 gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f; +F32 gAveLandCompression = 0.f, + gAveWaterCompression = 0.f, + gBestLandCompression = 1.f, + gBestWaterCompression = 1.f, + gWorstLandCompression = 0.f, + gWorstWaterCompression = 0.f; - - -U32 gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0; -U32 gObjectBits = 0; -F32 gAvgSimPing = 0.f; -U32 gTotalTextureBytesPerBoostLevel[LLGLTexture::MAX_GL_IMAGE_CATEGORY] = {0}; +U32Bytes gTotalWorldData, + gTotalObjectData, + gTotalTextureData; +U32 gSimPingCount = 0; +U32Bits gObjectData; +F32Milliseconds gAvgSimPing(0.f); +U32Bytes gTotalTextureBytesPerBoostLevel[LLGLTexture::MAX_GL_IMAGE_CATEGORY] = {U32Bytes(0)}; extern U32 gVisCompared; extern U32 gVisTested; @@ -591,8 +596,8 @@ LLFrameTimer gTextureTimer; void update_statistics() { - gTotalWorldBytes += gVLManager.getTotalBytes(); - gTotalObjectBytes += gObjectBits / 8; + gTotalWorldData += U32Bytes(gVLManager.getTotalBytes()); + gTotalObjectData += gObjectData; LLViewerStats& stats = LLViewerStats::instance(); @@ -633,8 +638,8 @@ void update_statistics() LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost()); if (cdp) { - stats.mSimPingStat.addValue(cdp->getPingDelay()); - gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1); + stats.mSimPingStat.addValue(cdp->getPingDelay().value()); + gAvgSimPing = ((gAvgSimPing * gSimPingCount) + cdp->getPingDelay()) / (gSimPingCount + 1); gSimPingCount++; } else @@ -643,11 +648,11 @@ void update_statistics() } stats.mFPSStat.addValue(1); - F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits()); - stats.mLayersKBitStat.addValue(layer_bits/1024.f); - stats.mObjectKBitStat.addValue(gObjectBits/1024.f); + F64Bits layer_bits = F64Bits(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits()); + stats.mLayersKBitStat.addValue((F32)layer_bits.valueInUnits()); + stats.mObjectKBitStat.addValue(gObjectData.valueInUnits()); stats.mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending()); - stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f); + stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET) / 1024); gTransferManager.resetTransferBitsIn(LLTCT_ASSET); if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) @@ -675,7 +680,7 @@ void update_statistics() // Reset all of these values. gVLManager.resetBitCounts(); - gObjectBits = 0; + gObjectData = (U32Bytes)0; // gDecodedBits = 0; // Only update texture stats periodically so that they are less noisy @@ -685,10 +690,10 @@ void update_statistics() if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) { stats.mHTTPTextureKBitStat.addValue(AICurlInterface::getHTTPBandwidth()/125.f); - stats.mUDPTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f); + stats.mUDPTextureKBitStat.addValue(LLViewerTextureList::sTextureBits.valueInUnits()); stats.mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets); - gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8; - LLViewerTextureList::sTextureBits = 0; + gTotalTextureData += U32Bits(LLViewerTextureList::sTextureBits); + LLViewerTextureList::sTextureBits = U32Bits(0); LLViewerTextureList::sTexturePackets = 0; texture_stats_timer.reset(); } @@ -792,14 +797,14 @@ void send_stats() gSimFrames = (F32) gFrameCount; agent["agents_in_view"] = LLVOAvatar::sNumVisibleAvatars; - agent["ping"] = gAvgSimPing; + agent["ping"] = gAvgSimPing.value(); agent["meters_traveled"] = gAgent.getDistanceTraveled(); agent["regions_visited"] = gAgent.getRegionsVisited(); agent["mem_use"] = LLMemory::getCurrentRSS() / 1024.0; LLSD &system = body["system"]; - system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB(); + system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB().value(); system["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple(); system["cpu"] = gSysCPU.getCPUString(); unsigned char MACAddress[MAC_ADDRESS_BYTES]; @@ -823,9 +828,9 @@ void send_stats() LLSD &download = body["downloads"]; - download["world_kbytes"] = gTotalWorldBytes / 1024.0; - download["object_kbytes"] = gTotalObjectBytes / 1024.0; - download["texture_kbytes"] = gTotalTextureBytes / 1024.0; + download["world_kbytes"] = F64Kilobytes(gTotalWorldData).value(); + download["object_kbytes"] = F64Kilobytes(gTotalObjectData).value(); + download["texture_kbytes"] = F64Kilobytes(gTotalTextureData).value(); download["mesh_kbytes"] = LLMeshRepository::sBytesReceived/1024.0; LLSD &in = body["stats"]["net"]["in"]; @@ -886,7 +891,10 @@ void send_stats() body["MinimalSkin"] = false; LLViewerStats::getInstance()->addToMessage(body); - LLHTTPClient::post(url, body, new ViewerStatsResponder); + + LL_INFOS("LogViewerStatsPacket") << "Sending viewer statistics: " << body << LL_ENDL; + LLHTTPClient::post(url, body, new ViewerStatsResponder()); + } LLViewerStats::PhaseMap::PhaseMap() diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index f6300d1e2..90b75a866 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -321,7 +321,7 @@ void update_statistics(); void send_stats(); extern LLFrameTimer gTextureTimer; -extern U32 gTotalTextureBytes; -extern U32 gTotalObjectBytes; -extern U32 gTotalTextureBytesPerBoostLevel[] ; +extern U32Bytes gTotalTextureData; +extern U32Bytes gTotalObjectData; +extern U32Bytes gTotalTextureBytesPerBoostLevel[] ; #endif // LL_LLVIEWERSTATS_H diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index 11b05813c..f447fe476 100644 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -63,6 +63,11 @@ #include "lltexturecache.h" /////////////////////////////////////////////////////////////////////////////// +// extern +const S32Megabytes gMinVideoRam(32); +const S32Megabytes gMaxVideoRam(1024); + + // statics LLPointer LLViewerTexture::sNullImagep = NULL; LLPointer LLViewerTexture::sBlackImagep = NULL; @@ -83,12 +88,12 @@ S32 LLViewerTexture::sAuxCount = 0; LLFrameTimer LLViewerTexture::sEvaluationTimer; F32 LLViewerTexture::sDesiredDiscardBias = 0.f; F32 LLViewerTexture::sDesiredDiscardScale = 1.1f; -S32 LLViewerTexture::sBoundTextureMemoryInBytes = 0; -S32 LLViewerTexture::sTotalTextureMemoryInBytes = 0; -S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0; -S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0; -S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ; -S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ; +S32Bytes LLViewerTexture::sBoundTextureMemory; +S32Bytes LLViewerTexture::sTotalTextureMemory; +S32Megabytes LLViewerTexture::sMaxBoundTextureMemory; +S32Megabytes LLViewerTexture::sMaxTotalTextureMem; +S32Bytes LLViewerTexture::sMaxDesiredTextureMem; +S8 LLViewerTexture::sCameraMovingDiscardBias = 0; F32 LLViewerTexture::sCameraMovingBias = 0.0f ; S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size const S32 MAX_CACHED_RAW_IMAGE_AREA = 64 * 64 ; @@ -265,6 +270,7 @@ LLPointer LLViewerTextureManager::getLocalTexture(const U32 wid LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( const LLUUID &image_id, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -272,11 +278,12 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( LLGLenum primary_format, LLHost request_from_host) { - return gTextureList.getImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; + return gTextureList.getImage(image_id, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host); } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( const std::string& filename, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -284,11 +291,12 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( LLGLenum primary_format, const LLUUID& force_id) { - return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; + return gTextureList.getImageFromFile(filename, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); } //static LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -297,12 +305,12 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const s const LLUUID& force_id ) { - return gTextureList.getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ; + return gTextureList.getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); } -LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) { - return gTextureList.getImageFromHost(image_id, host) ; + return gTextureList.getImageFromHost(image_id, f_type, host); } // Create a bridge to the viewer texture manager. @@ -375,7 +383,7 @@ void LLViewerTextureManager::init() LLViewerFetchedTexture::sDefaultImagep->dontDiscard(); LLViewerFetchedTexture::sDefaultImagep->setCategory(LLGLTexture::OTHER) ; - LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLGLTexture::BOOST_UI); + LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ; LLViewerTexture::initClass() ; @@ -450,8 +458,9 @@ bool LLViewerTexture::isMemoryForTextureLow() timer.reset() ; LLFastTimer t(FTM_TEXTURE_MEMORY_CHECK); - const static S32 MIN_FREE_TEXTURE_MEMORY = 5 ; //MB - const static S32 MIN_FREE_MAIN_MEMORy = 100 ; //MB + + static const S32Megabytes MIN_FREE_TEXTURE_MEMORY(5); //MB + static const S32Megabytes MIN_FREE_MAIN_MEMORY(100); //MB bool low_mem = false ; if (gGLManager.mHasATIMemInfo) @@ -459,7 +468,7 @@ bool LLViewerTexture::isMemoryForTextureLow() S32 meminfo[4]; glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, meminfo); - if(meminfo[0] / 1024 < MIN_FREE_TEXTURE_MEMORY) + if((S32Megabytes)meminfo[0] < MIN_FREE_TEXTURE_MEMORY) { low_mem = true ; } @@ -467,7 +476,7 @@ bool LLViewerTexture::isMemoryForTextureLow() if(!low_mem) //check main memory, only works for windows. { LLMemory::updateMemoryInfo() ; - if(LLMemory::getAvailableMemKB() / 1024 < MIN_FREE_MAIN_MEMORy) + if(LLMemory::getAvailableMemKB() < MIN_FREE_TEXTURE_MEMORY) { low_mem = true ; } @@ -511,17 +520,17 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity LLViewerMediaTexture::updateClass() ; } - sBoundTextureMemoryInBytes = LLImageGL::sBoundTextureMemoryInBytes;//in bytes - sTotalTextureMemoryInBytes = LLImageGL::sGlobalTextureMemoryInBytes;//in bytes - sMaxBoundTextureMemInMegaBytes = gTextureList.getMaxResidentTexMem();//in MB - sMaxTotalTextureMemInMegaBytes = gTextureList.getMaxTotalTextureMem() ;//in MB - sMaxDesiredTextureMemInBytes = MEGA_BYTES_TO_BYTES(sMaxTotalTextureMemInMegaBytes) ; //in Bytes, by default and when total used texture memory is small. + sBoundTextureMemory = LLImageGL::sBoundTextureMemory; + sTotalTextureMemory = LLImageGL::sGlobalTextureMemory; + sMaxBoundTextureMemory = S32Megabytes(gTextureList.getMaxResidentTexMem()); + sMaxTotalTextureMem = S32Megabytes(gTextureList.getMaxTotalTextureMem()); + sMaxDesiredTextureMem = sMaxTotalTextureMem; //in Bytes, by default and when total used texture memory is small. - if (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) >= sMaxBoundTextureMemInMegaBytes || - BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) >= sMaxTotalTextureMemInMegaBytes) + if (sBoundTextureMemory >= sMaxBoundTextureMemory || + sTotalTextureMemory >= sMaxTotalTextureMem) { - //when texture memory overflows, lower down the threashold to release the textures more aggressively. - sMaxDesiredTextureMemInBytes = llmin((S32)(sMaxDesiredTextureMemInBytes * 0.75f) , MEGA_BYTES_TO_BYTES(MAX_VIDEO_RAM_IN_MEGA_BYTES)) ;//512 MB + //when texture memory overflows, lower down the threshold to release the textures more aggressively. + sMaxDesiredTextureMem = llmin(sMaxDesiredTextureMem * 0.75f, F32Bytes(gMaxVideoRam)); // If we are using more texture memory than we should, // scale up the desired discard level @@ -537,8 +546,8 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity sEvaluationTimer.reset(); } else if (sDesiredDiscardBias > 0.0f && - BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < sMaxBoundTextureMemInMegaBytes * texmem_lower_bound_scale && - BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < sMaxTotalTextureMemInMegaBytes * texmem_lower_bound_scale) + sBoundTextureMemory < sMaxBoundTextureMemory * texmem_lower_bound_scale && + sTotalTextureMemory < sMaxTotalTextureMem * texmem_lower_bound_scale) { // If we are using less texture memory than we should, // scale down the desired discard level @@ -549,15 +558,14 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity } } sDesiredDiscardBias = llclamp(sDesiredDiscardBias, desired_discard_bias_min, desired_discard_bias_max); - //LLViewerTexture::sUseTextureAtlas = gSavedSettings.getBOOL("EnableTextureAtlas") ; - F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed() ; + F32 camera_moving_speed = LLViewerCamera::getInstance()->getAverageSpeed(); F32 camera_angular_speed = LLViewerCamera::getInstance()->getAverageAngularSpeed(); sCameraMovingBias = llmax(0.2f * camera_moving_speed, 2.0f * camera_angular_speed - 1); sCameraMovingDiscardBias = (S8)(sCameraMovingBias); - LLViewerTexture::sFreezeImageScalingDown = (BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) < 0.75f * sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale) && - (BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) < 0.75f * sMaxTotalTextureMemInMegaBytes * texmem_middle_bound_scale) ; + LLViewerTexture::sFreezeImageScalingDown = (sBoundTextureMemory < 0.75f * sMaxBoundTextureMemory * texmem_middle_bound_scale) && + (sTotalTextureMemory < 0.75f * sMaxTotalTextureMem * texmem_middle_bound_scale); } //end of static functions @@ -609,6 +617,7 @@ LLViewerTexture::~LLViewerTexture() // virtual void LLViewerTexture::init(bool firstinit) { + mSelectedTime = 0.f; mMaxVirtualSize = 0.f; mNeedsGLTexture = FALSE ; mMaxVirtualSizeResetInterval = 1; @@ -634,12 +643,37 @@ S8 LLViewerTexture::getType() const void LLViewerTexture::cleanup() { - mFaceList[LLRender::DIFFUSE_MAP].clear() ; - mFaceList[LLRender::NORMAL_MAP].clear() ; + notifyAboutMissingAsset(); + + mFaceList[LLRender::DIFFUSE_MAP].clear(); + mFaceList[LLRender::NORMAL_MAP].clear(); mFaceList[LLRender::SPECULAR_MAP].clear() ; mVolumeList.clear(); } +void LLViewerTexture::notifyAboutCreatingTexture() +{ + for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) + { + for(U32 f = 0; f < mNumFaces[ch]; f++) + { + mFaceList[ch][f]->notifyAboutCreatingTexture(this); + } + } +} + +void LLViewerTexture::notifyAboutMissingAsset() +{ + for(U32 ch = 0; ch < LLRender::NUM_TEXTURE_CHANNELS; ++ch) + { + for(U32 f = 0; f < mNumFaces[ch]; f++) + { + mFaceList[ch][f]->notifyAboutMissingAsset(this); + } + } +} + +// virtual void LLViewerTexture::dump() { LLGLTexture::dump(); @@ -649,6 +683,30 @@ void LLViewerTexture::dump() << LL_ENDL; } +void LLViewerTexture::setBoostLevel(S32 level) +{ + if(mBoostLevel != level) + { + mBoostLevel = level; + if(mBoostLevel != LLViewerTexture::BOOST_NONE && + mBoostLevel != LLViewerTexture::BOOST_SELECTED) + { + setNoDelete(); + } + } + + if (mBoostLevel == LLViewerTexture::BOOST_SELECTED) + { + mSelectedTime = gFrameTimeSeconds; + } + +} + +bool LLViewerTexture::isActiveFetching() +{ + return false; +} + bool LLViewerTexture::bindDefaultImage(S32 stage) { if (stage < 0) return false; @@ -908,30 +966,57 @@ void LLViewerTexture::updateBindStatsForTester() //end of LLViewerTexture //---------------------------------------------------------------------------------------------- +const std::string& fttype_to_string(const FTType& fttype) +{ + static const std::string ftt_unknown("FTT_UNKNOWN"); + static const std::string ftt_default("FTT_DEFAULT"); + static const std::string ftt_server_bake("FTT_SERVER_BAKE"); + static const std::string ftt_host_bake("FTT_HOST_BAKE"); + static const std::string ftt_map_tile("FTT_MAP_TILE"); + static const std::string ftt_local_file("FTT_LOCAL_FILE"); + static const std::string ftt_error("FTT_ERROR"); + switch(fttype) + { + case FTT_UNKNOWN: return ftt_unknown; break; + case FTT_DEFAULT: return ftt_default; break; + case FTT_SERVER_BAKE: return ftt_server_bake; break; + case FTT_HOST_BAKE: return ftt_host_bake; break; + case FTT_MAP_TILE: return ftt_map_tile; break; + case FTT_LOCAL_FILE: return ftt_local_file; break; + } + return ftt_error; +} + //---------------------------------------------------------------------------------------------- //start of LLViewerFetchedTexture //---------------------------------------------------------------------------------------------- -LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host, BOOL usemipmaps) : LLViewerTexture(id, usemipmaps), mTargetHost(host) { - init(TRUE) ; - generateGLTexture() ; - mGLTexturep->setNeedsAlphaAndPickMask(TRUE) ; + init(TRUE); + mFTType = f_type; + if (mFTType == FTT_HOST_BAKE) + { + LL_WARNS() << "Unsupported fetch type " << mFTType << LL_ENDL; + } + generateGLTexture(); } -LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps) : LLViewerTexture(raw, usemipmaps) { init(TRUE) ; + mFTType = f_type; } -LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps) +LLViewerFetchedTexture::LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps) : LLViewerTexture(id, usemipmaps), mUrl(url) { init(TRUE) ; + mFTType = f_type; generateGLTexture() ; mGLTexturep->setNeedsAlphaAndPickMask(TRUE) ; } @@ -940,6 +1025,7 @@ void LLViewerFetchedTexture::init(bool firstinit) { mOrigWidth = 0; mOrigHeight = 0; + mHasAux = FALSE; mNeedsAux = FALSE; mRequestedDiscardLevel = -1; mRequestedDownloadPriority = 0.f; @@ -997,6 +1083,8 @@ void LLViewerFetchedTexture::init(bool firstinit) mLastReferencedSavedRawImageTime = 0.0f ; mKeptSavedRawImageTime = 0.f ; mLastCallBackActiveTime = 0.f; + mForceCallbackFetch = FALSE; + mFTType = FTT_UNKNOWN; } LLViewerFetchedTexture::~LLViewerFetchedTexture() @@ -1014,7 +1102,12 @@ LLViewerFetchedTexture::~LLViewerFetchedTexture() //virtual S8 LLViewerFetchedTexture::getType() const { - return LLViewerTexture::FETCHED_TEXTURE ; + return LLViewerTexture::FETCHED_TEXTURE; +} + +FTType LLViewerFetchedTexture::getFTType() const +{ + return mFTType; } void LLViewerFetchedTexture::cleanup() @@ -1156,7 +1249,7 @@ void LLViewerFetchedTexture::dump() // ONLY called from LLViewerFetchedTextureList void LLViewerFetchedTexture::destroyTexture() { - if(LLImageGL::sGlobalTextureMemoryInBytes < sMaxDesiredTextureMemInBytes * 0.95f)//not ready to release unused memory. + if(LLImageGL::sGlobalTextureMemory < sMaxDesiredTextureMem * 0.95f)//not ready to release unused memory. { return ; } @@ -1343,6 +1436,7 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/) //{ res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel); //resetFaceAtlas() ; + notifyAboutCreatingTexture(); //} setActive() ; } @@ -1661,6 +1755,14 @@ void LLViewerFetchedTexture::updateVirtualSize() } } } + //reset whether or not a face was selected after 10 seconds + const F32 SELECTION_RESET_TIME = 10.f; + + if (getBoostLevel() == LLViewerTexture::BOOST_SELECTED && + gFrameTimeSeconds - mSelectedTime > SELECTION_RESET_TIME) + { + setBoostLevel(LLViewerTexture::BOOST_NONE); + } if(mMaxVirtualSizeResetCounter > 0) { @@ -1688,6 +1790,27 @@ S32 LLViewerFetchedTexture::getCurrentDiscardLevelForFetching() return current_discard ; } +bool LLViewerFetchedTexture::setDebugFetching(S32 debug_level) +{ + if(debug_level < 0) + { + mInDebug = FALSE; + return false; + } + mInDebug = TRUE; + + mDesiredDiscardLevel = debug_level; + + return true; +} + +bool LLViewerFetchedTexture::isActiveFetching() +{ + static LLCachedControl monitor_enabled(gSavedSettings,"DebugShowTextureInfo"); + + return mFetchState > 7 && mFetchState < 10 && monitor_enabled; //in state of WAIT_HTTP_REQ or DECODE_IMAGE. +} + bool LLViewerFetchedTexture::updateFetch() { static LLCachedControl textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); @@ -1740,7 +1863,11 @@ bool LLViewerFetchedTexture::updateFetch() if (mAuxRawImage.notNull()) sAuxCount--; bool finished = LLAppViewer::getTextureFetch()->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage); if (mRawImage.notNull()) sRawCount++; - if (mAuxRawImage.notNull()) sAuxCount++; + if (mAuxRawImage.notNull()) + { + mHasAux = TRUE; + sAuxCount++; + } if (finished) { mIsFetching = FALSE; @@ -1803,20 +1930,33 @@ bool LLViewerFetchedTexture::updateFetch() if ((decode_priority > 0) && (mRawDiscardLevel < 0 || mRawDiscardLevel == INVALID_DISCARD_LEVEL)) { // We finished but received no data - if (current_discard < 0) + if (getDiscardLevel() < 0) { - LL_WARNS() << "!mIsFetching, setting as missing, decode_priority " << decode_priority - << " mRawDiscardLevel " << mRawDiscardLevel - << " current_discard " << current_discard - << LL_ENDL; + if (getFTType() != FTT_MAP_TILE) + { + LL_WARNS() << mID + << " Fetch failure, setting as missing, decode_priority " << decode_priority + << " mRawDiscardLevel " << mRawDiscardLevel + << " current_discard " << current_discard + << LL_ENDL; + } setIsMissingAsset(); desired_discard = -1; } else { //LL_WARNS() << mID << ": Setting min discard to " << current_discard << LL_ENDL; - mMinDiscardLevel = current_discard; - desired_discard = current_discard; + if(current_discard >= 0) + { + mMinDiscardLevel = current_discard; + desired_discard = current_discard; + } + else + { + S32 dis_level = getDiscardLevel(); + mMinDiscardLevel = dis_level; + desired_discard = dis_level; + } } destroyRawImage(); } @@ -1922,7 +2062,7 @@ bool LLViewerFetchedTexture::updateFetch() // bypass texturefetch directly by pulling from LLTextureCache bool fetch_request_created = false; - fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mUrl, getID(),getTargetHost(), decode_priority, + fetch_request_created = LLAppViewer::getTextureFetch()->createRequest(mFTType, mUrl, getID(), getTargetHost(), decode_priority, w, h, c, desired_discard, needsAux(), mCanUseHTTP); if (fetch_request_created) @@ -1954,6 +2094,22 @@ bool LLViewerFetchedTexture::updateFetch() return mIsFetching ? true : false; } +void LLViewerFetchedTexture::clearFetchedResults() +{ + if(mNeedsCreateTexture || mIsFetching) + { + return; + } + + cleanup(); + destroyGLTexture(); + + if(getDiscardLevel() >= 0) //sculpty texture, force to invalidate + { + mGLTexturep->forceToInvalidateGLTexture(); + } +} + void LLViewerFetchedTexture::forceToDeleteRequest() { if (mHasFetcher) @@ -1968,26 +2124,45 @@ void LLViewerFetchedTexture::forceToDeleteRequest() mDesiredDiscardLevel = getMaxDiscardLevel() + 1; //defer LLAppViewer::getTextureFetch()->deleteRequest to updateFetch? } -void LLViewerFetchedTexture::setIsMissingAsset() +void LLViewerFetchedTexture::setIsMissingAsset(BOOL is_missing) { - if (mUrl.empty()) + if (is_missing == mIsMissingAsset) { - LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL; + return; + } + if (is_missing) + { + notifyAboutMissingAsset(); + + if (mUrl.empty()) + { + LL_WARNS() << mID << ": Marking image as missing" << LL_ENDL; + } + else + { + // This may or may not be an error - it is normal to have no + // map tile on an empty region, but bad if we're failing on a + // server bake texture. + if (getFTType() != FTT_MAP_TILE) + { + LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL; + } + } + if (mHasFetcher) + { + LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); + mHasFetcher = FALSE; + mIsFetching = FALSE; + mLastPacketTimer.reset(); + mFetchState = 0; + mFetchPriority = 0; + } } else { - LL_WARNS() << mUrl << ": Marking image as missing" << LL_ENDL; + LL_INFOS() << mID << ": un-flagging missing asset" << LL_ENDL; } - if (mHasFetcher) - { - LLAppViewer::getTextureFetch()->deleteRequest(getID(), true); - mHasFetcher = FALSE; - mIsFetching = FALSE; - mLastPacketTimer.reset(); - mFetchState = 0; - mFetchPriority = 0; - } - mIsMissingAsset = TRUE; + mIsMissingAsset = is_missing; } void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_callback, @@ -2030,10 +2205,19 @@ void LLViewerFetchedTexture::setLoadedCallback( loaded_callback_func loaded_call } if (mNeedsAux && mAuxRawImage.isNull() && getDiscardLevel() >= 0) { - // We need aux data, but we've already loaded the image, and it didn't have any - LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL; + if(mHasAux) + { + //trigger a refetch + forceToRefetchTexture(); + } + else + { + // We need aux data, but we've already loaded the image, and it didn't have any + LL_WARNS() << "No aux data available for callback for image:" << getID() << LL_ENDL; + } } mLastCallBackActiveTime = sCurrentTime ; + mLastReferencedSavedRawImageTime = sCurrentTime; } void LLViewerFetchedTexture::clearCallbackEntryList() @@ -2146,6 +2330,7 @@ void LLViewerFetchedTexture::unpauseLoadedCallbacks(const LLLoadedCallbackEntry: } mPauseLoadedCallBacks = FALSE ; mLastCallBackActiveTime = sCurrentTime ; + mForceCallbackFetch = TRUE; if(need_raw) { mSaveRawImage = TRUE ; @@ -2186,6 +2371,7 @@ void LLViewerFetchedTexture::pauseLoadedCallbacks(const LLLoadedCallbackEntry::s bool LLViewerFetchedTexture::doLoadedCallbacks() { static const F32 MAX_INACTIVE_TIME = 120.f ; //seconds + static const F32 MAX_IDLE_WAIT_TIME = 5.f ; //seconds if (mNeedsCreateTexture) { @@ -2198,6 +2384,15 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() } if(sCurrentTime - mLastCallBackActiveTime > MAX_INACTIVE_TIME && !mIsFetching) { + if (mFTType == FTT_SERVER_BAKE) + { + //output some debug info + LL_INFOS() << "baked texture: " << mID << "clears all call backs due to inactivity." << LL_ENDL; + LL_INFOS() << mUrl << LL_ENDL; + LL_INFOS() << "current discard: " << getDiscardLevel() << " current discard for fetch: " << getCurrentDiscardLevelForFetching() << + " Desired discard: " << getDesiredDiscardLevel() << "decode Pri: " << getDecodePriority() << LL_ENDL; + } + clearCallbackEntryList() ; //remove all callbacks. return false ; } @@ -2206,6 +2401,13 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() if (isMissingAsset()) { + if (mFTType == FTT_SERVER_BAKE) + { + //output some debug info + LL_INFOS() << "baked texture: " << mID << "is missing." << LL_ENDL; + LL_INFOS() << mUrl << LL_ENDL; + } + for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) { @@ -2390,6 +2592,9 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() } } + // Done with any raw image data at this point (will be re-created if we still have callbacks) + destroyRawImage(); + // // If we have no callbacks, take us off of the image callback list. // @@ -2397,10 +2602,12 @@ bool LLViewerFetchedTexture::doLoadedCallbacks() { gTextureList.mCallbackList.erase(this); } - - // Done with any raw image data at this point (will be re-created if we still have callbacks) - destroyRawImage(); - + else if(!res && mForceCallbackFetch && sCurrentTime - mLastCallBackActiveTime > MAX_IDLE_WAIT_TIME && !mIsFetching) + { + //wait for long enough but no fetching request issued, force one. + forceToRefetchTexture(mLoadedCallbackDesiredDiscardLevel, 5.f); + mForceCallbackFetch = FALSE; //fire once. + } return res; } @@ -2482,7 +2689,7 @@ bool LLViewerFetchedTexture::needsToSaveRawImage() void LLViewerFetchedTexture::destroyRawImage() { - if (mAuxRawImage.notNull()) + if (mAuxRawImage.notNull() && !needsToSaveRawImage()) { sAuxCount--; mAuxRawImage = NULL; @@ -2655,7 +2862,25 @@ void LLViewerFetchedTexture::saveRawImage() mForceToSaveRawImage = FALSE ; } + mLastReferencedSavedRawImageTime = sCurrentTime; +} + +//force to refetch the texture to the discard level +void LLViewerFetchedTexture::forceToRefetchTexture(S32 desired_discard, F32 kept_time) +{ + if(mForceToSaveRawImage) + { + desired_discard = llmin(desired_discard, mDesiredSavedRawDiscardLevel); + kept_time = llmax(kept_time, mKeptSavedRawImageTime); + } + + //trigger a new fetch. + mForceToSaveRawImage = TRUE ; + mDesiredSavedRawDiscardLevel = desired_discard ; + mKeptSavedRawImageTime = kept_time ; mLastReferencedSavedRawImageTime = sCurrentTime ; + mSavedRawImage = NULL ; + mSavedRawDiscardLevel = -1 ; } void LLViewerFetchedTexture::forceToSaveRawImage(S32 desired_discard, F32 kept_time) @@ -2705,6 +2930,12 @@ void LLViewerFetchedTexture::destroySavedRawImage() mDesiredSavedRawDiscardLevel = -1 ; mLastReferencedSavedRawImageTime = 0.0f ; mKeptSavedRawImageTime = 0.f ; + + if(mAuxRawImage.notNull()) + { + sAuxCount--; + mAuxRawImage = NULL; + } } LLImageRaw* LLViewerFetchedTexture::getSavedRawImage() @@ -2915,16 +3146,16 @@ BOOL LLViewerFetchedTexture::insertToAtlas() //---------------------------------------------------------------------------------------------- //start of LLViewerLODTexture //---------------------------------------------------------------------------------------------- -LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, const LLHost& host, BOOL usemipmaps) - : LLViewerFetchedTexture(id, host, usemipmaps) +LLViewerLODTexture::LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host, BOOL usemipmaps) + : LLViewerFetchedTexture(id, f_type, host, usemipmaps) { - init(TRUE) ; + init(TRUE); } -LLViewerLODTexture::LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps) - : LLViewerFetchedTexture(url, id, usemipmaps) +LLViewerLODTexture::LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps) + : LLViewerFetchedTexture(url, f_type, id, usemipmaps) { - init(TRUE) ; + init(TRUE); } void LLViewerLODTexture::init(bool firstinit) @@ -3049,13 +3280,13 @@ void LLViewerLODTexture::processTextureStats() scaleDown() ; } // Limit the amount of GL memory bound each frame - else if ( BYTES_TO_MEGA_BYTES(sBoundTextureMemoryInBytes) > sMaxBoundTextureMemInMegaBytes * texmem_middle_bound_scale && + else if ( sBoundTextureMemory > sMaxBoundTextureMemory * texmem_middle_bound_scale && (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) { scaleDown() ; } // Only allow GL to have 2x the video card memory - else if ( BYTES_TO_MEGA_BYTES(sTotalTextureMemoryInBytes) > sMaxTotalTextureMemInMegaBytes*texmem_middle_bound_scale && + else if ( sTotalTextureMemory > sMaxTotalTextureMem * texmem_middle_bound_scale && (!getBoundRecently() || mDesiredDiscardLevel >= mCachedRawDiscardLevel)) { scaleDown() ; @@ -3639,10 +3870,10 @@ LLTexturePipelineTester::LLTexturePipelineTester() : LLMetricPerformanceTesterWi addMetric("TotalBytesBoundForLargeImage") ; addMetric("PercentageBytesBound") ; - mTotalBytesLoaded = 0 ; - mTotalBytesLoadedFromCache = 0 ; - mTotalBytesLoadedForLargeImage = 0 ; - mTotalBytesLoadedForSculpties = 0 ; + mTotalBytesLoaded = (S32Bytes)0; + mTotalBytesLoadedFromCache = (S32Bytes)0; + mTotalBytesLoadedForLargeImage = (S32Bytes)0; + mTotalBytesLoadedForSculpties = (S32Bytes)0; reset() ; } @@ -3656,8 +3887,8 @@ void LLTexturePipelineTester::update() { mLastTotalBytesUsed = mTotalBytesUsed ; mLastTotalBytesUsedForLargeImage = mTotalBytesUsedForLargeImage ; - mTotalBytesUsed = 0 ; - mTotalBytesUsedForLargeImage = 0 ; + mTotalBytesUsed = (S32Bytes)0; + mTotalBytesUsedForLargeImage = (S32Bytes)0; if(LLAppViewer::getTextureFetch()->getNumRequests() > 0) //fetching list is not empty { @@ -3698,10 +3929,10 @@ void LLTexturePipelineTester::reset() mStartStablizingTime = 0.0f ; mEndStablizingTime = 0.0f ; - mTotalBytesUsed = 0 ; - mTotalBytesUsedForLargeImage = 0 ; - mLastTotalBytesUsed = 0 ; - mLastTotalBytesUsedForLargeImage = 0 ; + mTotalBytesUsed = (S32Bytes)0; + mTotalBytesUsedForLargeImage = (S32Bytes)0; + mLastTotalBytesUsed = (S32Bytes)0; + mLastTotalBytesUsedForLargeImage = (S32Bytes)0; mStartFetchingTime = 0.0f ; @@ -3716,59 +3947,59 @@ void LLTexturePipelineTester::reset() void LLTexturePipelineTester::outputTestRecord(LLSD *sd) { std::string currentLabel = getCurrentLabelName(); - (*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded ; - (*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache ; - (*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage ; - (*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties ; + (*sd)[currentLabel]["TotalBytesLoaded"] = (LLSD::Integer)mTotalBytesLoaded.value(); + (*sd)[currentLabel]["TotalBytesLoadedFromCache"] = (LLSD::Integer)mTotalBytesLoadedFromCache.value(); + (*sd)[currentLabel]["TotalBytesLoadedForLargeImage"] = (LLSD::Integer)mTotalBytesLoadedForLargeImage.value(); + (*sd)[currentLabel]["TotalBytesLoadedForSculpties"] = (LLSD::Integer)mTotalBytesLoadedForSculpties.value(); - (*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime ; - (*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime ; - (*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime ; + (*sd)[currentLabel]["StartFetchingTime"] = (LLSD::Real)mStartFetchingTime; + (*sd)[currentLabel]["TotalGrayTime"] = (LLSD::Real)mTotalGrayTime; + (*sd)[currentLabel]["TotalStablizingTime"] = (LLSD::Real)mTotalStablizingTime; - (*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties ; - (*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties ; + (*sd)[currentLabel]["StartTimeLoadingSculpties"] = (LLSD::Real)mStartTimeLoadingSculpties; + (*sd)[currentLabel]["EndTimeLoadingSculpties"] = (LLSD::Real)mEndTimeLoadingSculpties; - (*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime ; - (*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed ; - (*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage ; - (*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded) ; + (*sd)[currentLabel]["Time"] = LLImageGL::sLastFrameTime; + (*sd)[currentLabel]["TotalBytesBound"] = (LLSD::Integer)mLastTotalBytesUsed.value(); + (*sd)[currentLabel]["TotalBytesBoundForLargeImage"] = (LLSD::Integer)mLastTotalBytesUsedForLargeImage.value(); + (*sd)[currentLabel]["PercentageBytesBound"] = (LLSD::Real)(100.f * mLastTotalBytesUsed / mTotalBytesLoaded); } void LLTexturePipelineTester::updateTextureBindingStats(const LLViewerTexture* imagep) { - U32 mem_size = (U32)imagep->getTextureMemory() ; - mTotalBytesUsed += mem_size ; + U32Bytes mem_size = imagep->getTextureMemory(); + mTotalBytesUsed += mem_size; - if(MIN_LARGE_IMAGE_AREA <= (U32)(mem_size / (U32)imagep->getComponents())) + if(MIN_LARGE_IMAGE_AREA <= (U32)(mem_size.value() / (U32)imagep->getComponents())) { - mTotalBytesUsedForLargeImage += mem_size ; + mTotalBytesUsedForLargeImage += mem_size; } } void LLTexturePipelineTester::updateTextureLoadingStats(const LLViewerFetchedTexture* imagep, const LLImageRaw* raw_imagep, BOOL from_cache) { - U32 data_size = (U32)raw_imagep->getDataSize() ; - mTotalBytesLoaded += data_size ; + U32Bytes data_size = (U32Bytes)raw_imagep->getDataSize(); + mTotalBytesLoaded += data_size; if(from_cache) { - mTotalBytesLoadedFromCache += data_size ; + mTotalBytesLoadedFromCache += data_size; } - if(MIN_LARGE_IMAGE_AREA <= (U32)(data_size / (U32)raw_imagep->getComponents())) + if(MIN_LARGE_IMAGE_AREA <= (U32)(data_size.value() / (U32)raw_imagep->getComponents())) { - mTotalBytesLoadedForLargeImage += data_size ; + mTotalBytesLoadedForLargeImage += data_size; } if(imagep->forSculpt()) { - mTotalBytesLoadedForSculpties += data_size ; + mTotalBytesLoadedForSculpties += data_size; if(mStartTimeLoadingSculpties > mEndTimeLoadingSculpties) { - mStartTimeLoadingSculpties = LLImageGL::sLastFrameTime ; + mStartTimeLoadingSculpties = LLImageGL::sLastFrameTime; } - mEndTimeLoadingSculpties = LLImageGL::sLastFrameTime ; + mEndTimeLoadingSculpties = LLImageGL::sLastFrameTime; } } diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index 94eeaf19e..1c2e8f9a0 100644 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -41,8 +41,9 @@ #include #include -#define MIN_VIDEO_RAM_IN_MEGA_BYTES 32 -#define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons. +extern const S32Megabytes gMinVideoRam; +extern const S32Megabytes gMaxVideoRam; + class LLImageGL ; class LLImageRaw; @@ -131,9 +132,10 @@ public: /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; /*virtual*/ void forceImmediateUpdate() ; + /*virtual*/ bool isActiveFetching(); /*virtual*/ const LLUUID& getID() const { return mID; } - //void setBoostLevel(S32 level); + void setBoostLevel(S32 level); S32 getBoostLevel() { return mBoostLevel; } void addTextureStats(F32 virtual_size, BOOL needs_gltexture = TRUE) const; @@ -146,6 +148,8 @@ public: LLFrameTimer* getLastReferencedTimer() {return &mLastReferencedTimer ;} + S32 getFullWidth() const { return mFullWidth; } + S32 getFullHeight() const { return mFullHeight; } /*virtual*/ void setKnownDrawSize(S32 width, S32 height); virtual void addFace(U32 channel, LLFace* facep) ; @@ -173,6 +177,10 @@ protected: void init(bool firstinit) ; void reorganizeFaceList() ; void reorganizeVolumeList() ; + + void notifyAboutMissingAsset(); + void notifyAboutCreatingTexture(); + private: friend class LLBumpImageList; friend class LLUIImageList; @@ -183,7 +191,7 @@ private: static bool isMemoryForTextureLow() ; protected: LLUUID mID; - + F32 mSelectedTime; // time texture was last selected mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? mutable S32 mMaxVirtualSizeResetCounter ; mutable S32 mMaxVirtualSizeResetInterval; @@ -210,11 +218,11 @@ public: static LLFrameTimer sEvaluationTimer; static F32 sDesiredDiscardBias; static F32 sDesiredDiscardScale; - static S32 sBoundTextureMemoryInBytes; - static S32 sTotalTextureMemoryInBytes; - static S32 sMaxBoundTextureMemInMegaBytes; - static S32 sMaxTotalTextureMemInMegaBytes; - static S32 sMaxDesiredTextureMemInBytes ; + static S32Bytes sBoundTextureMemory; + static S32Bytes sTotalTextureMemory; + static S32Megabytes sMaxBoundTextureMemory; + static S32Megabytes sMaxTotalTextureMem; + static S32Bytes sMaxDesiredTextureMem ; static S8 sCameraMovingDiscardBias; static F32 sCameraMovingBias; static S32 sMaxSculptRez ; @@ -239,6 +247,18 @@ public: }; +enum FTType +{ + FTT_UNKNOWN = -1, + FTT_DEFAULT = 0, // standard texture fetched by id. + FTT_SERVER_BAKE, // texture produced by appearance service and fetched from there. + FTT_HOST_BAKE, // old-style baked texture uploaded by viewer and fetched from avatar's host. + FTT_MAP_TILE, // tiles are fetched from map server directly. + FTT_LOCAL_FILE // fetch directly from a local file. +}; + +const std::string& fttype_to_string(const FTType& fttype); + // //textures are managed in gTextureList. //raw image data is fetched from remote or local cache @@ -252,9 +272,9 @@ class LLViewerFetchedTexture : public LLViewerTexture protected: /*virtual*/ ~LLViewerFetchedTexture(); public: - LLViewerFetchedTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); - LLViewerFetchedTexture(const LLImageRaw* raw, BOOL usemipmaps); - LLViewerFetchedTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); + LLViewerFetchedTexture(const LLImageRaw* raw, FTType f_type, BOOL usemipmaps); + LLViewerFetchedTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); public: static F32 maxDecodePriority(); @@ -279,6 +299,7 @@ public: public: /*virtual*/ S8 getType() const ; + FTType getFTType() const; /*virtual*/ void forceImmediateUpdate() ; /*virtual*/ void dump() ; @@ -324,13 +345,17 @@ public: void setMinDiscardLevel(S32 discard) { mMinDesiredDiscardLevel = llmin(mMinDesiredDiscardLevel,(S8)discard); } bool updateFetch(); + bool setDebugFetching(S32 debug_level); + bool isInDebug() {return mInDebug;} + void clearFetchedResults(); //clear all fetched results, for debug use. + // Override the computation of discard levels if we know the exact output // size of the image. Used for UI textures to not decode, even if we have // more data. /*virtual*/ void setKnownDrawSize(S32 width, S32 height); - void setIsMissingAsset(); + void setIsMissingAsset(BOOL is_missing = true); /*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; } // returns dimensions of original image for local files (before power of two scaling) @@ -373,6 +398,7 @@ public: BOOL isCachedRawImageReady() const {return mCachedRawImageReady ;} BOOL isRawImageValid()const { return mIsRawImageValid ; } void forceToSaveRawImage(S32 desired_discard = 0, F32 kept_time = 0.f) ; + void forceToRefetchTexture(S32 desired_discard = 0, F32 kept_time = 60.f); /*virtual*/ void setCachedRawImage(S32 discard_level, LLImageRaw* imageraw) ; void destroySavedRawImage() ; LLImageRaw* getSavedRawImage() ; @@ -385,6 +411,7 @@ public: void forceToDeleteRequest(); void forceRefetch(); + /*virtual*/bool isActiveFetching(); //is actively in fetching by the fetching pipeline. protected: /*virtual*/ void switchToCachedImage(); @@ -405,6 +432,8 @@ private: private: BOOL mFullyLoaded; + BOOL mInDebug; + BOOL mForceCallbackFetch; protected: std::string mLocalFileName; @@ -432,12 +461,14 @@ protected: S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have S8 mNeedsAux; // We need to decode the auxiliary channels + S8 mHasAux; // We have aux channels S8 mDecodingAux; // Are we decoding high components S8 mIsRawImageValid; S8 mHasFetcher; // We've made a fecth request S8 mIsFetching; // Fetch request is active bool mCanUseHTTP ; //This texture can be fetched through http if true. - + + FTType mFTType; // What category of image is this - map tile, server bake, etc? mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. typedef std::list callback_list_t; @@ -498,8 +529,8 @@ protected: /*virtual*/ ~LLViewerLODTexture(){} public: - LLViewerLODTexture(const LLUUID& id, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); - LLViewerLODTexture(const std::string& url, const LLUUID& id, BOOL usemipmaps = TRUE); + LLViewerLODTexture(const LLUUID& id, FTType f_type, const LLHost& host = LLHost::invalid, BOOL usemipmaps = TRUE); + LLViewerLODTexture(const std::string& url, FTType f_type, const LLUUID& id, BOOL usemipmaps = TRUE); /*virtual*/ S8 getType() const; // Process image stats to determine priority/quality requirements. @@ -615,6 +646,7 @@ public: static LLPointer getLocalTexture(const U32 width, const U32 height, const U8 components, BOOL usemipmaps, BOOL generate_gl_tex = TRUE) ; static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id, + FTType f_type = FTT_DEFAULT, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -624,6 +656,7 @@ public: ); static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename, + FTType f_type = FTT_LOCAL_FILE, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -633,6 +666,7 @@ public: ); static LLViewerFetchedTexture* getFetchedTextureFromUrl(const std::string& url, + FTType f_type, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -641,7 +675,7 @@ public: const LLUUID& force_id = LLUUID::null ); - static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, LLHost host) ; + static LLViewerFetchedTexture* getFetchedTextureFromHost(const LLUUID& image_id, FTType f_type, LLHost host) ; static void init() ; static void cleanup() ; diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index d67fc1e08..0b1b51697 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -64,15 +64,18 @@ #include "llviewerstats.h" #include "pipeline.h" #include "llappviewer.h" +#include "llxuiparser.h" #include "llagent.h" #include "llviewerdisplay.h" +#include "llviewerwindow.h" +#include "llprogressview.h" #include "llflexibleobject.h" //////////////////////////////////////////////////////////////////////////// void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL; -U32 LLViewerTextureList::sTextureBits = 0; +U32Bits LLViewerTextureList::sTextureBits(0); U32 LLViewerTextureList::sTexturePackets = 0; S32 LLViewerTextureList::sNumImages = 0; @@ -95,8 +98,8 @@ void LLViewerTextureList::init() mInitialized = TRUE ; sNumImages = 0; mUpdateStats = TRUE; - mMaxResidentTexMemInMegaBytes = 0; - mMaxTotalTextureMemInMegaBytes = 0 ; + mMaxResidentTexMemInMegaBytes = (U32Bytes)0; + mMaxTotalTextureMemInMegaBytes = (U32Bytes)0; if (gNoRender) { // Don't initialize GL stuff if we're not rendering. @@ -104,7 +107,7 @@ void LLViewerTextureList::init() } // Update how much texture RAM we're allowed to use. - updateMaxResidentTexMem(0); // 0 = use current + updateMaxResidentTexMem(S32Megabytes(0)); // 0 = use current doPreloadImages(); } @@ -119,14 +122,14 @@ void LLViewerTextureList::doPreloadImages() llassert_always(mUUIDMap.empty()) ; // Set the "missing asset" image - LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); + LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); // Set the "white" image - LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); + LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI); LLTexUnit::sWhiteTexture = LLViewerFetchedTexture::sWhiteImagep->getTexName(); LLUIImageList* image_list = LLUIImageList::getInstance(); - LLViewerFetchedTexture::sFlatNormalImagep = LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_BUMP); + LLViewerFetchedTexture::sFlatNormalImagep = LLViewerTextureManager::getFetchedTextureFromFile("flatnormal.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_BUMP); image_list->initFromFile(); // turn off clamping and bilinear filtering for uv picking images @@ -138,47 +141,47 @@ void LLViewerTextureList::doPreloadImages() //uv_test->setMipFilterNearest(TRUE, TRUE); // prefetch specific UUIDs - LLViewerTextureManager::getFetchedTexture(IMG_SHOT, TRUE); - LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF, TRUE); - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + LLViewerTextureManager::getFetchedTexture(IMG_SHOT); + LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF); + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("noentrylines.j2c"/*"world/NoEntryLines.png"*/, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryLines.png", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("noentrypasslines.j2c"/*"world/NoEntryPassLines.png"*/, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + image = LLViewerTextureManager::getFetchedTextureFromFile("world/NoEntryPassLines.png", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); + image = LLViewerTextureManager::getFetchedTexture(DEFAULT_WATER_NORMAL, FTT_DEFAULT, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, 0,0,LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903")); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, 0,0,LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb")); if (image) { image->setAddressMode(LLTexUnit::TAM_WRAP); mImagePreloads.insert(image); } - image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, + image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", FTT_LOCAL_FILE, MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE, 0,0,LLUUID("38b86f85-2575-52a9-a531-23108d8da837")); if (image) { @@ -187,7 +190,7 @@ void LLViewerTextureList::doPreloadImages() } //Hideous hack to set filtering and address modes without messing with our texture classes. { - LLPointer temp_image = image_list->getUIImage("checkerboard.tga",LLViewerFetchedTexture::BOOST_UI); + LLPointer temp_image = image_list->getUIImage("checkerboard.tga", LLViewerFetchedTexture::BOOST_UI); if(temp_image.notNull() && temp_image->getImage().notNull()) { LLViewerTexture *tex = (LLViewerTexture*)temp_image->getImage().get(); @@ -200,7 +203,7 @@ void LLViewerTextureList::doPreloadImages() static std::string get_texture_list_name() { - return std::string("texture_list_") + gSavedSettings.getString("LoginLocation") + ".xml"; + return gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "texture_list_" + gSavedSettings.getString("LoginLocation") + ".xml"); } void LLViewerTextureList::doPrefetchImages() @@ -213,13 +216,22 @@ void LLViewerTextureList::doPrefetchImages() // Pre-fetch textures from last logout LLSD imagelist; - std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name()); + std::string filename = get_texture_list_name(); llifstream file; - file.open(filename); + file.open(filename.c_str()); if (file.is_open()) { - LLSDSerialize::fromXML(imagelist, file); + if ( ! LLSDSerialize::fromXML(imagelist, file) ) + { + file.close(); + LL_WARNS() << "XML parse error reading texture list '" << filename << "'" << LL_ENDL; + LL_WARNS() << "Removing invalid texture list '" << filename << "'" << LL_ENDL; + LLFile::remove(filename); + return; + } + file.close(); } + S32 texture_count = 0; for (LLSD::array_iterator iter = imagelist.beginArray(); iter != imagelist.endArray(); ++iter) { @@ -230,13 +242,15 @@ void LLViewerTextureList::doPrefetchImages() if(LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type) { - LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, texture_type); + LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_NONE, texture_type); if (image) { + texture_count += 1; image->addTextureStats((F32)pixel_area); } } } + LL_DEBUGS() << "fetched " << texture_count << " images from " << filename << LL_ENDL; } /////////////////////////////////////////////////////////////////////////////// @@ -356,6 +370,7 @@ void LLViewerTextureList::restoreGL() /////////////////////////////////////////////////////////////////////////////// LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -372,15 +387,16 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& if (full_path.empty()) { LL_WARNS() << "Failed to find local image file: " << filename << LL_ENDL; - return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); } std::string url = "file://" + full_path; - return getImageFromUrl(url, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); + return getImageFromUrl(url, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id); } LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& url, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -397,7 +413,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& { // Never mind that this ignores image_set_id; // getImage() will handle that later. - return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI); + return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); } // generate UUID based on hash of filename @@ -435,10 +451,10 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& switch(texture_type) { case LLViewerTexture::FETCHED_TEXTURE: - imagep = new LLViewerFetchedTexture(url, new_id, usemipmaps); + imagep = new LLViewerFetchedTexture(url, f_type, new_id, usemipmaps); break ; case LLViewerTexture::LOD_TEXTURE: - imagep = new LLViewerLODTexture(url, new_id, usemipmaps); + imagep = new LLViewerLODTexture(url, f_type, new_id, usemipmaps); break ; default: LL_ERRS() << "Invalid texture type " << texture_type << LL_ENDL ; @@ -468,7 +484,8 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& } -LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, +LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -487,7 +504,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, if ((&image_id == NULL) || image_id.isNull()) { - return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLGLTexture::BOOST_UI)); + return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI)); } LLPointer imagep = findImage(image_id); @@ -506,11 +523,15 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, LL_WARNS() << "Requested texture " << image_id << " already exists with a different target host, requested: " << request_from_host << " current: " << texture->getTargetHost() << LL_ENDL; } + if (f_type != FTT_DEFAULT && imagep->getFTType() != f_type) + { + LL_WARNS() << "FTType mismatch: requested " << f_type << " image has " << imagep->getFTType() << LL_ENDL; + } } if (imagep.isNull()) { - imagep = createImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; + imagep = createImage(image_id, f_type, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ; } imagep->setGLTextureCreated(true); @@ -520,6 +541,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, //when this function is called, there is no such texture in the gTextureList with image_id. LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, + FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, S8 texture_type, @@ -531,10 +553,10 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, switch(texture_type) { case LLViewerTexture::FETCHED_TEXTURE: - imagep = new LLViewerFetchedTexture(image_id, request_from_host, usemipmaps); + imagep = new LLViewerFetchedTexture(image_id, f_type, request_from_host, usemipmaps); break ; case LLViewerTexture::LOD_TEXTURE: - imagep = new LLViewerLODTexture(image_id, request_from_host, usemipmaps); + imagep = new LLViewerLODTexture(image_id, f_type, request_from_host, usemipmaps); break ; default: LL_ERRS() << "Invalid texture type " << texture_type << LL_ENDL ; @@ -581,38 +603,62 @@ void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image) llassert_always(mInitialized) ; llassert(image); if (image->isInImageList()) - { - LL_ERRS() << "LLViewerTextureList::addImageToList - Image already in list" << LL_ENDL; + { // Flag is already set? + LL_WARNS() << "LLViewerTextureList::addImageToList - image " << image->getID() << " already in list" << LL_ENDL; } + else + { if((mImageList.insert(image)).second != true) { - LL_ERRS() << "Error happens when insert image to mImageList!" << LL_ENDL ; + LL_WARNS() << "Error happens when insert image " << image->getID() << " into mImageList!" << LL_ENDL ; } - image->setInImageList(TRUE) ; } +} void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image) { assert_main_thread(); llassert_always(mInitialized) ; llassert(image); - if (!image->isInImageList()) - { - LL_INFOS() << "RefCount: " << image->getNumRefs() << LL_ENDL ; - uuid_map_t::iterator iter = mUUIDMap.find(image->getID()); - if(iter == mUUIDMap.end() || iter->second != image) - { - LL_INFOS() << "Image is not in mUUIDMap!" << LL_ENDL ; - } - LL_ERRS() << "LLViewerTextureList::removeImageFromList - Image not in list" << LL_ENDL; - } - S32 count = mImageList.erase(image) ; - if(count != 1) + S32 count = 0; + if (image->isInImageList()) { - LL_INFOS() << image->getID() << LL_ENDL ; - LL_ERRS() << "Error happens when remove image from mImageList: " << count << LL_ENDL ; + count = mImageList.erase(image) ; + if(count != 1) + { + LL_INFOS() << "Image " << image->getID() + << " had mInImageList set but mImageList.erase() returned " << count + << LL_ENDL; + } + } + else + { // Something is wrong, image is expected in list or callers should check first + LL_INFOS() << "Calling removeImageFromList() for " << image->getID() + << " but doesn't have mInImageList set" + << " ref count is " << image->getNumRefs() + << LL_ENDL; + uuid_map_t::iterator iter = mUUIDMap.find(image->getID()); + if(iter == mUUIDMap.end()) + { + LL_INFOS() << "Image " << image->getID() << " is also not in mUUIDMap!" << LL_ENDL ; + } + else if (iter->second != image) + { + LL_INFOS() << "Image " << image->getID() << " was in mUUIDMap but with different pointer" << LL_ENDL ; + } + else + { + LL_INFOS() << "Image " << image->getID() << " was in mUUIDMap with same pointer" << LL_ENDL ; + } + count = mImageList.erase(image) ; + if(count != 0) + { // it was in the list already? + LL_WARNS() << "Image " << image->getID() + << " had mInImageList false but mImageList.erase() returned " << count + << LL_ENDL; + } } image->setInImageList(FALSE) ; @@ -630,7 +676,7 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image) LLViewerFetchedTexture *image = findImage(image_id); if (image) { - LL_WARNS() << "Image with ID " << image_id << " already in list" << LL_ENDL; + LL_INFOS() << "Image with ID " << image_id << " already in list" << LL_ENDL; } sNumImages++; @@ -706,8 +752,8 @@ void LLViewerTextureList::updateImages(F32 max_time) } LLViewerStats::getInstance()->mNumImagesStat.addValue(sNumImages); LLViewerStats::getInstance()->mNumRawImagesStat.addValue(LLImageRaw::sRawImageCount); - LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sGlobalTextureMemoryInBytes)); - LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageGL::sBoundTextureMemoryInBytes)); + LLViewerStats::getInstance()->mGLTexMemStat.addValue((F32)LLImageGL::sGlobalTextureMemory.valueInUnits()); + LLViewerStats::getInstance()->mGLBoundMemStat.addValue((F32)LLImageGL::sBoundTextureMemory.valueInUnits()); LLViewerStats::getInstance()->mRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(global_raw_memory)); LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory)); @@ -785,6 +831,13 @@ void LLViewerTextureList::updateImagesDecodePriorities() { // Update the decode priority for N images each frame { + F32 lazy_flush_timeout = 30.f; // stop decoding + F32 max_inactive_time = 20.f; // actually delete + S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference + + //reset imagep->getLastReferencedTimer() when screen is showing the progress view to avoid removing pre-fetched textures too soon. + bool reset_timer = gViewerWindow->getProgressView()->getVisible(); + static const S32 MAX_PRIO_UPDATES = gSavedSettings.getS32("TextureFetchUpdatePriorities"); // default: 32 const size_t max_update_count = llmin((S32) (MAX_PRIO_UPDATES*MAX_PRIO_UPDATES*gFrameIntervalSeconds) + 1, MAX_PRIO_UPDATES); S32 update_counter = llmin(max_update_count, mUUIDMap.size()); @@ -802,14 +855,14 @@ void LLViewerTextureList::updateImagesDecodePriorities() // // Flush formatted images using a lazy flush // - const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding - const F32 MAX_INACTIVE_TIME = 50.f; // actually delete - S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference - S32 num_refs = imagep->getNumRefs(); if (num_refs == min_refs) { - if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > LAZY_FLUSH_TIMEOUT) + if(reset_timer) + { + imagep->getLastReferencedTimer()->reset(); + } + else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout) { // Remove the unused image from the image list deleteImage(imagep); @@ -821,7 +874,7 @@ void LLViewerTextureList::updateImagesDecodePriorities() { if(imagep->hasSavedRawImage()) { - if(imagep->getElapsedLastReferencedSavedRawImageTime() > MAX_INACTIVE_TIME) + if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time) { imagep->destroySavedRawImage() ; } @@ -838,7 +891,11 @@ void LLViewerTextureList::updateImagesDecodePriorities() } else if(imagep->isInactive()) { - if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) + if(reset_timer) + { + imagep->getLastReferencedTimer()->reset(); + } + else if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time) { imagep->setDeletionCandidate() ; } @@ -960,12 +1017,10 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) static const bool SKIP_LOW_PRIO = gSavedSettings.getBOOL("TextureFetchUpdateSkipLowPriority"); // default: false size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*MAX_HIGH_PRIO_COUNT*gFrameIntervalSeconds)+1, MAX_HIGH_PRIO_COUNT); - //Old: size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*40.f*gFrameIntervalSeconds)+1, MAX_HIGH_PRIO_COUNT); max_priority_count = llmin(max_priority_count, mImageList.size()); size_t total_update_count = mUUIDMap.size(); size_t max_update_count = llmin((S32) (MAX_UPDATE_COUNT*MAX_UPDATE_COUNT*gFrameIntervalSeconds)+1, MAX_UPDATE_COUNT); - //Old: size_t max_priority_count = llmin((S32) (MAX_UPDATE_COUNT*40.f*gFrameIntervalSeconds)+1, MAX_UPDATE_COUNT); max_update_count = llmin(max_update_count, total_update_count); // MAX_HIGH_PRIO_COUNT high priority entries @@ -1218,20 +1273,16 @@ LLPointer LLViewerTextureList::convertToUploadFile(LLPointer 2000) - return 128; - else if (system_ram > 1000) - return 64; - else - return MIN_VIDEO_RAM_IN_MEGA_BYTES; + S32Megabytes system_ram = gSysMemory.getPhysicalMemoryClamped(); + //min texture mem sets to 64M if total physical mem is more than 1.5GB + return (system_ram > S32Megabytes(1500)) ? S32Megabytes(64) : gMinVideoRam ; } //static // Returns max setting for TextureMemory (in MB) -S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended) +S32Megabytes LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended, float mem_multiplier) { #if LL_LINUX if (gGLManager.mIsIntel && gGLManager.mGLVersion >= 3.f && !gGLManager.mVRAM) @@ -1239,12 +1290,12 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended) gGLManager.mVRAM = 512; } #endif - S32 max_texmem; + S32Megabytes max_texmem; if (gGLManager.mVRAM != 0) { // Treat any card with < 32 MB (shudder) as having 32 MB // - it's going to be swapping constantly regardless - S32 max_vram = gGLManager.mVRAM; + S32Megabytes max_vram(gGLManager.mVRAM); max_vram = llmax(max_vram, getMinVideoRamSetting()); max_texmem = max_vram; if (!get_recommended) @@ -1252,72 +1303,81 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended) } else { - if (get_recommended) - max_texmem = 128; + if (!get_recommended) + { + max_texmem = (S32Megabytes)512; + } + else if (gSavedSettings.getBOOL("NoHardwareProbe")) //did not do hardware detection at startup + { + max_texmem = (S32Megabytes)512; + } else - max_texmem = 512; + { + max_texmem = (S32Megabytes)128; + } + LL_WARNS() << "VRAM amount not detected, defaulting to " << max_texmem << " MB" << LL_ENDL; } - S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB + S32Megabytes system_ram = gSysMemory.getPhysicalMemoryClamped(); // In MB //LL_INFOS() << "*** DETECTED " << system_ram << " MB of system memory." << LL_ENDL; if (get_recommended) - max_texmem = llmin(max_texmem, (S32)(system_ram/2)); + max_texmem = llmin(max_texmem, system_ram/2); else - max_texmem = llmin(max_texmem, (S32)(system_ram)); + max_texmem = llmin(max_texmem, system_ram); - max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES); + // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise + max_texmem = llmin(max_texmem, (S32Megabytes) (mem_multiplier * max_texmem)); + + max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), gMaxVideoRam); return max_texmem; } -const S32 VIDEO_CARD_FRAMEBUFFER_MEM = 12; // MB -const S32 MIN_MEM_FOR_NON_TEXTURE = 512 ; //MB -void LLViewerTextureList::updateMaxResidentTexMem(S32 mem) +const S32Megabytes VIDEO_CARD_FRAMEBUFFER_MEM(12); +const S32Megabytes MIN_MEM_FOR_NON_TEXTURE(512); +void LLViewerTextureList::updateMaxResidentTexMem(S32Megabytes mem) { // Initialize the image pipeline VRAM settings - S32 cur_mem = gSavedSettings.getS32("TextureMemory"); + S32Megabytes cur_mem(gSavedSettings.getS32("TextureMemory")); F32 mem_multiplier = gSavedSettings.getF32("RenderTextureMemoryMultiple"); - S32 default_mem = getMaxVideoRamSetting(true); // recommended default - if (mem == 0) + S32Megabytes default_mem = getMaxVideoRamSetting(true, mem_multiplier); // recommended default + if (mem == (S32Bytes)0) { - mem = cur_mem > 0 ? cur_mem : default_mem; + mem = cur_mem > (S32Bytes)0 ? cur_mem : default_mem; } - else if (mem < 0) + else if (mem < (S32Bytes)0) { mem = default_mem; } - // limit the texture memory to a multiple of the default if we've found some cards to behave poorly otherwise - mem = llmin(mem, (S32) (mem_multiplier * (F32) default_mem)); - - mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting()); + mem = llclamp(mem, getMinVideoRamSetting(), getMaxVideoRamSetting(false, mem_multiplier)); if (mem != cur_mem) { - gSavedSettings.setS32("TextureMemory", mem); + gSavedSettings.setS32("TextureMemory", mem.value()); return; //listener will re-enter this function } // TODO: set available resident texture mem based on use by other subsystems // currently max(12MB, VRAM/4) assumed... - S32 vb_mem = mem; - S32 fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4); + S32Megabytes vb_mem = mem; + S32Megabytes fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vb_mem/4); mMaxResidentTexMemInMegaBytes = (vb_mem - fb_mem) ; //in MB mMaxTotalTextureMemInMegaBytes = mMaxResidentTexMemInMegaBytes * 2; - if (mMaxResidentTexMemInMegaBytes > 640) + if (mMaxResidentTexMemInMegaBytes > (S32Megabytes)640) { - mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes >> 2); + mMaxTotalTextureMemInMegaBytes -= (mMaxResidentTexMemInMegaBytes / 4); } //system mem - S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); // In MB + S32Megabytes system_ram = gSysMemory.getPhysicalMemoryClamped(); //minimum memory reserved for non-texture use. //if system_raw >= 1GB, reserve at least 512MB for non-texture use; //otherwise reserve half of the system_ram for non-texture use. - S32 min_non_texture_mem = llmin(system_ram / 2, MIN_MEM_FOR_NON_TEXTURE) ; + S32Megabytes min_non_texture_mem = llmin(system_ram / 2, MIN_MEM_FOR_NON_TEXTURE) ; if (mMaxTotalTextureMemInMegaBytes > system_ram - min_non_texture_mem) { @@ -1345,17 +1405,17 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d char ip_string[256]; u32_to_ip_string(msg->getSenderIP(),ip_string); - U32 received_size ; + U32Bytes received_size ; if (msg->getReceiveCompressedSize()) { - received_size = msg->getReceiveCompressedSize() ; + received_size = (U32Bytes)msg->getReceiveCompressedSize() ; } else { - received_size = msg->getReceiveSize() ; + received_size = (U32Bytes)msg->getReceiveSize() ; } // Only used for statistics and texture console. - gTextureList.sTextureBits += received_size * 8; + gTextureList.sTextureBits += received_size; gTextureList.sTexturePackets++; U8 codec; @@ -1384,7 +1444,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d U8 *data = new U8[data_size]; msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (!image) { delete [] data; @@ -1419,16 +1479,16 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d char ip_string[256]; u32_to_ip_string(msg->getSenderIP(),ip_string); - U32 received_size ; + U32Bytes received_size ; if (msg->getReceiveCompressedSize()) { - received_size = msg->getReceiveCompressedSize() ; + received_size = (U32Bytes)msg->getReceiveCompressedSize() ; } else { - received_size = msg->getReceiveSize() ; + received_size = (U32Bytes)msg->getReceiveSize() ; } - gTextureList.sTextureBits += received_size * 8; + gTextureList.sTextureBits += received_size; gTextureList.sTexturePackets++; //llprintline("Start decode, image header..."); @@ -1456,7 +1516,7 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d U8 *data = new U8[data_size]; msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); if (!image) { delete [] data; @@ -1494,24 +1554,6 @@ void LLViewerTextureList::processImageNotInDatabase(LLMessageSystem *msg,void ** /////////////////////////////////////////////////////////////////////////////// -//static -const U32 SIXTEEN_MEG = 0x1000000; -S32 LLViewerTextureList::calcMaxTextureRAM() -{ - // Decide the maximum amount of RAM we should allow the user to allocate to texture cache - LLMemoryInfo memory_info; - U32 available_memory = memory_info.getPhysicalMemoryClamped(); - - clamp_rescale((F32)available_memory, - (F32)(SIXTEEN_MEG * 16), - (F32)U32_MAX, - (F32)(SIXTEEN_MEG * 4), - (F32)(U32_MAX >> 1)); - return available_memory; -} - -/////////////////////////////////////////////////////////////////////////////// - // explicitly cleanup resources, as this is a singleton class with process // lifetime so ability to perform std::map operations in destructor is not // guaranteed. @@ -1555,28 +1597,31 @@ LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name, S32 priori } LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename, - BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority ) + BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority, + LLUIImage::EScaleStyle scale_style) { if (boost_priority == LLGLTexture::BOOST_NONE) { boost_priority = LLGLTexture::BOOST_UI; } - LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, boost_priority); - return loadUIImage(imagep, name, use_mips, scale_rect, clip_rect); + LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, FTT_LOCAL_FILE, MIPMAP_NO, boost_priority); + return loadUIImage(imagep, name, use_mips, scale_rect, clip_rect, scale_style); } LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id, - BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority) + BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLViewerTexture::EBoostLevel boost_priority, + LLUIImage::EScaleStyle scale_style) { if (boost_priority == LLGLTexture::BOOST_NONE) { boost_priority = LLGLTexture::BOOST_UI; } - LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, boost_priority); - return loadUIImage(imagep, id.asString(), use_mips, scale_rect, clip_rect); + LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, MIPMAP_NO, boost_priority); + return loadUIImage(imagep, id.asString(), use_mips, scale_rect, clip_rect, scale_style); } -LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect) +LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, + LLUIImage::EScaleStyle scale_style) { if (!imagep) return NULL; @@ -1589,6 +1634,7 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st imagep->setNoDelete(); LLUIImagePtr new_imagep = new LLUIImage(name, imagep); + new_imagep->setScaleStyle(scale_style); mUIImages.insert(std::make_pair(name, new_imagep)); mUITextureList.push_back(imagep); @@ -1607,7 +1653,7 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st return new_imagep; } -LLUIImagePtr LLUIImageList::preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect) +LLUIImagePtr LLUIImageList::preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLUIImage::EScaleStyle scale_style) { // look for existing image uuid_ui_image_map_t::iterator found_it = mUIImages.find(name); @@ -1617,7 +1663,7 @@ LLUIImagePtr LLUIImageList::preloadUIImage(const std::string& name, const std::s LL_ERRS() << "UI Image " << name << " already loaded." << LL_ENDL; } - return loadUIImageByName(name, filename, use_mips, scale_rect, clip_rect); + return loadUIImageByName(name, filename, use_mips, scale_rect, clip_rect, LLGLTexture::BOOST_UI, scale_style); } //static @@ -1677,20 +1723,37 @@ void LLUIImageList::onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_v } } -/*struct UIImageDeclaration : public LLInitParam::Block +namespace LLInitParam { - Mandatory name; - Optional file_name; - Optional preload; - Optional scale; - Optional use_mips; + template<> + struct TypeValues : public TypeValuesHelper + { + static void declareValues() + { + declare("scale_inner", LLUIImage::SCALE_INNER); + declare("scale_outer", LLUIImage::SCALE_OUTER); + } + }; +} + +struct UIImageDeclaration : public LLInitParam::Block +{ + Mandatory name; + Optional file_name; + Optional preload; + Optional scale; + Optional clip; + Optional use_mips; + Optional scale_type; UIImageDeclaration() : name("name"), file_name("file_name"), preload("preload", false), scale("scale"), - use_mips("use_mips", false) + clip("clip"), + use_mips("use_mips", false), + scale_type("scale_type", LLUIImage::SCALE_INNER) {} }; @@ -1707,49 +1770,43 @@ struct UIImageDeclarations : public LLInitParam::Block bool LLUIImageList::initFromFile() { - // construct path to canonical textures.xml in default skin dir - std::string base_file_path = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "default", "textures", "textures.xml"); - - LLXMLNodePtr root; - - if (!LLXMLNode::parseFile(base_file_path, root, NULL)) + // Look for textures.xml in all the right places. Pass + // constraint=LLDir::ALL_SKINS because we want to overlay textures.xml + // from all the skins directories. + std::vector textures_paths = + gDirUtilp->findSkinnedFilenames(LLDir::TEXTURES, "textures.xml", LLDir::ALL_SKINS); + std::vector::const_iterator pi(textures_paths.begin()), pend(textures_paths.end()); + if (pi == pend) { - LL_WARNS() << "Unable to parse UI image list file " << base_file_path << LL_ENDL; + LL_WARNS() << "No textures.xml found in skins directories" << LL_ENDL; + return false; + } + + // The first (most generic) file gets special validations + LLXMLNodePtr root; + if (!LLXMLNode::parseFile(*pi, root, NULL)) + { + LL_WARNS() << "Unable to parse UI image list file " << *pi << LL_ENDL; return false; } if (!root->hasAttribute("version")) { - LL_WARNS() << "No valid version number in UI image list file " << base_file_path << LL_ENDL; + LL_WARNS() << "No valid version number in UI image list file " << *pi << LL_ENDL; return false; } UIImageDeclarations images; LLXUIParser parser; - parser.readXUI(root, images, base_file_path); + parser.readXUI(root, images, *pi); - // add components defined in current skin - std::string skin_update_path = gDirUtilp->getSkinDir() - + gDirUtilp->getDirDelimiter() - + "textures" - + gDirUtilp->getDirDelimiter() - + "textures.xml"; - LLXMLNodePtr update_root; - if (skin_update_path != base_file_path - && LLXMLNode::parseFile(skin_update_path, update_root, NULL)) + // add components defined in the rest of the skin paths + while (++pi != pend) { - parser.readXUI(update_root, images, skin_update_path); - } - - // add components defined in user override of current skin - skin_update_path = gDirUtilp->getUserSkinDir() - + gDirUtilp->getDirDelimiter() - + "textures" - + gDirUtilp->getDirDelimiter() - + "textures.xml"; - if (skin_update_path != base_file_path - && LLXMLNode::parseFile(skin_update_path, update_root, NULL)) - { - parser.readXUI(update_root, images, skin_update_path); + LLXMLNodePtr update_root; + if (LLXMLNode::parseFile(*pi, update_root, NULL)) + { + parser.readXUI(update_root, images, *pi); + } } if (!images.validateBlock()) return false; @@ -1784,7 +1841,7 @@ bool LLUIImageList::initFromFile() { continue; } - preloadUIImage(image.name, file_name, image.use_mips, image.scale); + preloadUIImage(image.name, file_name, image.use_mips, image.scale, image.clip, image.scale_type); } if (cur_pass == PASS_DECODE_NOW && !gSavedSettings.getBOOL("NoPreload")) @@ -1793,115 +1850,6 @@ bool LLUIImageList::initFromFile() } } return true; -}*/ -bool LLUIImageList::initFromFile() -{ - // construct path to canonical textures.xml in default skin dir - std::string base_file_path = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "default", "textures", "textures.xml"); - - LLXMLNodePtr root; - - if (!LLXMLNode::parseFile(base_file_path, root, NULL)) - { - LL_WARNS() << "Unable to parse UI image list file " << base_file_path << LL_ENDL; - return false; - } - - if (!root->hasAttribute("version")) - { - LL_WARNS() << "No valid version number in UI image list file " << base_file_path << LL_ENDL; - return false; - } - - std::vector paths; - // path to current selected skin - paths.push_back(gDirUtilp->getSkinDir() - + gDirUtilp->getDirDelimiter() - + "textures" - + gDirUtilp->getDirDelimiter() - + "textures.xml"); - // path to user overrides on current skin - paths.push_back(gDirUtilp->getUserSkinDir() - + gDirUtilp->getDirDelimiter() - + "textures" - + gDirUtilp->getDirDelimiter() - + "textures.xml"); - - // apply skinned xml files incrementally - for(std::vector::iterator path_it = paths.begin(); - path_it != paths.end(); - ++path_it) - { - // don't reapply base file to itself - if (!path_it->empty() && (*path_it) != base_file_path) - { - LLXMLNodePtr update_root; - if (LLXMLNode::parseFile(*path_it, update_root, NULL)) - { - LLXMLNode::updateNode(root, update_root); - } - } - } - - enum - { - PASS_DECODE_NOW, - PASS_DECODE_LATER, - NUM_PASSES - }; - - for (S32 pass = PASS_DECODE_NOW; pass < NUM_PASSES; pass++) - { - LLXMLNodePtr child_nodep = root->getFirstChild(); - while(child_nodep.notNull()) - { - std::string image_name; - child_nodep->getAttributeString("name", image_name); - - std::string file_name = image_name; - LLRect scale_rect; - BOOL use_mip_maps = FALSE; - - BOOL preload = FALSE; - child_nodep->getAttributeBOOL("preload", preload); - - // load high priority textures on first pass (to kick off decode) - if (preload) - { - if (pass == PASS_DECODE_LATER) - { - child_nodep = child_nodep->getNextSibling(); - continue; - } - } - else - { - if (pass == PASS_DECODE_NOW) - { - child_nodep = child_nodep->getNextSibling(); - continue; - } - } - - child_nodep->getAttributeString("file_name", file_name); - child_nodep->getAttributeBOOL("use_mips", use_mip_maps); - - child_nodep->getAttributeS32("scale_left", scale_rect.mLeft); - child_nodep->getAttributeS32("scale_right", scale_rect.mRight); - child_nodep->getAttributeS32("scale_bottom", scale_rect.mBottom); - child_nodep->getAttributeS32("scale_top", scale_rect.mTop); - - preloadUIImage(image_name, file_name, use_mip_maps, scale_rect, LLRectBase::null); - - child_nodep = child_nodep->getNextSibling(); - } - - if (pass == PASS_DECODE_NOW && !gSavedSettings.getBOOL("NoPreload")) - { - gTextureList.decodeAllImages(10.f); // decode preloaded images - } - } - return true; } diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 57d6bc91d..b24fd8702 100644 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -71,7 +71,6 @@ public: static BOOL verifyUploadFile(const std::string& out_filename, const U8 codec); static LLPointer convertToUploadFile(LLPointer raw_image); static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data ); - static S32 calcMaxTextureRAM(); static void receiveImageHeader(LLMessageSystem *msg, void **user_data); static void receiveImagePacket(LLMessageSystem *msg, void **user_data); @@ -101,19 +100,19 @@ public: void setUpdateStats(BOOL b) { mUpdateStats = b; } - S32 getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; } - S32 getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;} + S32Megabytes getMaxResidentTexMem() const { return mMaxResidentTexMemInMegaBytes; } + S32Megabytes getMaxTotalTextureMem() const { return mMaxTotalTextureMemInMegaBytes;} S32 getNumImages() { return mImageList.size(); } - void updateMaxResidentTexMem(S32 mem); + void updateMaxResidentTexMem(S32Megabytes mem); void doPreloadImages(); void doPrefetchImages(); void clearFetchingRequests(); - static S32 getMinVideoRamSetting(); - static S32 getMaxVideoRamSetting(bool get_recommended = false); + static S32Megabytes getMinVideoRamSetting(); + static S32Megabytes getMaxVideoRamSetting(bool get_recommended, float mem_multiplier); private: void updateImagesDecodePriorities(); @@ -130,6 +129,7 @@ private: void removeImageFromList(LLViewerFetchedTexture *image); LLViewerFetchedTexture * getImage(const LLUUID &image_id, + FTType f_type = FTT_DEFAULT, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -139,6 +139,7 @@ private: ); LLViewerFetchedTexture * getImageFromFile(const std::string& filename, + FTType f_type = FTT_LOCAL_FILE, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -148,6 +149,7 @@ private: ); LLViewerFetchedTexture* getImageFromUrl(const std::string& url, + FTType f_type, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -157,6 +159,7 @@ private: ); LLViewerFetchedTexture* createImage(const LLUUID &image_id, + FTType f_type, BOOL usemipmap = TRUE, LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_NONE, // Get the requested level immediately upon creation. S8 texture_type = LLViewerTexture::FETCHED_TEXTURE, @@ -167,8 +170,8 @@ private: // Request image from a specific host, used for baked avatar textures. // Implemented in header in case someone changes default params above. JC - LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, LLHost host) - { return getImage(image_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } + LLViewerFetchedTexture* getImageFromHost(const LLUUID& image_id, FTType f_type, LLHost host) + { return getImage(image_id, f_type, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } public: typedef std::set > image_list_t; @@ -195,12 +198,12 @@ private: BOOL mInitialized ; BOOL mUpdateStats; - S32 mMaxResidentTexMemInMegaBytes; - S32 mMaxTotalTextureMemInMegaBytes; + S32Megabytes mMaxResidentTexMemInMegaBytes; + S32Megabytes mMaxTotalTextureMemInMegaBytes; LLFrameTimer mForceDecodeTimer; public: - static U32 sTextureBits; + static U32Bits sTextureBits; static U32 sTexturePackets; private: @@ -218,20 +221,22 @@ public: bool initFromFile(); - LLPointer preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect); + LLPointer preloadUIImage(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect, const LLRect& clip_rect, LLUIImage::EScaleStyle stype); static void onUIImageLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); private: LLPointer loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null, - LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI); + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI, + LLUIImage::EScaleStyle = LLUIImage::SCALE_INNER); LLPointer loadUIImageByID(const LLUUID& id, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null, - LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI); + LLViewerTexture::EBoostLevel boost_priority = LLGLTexture::BOOST_UI, + LLUIImage::EScaleStyle = LLUIImage::SCALE_INNER); - LLPointer loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null); + LLPointer loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, const LLRect& clip_rect = LLRect::null, LLUIImage::EScaleStyle = LLUIImage::SCALE_INNER); struct LLUIImageLoadData diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index 71bf61541..6b9c37586 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -368,7 +368,7 @@ void LLViewerWearable::writeToAvatar(LLAvatarAppearance *avatarp) { image_id = getDefaultTextureImageID((ETextureIndex) te); } - LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); + LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE ); // MULTI-WEARABLE: assume index 0 will be used when writing to avatar. TODO: eliminate the need for this. viewer_avatar->setLocalTextureTE(te, image, 0); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index 1b753104e..1c985eaa0 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -1777,8 +1777,7 @@ LLViewerWindow::LLViewerWindow( LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), mDisplayScale.mV[VX], mDisplayScale.mV[VY], - gDirUtilp->getAppRODataDir(), - LLUICtrlFactory::getXUIPaths()); + gDirUtilp->getAppRODataDir()); } // Create container for all sub-views LLView::Params rvp; @@ -5356,7 +5355,7 @@ void LLViewerWindow::stopGL(BOOL save_state) gGL.resetVertexBuffers(); - LL_INFOS() << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << LL_ENDL; + LL_INFOS() << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemory << " bytes" << LL_ENDL; } } @@ -5425,8 +5424,7 @@ void LLViewerWindow::initFonts(F32 zoom_factor) LLFontGL::initClass( gSavedSettings.getF32("FontScreenDPI"), mDisplayScale.mV[VX] * zoom_factor, mDisplayScale.mV[VY] * zoom_factor, - gDirUtilp->getAppRODataDir(), - LLUICtrlFactory::getXUIPaths()); + gDirUtilp->getAppRODataDir()); LLFontGL::loadDefaultFonts(); } void LLViewerWindow::toggleFullscreen(BOOL show_progress) diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 1631fd117..9f44df5b4 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -139,6 +139,8 @@ size_t strnlen(const char *s, size_t n) } #endif +extern U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG; + const F32 MAX_HOVER_Z = 2.0; const F32 MIN_HOVER_Z = -2.0; @@ -290,6 +292,9 @@ const F32 HEAD_MOVEMENT_AVG_TIME = 0.9f; const S32 MORPH_MASK_REQUESTED_DISCARD = 0; +const F32 MAX_STANDOFF_FROM_ORIGIN = 3; +const F32 MAX_STANDOFF_DISTANCE_CHANGE = 32; + // Discard level at which to switch to baked textures // Should probably be 4 or 3, but didn't want to change it while change other logic - SJB const S32 SWITCH_TO_BAKED_DISCARD = 5; @@ -1095,7 +1100,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mVisualComplexityStale(TRUE), mSupportsAlphaLayers(FALSE), mLoadedCallbacksPaused(FALSE), - mHasPelvisOffset( FALSE ), mLastRezzedStatus(-1), mIsEditingAppearance(FALSE), mUseLocalAppearance(FALSE), @@ -1169,10 +1173,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mRuthDebugTimer.reset(); mDebugExistenceTimer.reset(); mLastAppearanceMessageTimer.reset(); - mPelvisOffset = LLVector3(0.0f,0.0f,0.0f); - mLastPelvisToFoot = 0.0f; - mPelvisFixup = 0.0f; - mLastPelvisFixup = 0.0f; } std::string LLVOAvatar::avString() const @@ -1530,7 +1530,6 @@ void LLVOAvatar::deleteCachedImages(bool clearAll) } LLViewerTexLayerSet::sHasCaches = FALSE; } - LLVOAvatarSelf::deleteScratchTextures(); LLTexLayerStaticImageList::getInstance()->deleteCachedImages(); } @@ -1667,11 +1666,12 @@ const LLVector3 LLVOAvatar::getRenderPosition() const } else if (isRoot() || !mDrawable->getParent()) { - if ( mHasPelvisOffset ) + F32 fixup; + if ( hasPelvisFixup( fixup) ) { //Apply a pelvis fixup (as defined by the avs skin) LLVector3 pos = mDrawable->getPositionAgent(); - pos[VZ] += mPelvisFixup; + pos[VZ] += fixup; return pos; } else @@ -2423,18 +2423,23 @@ LLViewerFetchedTexture *LLVOAvatar::getBakedTextureImage(const U8 te, const LLUU if (!result) { const std::string url = getImageURL(te,uuid); + if (!url.empty()) { - LL_DEBUGS("Avatar") << avString() << "from URL " << url << LL_ENDL; + LL_DEBUGS("Avatar") << avString() << "get server-bake image from URL " << url << LL_ENDL; result = LLViewerTextureManager::getFetchedTextureFromUrl( - url, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); + url, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, uuid); + if (result->isMissingAsset()) + { + result->setIsMissingAsset(false); + } } else { LL_DEBUGS("Avatar") << avString() << "from host " << uuid << LL_ENDL; LLHost host = getObjectHost(); result = LLViewerTextureManager::getFetchedTexture( - uuid, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); + uuid, FTT_SERVER_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); } } return result; @@ -2572,7 +2577,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // animate the character // store off last frame's root position to be consistent with camera position - LLVector3 root_pos_last = mRoot->getWorldPosition(); + mLastRootPos = mRoot->getWorldPosition(); bool detailed_update; { LLFastTimer t(FTM_CHARACTER_UPDATE); @@ -2601,7 +2606,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) idleUpdateWindEffect(); } - idleUpdateNameTag(root_pos_last); + idleUpdateNameTag( mLastRootPos ); idleUpdateRenderCost(); } } @@ -3848,18 +3853,8 @@ void LLVOAvatar::resetFreezeTime() } -//------------------------------------------------------------------------ -// updateCharacter() -// called on both your avatar and other avatars -//------------------------------------------------------------------------ -BOOL LLVOAvatar::updateCharacter(LLAgent &agent) +void LLVOAvatar::updateDebugText() { - // Frozen! - if (areAnimationsPaused()) - { - updateMotions(LLCharacter::NORMAL_UPDATE); // This is necessary to get unpaused again. - return FALSE; - } if (gSavedSettings.getBOOL("DebugAvatarAppearanceMessage")) { @@ -3950,6 +3945,34 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) } } + if (!mDebugText.size() && mText.notNull()) + { + mText->markDead(); + mText = NULL; + } + else if (mDebugText.size()) + { + setDebugText(mDebugText); + } + mDebugText.clear(); + +} + +//------------------------------------------------------------------------ +// updateCharacter() +// called on both your avatar and other avatars +//------------------------------------------------------------------------ +BOOL LLVOAvatar::updateCharacter(LLAgent &agent) +{ + // Frozen! + if (areAnimationsPaused()) + { + updateMotions(LLCharacter::NORMAL_UPDATE); // This is necessary to get unpaused again. + return FALSE; + } + + updateDebugText(); + if (gNoRender) { // Hack if we're running drones... @@ -3960,9 +3983,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) return FALSE; } - - LLVector3d root_pos_global; - if (!mIsBuilt) { return FALSE; @@ -4447,17 +4467,6 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) mRoot->updateWorldMatrixChildren(); - if (!mDebugText.size() && mText.notNull()) - { - mText->markDead(); - mText = NULL; - } - else if (mDebugText.size()) - { - setDebugText(mDebugText); - } - mDebugText.clear(); - //mesh vertices need to be reskinned mNeedsSkin = TRUE; @@ -4488,39 +4497,13 @@ void LLVOAvatar::updateHeadOffset() } } //------------------------------------------------------------------------ -// setPelvisOffset -//------------------------------------------------------------------------ -void LLVOAvatar::setPelvisOffset( bool hasOffset, const LLVector3& offsetAmount, F32 pelvisFixup ) -{ - mHasPelvisOffset = hasOffset; - if ( mHasPelvisOffset ) - { - //Store off last pelvis to foot value - mLastPelvisToFoot = mPelvisToFoot; - mPelvisOffset = offsetAmount; - mLastPelvisFixup = mPelvisFixup; - mPelvisFixup = pelvisFixup; - } -} -//------------------------------------------------------------------------ // postPelvisSetRecalc //------------------------------------------------------------------------ void LLVOAvatar::postPelvisSetRecalc( void ) -{ - computeBodySize(); - mRoot->touch(); - mRoot->updateWorldMatrixChildren(); - dirtyMesh(); - updateHeadOffset(); -} -//------------------------------------------------------------------------ -// pelisPoke -//------------------------------------------------------------------------ -void LLVOAvatar::setPelvisOffset( F32 pelvisFixupAmount ) -{ - mHasPelvisOffset = true; - mLastPelvisFixup = mPelvisFixup; - mPelvisFixup = pelvisFixupAmount; +{ + mRoot->updateWorldMatrixChildren(); + computeBodySize(); + dirtyMesh(2); } //------------------------------------------------------------------------ // updateVisibility() @@ -5172,9 +5155,9 @@ std::string LLVOAvatar::bakedTextureOriginInfo() return result; } -S32 LLVOAvatar::totalTextureMemForUUIDS(std::set& ids) +S32Bytes LLVOAvatar::totalTextureMemForUUIDS(std::set& ids) { - S32 result = 0; + S32Bytes result(0); for (std::set::const_iterator it = ids.begin(); it != ids.end(); ++it) { LLViewerFetchedTexture *imagep = gTextureList.findImage(*it); @@ -5239,12 +5222,12 @@ void LLVOAvatar::collectTextureUUIDs(std::set& ids) void LLVOAvatar::releaseOldTextures() { - S32 current_texture_mem = 0; + S32Bytes current_texture_mem; // Any textures that we used to be using but are no longer using should no longer be flagged as "NO_DELETE" std::set baked_texture_ids; collectBakedTextureUUIDs(baked_texture_ids); - S32 new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids); + S32Bytes new_baked_mem = totalTextureMemForUUIDS(baked_texture_ids); std::set local_texture_ids; collectLocalTextureUUIDs(local_texture_ids); @@ -5253,7 +5236,7 @@ void LLVOAvatar::releaseOldTextures() std::set new_texture_ids; new_texture_ids.insert(baked_texture_ids.begin(),baked_texture_ids.end()); new_texture_ids.insert(local_texture_ids.begin(),local_texture_ids.end()); - S32 new_total_mem = totalTextureMemForUUIDS(new_texture_ids); + S32Bytes new_total_mem = totalTextureMemForUUIDS(new_texture_ids); //S32 old_total_mem = totalTextureMemForUUIDS(mTextureIDs); //LL_DEBUGS("Avatar") << getFullname() << " old_total_mem: " << old_total_mem << " new_total_mem (L/B): " << new_total_mem << " (" << new_local_mem <<", " << new_baked_mem << ")" << LL_ENDL; @@ -5776,6 +5759,12 @@ BOOL LLVOAvatar::processSingleAnimationStateChange( const LLUUID& anim_id, BOOL { sitDown(FALSE); } + if ((anim_id == ANIM_AGENT_BUSY) && gAgent.isDoNotDisturb()) + { + // re-assert DND tag animation + gAgent.sendAnimationRequest(ANIM_AGENT_BUSY, ANIM_REQUEST_START); + return result; + } stopMotion(anim_id); result = TRUE; } @@ -5988,11 +5977,163 @@ LLJoint *LLVOAvatar::getJoint( const std::string &name ) return jointp; } + //----------------------------------------------------------------------------- -// resetJointPositionsToDefault +// getRiggedMeshID +// +// If viewer object is a rigged mesh, set the mesh id and return true. +// Otherwise, null out the id and return false. //----------------------------------------------------------------------------- -void LLVOAvatar::resetJointPositionsToDefault( void ) +// static +bool LLVOAvatar::getRiggedMeshID(LLViewerObject* pVO, LLUUID& mesh_id) { + mesh_id.setNull(); + + //If a VO has a skin that we'll reset the joint positions to their default + if ( pVO && pVO->mDrawable ) + { + LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); + if ( pVObj ) + { + const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); + if (pSkinData + && pSkinData->mJointNames.size() > JOINT_COUNT_REQUIRED_FOR_FULLRIG // full rig + && pSkinData->mAlternateBindMatrix.size() > 0 ) + { + mesh_id = pSkinData->mMeshID; + return true; + } + } + } + return false; +} + +void LLVOAvatar::clearAttachmentPosOverrides() +{ + //Subsequent joints are relative to pelvis + avatar_joint_list_t::iterator iter = mSkeleton.begin(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + + for (; iter != end; ++iter) + { + LLJoint* pJoint = (*iter); + pJoint->clearAttachmentPosOverrides(); + } +} + +//----------------------------------------------------------------------------- +// addAttachmentPosOverridesForObject +//----------------------------------------------------------------------------- +void LLVOAvatar::addAttachmentPosOverridesForObject(LLViewerObject *vo) +{ + LLVOAvatar *av = vo->getAvatarAncestor(); + if (!av || (av != this)) + { + LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; + } + + // Process all children + LLViewerObject::const_child_list_t& children = vo->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); + it != children.end(); ++it) + { + LLViewerObject *childp = *it; + addAttachmentPosOverridesForObject(childp); + } + + LLVOVolume *vobj = dynamic_cast(vo); + bool pelvisGotSet = false; + + if (!vobj) + { + return; + } + if (vobj->isMesh() && + ((vobj->getVolume() && !vobj->getVolume()->isMeshAssetLoaded()) || !gMeshRepo.meshRezEnabled())) + { + return; + } + LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); + const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); + + if ( vobj && vobj->isAttachment() && vobj->isMesh() && pSkinData ) + { + const int bindCnt = pSkinData->mAlternateBindMatrix.size(); + if ( bindCnt > 0 ) + { + const U32 jointCnt = pSkinData->mJointNames.size(); + const F32 pelvisZOffset = pSkinData->mPelvisOffset; + const LLUUID& mesh_id = pSkinData->mMeshID; + bool fullRig = (jointCnt>=JOINT_COUNT_REQUIRED_FOR_FULLRIG) ? true : false; + if ( fullRig ) + { + for ( U32 i=0; imJointNames[i].c_str(); + LLJoint* pJoint = getJoint( lookingForJoint ); + if ( pJoint && pJoint->getId() != currentId ) + { + pJoint->setId( currentId ); + const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); + //Set the joint position + pJoint->addAttachmentPosOverride( jointPos, mesh_id, avString() ); + + //If joint is a pelvis then handle old/new pelvis to foot values + if ( lookingForJoint == "mPelvis" ) + { + pelvisGotSet = true; + } + } + } + if (pelvisZOffset != 0.0F) + { + addPelvisFixup( pelvisZOffset, mesh_id ); + pelvisGotSet = true; + } + } + } + } + + //Rebuild body data if we altered joints/pelvis + if ( pelvisGotSet ) + { + postPelvisSetRecalc(); + } +} + +//----------------------------------------------------------------------------- +// resetJointPositionsOnDetach +//----------------------------------------------------------------------------- +void LLVOAvatar::resetJointPositionsOnDetach(LLViewerObject *vo) +{ + LLVOAvatar *av = vo->getAvatarAncestor(); + if (!av || (av != this)) + { + LL_WARNS("Avatar") << "called with invalid avatar" << LL_ENDL; + } + + // Process all children + LLViewerObject::const_child_list_t& children = vo->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator it = children.begin(); + it != children.end(); ++it) + { + LLViewerObject *childp = *it; + resetJointPositionsOnDetach(childp); + } + + // Process self. + LLUUID mesh_id; + if (getRiggedMeshID(vo,mesh_id)) + { + resetJointPositionsOnDetach(mesh_id); + } +} + +//----------------------------------------------------------------------------- +// resetJointPositionsOnDetach +//----------------------------------------------------------------------------- +void LLVOAvatar::resetJointPositionsOnDetach(const LLUUID& mesh_id) +{ //Subsequent joints are relative to pelvis avatar_joint_list_t::iterator iter = mSkeleton.begin(); avatar_joint_list_t::iterator end = mSkeleton.end(); @@ -6003,24 +6144,19 @@ void LLVOAvatar::resetJointPositionsToDefault( void ) { LLJoint* pJoint = (*iter); //Reset joints except for pelvis - if ( pJoint && pJoint != pJointPelvis && pJoint->doesJointNeedToBeReset() ) - { + if ( pJoint ) + { pJoint->setId( LLUUID::null ); - pJoint->restoreOldXform(); - } - else - if ( pJoint && pJoint == pJointPelvis && pJoint->doesJointNeedToBeReset() ) + pJoint->removeAttachmentPosOverride(mesh_id, avString()); + } + if ( pJoint && pJoint == pJointPelvis) { - pJoint->setId( LLUUID::null ); + removePelvisFixup( mesh_id ); pJoint->setPosition( LLVector3( 0.0f, 0.0f, 0.0f) ); - //pJoint->setJointResetFlag( false ); // Singu TODO - } - } - - //make sure we don't apply the joint offset - mHasPelvisOffset = false; - mPelvisFixup = mLastPelvisFixup; - postPelvisSetRecalc(); + } + } + + postPelvisSetRecalc(); } //----------------------------------------------------------------------------- // getCharacterPosition() @@ -6092,7 +6228,7 @@ void LLVOAvatar::getGround(const LLVector3 &in_pos_agent, LLVector3 &out_pos_age //----------------------------------------------------------------------------- F32 LLVOAvatar::getTimeDilation() { - return mTimeDilation; + return mRegionp ? mRegionp->getTimeDilation() : 1.f; } @@ -6464,12 +6600,20 @@ BOOL LLVOAvatar::setParent(LLViewerObject* parent) void LLVOAvatar::addChild(LLViewerObject *childp) { childp->extractAttachmentItemID(); // find the inventory item this object is associated with. + if (isSelf()) + { + const LLUUID& item_id = childp->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attachment child added " << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + + } + LLViewerObject::addChild(childp); if (childp->mDrawable) { if (!attachObject(childp)) { - LL_WARNS() << "addChild() failed for " + LL_WARNS() << "ATT addChild() failed for " << childp->getID() << " item " << childp->getAttachmentItemID() << LL_ENDL; @@ -6555,10 +6699,21 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi //----------------------------------------------------------------------------- const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object) { + if (isSelf()) + { + const LLUUID& item_id = viewer_object->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attaching object " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + } LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object); if (!attachment || !attachment->addObject(viewer_object)) { + const LLUUID& item_id = viewer_object->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_WARNS("Avatar") << "ATT attach failed " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; return 0; } @@ -6625,7 +6780,14 @@ void LLVOAvatar::lazyAttach() LLPointer cur_attachment = mPendingAttachment[i]; if (cur_attachment->mDrawable) { - if(!attachObject(cur_attachment)) + if (isSelf()) + { + const LLUUID& item_id = cur_attachment->getAttachmentItemID(); + LLViewerInventoryItem *item = gInventory.getItem(item_id); + LL_DEBUGS("Avatar") << "ATT attaching object " + << (item ? item->getName() : "UNKNOWN") << " id " << item_id << LL_ENDL; + } + if (!attachObject(cur_attachment)) { // Drop it LL_WARNS() << "attachObject() failed for " << cur_attachment->getID() @@ -6691,27 +6853,15 @@ void LLVOAvatar::rebuildRiggedAttachments( void ) //----------------------------------------------------------------------------- void LLVOAvatar::cleanupAttachedMesh( LLViewerObject* pVO ) { - //If a VO has a skin that we'll reset the joint positions to their default - if ( pVO && pVO->mDrawable ) + LLUUID mesh_id; + if (getRiggedMeshID(pVO, mesh_id)) { - LLVOVolume* pVObj = pVO->mDrawable->getVOVolume(); - if ( pVObj ) + resetJointPositionsOnDetach(mesh_id); + if ( gAgentCamera.cameraCustomizeAvatar() ) { - const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( pVObj->getVolume()->getParams().getSculptID(), pVObj ); - if ( pSkinData - && pSkinData->mJointNames.size() > 20 // full rig - && pSkinData->mAlternateBindMatrix.size() > 0 ) - { - LLVOAvatar::resetJointPositionsToDefault(); - //Need to handle the repositioning of the cam, updating rig data etc during outfit editing - //This handles the case where we detach a replacement rig. - if ( gAgentCamera.cameraCustomizeAvatar() ) - { - gAgent.unpauseAnimation(); - //Still want to refocus on head bone - gAgentCamera.changeCameraToCustomizeAvatar(); - } - } + gAgent.unpauseAnimation(); + //Still want to refocus on head bone + gAgentCamera.changeCameraToCustomizeAvatar(); } } } @@ -6851,9 +7001,18 @@ void LLVOAvatar::getOffObject() LLVector3 cur_position_world = mDrawable->getWorldPosition(); LLQuaternion cur_rotation_world = mDrawable->getWorldRotation(); + if (mLastRootPos.length() >= MAX_STANDOFF_FROM_ORIGIN + && (cur_position_world.length() < MAX_STANDOFF_FROM_ORIGIN + || dist_vec(cur_position_world, mLastRootPos) > MAX_STANDOFF_DISTANCE_CHANGE)) + { + // Most likely drawable got updated too early or some updates were missed - we got relative position to non-existing parent + // restore coordinates from cache + cur_position_world = mLastRootPos; + } + // set *local* position based on last *world* position, since we're unparenting the avatar mDrawable->mXform.setPosition(cur_position_world); - mDrawable->mXform.setRotation(cur_rotation_world); + mDrawable->mXform.setRotation(cur_rotation_world); gPipeline.markMoved(mDrawable, TRUE); @@ -7071,6 +7230,7 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color, bool BOOL LLVOAvatar::isVisible() const { return mDrawable.notNull() + && (!mOrphaned || isSelf()) && (mDrawable->isVisible() || mIsDummy); } @@ -7115,6 +7275,7 @@ void LLVOAvatar::updateRezzedStatusTimers() for (S32 i = 1; i < 4; i++) { startPhase("load_" + LLVOAvatar::rezStatusToString(i)); + startPhase("first_load_" + LLVOAvatar::rezStatusToString(i)); } } if (rez_status < mLastRezzedStatus) @@ -7131,6 +7292,7 @@ void LLVOAvatar::updateRezzedStatusTimers() for (S32 i = llmax(mLastRezzedStatus+1,1); i <= rez_status; i++) { stopPhase("load_" + LLVOAvatar::rezStatusToString(i)); + stopPhase("first_load_" + LLVOAvatar::rezStatusToString(i), false); } if (rez_status == 3) { @@ -7260,14 +7422,7 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse record["grid_y"] = LLSD::Integer(grid_y); record["is_using_server_bakes"] = ((bool) isUsingServerBakes()); record["is_self"] = isSelf(); - - -#if 0 // verbose logging - std::ostringstream ostr; - ostr << LLSDNotationStreamer(record); - LL_DEBUGS("Avatar") << "record\n" << ostr.str() << LL_ENDL; -#endif - + if (isAgentAvatarValid()) { gAgentAvatarp->addMetricsTimerRecord(record); @@ -7500,7 +7655,7 @@ void LLVOAvatar::updateMeshTextures() const std::string url = getImageURL(te, mBakedTextureDatas[i].mLastTextureID); if (!url.empty()) { - baked_img = LLViewerTextureManager::getFetchedTextureFromUrl(url, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, mBakedTextureDatas[i].mLastTextureID); + baked_img = LLViewerTextureManager::getFetchedTextureFromUrl(url, FTT_HOST_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, mBakedTextureDatas[i].mLastTextureID); } else { @@ -7511,7 +7666,7 @@ void LLVOAvatar::updateMeshTextures() LL_WARNS() << "updateMeshTextures: invalid host for object: " << getID() << LL_ENDL; } - baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureID, target_host ); + baked_img = LLViewerTextureManager::getFetchedTextureFromHost( mBakedTextureDatas[i].mLastTextureID, FTT_HOST_BAKE, target_host ); } llassert(baked_img == existing_baked_img); @@ -7541,6 +7696,8 @@ void LLVOAvatar::updateMeshTextures() // we'll consider it loaded and use it (rather than // doing compositing). useBakedTexture( baked_img->getID() ); + mLoadedCallbacksPaused |= !isVisible(); + checkTextureLoading(); } else { @@ -7553,6 +7710,10 @@ void LLVOAvatar::updateMeshTextures() } baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); + + // this could add paused texture callbacks + mLoadedCallbacksPaused |= paused; + checkTextureLoading(); } } else if (layerset && isUsingLocalAppearance()) @@ -7621,7 +7782,15 @@ void LLVOAvatar::updateMeshTextures() } } } - removeMissingBakedTextures(); + + // removeMissingBakedTextures() will call back into this rountine if something is removed, and can blow up the stack + static bool call_remove_missing = true; + if (call_remove_missing) + { + call_remove_missing = false; + removeMissingBakedTextures(); // May call back into this function if anything is removed + call_remove_missing = true; + } } // virtual @@ -7922,6 +8091,9 @@ void LLVOAvatar::onFirstTEMessageReceived() LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL; image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); + + // this could add paused texture callbacks + mLoadedCallbacksPaused |= paused; } } @@ -8261,7 +8433,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) { LL_DEBUGS("Avatar") << avString() << " baked_index " << (S32) baked_index << " using mLastTextureID " << mBakedTextureDatas[baked_index].mLastTextureID << LL_ENDL; setTEImage(mBakedTextureDatas[baked_index].mTextureIndex, - LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureID, FTT_HOST_BAKE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } else { @@ -8500,7 +8672,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture } if (!found_texture_id) { - LL_INFOS() << "onBakedTextureMasksLoaded(): unexpected image id: " << id << LL_ENDL; + LL_INFOS() << "unexpected image id: " << id << LL_ENDL; } self->dirtyMesh(); } diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index f3687166a..8a5e879d4 100644 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -184,7 +184,7 @@ public: void updateLODRiggedAttachments( void ); void updateSoftwareSkinnedVertices(const LLMeshSkinInfo* skin, const LLVector4a* weight, const LLVolumeFace& vol_face, LLVertexBuffer *buffer); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. - S32 totalTextureMemForUUIDS(std::set& ids); + S32Bytes totalTextureMemForUUIDS(std::set& ids); bool allTexturesCompletelyDownloaded(std::set& ids) const; bool allLocalTexturesCompletelyDownloaded() const; bool allBakedTexturesCompletelyDownloaded() const; @@ -249,7 +249,10 @@ public: virtual LLJoint* getJoint(const std::string &name); - void resetJointPositionsToDefault( void ); + void addAttachmentPosOverridesForObject(LLViewerObject *vo); + void resetJointPositionsOnDetach(const LLUUID& mesh_id); + void resetJointPositionsOnDetach(LLViewerObject *vo); + void clearAttachmentPosOverrides(); /*virtual*/ const LLUUID& getID() const; /*virtual*/ void addDebugText(const std::string& text); @@ -283,6 +286,7 @@ private: // Updates //-------------------------------------------------------------------- public: + void updateDebugText(); virtual BOOL updateCharacter(LLAgent &agent); void idleUpdateVoiceVisualizer(bool voice_enabled); void idleUpdateMisc(bool detailed_update); @@ -409,19 +413,13 @@ protected: /*virtual*/ LLAvatarJointMesh* createAvatarJointMesh(); // Returns LLViewerJointMesh public: void updateHeadOffset(); - void setPelvisOffset( bool hasOffset, const LLVector3& translation, F32 offset ) ; - bool hasPelvisOffset( void ) { return mHasPelvisOffset; } void postPelvisSetRecalc( void ); - void setPelvisOffset( F32 pelvixFixupAmount ); /*virtual*/ BOOL loadSkeletonNode(); /*virtual*/ void buildCharacter(); - bool mHasPelvisOffset; - LLVector3 mPelvisOffset; - F32 mLastPelvisToFoot; - F32 mPelvisFixup; - F32 mLastPelvisFixup; + LLVector3 mCurRootToHeadOffset; + LLVector3 mTargetRootToHeadOffset; S32 mLastSkeletonSerialNum; @@ -762,6 +760,7 @@ public: void clampAttachmentPositions(); virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object); virtual BOOL detachObject(LLViewerObject *viewer_object); + static bool getRiggedMeshID( LLViewerObject* pVO, LLUUID& mesh_id ); void cleanupAttachedMesh( LLViewerObject* pVO ); static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj); /*virtual*/ BOOL isWearingWearableType(LLWearableType::EType type ) const; @@ -923,6 +922,8 @@ public: private: // set this property only with LLVOAvatar::sitDown method BOOL mIsSitting; + // position backup in case of missing data + LLVector3 mLastRootPos; /** Hierarchy ** ** diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 46b991c9e..197865ec4 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -153,15 +153,6 @@ typedef LLHTTPClient::ResponderIgnore LLHoverHeightResponder; ** ** *********************************************************************************/ - -//----------------------------------------------------------------------------- -// Static Data -//----------------------------------------------------------------------------- -S32 LLVOAvatarSelf::sScratchTexBytes = 0; -LLMap< LLGLenum, LLGLuint*> LLVOAvatarSelf::sScratchTexNames; -LLMap< LLGLenum, F32*> LLVOAvatarSelf::sScratchTexLastBindTime; - - /********************************************************************************* ** ** ** Begin LLVOAvatarSelf Constructor routines @@ -2685,13 +2676,9 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe { F32 desired_pixels; desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); - - // DRANO what priority should wearable-based textures have? - if (isUsingLocalAppearance()) - { - imagep->setBoostLevel(getAvatarBoostLevel()); - imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; - } + + imagep->setBoostLevel(getAvatarBoostLevel()); + imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; imagep->resetTextureStats(); imagep->setMaxVirtualSizeResetInterval(MAX_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); imagep->addTextureStats( desired_pixels / texel_area_ratio ); @@ -2755,7 +2742,7 @@ void LLVOAvatarSelf::setNewBakedTexture( ETextureIndex te, const LLUUID& uuid ) { // Baked textures live on other sims. LLHost target_host = getObjectHost(); - setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, target_host ) ); + setTEImage( te, LLViewerTextureManager::getFetchedTextureFromHost( uuid, FTT_HOST_BAKE, target_host ) ); updateMeshTextures(); dirtyMesh(); @@ -3210,77 +3197,6 @@ BOOL LLVOAvatarSelf::needsRenderBeam() return is_touching_or_grabbing || (mState & AGENT_STATE_EDITING && LLSelectMgr::getInstance()->shouldShowSelection()); } -// static -void LLVOAvatarSelf::deleteScratchTextures() -{ - if(gAuditTexture) - { - S32 total_tex_size = sScratchTexBytes ; - S32 tex_size = SCRATCH_TEX_WIDTH * SCRATCH_TEX_HEIGHT ; - - if( sScratchTexNames.checkData( GL_LUMINANCE ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( GL_ALPHA ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( GL_COLOR_INDEX ) ) - { - LLImageGL::decTextureCounter(tex_size, 1, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= tex_size ; - } - if( sScratchTexNames.checkData( LLRender::sGLCoreProfile ? GL_RG : GL_LUMINANCE_ALPHA ) ) - { - LLImageGL::decTextureCounter(tex_size, 2, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 2 * tex_size ; - } - if( sScratchTexNames.checkData( GL_RGB ) ) - { - LLImageGL::decTextureCounter(tex_size, 3, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 3 * tex_size ; - } - if( sScratchTexNames.checkData( GL_RGBA ) ) - { - LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 4 * tex_size ; - } - //others - while(total_tex_size > 0) - { - LLImageGL::decTextureCounter(tex_size, 4, LLViewerTexture::AVATAR_SCRATCH_TEX) ; - total_tex_size -= 4 * tex_size ; - } - } - - for( LLGLuint* namep = sScratchTexNames.getFirstData(); - namep; - namep = sScratchTexNames.getNextData() ) - { - LLImageGL::deleteTextures(1, (U32 *)namep ); - stop_glerror(); - } - - if( sScratchTexBytes ) - { - LL_DEBUGS() << "Clearing Scratch Textures " << (sScratchTexBytes/1024) << "KB" << LL_ENDL; - - sScratchTexNames.deleteAllData(); - sScratchTexLastBindTime.deleteAllData(); - LLImageGL::sGlobalTextureMemoryInBytes -= sScratchTexBytes; - sScratchTexBytes = 0; - } -} - -// static -void LLVOAvatarSelf::dumpScratchTextureByteCount() -{ - LL_INFOS() << "Scratch Texture GL: " << (sScratchTexBytes/1024) << "KB" << LL_ENDL; -} - void dump_visual_param(LLAPRFile& file, LLVisualParam const* viewer_param, F32 value); void LLVOAvatarSelf::dumpWearableInfo(LLAPRFile& outfile) diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h index 1988a51fd..c8f9dc86b 100644 --- a/indra/newview/llvoavatarself.h +++ b/indra/newview/llvoavatarself.h @@ -30,6 +30,7 @@ #include "llviewertexture.h" #include "llvoavatar.h" +#include struct LocalTextureData; class LLInventoryCallback; @@ -266,17 +267,6 @@ public: const LLUUID& grabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; BOOL canGrabBakedTexture(LLAvatarAppearanceDefines::EBakedTextureIndex baked_index) const; - - //-------------------------------------------------------------------- - // Scratch textures (used for compositing) - //-------------------------------------------------------------------- -public: - static void deleteScratchTextures(); -private: - static S32 sScratchTexBytes; - static LLMap< LLGLenum, LLGLuint*> sScratchTexNames; - static LLMap< LLGLenum, F32*> sScratchTexLastBindTime; - /** Textures ** ** *******************************************************************************/ @@ -383,7 +373,6 @@ public: public: static void dumpTotalLocalTextureByteCount(); void dumpLocalTextures() const; - static void dumpScratchTextureByteCount(); void dumpWearableInfo(LLAPRFile& outfile); //-------------------------------------------------------------------- diff --git a/indra/newview/llvoclouds.cpp b/indra/newview/llvoclouds.cpp index 8b7ca2905..c284a64ce 100644 --- a/indra/newview/llvoclouds.cpp +++ b/indra/newview/llvoclouds.cpp @@ -295,7 +295,8 @@ void LLVOClouds::updateDrawable(BOOL force_damped) clearChanged(SHIFTED); } -LLCloudPartition::LLCloudPartition() +LLCloudPartition::LLCloudPartition(LLViewerRegion* region) + : LLParticlePartition(region) { mDrawableType = LLPipeline::RENDER_TYPE_CLASSIC_CLOUDS; mPartitionType = LLViewerRegion::PARTITION_CLOUD; diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 57f83616f..5d7002ae3 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -111,7 +111,7 @@ void LLVOGrass::updateSpecies() SpeciesMap::const_iterator it = sSpeciesTable.begin(); mSpecies = (*it).first; } - setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); } @@ -626,8 +626,8 @@ U32 LLVOGrass::getPartitionType() const return LLViewerRegion::PARTITION_GRASS; } -LLGrassPartition::LLGrassPartition() -: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB) +LLGrassPartition::LLGrassPartition(LLViewerRegion* regionp) +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB, regionp) { mDrawableType = LLPipeline::RENDER_TYPE_GRASS; mPartitionType = LLViewerRegion::PARTITION_GRASS; diff --git a/indra/newview/llvoicevisualizer.cpp b/indra/newview/llvoicevisualizer.cpp index 05479878c..bfed1afcf 100644 --- a/indra/newview/llvoicevisualizer.cpp +++ b/indra/newview/llvoicevisualizer.cpp @@ -142,7 +142,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type ) for (int i=0; isetAddressMode(LLTexUnit::TAM_CLAMP); - mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLGLTexture::BOOST_UI); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); mBloomTexturep->setNoDelete() ; @@ -478,9 +478,9 @@ void LLVOSky::restoreGL() { mSkyTex[i].restoreGL(); } - mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLGLTexture::BOOST_UI); + mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); - mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLGLTexture::BOOST_UI); + mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_UI); mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1); mBloomTexturep->setNoDelete() ; diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index a661b0e34..d44108ca7 100644 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -1062,8 +1062,8 @@ U32 LLVOSurfacePatch::getPartitionType() const return LLViewerRegion::PARTITION_TERRAIN; } -LLTerrainPartition::LLTerrainPartition() -: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB) +LLTerrainPartition::LLTerrainPartition(LLViewerRegion* regionp) +: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK, FALSE, GL_DYNAMIC_DRAW_ARB, regionp) { mOcclusionEnabled = FALSE; mInfiniteFarClip = TRUE; diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 48fca70a9..63057bb9a 100644 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -337,7 +337,7 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys, // Load Species-Specific data // static const S32 MAX_TREE_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL = 32 ; //frames. - mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); mTreeImagep->setMaxVirtualSizeResetInterval(MAX_TREE_TEXTURE_VIRTUAL_SIZE_RESET_INTERVAL); //allow to wait for at most 16 frames to reset virtual size. mBranchLength = sSpeciesTable[mSpecies]->mBranchLength; @@ -1260,8 +1260,8 @@ U32 LLVOTree::getPartitionType() const return LLViewerRegion::PARTITION_TREE; } -LLTreePartition::LLTreePartition() -: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB) +LLTreePartition::LLTreePartition(LLViewerRegion* regionp) +: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB, regionp) { mDrawableType = LLPipeline::RENDER_TYPE_TREE; mPartitionType = LLViewerRegion::PARTITION_TREE; diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index 2faca387d..874938d64 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -93,6 +93,7 @@ const S32 MIN_QUIET_FRAMES_COALESCE = 30; const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; const F32 FORCE_CULL_AREA = 8.f; +U32 JOINT_COUNT_REQUIRED_FOR_FULLRIG = 20; BOOL gAnimateTextures = TRUE; //extern BOOL gHideSelectedObjects; @@ -1005,7 +1006,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams ¶ms_in, const S32 detail, bo if (is404) { - setIcon(LLViewerTextureManager::getFetchedTextureFromFile("inv_item_mesh.tga", TRUE, LLGLTexture::BOOST_UI)); + setIcon(LLViewerTextureManager::getFetchedTextureFromFile("inv_item_mesh.tga", FTT_LOCAL_FILE, TRUE, LLGLTexture::BOOST_UI)); //render prim proxy when mesh loading attempts give up volume_params.setSculptID(LLUUID::null, LL_SCULPT_TYPE_NONE); @@ -1089,7 +1090,7 @@ void LLVOVolume::updateSculptTexture() LLUUID id = sculpt_params->getSculptTexture(); if (id.notNull()) { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); } } else @@ -1564,6 +1565,65 @@ static LLFastTimer::DeclareTimer FTM_GEN_FLEX("Generate Flexies"); static LLFastTimer::DeclareTimer FTM_UPDATE_PRIMITIVES("Update Primitives"); static LLFastTimer::DeclareTimer FTM_UPDATE_RIGGED_VOLUME("Update Rigged"); +bool LLVOVolume::lodOrSculptChanged(LLDrawable *drawable) +{ + bool regen_faces = false; + + LLVolume *old_volumep, *new_volumep; + F32 old_lod, new_lod; + S32 old_num_faces, new_num_faces ; + + old_volumep = getVolume(); + old_lod = old_volumep->getDetail(); + old_num_faces = old_volumep->getNumFaces() ; + old_volumep = NULL ; + + { + LLFastTimer ftm(FTM_GEN_VOLUME); + const LLVolumeParams &volume_params = getVolume()->getParams(); + setVolume(volume_params, 0); + } + + new_volumep = getVolume(); + new_lod = new_volumep->getDetail(); + new_num_faces = new_volumep->getNumFaces() ; + new_volumep = NULL ; + + if ((new_lod != old_lod) || mSculptChanged) + { + sNumLODChanges += new_num_faces ; + + if((S32)getNumTEs() != getVolume()->getNumFaces()) + { + setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. + } + + drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() + + { + LLFastTimer t(FTM_GEN_TRIANGLES); + regen_faces = new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs(); + if (regen_faces) + { + regenFaces(); + } + + if (mSculptChanged) + { //changes in sculpt maps can thrash an object bounding box without + //triggering a spatial group bounding box update -- force spatial group + //to update bounding boxes + LLSpatialGroup* group = mDrawable->getSpatialGroup(); + if (group) + { + group->unbound(); + } + } + } + } + + return regen_faces; +} + BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { LLFastTimer t(FTM_UPDATE_PRIMITIVES); @@ -1595,8 +1655,6 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) group->dirtyMesh(); } - BOOL compiled = FALSE; - updateRelativeXform(); if (mDrawable.isNull()) // Not sure why this is happening, but it is... @@ -1608,83 +1666,35 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); - compiled = TRUE; + bool was_regen_faces = false; if (mVolumeChanged) { - LLFastTimer ftm(FTM_GEN_VOLUME); - LLVolumeParams volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); + was_regen_faces = lodOrSculptChanged(drawable); drawable->setState(LLDrawable::REBUILD_VOLUME); } - + else if (mSculptChanged || mLODChanged) { + was_regen_faces = lodOrSculptChanged(drawable); + } + + if (!was_regen_faces) { LLFastTimer t(FTM_GEN_TRIANGLES); regenFaces(); - genBBoxes(FALSE); } + + genBBoxes(FALSE); } - else if ((mLODChanged) || (mSculptChanged)) + else if (mLODChanged || mSculptChanged) { dirtySpatialGroup(drawable->isState(LLDrawable::IN_REBUILD_Q1)); + lodOrSculptChanged(drawable); + genBBoxes(FALSE); - LLVolume *old_volumep, *new_volumep; - F32 old_lod, new_lod; - S32 old_num_faces, new_num_faces ; - - old_volumep = getVolume(); - old_lod = old_volumep->getDetail(); - old_num_faces = old_volumep->getNumFaces() ; - old_volumep = NULL ; - - { - LLFastTimer ftm(FTM_GEN_VOLUME); - LLVolumeParams volume_params = getVolume()->getParams(); - setVolume(volume_params, 0); - } - - new_volumep = getVolume(); - new_lod = new_volumep->getDetail(); - new_num_faces = new_volumep->getNumFaces() ; - new_volumep = NULL ; - - if ((new_lod != old_lod) || mSculptChanged) - { - compiled = TRUE; - sNumLODChanges += new_num_faces ; - - if((S32)getNumTEs() != getVolume()->getNumFaces()) - { - setNumTEs(getVolume()->getNumFaces()); //mesh loading may change number of faces. - } - - drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() - - { - LLFastTimer t(FTM_GEN_TRIANGLES); - if (new_num_faces != old_num_faces || mNumFaces != (S32)getNumTEs()) - { - regenFaces(); - } - genBBoxes(FALSE); - - if (mSculptChanged) - { //changes in sculpt maps can thrash an object bounding box without - //triggering a spatial group bounding box update -- force spatial group - //to update bounding boxes - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->unbound(); - } - } - } - } } // it has its own drawable (it's moved) or it has changed UVs or it has changed xforms from global<->local else { - compiled = TRUE; // All it did was move or we changed the texture coordinate offset LLFastTimer t(FTM_GEN_TRIANGLES); genBBoxes(FALSE); @@ -1692,7 +1702,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) // Update face flags updateFaceFlags(); - + mVolumeChanged = FALSE; mLODChanged = FALSE; mSculptChanged = FALSE; @@ -1819,7 +1829,7 @@ S32 LLVOVolume::setTEColor(const U8 te, const LLColor4& color) const LLTextureEntry *tep = getTE(te); if (!tep) { - LL_WARNS() << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; + LL_WARNS("MaterialTEs") << "No texture entry for te " << (S32)te << ", object " << mID << LL_ENDL; } else if (color != tep->getColor()) { @@ -1971,10 +1981,237 @@ S32 LLVOVolume::setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID) return res; } +bool LLVOVolume::notifyAboutCreatingTexture(LLViewerTexture *texture) +{ //Ok, here we have confirmation about texture creation, check our wait-list + //and make changes, or return false + + std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); + + typedef std::map map_te_material; + map_te_material new_material; + + for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) + { + LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); + + //here we just interesting in DIFFUSE_MAP only! + if(cur_material.notNull() && LLRender::DIFFUSE_MAP == range_it->second.map && GL_RGBA != texture->getPrimaryFormat()) + { //ok let's check the diffuse mode + switch(cur_material->getDiffuseAlphaMode()) + { + case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: + case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: + case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: + { //uups... we have non 32 bit texture with LLMaterial::DIFFUSE_ALPHA_MODE_* => LLMaterial::DIFFUSE_ALPHA_MODE_NONE + + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + + } break; + } //switch + } //if + } //for + + //setup new materials + for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) + { + LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); + LLViewerObject::setTEMaterialParams(it->first, it->second); + } + + //clear wait-list + mWaitingTextureInfo.erase(range.first, range.second); + + return 0 != new_material.size(); +} + +bool LLVOVolume::notifyAboutMissingAsset(LLViewerTexture *texture) +{ //Ok, here if we wait information about texture and it's missing + //then depending from the texture map (diffuse, normal, or specular) + //make changes in material and confirm it. If not return false. + std::pair range = mWaitingTextureInfo.equal_range(texture->getID()); + if(range.first == range.second) return false; + + typedef std::map map_te_material; + map_te_material new_material; + + for(mmap_UUID_MAP_t::iterator range_it = range.first; range_it != range.second; ++range_it) + { + LLMaterialPtr cur_material = getTEMaterialParams(range_it->second.te); + if (cur_material.isNull()) + continue; + + switch(range_it->second.map) + { + case LLRender::DIFFUSE_MAP: + { + if(LLMaterial::DIFFUSE_ALPHA_MODE_NONE != cur_material->getDiffuseAlphaMode()) + { //missing texture + !LLMaterial::DIFFUSE_ALPHA_MODE_NONE => LLMaterial::DIFFUSE_ALPHA_MODE_NONE + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + } + } break; + case LLRender::NORMAL_MAP: + { //missing texture => reset material texture id + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setNormalID(LLUUID::null); + } break; + case LLRender::SPECULAR_MAP: + { //missing texture => reset material texture id + LLMaterialPtr mat = NULL; + map_te_material::iterator it = new_material.find(range_it->second.te); + if(new_material.end() == it) { + mat = new LLMaterial(cur_material->asLLSD()); + new_material.insert(map_te_material::value_type(range_it->second.te, mat)); + } else { + mat = it->second; + } + + mat->setSpecularID(LLUUID::null); + } break; + case LLRender::NUM_TEXTURE_CHANNELS: + //nothing to do, make compiler happy + break; + } //switch + } //for + + //setup new materials + for(map_te_material::const_iterator it = new_material.begin(), end = new_material.end(); it != end; ++it) + { + LLMaterialMgr::getInstance()->put(getID(), it->first, *it->second); + LLViewerObject::setTEMaterialParams(it->first, it->second); + } + + //clear wait-list + mWaitingTextureInfo.erase(range.first, range.second); + + return 0 != new_material.size(); +} + S32 LLVOVolume::setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams) { - S32 res = LLViewerObject::setTEMaterialParams(te, pMaterialParams); - LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterialParams) ? pMaterialParams->asLLSD() : LLSD("null")) << " res " << res + LLMaterialPtr pMaterial = const_cast(pMaterialParams); + + if(pMaterialParams) + { //check all of them according to material settings + + LLViewerTexture *img_diffuse = getTEImage(te); + LLViewerTexture *img_normal = getTENormalMap(te); + LLViewerTexture *img_specular = getTESpecularMap(te); + + llassert(NULL != img_diffuse); + + LLMaterialPtr new_material = NULL; + + //diffuse + if(NULL != img_diffuse) + { //guard + if(0 == img_diffuse->getPrimaryFormat() && !img_diffuse->isMissingAsset()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(img_diffuse->getID(), material_info(LLRender::DIFFUSE_MAP, te))); + } + else + { + bool bSetDiffuseNone = false; + if(img_diffuse->isMissingAsset()) + { + bSetDiffuseNone = true; + } + else + { + switch(pMaterialParams->getDiffuseAlphaMode()) + { + case LLMaterial::DIFFUSE_ALPHA_MODE_BLEND: + case LLMaterial::DIFFUSE_ALPHA_MODE_EMISSIVE: + case LLMaterial::DIFFUSE_ALPHA_MODE_MASK: + { //all of them modes available only for 32 bit textures + if(GL_RGBA != img_diffuse->getPrimaryFormat()) + { + bSetDiffuseNone = true; + } + } break; + } + } //else + + + if(bSetDiffuseNone) + { //upps... we should substitute this material with LLMaterial::DIFFUSE_ALPHA_MODE_NONE + new_material = new LLMaterial(pMaterialParams->asLLSD()); + new_material->setDiffuseAlphaMode(LLMaterial::DIFFUSE_ALPHA_MODE_NONE); + } + } + } + + //normal + if(LLUUID::null != pMaterialParams->getNormalID()) + { + if(img_normal && img_normal->isMissingAsset() && img_normal->getID() == pMaterialParams->getNormalID()) + { + if(!new_material) { + new_material = new LLMaterial(pMaterialParams->asLLSD()); + } + new_material->setNormalID(LLUUID::null); + } + else if(NULL == img_normal || 0 == img_normal->getPrimaryFormat()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getNormalID(), material_info(LLRender::NORMAL_MAP,te))); + } + + } + + + //specular + if(LLUUID::null != pMaterialParams->getSpecularID()) + { + if(img_specular && img_specular->isMissingAsset() && img_specular->getID() == pMaterialParams->getSpecularID()) + { + if(!new_material) { + new_material = new LLMaterial(pMaterialParams->asLLSD()); + } + new_material->setSpecularID(LLUUID::null); + } + else if(NULL == img_specular || 0 == img_specular->getPrimaryFormat()) + { //ok here we don't have information about texture, let's belief and leave material settings + //but we remember this case + mWaitingTextureInfo.insert(mmap_UUID_MAP_t::value_type(pMaterialParams->getSpecularID(), material_info(LLRender::SPECULAR_MAP, te))); + } + } + + if(new_material) { + pMaterial = new_material; + LLMaterialMgr::getInstance()->put(getID(),te,*pMaterial); + } + } + + S32 res = LLViewerObject::setTEMaterialParams(te, pMaterial); + + LL_DEBUGS("MaterialTEs") << "te " << (S32)te << " material " << ((pMaterial) ? pMaterial->asLLSD() : LLSD("null")) << " res " << res << ( LLSelectMgr::getInstance()->getSelection()->contains(const_cast(this), te) ? " selected" : " not selected" ) << LL_ENDL; setChanged(ALL_CHANGED); @@ -4000,8 +4237,9 @@ U32 LLVOVolume::getPartitionType() const return LLViewerRegion::PARTITION_VOLUME; } -LLVolumePartition::LLVolumePartition() -: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB) +LLVolumePartition::LLVolumePartition(LLViewerRegion* regionp) +: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, TRUE, GL_DYNAMIC_DRAW_ARB, regionp), +LLVolumeGeometryManager() { mLODPeriod = 32; mDepthMask = FALSE; @@ -4011,8 +4249,9 @@ LLVolumePartition::LLVolumePartition() mBufferUsage = GL_DYNAMIC_DRAW_ARB; } -LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) -: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK) +LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep, LLViewerRegion* regionp) +: LLSpatialBridge(drawablep, TRUE, LLVOVolume::VERTEX_DATA_MASK, regionp), +LLVolumeGeometryManager() { mDepthMask = FALSE; mLODPeriod = 32; @@ -4024,8 +4263,8 @@ LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) mSlopRatio = 0.25f; } -LLAttachmentBridge::LLAttachmentBridge(LLDrawable* drawablep) - : LLVolumeBridge(drawablep) +LLAttachmentBridge::LLAttachmentBridge(LLDrawable* drawablep, LLViewerRegion* regionp) + : LLVolumeBridge(drawablep, regionp) { mPartitionType = LLViewerRegion::PARTITION_ATTACHMENT; } @@ -4073,6 +4312,70 @@ bool can_batch_texture(const LLFace* facep) return true; } +const static U32 MAX_FACE_COUNT = 4096U; +int32_t LLVolumeGeometryManager::sInstanceCount = 0; +LLFace** LLVolumeGeometryManager::sFullbrightFaces = NULL; +LLFace** LLVolumeGeometryManager::sBumpFaces = NULL; +LLFace** LLVolumeGeometryManager::sSimpleFaces = NULL; +LLFace** LLVolumeGeometryManager::sNormFaces = NULL; +LLFace** LLVolumeGeometryManager::sSpecFaces = NULL; +LLFace** LLVolumeGeometryManager::sNormSpecFaces = NULL; +LLFace** LLVolumeGeometryManager::sAlphaFaces = NULL; + +LLVolumeGeometryManager::LLVolumeGeometryManager() + : LLGeometryManager() +{ + llassert(sInstanceCount >= 0); + if (sInstanceCount == 0) + { + allocateFaces(MAX_FACE_COUNT); + } + + ++sInstanceCount; +} + +LLVolumeGeometryManager::~LLVolumeGeometryManager() +{ + llassert(sInstanceCount > 0); + --sInstanceCount; + + if (sInstanceCount <= 0) + { + freeFaces(); + sInstanceCount = 0; + } +} + +void LLVolumeGeometryManager::allocateFaces(U32 pMaxFaceCount) +{ + sFullbrightFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sBumpFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sSimpleFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sNormFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sNormSpecFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); + sAlphaFaces = static_cast(ll_aligned_malloc<64>(pMaxFaceCount*sizeof(LLFace*))); +} + +void LLVolumeGeometryManager::freeFaces() +{ + ll_aligned_free<64>(sFullbrightFaces); + ll_aligned_free<64>(sBumpFaces); + ll_aligned_free<64>(sSimpleFaces); + ll_aligned_free<64>(sNormFaces); + ll_aligned_free<64>(sSpecFaces); + ll_aligned_free<64>(sNormSpecFaces); + ll_aligned_free<64>(sAlphaFaces); + + sFullbrightFaces = NULL; + sBumpFaces = NULL; + sSimpleFaces = NULL; + sNormFaces = NULL; + sSpecFaces = NULL; + sNormSpecFaces = NULL; + sAlphaFaces = NULL; +} + static LLFastTimer::DeclareTimer FTM_REGISTER_FACE("Register Face"); void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) @@ -4427,16 +4730,6 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) group->clearDrawMap(); mFaceList.clear(); - - const U32 MAX_FACE_COUNT = 4096; - - static LLFace** fullbright_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); - static LLFace** bump_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); - static LLFace** simple_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); - static LLFace** norm_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64); - static LLFace** spec_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64); - static LLFace** normspec_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*), 64); - static LLFace** alpha_faces = (LLFace**) ll_aligned_malloc(MAX_FACE_COUNT*sizeof(LLFace*),64); U32 fullbright_count = 0; U32 bump_count = 0; @@ -4541,60 +4834,12 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //get drawpool of avatar with rigged face LLDrawPoolAvatar* pool = get_avatar_drawpool(vobj); - - //Determine if we've received skininfo that contains an - //alternate bind matrix - if it does then apply the translational component - //to the joints of the avatar. - bool pelvisGotSet = false; - + + // FIXME should this be inside the face loop? + // doesn't seem to depend on any per-face state. if ( pAvatarVO ) { - LLUUID currentId = vobj->getVolume()->getParams().getSculptID(); - const LLMeshSkinInfo* pSkinData = gMeshRepo.getSkinInfo( currentId, vobj ); - - if ( pSkinData ) - { - const int bindCnt = pSkinData->mAlternateBindMatrix.size(); - if ( bindCnt > 0 ) - { - const int jointCnt = pSkinData->mJointNames.size(); - const F32 pelvisZOffset = pSkinData->mPelvisOffset; - bool fullRig = (jointCnt>=20) ? true : false; - if ( fullRig ) - { - for ( int i=0; imJointNames[i].c_str(); - //LL_INFOS() <<"joint name "<getJoint( lookingForJoint ); - if ( pJoint && pJoint->getId() != currentId ) - { - pJoint->setId( currentId ); - const LLVector3& jointPos = pSkinData->mAlternateBindMatrix[i].getTranslation(); - //Set the joint position - pJoint->storeCurrentXform( jointPos ); - //If joint is a pelvis then handle old/new pelvis to foot values - if ( lookingForJoint == "mPelvis" ) - { - pJoint->storeCurrentXform( jointPos ); - if ( !pAvatarVO->hasPelvisOffset() ) - { - pAvatarVO->setPelvisOffset( true, jointPos, pelvisZOffset ); - //Trigger to rebuild viewer AV - pelvisGotSet = true; - } - } - } - } - } - } - } - } - //If we've set the pelvis to a new position we need to also rebuild some information that the - //viewer does at launch (e.g. body size etc.) - if ( pelvisGotSet ) - { - pAvatarVO->postPelvisSetRecalc(); + pAvatarVO->addAttachmentPosOverridesForObject(vobj); } if (pool) @@ -4931,7 +5176,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //can be treated as alpha mask if (simple_count < MAX_FACE_COUNT) { - simple_faces[simple_count++] = facep; + sSimpleFaces[simple_count++] = facep; } } else @@ -4942,7 +5187,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) } if (alpha_count < MAX_FACE_COUNT) { - alpha_faces[alpha_count++] = facep; + sAlphaFaces[alpha_count++] = facep; } } } @@ -4967,14 +5212,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) if (normspec_count < MAX_FACE_COUNT) { - normspec_faces[normspec_count++] = facep; + sNormSpecFaces[normspec_count++] = facep; } } else { //has normal map (needs texcoord1 and tangent) if (norm_count < MAX_FACE_COUNT) { - norm_faces[norm_count++] = facep; + sNormFaces[norm_count++] = facep; } } } @@ -4982,14 +5227,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //has specular map but no normal map, needs texcoord2 if (spec_count < MAX_FACE_COUNT) { - spec_faces[spec_count++] = facep; + sSpecFaces[spec_count++] = facep; } } else { //has neither specular map nor normal map, only needs texcoord0 if (simple_count < MAX_FACE_COUNT) { - simple_faces[simple_count++] = facep; + sSimpleFaces[simple_count++] = facep; } } } @@ -4997,14 +5242,14 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal + tangent if (bump_count < MAX_FACE_COUNT) { - bump_faces[bump_count++] = facep; + sBumpFaces[bump_count++] = facep; } } else if (te->getShiny() || !te->getFullbright()) { //needs normal if (simple_count < MAX_FACE_COUNT) { - simple_faces[simple_count++] = facep; + sSimpleFaces[simple_count++] = facep; } } else @@ -5012,7 +5257,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->setState(LLFace::FULLBRIGHT); if (fullbright_count < MAX_FACE_COUNT) { - fullbright_faces[fullbright_count++] = facep; + sFullbrightFaces[fullbright_count++] = facep; } } } @@ -5022,7 +5267,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal + tangent if (bump_count < MAX_FACE_COUNT) { - bump_faces[bump_count++] = facep; + sBumpFaces[bump_count++] = facep; } } else if ((te->getShiny() && LLPipeline::sRenderBump) || @@ -5030,7 +5275,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal if (simple_count < MAX_FACE_COUNT) { - simple_faces[simple_count++] = facep; + sSimpleFaces[simple_count++] = facep; } } else @@ -5038,7 +5283,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) facep->setState(LLFace::FULLBRIGHT); if (fullbright_count < MAX_FACE_COUNT) { - fullbright_faces[fullbright_count++] = facep; + sFullbrightFaces[fullbright_count++] = facep; } } } @@ -5051,7 +5296,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if (type == LLDrawPool::POOL_ALPHA) { - cur_type = &alpha_faces; + cur_type = &sAlphaFaces; cur_count = &alpha_count; if (te->getColor().mV[3] > 0.f) @@ -5066,30 +5311,30 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (mat->getSpecularID().notNull()) { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) - cur_type = &normspec_faces; + cur_type = &sNormSpecFaces; cur_count = &normspec_count; } else { //has normal map (needs texcoord1 and tangent) - cur_type = &norm_faces; + cur_type = &sNormFaces; cur_count = &norm_count; } } else if (mat->getSpecularID().notNull()) { //has specular map but no normal map, needs texcoord2 - cur_type = &spec_faces; + cur_type = &sSpecFaces; cur_count = &spec_count; } } } else if(type == LLDrawPool::POOL_ALPHA_MASK) { - cur_type = &simple_faces; + cur_type = &sSimpleFaces; cur_count = &simple_count; } else if(type == LLDrawPool::POOL_FULLBRIGHT_ALPHA_MASK) { - cur_type = &fullbright_faces; + cur_type = &sFullbrightFaces; cur_count = &fullbright_count; } else @@ -5103,30 +5348,30 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { //needs normal + tangent if(te->getBumpmap() > 0 && te->getBumpmap() < 18) { - cur_type = &bump_faces; + cur_type = &sBumpFaces; cur_count = &bump_count; } else if(te->getShiny()) { - cur_type = &simple_faces; + cur_type = &sSimpleFaces; cur_count = &simple_count; } } else if (type == LLDrawPool::POOL_SIMPLE) { //needs normal + tangent - cur_type = &simple_faces; + cur_type = &sSimpleFaces; cur_count = &simple_count; } else if (type == LLDrawPool::POOL_FULLBRIGHT) { //doesn't need normal... if(LLPipeline::sRenderBump && te->getShiny()) //unless it's shiny.. { - cur_type = &simple_faces; + cur_type = &sSimpleFaces; cur_count = &simple_count; } else { - cur_type = &fullbright_faces; + cur_type = &sFullbrightFaces; cur_count = &fullbright_count; } } @@ -5140,23 +5385,23 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) { if (mat->getSpecularID().notNull()) { //has normal and specular maps (needs texcoord1, texcoord2, and tangent) - cur_type = &normspec_faces; + cur_type = &sNormSpecFaces; cur_count = &normspec_count; } else { //has normal map (needs texcoord1 and tangent) - cur_type = &norm_faces; + cur_type = &sNormFaces; cur_count = &norm_count; } } else if (mat->getSpecularID().notNull()) { //has specular map but no normal map, needs texcoord2 - cur_type = &spec_faces; + cur_type = &sSpecFaces; cur_count = &spec_count; } else { //has neither specular map nor normal map, only needs texcoord0 - cur_type = &simple_faces; + cur_type = &sSimpleFaces; cur_count = &simple_count; } } @@ -5218,13 +5463,13 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) if(emissive) additional_flags |= LLVertexBuffer::MAP_EMISSIVE; - genDrawInfo(group, simple_mask | additional_flags, simple_faces, simple_count, FALSE, batch_textures); - genDrawInfo(group, fullbright_mask | additional_flags, fullbright_faces, fullbright_count, FALSE, batch_textures); - genDrawInfo(group, alpha_mask | additional_flags, alpha_faces, alpha_count, TRUE, batch_textures); - genDrawInfo(group, bump_mask | additional_flags, bump_faces, bump_count, FALSE); - genDrawInfo(group, norm_mask | additional_flags, norm_faces, norm_count, FALSE); - genDrawInfo(group, spec_mask | additional_flags, spec_faces, spec_count, FALSE); - genDrawInfo(group, normspec_mask | additional_flags, normspec_faces, normspec_count, FALSE); + genDrawInfo(group, simple_mask | additional_flags, sSimpleFaces, simple_count, FALSE, batch_textures); + genDrawInfo(group, fullbright_mask | additional_flags, sFullbrightFaces, fullbright_count, FALSE, batch_textures); + genDrawInfo(group, alpha_mask | additional_flags, sAlphaFaces, alpha_count, TRUE, batch_textures); + genDrawInfo(group, bump_mask | additional_flags, sBumpFaces, bump_count, FALSE); + genDrawInfo(group, norm_mask | additional_flags, sNormFaces, norm_count, FALSE); + genDrawInfo(group, spec_mask | additional_flags, sSpecFaces, spec_count, FALSE); + genDrawInfo(group, normspec_mask | additional_flags, sNormSpecFaces, normspec_count, FALSE); if (!LLPipeline::sDelayVBUpdate) { @@ -5351,6 +5596,10 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if(!drawablep) + { + continue; + } for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { LLFace* face = drawablep->getFace(i); @@ -6348,7 +6597,8 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun group->mBufferUsage = usage; } -LLHUDPartition::LLHUDPartition() +LLHUDPartition::LLHUDPartition(LLViewerRegion* regionp) + : LLBridgePartition(regionp) { mPartitionType = LLViewerRegion::PARTITION_HUD; mDrawableType = LLPipeline::RENDER_TYPE_HUD; diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h index e70a6a64d..7298b866e 100644 --- a/indra/newview/llvovolume.h +++ b/indra/newview/llvovolume.h @@ -358,6 +358,10 @@ protected: void cleanUpMediaImpls(); void addMediaImpl(LLViewerMediaImpl* media_impl, S32 texture_index) ; void removeMediaImpl(S32 texture_index) ; + +private: + bool lodOrSculptChanged(LLDrawable *drawable); + public: static S32 getRenderComplexityMax() {return mRenderComplexity_last;} @@ -402,6 +406,26 @@ protected: static S32 sNumLODChanges; friend class LLVolumeImplFlexible; + +public: + bool notifyAboutCreatingTexture(LLViewerTexture *texture); + bool notifyAboutMissingAsset(LLViewerTexture *texture); + +private: + struct material_info + { + LLRender::eTexIndex map; + U8 te; + + material_info(LLRender::eTexIndex map_, U8 te_) + : map(map_) + , te(te_) + {} + }; + + typedef std::multimap mmap_UUID_MAP_t; + mmap_UUID_MAP_t mWaitingTextureInfo; + }; #endif // LL_LLVOVOLUME_H diff --git a/indra/newview/llvowater.cpp b/indra/newview/llvowater.cpp index 516429f22..89bb6ba23 100644 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -307,15 +307,16 @@ U32 LLVOVoidWater::getPartitionType() const return LLViewerRegion::PARTITION_VOIDWATER; } -LLWaterPartition::LLWaterPartition() -: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB) +LLWaterPartition::LLWaterPartition(LLViewerRegion* regionp) +: LLSpatialPartition(0, FALSE, GL_DYNAMIC_DRAW_ARB, regionp) { mInfiniteFarClip = TRUE; mDrawableType = LLPipeline::RENDER_TYPE_WATER; mPartitionType = LLViewerRegion::PARTITION_WATER; } -LLVoidWaterPartition::LLVoidWaterPartition() +LLVoidWaterPartition::LLVoidWaterPartition(LLViewerRegion* regionp) + : LLWaterPartition(regionp) { //mOcclusionEnabled = FALSE; mDrawableType = LLPipeline::RENDER_TYPE_VOIDWATER; diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp index 2111ec437..8f33a56ac 100644 --- a/indra/newview/llworldmap.cpp +++ b/indra/newview/llworldmap.cpp @@ -104,7 +104,7 @@ void LLSimInfo::setLandForSaleImage (LLUUID image_id) // Fetch the image if (mMapImageID[SIM_LAYER_OVERLAY].notNull()) { - mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); if (is_aurora) mLayerImage[SIM_LAYER_OVERLAY]->forceImmediateUpdate(); mLayerImage[SIM_LAYER_OVERLAY]->setAddressMode(LLTexUnit::TAM_CLAMP); } @@ -119,7 +119,7 @@ LLPointer LLSimInfo::getLandForSaleImage () if (mLayerImage[SIM_LAYER_OVERLAY].isNull() && mMapImageID[SIM_LAYER_OVERLAY].notNull()) { // Fetch the image if it hasn't been done yet (unlikely but...) - mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + mLayerImage[SIM_LAYER_OVERLAY] = LLViewerTextureManager::getFetchedTexture(mMapImageID[SIM_LAYER_OVERLAY], FTT_DEFAULT, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); mLayerImage[SIM_LAYER_OVERLAY]->setAddressMode(LLTexUnit::TAM_CLAMP); } if (!mLayerImage[SIM_LAYER_OVERLAY].isNull()) @@ -517,7 +517,7 @@ void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**) msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Top, top, block); msg->getU32Fast(_PREHASH_LayerData, _PREHASH_Bottom, bottom, block); - new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, FTT_MAP_TILE, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); gGL.getTexUnit(0)->bind(new_layer.LayerImage.get()); new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP); diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 6e1e1b0e0..10447ecfa 100644 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -149,10 +149,10 @@ void LLWorldMapView::initClass() sHomeImage = LLUI::getUIImage("map_home.tga"); sTelehubImage = LLUI::getUIImage("map_telehub.tga"); sInfohubImage = LLUI::getUIImage("map_infohub.tga"); - sEventImage = LLUI::getUIImage("map_event.tga"); - sEventMatureImage = LLUI::getUIImage("map_event_mature.tga"); + sEventImage = LLUI::getUIImage("Parcel_PG_Light"); + sEventMatureImage = LLUI::getUIImage("Parcel_M_Light"); // To Do: update the image resource for adult events. - sEventAdultImage = LLUI::getUIImage("map_event_adult.tga"); + sEventAdultImage = LLUI::getUIImage("Parcel_R_Light"); sTrackCircleImage = LLUI::getUIImage("map_track_16.tga"); sTrackArrowImage = LLUI::getUIImage("direction_arrow.tga"); @@ -890,7 +890,7 @@ F32 LLWorldMapView::drawLegacySimTile(LLSimInfo& sim_info, S32 left, S32 top, S3 (textures_requested_this_tick < MAX_REQUEST_PER_TICK))) { textures_requested_this_tick++; - simimage = sim_info.mLayerImage[SIM_LAYER_COMPOSITE] = LLViewerTextureManager::getFetchedTexture(sim_info.mMapImageID[SIM_LAYER_COMPOSITE], MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); + simimage = sim_info.mLayerImage[SIM_LAYER_COMPOSITE] = LLViewerTextureManager::getFetchedTexture(sim_info.mMapImageID[SIM_LAYER_COMPOSITE], FTT_MAP_TILE, MIPMAP_TRUE, LLGLTexture::BOOST_MAP, LLViewerTexture::LOD_TEXTURE); simimage->setAddressMode(LLTexUnit::TAM_CLAMP); } } diff --git a/indra/newview/llworldmipmap.cpp b/indra/newview/llworldmipmap.cpp index 66ee60d47..6de118940 100644 --- a/indra/newview/llworldmipmap.cpp +++ b/indra/newview/llworldmipmap.cpp @@ -198,7 +198,7 @@ LLPointer LLWorldMipmap::loadObjectsTile(U32 grid_x, U32 // END DEBUG //LL_INFOS("World Map") << "LLWorldMipmap::loadObjectsTile(), URL = " << imageurl << LL_ENDL; - LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); + LLPointer img = LLViewerTextureManager::getFetchedTextureFromUrl(imageurl, FTT_MAP_TILE, TRUE, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); img->setBoostLevel(LLGLTexture::BOOST_MAP); // Return the smart pointer diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 3befdff47..7eaf9f529 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2830,7 +2830,7 @@ void LLPipeline::updateGeom(F32 max_dtime) S32 count = 0; - max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime); + max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, F32SecondsImplicit(max_dtime)); LLSpatialGroup* last_group = NULL; LLSpatialBridge* last_bridge = NULL; diff --git a/indra/newview/skins/apollo/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/apollo/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e379309..000000000 Binary files a/indra/newview/skins/apollo/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/account_id_green.tga b/indra/newview/skins/apollo/textures/account_id_green.tga deleted file mode 100644 index 9be215eed..000000000 Binary files a/indra/newview/skins/apollo/textures/account_id_green.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/account_id_orange.tga b/indra/newview/skins/apollo/textures/account_id_orange.tga deleted file mode 100644 index 6b41e8663..000000000 Binary files a/indra/newview/skins/apollo/textures/account_id_orange.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/active_speakers.tga b/indra/newview/skins/apollo/textures/active_speakers.tga deleted file mode 100644 index 02d3643d7..000000000 Binary files a/indra/newview/skins/apollo/textures/active_speakers.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/active_voice_tab.tga b/indra/newview/skins/apollo/textures/active_voice_tab.tga deleted file mode 100644 index 2d0dfaabc..000000000 Binary files a/indra/newview/skins/apollo/textures/active_voice_tab.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/alpha_gradient.tga b/indra/newview/skins/apollo/textures/alpha_gradient.tga deleted file mode 100644 index 6fdba25d4..000000000 Binary files a/indra/newview/skins/apollo/textures/alpha_gradient.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/arrow_down.tga b/indra/newview/skins/apollo/textures/arrow_down.tga deleted file mode 100644 index 81dc9d3b6..000000000 Binary files a/indra/newview/skins/apollo/textures/arrow_down.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/arrow_up.tga b/indra/newview/skins/apollo/textures/arrow_up.tga deleted file mode 100644 index 22195cf7f..000000000 Binary files a/indra/newview/skins/apollo/textures/arrow_up.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/avatar_gone.tga b/indra/newview/skins/apollo/textures/avatar_gone.tga deleted file mode 100644 index e5c2c070b..000000000 Binary files a/indra/newview/skins/apollo/textures/avatar_gone.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/avatar_new.tga b/indra/newview/skins/apollo/textures/avatar_new.tga deleted file mode 100644 index 854b70c32..000000000 Binary files a/indra/newview/skins/apollo/textures/avatar_new.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/avatar_typing.tga b/indra/newview/skins/apollo/textures/avatar_typing.tga deleted file mode 100644 index 2c549025d..000000000 Binary files a/indra/newview/skins/apollo/textures/avatar_typing.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/button_anim_pause_disabled.tga b/indra/newview/skins/apollo/textures/button_anim_pause_disabled.tga deleted file mode 100644 index 4d604c63c..000000000 Binary files a/indra/newview/skins/apollo/textures/button_anim_pause_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/button_anim_play_disabled.tga b/indra/newview/skins/apollo/textures/button_anim_play_disabled.tga deleted file mode 100644 index 444062f37..000000000 Binary files a/indra/newview/skins/apollo/textures/button_anim_play_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/button_anim_stop_disabled.tga b/indra/newview/skins/apollo/textures/button_anim_stop_disabled.tga deleted file mode 100644 index cf1532a42..000000000 Binary files a/indra/newview/skins/apollo/textures/button_anim_stop_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/checkerboard_transparency_bg.png b/indra/newview/skins/apollo/textures/checkerboard_transparency_bg.png deleted file mode 100644 index fe06d38ef..000000000 Binary files a/indra/newview/skins/apollo/textures/checkerboard_transparency_bg.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/circle.tga b/indra/newview/skins/apollo/textures/circle.tga deleted file mode 100644 index d7097e3a3..000000000 Binary files a/indra/newview/skins/apollo/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/color_swatch_alpha.tga b/indra/newview/skins/apollo/textures/color_swatch_alpha.tga deleted file mode 100644 index 814a004e6..000000000 Binary files a/indra/newview/skins/apollo/textures/color_swatch_alpha.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/crosshairs.tga b/indra/newview/skins/apollo/textures/crosshairs.tga deleted file mode 100644 index ac4d63dc5..000000000 Binary files a/indra/newview/skins/apollo/textures/crosshairs.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/down_arrow.png b/indra/newview/skins/apollo/textures/down_arrow.png deleted file mode 100644 index d376d980d..000000000 Binary files a/indra/newview/skins/apollo/textures/down_arrow.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/ff_edit_mine.tga b/indra/newview/skins/apollo/textures/ff_edit_mine.tga deleted file mode 100644 index 8f0c35b98..000000000 Binary files a/indra/newview/skins/apollo/textures/ff_edit_mine.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/ff_edit_theirs.tga b/indra/newview/skins/apollo/textures/ff_edit_theirs.tga deleted file mode 100644 index 005ada2de..000000000 Binary files a/indra/newview/skins/apollo/textures/ff_edit_theirs.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/ff_visible_map.tga b/indra/newview/skins/apollo/textures/ff_visible_map.tga deleted file mode 100644 index a4dad78da..000000000 Binary files a/indra/newview/skins/apollo/textures/ff_visible_map.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/ff_visible_online.tga b/indra/newview/skins/apollo/textures/ff_visible_online.tga deleted file mode 100644 index 74e3a4e31..000000000 Binary files a/indra/newview/skins/apollo/textures/ff_visible_online.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef3..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f946..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/apollo/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad34..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_clear_lineeditor.tga b/indra/newview/skins/apollo/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c6..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-pause.tga b/indra/newview/skins/apollo/textures/icn_media-pause.tga deleted file mode 100644 index 0713af0b4..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-pause.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-pause_active.tga b/indra/newview/skins/apollo/textures/icn_media-pause_active.tga deleted file mode 100644 index 21384316a..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-pause_active.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-pause_disabled.tga b/indra/newview/skins/apollo/textures/icn_media-pause_disabled.tga deleted file mode 100644 index 4d604c63c..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-pause_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-pause_enabled.tga b/indra/newview/skins/apollo/textures/icn_media-pause_enabled.tga deleted file mode 100644 index 577f9195d..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-pause_enabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-play.tga b/indra/newview/skins/apollo/textures/icn_media-play.tga deleted file mode 100644 index bdd9f1611..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-play.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-play_active.tga b/indra/newview/skins/apollo/textures/icn_media-play_active.tga deleted file mode 100644 index b166a4178..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-play_active.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-play_disabled.tga b/indra/newview/skins/apollo/textures/icn_media-play_disabled.tga deleted file mode 100644 index 444062f37..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-play_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-play_enabled.tga b/indra/newview/skins/apollo/textures/icn_media-play_enabled.tga deleted file mode 100644 index 9ed55f829..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-play_enabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-stop_active.tga b/indra/newview/skins/apollo/textures/icn_media-stop_active.tga deleted file mode 100644 index 03efac206..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-stop_active.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-stop_disabled.tga b/indra/newview/skins/apollo/textures/icn_media-stop_disabled.tga deleted file mode 100644 index cf1532a42..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-stop_disabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media-stop_enabled.tga b/indra/newview/skins/apollo/textures/icn_media-stop_enabled.tga deleted file mode 100644 index 011b98c49..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media-stop_enabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_media.tga b/indra/newview/skins/apollo/textures/icn_media.tga deleted file mode 100644 index 43dd342c9..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_media.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_music-pause.tga b/indra/newview/skins/apollo/textures/icn_music-pause.tga deleted file mode 100644 index 548ccf4e4..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_music-pause.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_music-play.tga b/indra/newview/skins/apollo/textures/icn_music-play.tga deleted file mode 100644 index 1a67d3440..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_music-play.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_music.tga b/indra/newview/skins/apollo/textures/icn_music.tga deleted file mode 100644 index 9470601db..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_music.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_scrollbar.tga b/indra/newview/skins/apollo/textures/icn_scrollbar.tga deleted file mode 100644 index a19a8a5d1..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_scrollbar.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_scrollbar_bg.tga b/indra/newview/skins/apollo/textures/icn_scrollbar_bg.tga deleted file mode 100644 index 1e4bc7a8a..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_scrollbar_bg.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_scrollbar_thumb.tga b/indra/newview/skins/apollo/textures/icn_scrollbar_thumb.tga deleted file mode 100644 index d63c31472..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_scrollbar_thumb.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_speaker-muted_dark.tga b/indra/newview/skins/apollo/textures/icn_speaker-muted_dark.tga deleted file mode 100644 index a7d29a14b..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_speaker-muted_dark.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_stop.tga b/indra/newview/skins/apollo/textures/icn_stop.tga deleted file mode 100644 index 7a53bccc2..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_stop.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_textfield_enabled.tga b/indra/newview/skins/apollo/textures/icn_textfield_enabled.tga deleted file mode 100644 index fc681a195..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_textfield_enabled.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice-call-end.tga b/indra/newview/skins/apollo/textures/icn_voice-call-end.tga deleted file mode 100644 index 2da4e856b..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice-call-end.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice-call-start.tga b/indra/newview/skins/apollo/textures/icn_voice-call-start.tga deleted file mode 100644 index 07701cb5a..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice-call-start.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice-groupfocus.tga b/indra/newview/skins/apollo/textures/icn_voice-groupfocus.tga deleted file mode 100644 index 9f48d4609..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice-groupfocus.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice-localchat.tga b/indra/newview/skins/apollo/textures/icn_voice-localchat.tga deleted file mode 100644 index 7cf267eaf..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice-localchat.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice-pvtfocus.tga b/indra/newview/skins/apollo/textures/icn_voice-pvtfocus.tga deleted file mode 100644 index abadb09aa..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice-pvtfocus.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice_ptt-off.tga b/indra/newview/skins/apollo/textures/icn_voice_ptt-off.tga deleted file mode 100644 index 15ecbdff9..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice_ptt-off.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl1.tga b/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl1.tga deleted file mode 100644 index ae72af131..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl2.tga b/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl2.tga deleted file mode 100644 index 4dfc2dd29..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl3.tga b/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl3.tga deleted file mode 100644 index 018b0bef4..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice_ptt-on-lvl3.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icn_voice_ptt-on.tga b/indra/newview/skins/apollo/textures/icn_voice_ptt-on.tga deleted file mode 100644 index 9eb643110..000000000 Binary files a/indra/newview/skins/apollo/textures/icn_voice_ptt-on.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_auction.tga b/indra/newview/skins/apollo/textures/icon_auction.tga deleted file mode 100644 index d121833b4..000000000 Binary files a/indra/newview/skins/apollo/textures/icon_auction.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_avatar_online.tga b/indra/newview/skins/apollo/textures/icon_avatar_online.tga deleted file mode 100644 index 45221213e..000000000 Binary files a/indra/newview/skins/apollo/textures/icon_avatar_online.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_day_cycle.tga b/indra/newview/skins/apollo/textures/icon_day_cycle.tga deleted file mode 100644 index 2d5dee1e9..000000000 Binary files a/indra/newview/skins/apollo/textures/icon_day_cycle.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_diurnal.tga b/indra/newview/skins/apollo/textures/icon_diurnal.tga deleted file mode 100644 index fc720c826..000000000 Binary files a/indra/newview/skins/apollo/textures/icon_diurnal.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_event_mature.tga b/indra/newview/skins/apollo/textures/icon_event_mature.tga deleted file mode 100644 index 61c879bc9..000000000 Binary files a/indra/newview/skins/apollo/textures/icon_event_mature.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/icon_popular.tga b/indra/newview/skins/apollo/textures/icon_popular.tga deleted file mode 100644 index f1165b8aa..000000000 Binary files a/indra/newview/skins/apollo/textures/icon_popular.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/lag_status_critical.tga b/indra/newview/skins/apollo/textures/lag_status_critical.tga deleted file mode 100644 index bbc71d9e7..000000000 Binary files a/indra/newview/skins/apollo/textures/lag_status_critical.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/lag_status_good.tga b/indra/newview/skins/apollo/textures/lag_status_good.tga deleted file mode 100644 index 680ba90f1..000000000 Binary files a/indra/newview/skins/apollo/textures/lag_status_good.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/lag_status_warning.tga b/indra/newview/skins/apollo/textures/lag_status_warning.tga deleted file mode 100644 index 13ce3cc39..000000000 Binary files a/indra/newview/skins/apollo/textures/lag_status_warning.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/legend.tga b/indra/newview/skins/apollo/textures/legend.tga deleted file mode 100644 index 0dbb8fda4..000000000 Binary files a/indra/newview/skins/apollo/textures/legend.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/lightgray.tga b/indra/newview/skins/apollo/textures/lightgray.tga deleted file mode 100644 index 2063d685a..000000000 Binary files a/indra/newview/skins/apollo/textures/lightgray.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_16.tga b/indra/newview/skins/apollo/textures/map_avatar_16.tga deleted file mode 100644 index ce129e359..000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_16.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_32.tga b/indra/newview/skins/apollo/textures/map_avatar_32.tga deleted file mode 100644 index aebeab409..000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_32.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_8.tga b/indra/newview/skins/apollo/textures/map_avatar_8.tga deleted file mode 100644 index 28552f223..000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_8.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_above_32.tga b/indra/newview/skins/apollo/textures/map_avatar_above_32.tga deleted file mode 100644 index 65bd0561a..000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_above_32.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_above_8.tga b/indra/newview/skins/apollo/textures/map_avatar_above_8.tga deleted file mode 100644 index 193428e53..000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_above_8.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_below_32.tga b/indra/newview/skins/apollo/textures/map_avatar_below_32.tga deleted file mode 100644 index 496c44b36..000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_below_32.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_below_8.tga b/indra/newview/skins/apollo/textures/map_avatar_below_8.tga deleted file mode 100644 index 9e14bfab9..000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_below_8.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_you_32.tga b/indra/newview/skins/apollo/textures/map_avatar_you_32.tga deleted file mode 100644 index 782207efd..000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_you_32.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_avatar_you_8.tga b/indra/newview/skins/apollo/textures/map_avatar_you_8.tga deleted file mode 100644 index 61f319fd9..000000000 Binary files a/indra/newview/skins/apollo/textures/map_avatar_you_8.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_home.tga b/indra/newview/skins/apollo/textures/map_home.tga deleted file mode 100644 index 7478de371..000000000 Binary files a/indra/newview/skins/apollo/textures/map_home.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_infohub.tga b/indra/newview/skins/apollo/textures/map_infohub.tga deleted file mode 100644 index 173b93e39..000000000 Binary files a/indra/newview/skins/apollo/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_track_16.tga b/indra/newview/skins/apollo/textures/map_track_16.tga deleted file mode 100644 index 451ce24cf..000000000 Binary files a/indra/newview/skins/apollo/textures/map_track_16.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/map_track_8.tga b/indra/newview/skins/apollo/textures/map_track_8.tga deleted file mode 100644 index 53425ff45..000000000 Binary files a/indra/newview/skins/apollo/textures/map_track_8.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/media_icon.tga b/indra/newview/skins/apollo/textures/media_icon.tga deleted file mode 100644 index 289520cde..000000000 Binary files a/indra/newview/skins/apollo/textures/media_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/minimize.tga b/indra/newview/skins/apollo/textures/minimize.tga deleted file mode 100644 index a21fd9148..000000000 Binary files a/indra/newview/skins/apollo/textures/minimize.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/missing_asset.tga b/indra/newview/skins/apollo/textures/missing_asset.tga deleted file mode 100644 index 9a43f4db5..000000000 Binary files a/indra/newview/skins/apollo/textures/missing_asset.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/music_icon.tga b/indra/newview/skins/apollo/textures/music_icon.tga deleted file mode 100644 index aeaff02e0..000000000 Binary files a/indra/newview/skins/apollo/textures/music_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/mute_icon.tga b/indra/newview/skins/apollo/textures/mute_icon.tga deleted file mode 100644 index 879b9e618..000000000 Binary files a/indra/newview/skins/apollo/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/notify_box_icon.tga b/indra/newview/skins/apollo/textures/notify_box_icon.tga deleted file mode 100644 index 0672c89ee..000000000 Binary files a/indra/newview/skins/apollo/textures/notify_box_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/notify_caution_icon.tga b/indra/newview/skins/apollo/textures/notify_caution_icon.tga deleted file mode 100644 index abc23d1d7..000000000 Binary files a/indra/newview/skins/apollo/textures/notify_caution_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/notify_tip_icon.tga b/indra/newview/skins/apollo/textures/notify_tip_icon.tga deleted file mode 100644 index f79a634a9..000000000 Binary files a/indra/newview/skins/apollo/textures/notify_tip_icon.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/progress_fill.tga b/indra/newview/skins/apollo/textures/progress_fill.tga deleted file mode 100644 index a913fe762..000000000 Binary files a/indra/newview/skins/apollo/textures/progress_fill.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/propertyline.tga b/indra/newview/skins/apollo/textures/propertyline.tga deleted file mode 100644 index 0c504eea7..000000000 Binary files a/indra/newview/skins/apollo/textures/propertyline.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_dark.png b/indra/newview/skins/apollo/textures/skin_thumbnail_dark.png deleted file mode 100644 index fc102a014..000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_dark.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_default.png b/indra/newview/skins/apollo/textures/skin_thumbnail_default.png deleted file mode 100644 index e22b1c164..000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_default.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_gred.png b/indra/newview/skins/apollo/textures/skin_thumbnail_gred.png deleted file mode 100644 index d60584743..000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_gred.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_phoenix.png b/indra/newview/skins/apollo/textures/skin_thumbnail_phoenix.png deleted file mode 100644 index f2ab49e6d..000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_phoenix.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_pslgreen.png b/indra/newview/skins/apollo/textures/skin_thumbnail_pslgreen.png deleted file mode 100644 index 3eb7263d6..000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_pslgreen.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_pslpurple.png b/indra/newview/skins/apollo/textures/skin_thumbnail_pslpurple.png deleted file mode 100644 index 877514d8c..000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_pslpurple.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_ruby.png b/indra/newview/skins/apollo/textures/skin_thumbnail_ruby.png deleted file mode 100644 index 944b51985..000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_ruby.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_saphire.png b/indra/newview/skins/apollo/textures/skin_thumbnail_saphire.png deleted file mode 100644 index 2ee896780..000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_saphire.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/skin_thumbnail_silver.png b/indra/newview/skins/apollo/textures/skin_thumbnail_silver.png deleted file mode 100644 index 51f4cceb0..000000000 Binary files a/indra/newview/skins/apollo/textures/skin_thumbnail_silver.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/slim_icon_16_viewer.tga b/indra/newview/skins/apollo/textures/slim_icon_16_viewer.tga deleted file mode 100644 index 552181d36..000000000 Binary files a/indra/newview/skins/apollo/textures/slim_icon_16_viewer.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/sm_rounded_corners_simple.tga b/indra/newview/skins/apollo/textures/sm_rounded_corners_simple.tga deleted file mode 100644 index 85157e461..000000000 Binary files a/indra/newview/skins/apollo/textures/sm_rounded_corners_simple.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/smicon_warn.tga b/indra/newview/skins/apollo/textures/smicon_warn.tga deleted file mode 100644 index 90ccaa07e..000000000 Binary files a/indra/newview/skins/apollo/textures/smicon_warn.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spacer24.tga b/indra/newview/skins/apollo/textures/spacer24.tga deleted file mode 100644 index c7cab6b38..000000000 Binary files a/indra/newview/skins/apollo/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spacer35.tga b/indra/newview/skins/apollo/textures/spacer35.tga deleted file mode 100644 index b88bc6680..000000000 Binary files a/indra/newview/skins/apollo/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spin_down_in_blue.tga b/indra/newview/skins/apollo/textures/spin_down_in_blue.tga deleted file mode 100644 index b9eb36ba9..000000000 Binary files a/indra/newview/skins/apollo/textures/spin_down_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spin_down_out_blue.tga b/indra/newview/skins/apollo/textures/spin_down_out_blue.tga deleted file mode 100644 index c9cb5e8bf..000000000 Binary files a/indra/newview/skins/apollo/textures/spin_down_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spin_up_in_blue.tga b/indra/newview/skins/apollo/textures/spin_up_in_blue.tga deleted file mode 100644 index b604b8843..000000000 Binary files a/indra/newview/skins/apollo/textures/spin_up_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/spin_up_out_blue.tga b/indra/newview/skins/apollo/textures/spin_up_out_blue.tga deleted file mode 100644 index 4e3941e45..000000000 Binary files a/indra/newview/skins/apollo/textures/spin_up_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_busy.tga b/indra/newview/skins/apollo/textures/status_busy.tga deleted file mode 100644 index 7743d9c7b..000000000 Binary files a/indra/newview/skins/apollo/textures/status_busy.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_health.tga b/indra/newview/skins/apollo/textures/status_health.tga deleted file mode 100644 index 3d5f455fc..000000000 Binary files a/indra/newview/skins/apollo/textures/status_health.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_money.tga b/indra/newview/skins/apollo/textures/status_money.tga deleted file mode 100644 index d5be31fc6..000000000 Binary files a/indra/newview/skins/apollo/textures/status_money.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_no_build.tga b/indra/newview/skins/apollo/textures/status_no_build.tga deleted file mode 100644 index 8e471e185..000000000 Binary files a/indra/newview/skins/apollo/textures/status_no_build.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_no_fly.tga b/indra/newview/skins/apollo/textures/status_no_fly.tga deleted file mode 100644 index cde2700ab..000000000 Binary files a/indra/newview/skins/apollo/textures/status_no_fly.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_no_push.tga b/indra/newview/skins/apollo/textures/status_no_push.tga deleted file mode 100644 index 5ccbfa50f..000000000 Binary files a/indra/newview/skins/apollo/textures/status_no_push.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_no_scripts.tga b/indra/newview/skins/apollo/textures/status_no_scripts.tga deleted file mode 100644 index 52ecdb1b8..000000000 Binary files a/indra/newview/skins/apollo/textures/status_no_scripts.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_no_voice.tga b/indra/newview/skins/apollo/textures/status_no_voice.tga deleted file mode 100644 index 4ab4498cb..000000000 Binary files a/indra/newview/skins/apollo/textures/status_no_voice.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_script_debug.tga b/indra/newview/skins/apollo/textures/status_script_debug.tga deleted file mode 100644 index 6fca61483..000000000 Binary files a/indra/newview/skins/apollo/textures/status_script_debug.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_search.tga b/indra/newview/skins/apollo/textures/status_search.tga deleted file mode 100644 index 3ac10c476..000000000 Binary files a/indra/newview/skins/apollo/textures/status_search.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_search_btn.png b/indra/newview/skins/apollo/textures/status_search_btn.png deleted file mode 100644 index e648ba849..000000000 Binary files a/indra/newview/skins/apollo/textures/status_search_btn.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_search_btn_pressed.png b/indra/newview/skins/apollo/textures/status_search_btn_pressed.png deleted file mode 100644 index ec4254f4d..000000000 Binary files a/indra/newview/skins/apollo/textures/status_search_btn_pressed.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/status_voice.tga b/indra/newview/skins/apollo/textures/status_voice.tga deleted file mode 100644 index 4ab4498cb..000000000 Binary files a/indra/newview/skins/apollo/textures/status_voice.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/tab_background_darkpurple.tga b/indra/newview/skins/apollo/textures/tab_background_darkpurple.tga deleted file mode 100644 index 8169f9869..000000000 Binary files a/indra/newview/skins/apollo/textures/tab_background_darkpurple.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/tab_background_lightgrey.tga b/indra/newview/skins/apollo/textures/tab_background_lightgrey.tga deleted file mode 100644 index c2f8818f7..000000000 Binary files a/indra/newview/skins/apollo/textures/tab_background_lightgrey.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/tab_background_purple.tga b/indra/newview/skins/apollo/textures/tab_background_purple.tga deleted file mode 100644 index aa01b3cb6..000000000 Binary files a/indra/newview/skins/apollo/textures/tab_background_purple.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/tabarea.tga b/indra/newview/skins/apollo/textures/tabarea.tga deleted file mode 100644 index 5517aebfc..000000000 Binary files a/indra/newview/skins/apollo/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/textures.xml b/indra/newview/skins/apollo/textures/textures.xml index 2c4b0cbea..48fcecbfe 100644 --- a/indra/newview/skins/apollo/textures/textures.xml +++ b/indra/newview/skins/apollo/textures/textures.xml @@ -1,382 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/indra/newview/skins/apollo/textures/toolbar_bg.tga b/indra/newview/skins/apollo/textures/toolbar_bg.tga deleted file mode 100644 index 3a0577627..000000000 Binary files a/indra/newview/skins/apollo/textures/toolbar_bg.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/toolbar_tab.tga b/indra/newview/skins/apollo/textures/toolbar_tab.tga deleted file mode 100644 index 5ea1a28d2..000000000 Binary files a/indra/newview/skins/apollo/textures/toolbar_tab.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/up_arrow.png b/indra/newview/skins/apollo/textures/up_arrow.png deleted file mode 100644 index a1a5d3823..000000000 Binary files a/indra/newview/skins/apollo/textures/up_arrow.png and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/up_arrow.tga b/indra/newview/skins/apollo/textures/up_arrow.tga deleted file mode 100644 index c2bd8cceb..000000000 Binary files a/indra/newview/skins/apollo/textures/up_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/uv_test2.tga b/indra/newview/skins/apollo/textures/uv_test2.tga deleted file mode 100644 index a16000d1e..000000000 Binary files a/indra/newview/skins/apollo/textures/uv_test2.tga and /dev/null differ diff --git a/indra/newview/skins/apollo/textures/white.tga b/indra/newview/skins/apollo/textures/white.tga deleted file mode 100644 index 9fe68631c..000000000 Binary files a/indra/newview/skins/apollo/textures/white.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/blackdark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e379309..000000000 Binary files a/indra/newview/skins/blackdark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/circle.tga b/indra/newview/skins/blackdark/textures/circle.tga deleted file mode 100644 index d7097e3a3..000000000 Binary files a/indra/newview/skins/blackdark/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef3..000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa..000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1..000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0..000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f946..000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/blackdark/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad34..000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/icn_clear_lineeditor.tga b/indra/newview/skins/blackdark/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c6..000000000 Binary files a/indra/newview/skins/blackdark/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/map_infohub.tga b/indra/newview/skins/blackdark/textures/map_infohub.tga deleted file mode 100644 index 173b93e39..000000000 Binary files a/indra/newview/skins/blackdark/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/mute_icon.tga b/indra/newview/skins/blackdark/textures/mute_icon.tga deleted file mode 100644 index 879b9e618..000000000 Binary files a/indra/newview/skins/blackdark/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/rounded_square.j2c b/indra/newview/skins/blackdark/textures/rounded_square.j2c deleted file mode 100644 index c3dfe8f10..000000000 Binary files a/indra/newview/skins/blackdark/textures/rounded_square.j2c and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/spacer24.tga b/indra/newview/skins/blackdark/textures/spacer24.tga deleted file mode 100644 index c7cab6b38..000000000 Binary files a/indra/newview/skins/blackdark/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/spacer35.tga b/indra/newview/skins/blackdark/textures/spacer35.tga deleted file mode 100644 index b88bc6680..000000000 Binary files a/indra/newview/skins/blackdark/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/tabarea.tga b/indra/newview/skins/blackdark/textures/tabarea.tga deleted file mode 100644 index 5517aebfc..000000000 Binary files a/indra/newview/skins/blackdark/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/blackdark/textures/textures.xml b/indra/newview/skins/blackdark/textures/textures.xml index 9f617f56b..1d61522a1 100644 --- a/indra/newview/skins/blackdark/textures/textures.xml +++ b/indra/newview/skins/blackdark/textures/textures.xml @@ -1,385 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/indra/newview/skins/blacklightblue/textures/icon_diurnal.tga b/indra/newview/skins/blacklightblue/textures/icon_diurnal.tga deleted file mode 100644 index fc720c826..000000000 Binary files a/indra/newview/skins/blacklightblue/textures/icon_diurnal.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/map_infohub.tga b/indra/newview/skins/blacklightblue/textures/map_infohub.tga deleted file mode 100644 index 173b93e39..000000000 Binary files a/indra/newview/skins/blacklightblue/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/mute_icon.tga b/indra/newview/skins/blacklightblue/textures/mute_icon.tga deleted file mode 100644 index 879b9e618..000000000 Binary files a/indra/newview/skins/blacklightblue/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/rounded_square.j2c b/indra/newview/skins/blacklightblue/textures/rounded_square.j2c deleted file mode 100644 index c3dfe8f10..000000000 Binary files a/indra/newview/skins/blacklightblue/textures/rounded_square.j2c and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/spacer24.tga b/indra/newview/skins/blacklightblue/textures/spacer24.tga deleted file mode 100644 index c7cab6b38..000000000 Binary files a/indra/newview/skins/blacklightblue/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/spacer35.tga b/indra/newview/skins/blacklightblue/textures/spacer35.tga deleted file mode 100644 index b88bc6680..000000000 Binary files a/indra/newview/skins/blacklightblue/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/tabarea.tga b/indra/newview/skins/blacklightblue/textures/tabarea.tga deleted file mode 100644 index 5517aebfc..000000000 Binary files a/indra/newview/skins/blacklightblue/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/blacklightblue/textures/textures.xml b/indra/newview/skins/blacklightblue/textures/textures.xml index 9f617f56b..1d61522a1 100644 --- a/indra/newview/skins/blacklightblue/textures/textures.xml +++ b/indra/newview/skins/blacklightblue/textures/textures.xml @@ -1,385 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/indra/newview/skins/blackred/textures/map_infohub.tga b/indra/newview/skins/blackred/textures/map_infohub.tga deleted file mode 100644 index 173b93e39..000000000 Binary files a/indra/newview/skins/blackred/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/blackred/textures/rounded_square.j2c b/indra/newview/skins/blackred/textures/rounded_square.j2c deleted file mode 100644 index c3dfe8f10..000000000 Binary files a/indra/newview/skins/blackred/textures/rounded_square.j2c and /dev/null differ diff --git a/indra/newview/skins/blackred/textures/textures.xml b/indra/newview/skins/blackred/textures/textures.xml index 9f617f56b..1d61522a1 100644 --- a/indra/newview/skins/blackred/textures/textures.xml +++ b/indra/newview/skins/blackred/textures/textures.xml @@ -1,385 +1,33 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/indra/newview/skins/blackred/textures/textures_new.xml b/indra/newview/skins/blackred/textures/textures_new.xml new file mode 100644 index 000000000..1d61522a1 --- /dev/null +++ b/indra/newview/skins/blackred/textures/textures_new.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/dark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/dark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e379309..000000000 Binary files a/indra/newview/skins/dark/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/circle.tga b/indra/newview/skins/dark/textures/circle.tga deleted file mode 100644 index d7097e3a3..000000000 Binary files a/indra/newview/skins/dark/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/folder_arrow.tga b/indra/newview/skins/dark/textures/folder_arrow.tga deleted file mode 100644 index 77d470731..000000000 Binary files a/indra/newview/skins/dark/textures/folder_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef3..000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa..000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1..000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/dark/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0..000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/dark/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f946..000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/dark/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad34..000000000 Binary files a/indra/newview/skins/dark/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_clear_lineeditor.tga b/indra/newview/skins/dark/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c6..000000000 Binary files a/indra/newview/skins/dark/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/icn_scrollbar.tga b/indra/newview/skins/dark/textures/icn_scrollbar.tga deleted file mode 100644 index a19a8a5d1..000000000 Binary files a/indra/newview/skins/dark/textures/icn_scrollbar.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/mute_icon.tga b/indra/newview/skins/dark/textures/mute_icon.tga deleted file mode 100644 index 879b9e618..000000000 Binary files a/indra/newview/skins/dark/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/spacer24.tga b/indra/newview/skins/dark/textures/spacer24.tga deleted file mode 100644 index c7cab6b38..000000000 Binary files a/indra/newview/skins/dark/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/spacer35.tga b/indra/newview/skins/dark/textures/spacer35.tga deleted file mode 100644 index b88bc6680..000000000 Binary files a/indra/newview/skins/dark/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/tabarea.tga b/indra/newview/skins/dark/textures/tabarea.tga deleted file mode 100644 index 5517aebfc..000000000 Binary files a/indra/newview/skins/dark/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/dark/textures/textures.xml b/indra/newview/skins/dark/textures/textures.xml deleted file mode 100644 index 451b70062..000000000 --- a/indra/newview/skins/dark/textures/textures.xml +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/darkcatalan/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/darkcatalan/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e379309..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/account_id_green.tga b/indra/newview/skins/darkcatalan/textures/account_id_green.tga deleted file mode 100644 index 9be215eed..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/account_id_green.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/account_id_orange.tga b/indra/newview/skins/darkcatalan/textures/account_id_orange.tga deleted file mode 100644 index 6b41e8663..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/account_id_orange.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/active_speakers.tga b/indra/newview/skins/darkcatalan/textures/active_speakers.tga deleted file mode 100644 index 02d3643d7..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/active_speakers.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/alpha_gradient.tga b/indra/newview/skins/darkcatalan/textures/alpha_gradient.tga deleted file mode 100644 index 6fdba25d4..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/alpha_gradient.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/avatar_gone.tga b/indra/newview/skins/darkcatalan/textures/avatar_gone.tga deleted file mode 100644 index e5c2c070b..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/avatar_gone.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/avatar_new.tga b/indra/newview/skins/darkcatalan/textures/avatar_new.tga deleted file mode 100644 index 854b70c32..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/avatar_new.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/checkerboard_transparency_bg.png b/indra/newview/skins/darkcatalan/textures/checkerboard_transparency_bg.png deleted file mode 100644 index fe06d38ef..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/checkerboard_transparency_bg.png and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/circle.tga b/indra/newview/skins/darkcatalan/textures/circle.tga deleted file mode 100644 index d7097e3a3..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/close_in_blue.tga b/indra/newview/skins/darkcatalan/textures/close_in_blue.tga deleted file mode 100644 index 8200eba32..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/close_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/close_inactive_blue.tga b/indra/newview/skins/darkcatalan/textures/close_inactive_blue.tga deleted file mode 100644 index 191c5d3e8..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/close_inactive_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/closebox.tga b/indra/newview/skins/darkcatalan/textures/closebox.tga deleted file mode 100644 index 294d4fb24..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/closebox.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/color_swatch_alpha.tga b/indra/newview/skins/darkcatalan/textures/color_swatch_alpha.tga deleted file mode 100644 index 814a004e6..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/color_swatch_alpha.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/combobox_arrow.tga b/indra/newview/skins/darkcatalan/textures/combobox_arrow.tga deleted file mode 100644 index ad08f32bb..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/combobox_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/crosshairs.tga b/indra/newview/skins/darkcatalan/textures/crosshairs.tga deleted file mode 100644 index ac4d63dc5..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/crosshairs.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/darkgray.tga b/indra/newview/skins/darkcatalan/textures/darkgray.tga deleted file mode 100644 index 2063d685a..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/darkgray.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/down_arrow.png b/indra/newview/skins/darkcatalan/textures/down_arrow.png deleted file mode 100644 index d376d980d..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/down_arrow.png and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/folder_arrow.tga b/indra/newview/skins/darkcatalan/textures/folder_arrow.tga deleted file mode 100644 index 77d470731..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/folder_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef3..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f946..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad34..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_clear_lineeditor.tga b/indra/newview/skins/darkcatalan/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c6..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_rounded-text-field.tga b/indra/newview/skins/darkcatalan/textures/icn_rounded-text-field.tga deleted file mode 100644 index 7da504f93..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_rounded-text-field.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_scrollbar.tga b/indra/newview/skins/darkcatalan/textures/icn_scrollbar.tga deleted file mode 100644 index a19a8a5d1..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_scrollbar.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_scrollbar_bg.tga b/indra/newview/skins/darkcatalan/textures/icn_scrollbar_bg.tga deleted file mode 100644 index 1e4bc7a8a..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_scrollbar_bg.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_scrollbar_thumb.tga b/indra/newview/skins/darkcatalan/textures/icn_scrollbar_thumb.tga deleted file mode 100644 index d63c31472..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_scrollbar_thumb.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_speaker-muted_dark.tga b/indra/newview/skins/darkcatalan/textures/icn_speaker-muted_dark.tga deleted file mode 100644 index a7d29a14b..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_speaker-muted_dark.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_textfield_enabled.tga b/indra/newview/skins/darkcatalan/textures/icn_textfield_enabled.tga deleted file mode 100644 index fc681a195..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_textfield_enabled.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice-call-end.tga b/indra/newview/skins/darkcatalan/textures/icn_voice-call-end.tga deleted file mode 100644 index 2da4e856b..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice-call-end.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice-call-start.tga b/indra/newview/skins/darkcatalan/textures/icn_voice-call-start.tga deleted file mode 100644 index 07701cb5a..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice-call-start.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice-groupfocus.tga b/indra/newview/skins/darkcatalan/textures/icn_voice-groupfocus.tga deleted file mode 100644 index 9f48d4609..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice-groupfocus.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice-pvtfocus.tga b/indra/newview/skins/darkcatalan/textures/icn_voice-pvtfocus.tga deleted file mode 100644 index abadb09aa..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice-pvtfocus.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl1.tga b/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl1.tga deleted file mode 100644 index ae72af131..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl2.tga b/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl2.tga deleted file mode 100644 index 4dfc2dd29..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl3.tga b/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl3.tga deleted file mode 100644 index 018b0bef4..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on-lvl3.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on.tga b/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on.tga deleted file mode 100644 index 9eb643110..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icn_voice_ptt-on.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_auction.tga b/indra/newview/skins/darkcatalan/textures/icon_auction.tga deleted file mode 100644 index d121833b4..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_auction.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_day_cycle.tga b/indra/newview/skins/darkcatalan/textures/icon_day_cycle.tga deleted file mode 100644 index 2d5dee1e9..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_day_cycle.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_diurnal.tga b/indra/newview/skins/darkcatalan/textures/icon_diurnal.tga deleted file mode 100644 index fc720c826..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_diurnal.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_event.tga b/indra/newview/skins/darkcatalan/textures/icon_event.tga deleted file mode 100644 index 7805dbce6..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_event.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_event_mature.tga b/indra/newview/skins/darkcatalan/textures/icon_event_mature.tga deleted file mode 100644 index 61c879bc9..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_event_mature.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_for_sale.tga b/indra/newview/skins/darkcatalan/textures/icon_for_sale.tga deleted file mode 100644 index 455b1aeb1..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_for_sale.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_group.tga b/indra/newview/skins/darkcatalan/textures/icon_group.tga deleted file mode 100644 index 22122d6cf..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_group.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_groupnotice.tga b/indra/newview/skins/darkcatalan/textures/icon_groupnotice.tga deleted file mode 100644 index edf2c6180..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_groupnotice.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_groupnoticeinventory.tga b/indra/newview/skins/darkcatalan/textures/icon_groupnoticeinventory.tga deleted file mode 100644 index f31390632..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_groupnoticeinventory.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_lock.tga b/indra/newview/skins/darkcatalan/textures/icon_lock.tga deleted file mode 100644 index 23521aa11..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_lock.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_place.tga b/indra/newview/skins/darkcatalan/textures/icon_place.tga deleted file mode 100644 index 2170c9849..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_place.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/icon_popular.tga b/indra/newview/skins/darkcatalan/textures/icon_popular.tga deleted file mode 100644 index f1165b8aa..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/icon_popular.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_animation.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_animation.tga deleted file mode 100644 index 1b4df7a2d..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_animation.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_bodypart.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_bodypart.tga deleted file mode 100644 index abcb1bda7..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_bodypart.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_callingcard.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_callingcard.tga deleted file mode 100644 index db7d8f7b0..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_callingcard.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_clothing.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_clothing.tga deleted file mode 100644 index d214789cb..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_clothing.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_gesture.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_gesture.tga deleted file mode 100644 index 83accbb1e..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_gesture.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_landmark.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_landmark.tga deleted file mode 100644 index 6923dd228..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_landmark.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_lostandfound.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_lostandfound.tga deleted file mode 100644 index 67f9a9a83..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_lostandfound.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_notecard.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_notecard.tga deleted file mode 100644 index 400ef3cc4..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_notecard.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_object.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_object.tga deleted file mode 100644 index c3d04bf27..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_object.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_plain_closed.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_plain_closed.tga deleted file mode 100644 index e351836e2..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_plain_closed.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_plain_open.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_plain_open.tga deleted file mode 100644 index 7bc80347b..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_plain_open.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_script.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_script.tga deleted file mode 100644 index 3e1a164da..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_script.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_snapshot.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_snapshot.tga deleted file mode 100644 index d32538d9c..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_snapshot.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_sound.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_sound.tga deleted file mode 100644 index 5e54c4774..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_sound.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_texture.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_texture.tga deleted file mode 100644 index 4fe75d07d..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_texture.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_folder_trash.tga b/indra/newview/skins/darkcatalan/textures/inv_folder_trash.tga deleted file mode 100644 index 54043e9cf..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_folder_trash.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_animation.tga b/indra/newview/skins/darkcatalan/textures/inv_item_animation.tga deleted file mode 100644 index 2b12b2809..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_animation.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_attach.tga b/indra/newview/skins/darkcatalan/textures/inv_item_attach.tga deleted file mode 100644 index 053899332..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_attach.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_offline.tga b/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_offline.tga deleted file mode 100644 index 44222d306..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_offline.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_online.tga b/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_online.tga deleted file mode 100644 index 42be4d2e1..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_callingcard_online.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_clothing.tga b/indra/newview/skins/darkcatalan/textures/inv_item_clothing.tga deleted file mode 100644 index 4c4c9391b..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_clothing.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_eyes.tga b/indra/newview/skins/darkcatalan/textures/inv_item_eyes.tga deleted file mode 100644 index 053ffbe23..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_eyes.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_gesture.tga b/indra/newview/skins/darkcatalan/textures/inv_item_gesture.tga deleted file mode 100644 index 52ac90c90..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_gesture.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_gloves.tga b/indra/newview/skins/darkcatalan/textures/inv_item_gloves.tga deleted file mode 100644 index 26041711b..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_gloves.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_hair.tga b/indra/newview/skins/darkcatalan/textures/inv_item_hair.tga deleted file mode 100644 index 03156a7b7..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_hair.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_jacket.tga b/indra/newview/skins/darkcatalan/textures/inv_item_jacket.tga deleted file mode 100644 index f37c593d8..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_jacket.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_landmark.tga b/indra/newview/skins/darkcatalan/textures/inv_item_landmark.tga deleted file mode 100644 index c161deb38..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_landmark.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_landmark_visited.tga b/indra/newview/skins/darkcatalan/textures/inv_item_landmark_visited.tga deleted file mode 100644 index 372a0f63f..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_landmark_visited.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_notecard.tga b/indra/newview/skins/darkcatalan/textures/inv_item_notecard.tga deleted file mode 100644 index 2534d1b2a..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_notecard.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_object.tga b/indra/newview/skins/darkcatalan/textures/inv_item_object.tga deleted file mode 100644 index edad15fdc..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_object.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_object_multi.tga b/indra/newview/skins/darkcatalan/textures/inv_item_object_multi.tga deleted file mode 100644 index 7af666b61..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_object_multi.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_pants.tga b/indra/newview/skins/darkcatalan/textures/inv_item_pants.tga deleted file mode 100644 index ec3246ea7..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_pants.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_script.tga b/indra/newview/skins/darkcatalan/textures/inv_item_script.tga deleted file mode 100644 index e396d0986..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_script.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_script_dangerous.tga b/indra/newview/skins/darkcatalan/textures/inv_item_script_dangerous.tga deleted file mode 100644 index 1ee742a8b..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_script_dangerous.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_shape.tga b/indra/newview/skins/darkcatalan/textures/inv_item_shape.tga deleted file mode 100644 index 5d9db4e44..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_shape.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_shirt.tga b/indra/newview/skins/darkcatalan/textures/inv_item_shirt.tga deleted file mode 100644 index 2e1c627da..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_shirt.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_shoes.tga b/indra/newview/skins/darkcatalan/textures/inv_item_shoes.tga deleted file mode 100644 index ae93bfe70..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_shoes.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_skin.tga b/indra/newview/skins/darkcatalan/textures/inv_item_skin.tga deleted file mode 100644 index f0d7f2059..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_skin.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_skirt.tga b/indra/newview/skins/darkcatalan/textures/inv_item_skirt.tga deleted file mode 100644 index d8f397285..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_skirt.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_snapshot.tga b/indra/newview/skins/darkcatalan/textures/inv_item_snapshot.tga deleted file mode 100644 index c9d41a68d..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_snapshot.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_socks.tga b/indra/newview/skins/darkcatalan/textures/inv_item_socks.tga deleted file mode 100644 index dabcf6d82..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_socks.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_sound.tga b/indra/newview/skins/darkcatalan/textures/inv_item_sound.tga deleted file mode 100644 index efa113226..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_sound.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_texture.tga b/indra/newview/skins/darkcatalan/textures/inv_item_texture.tga deleted file mode 100644 index fc5a42061..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_texture.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_underpants.tga b/indra/newview/skins/darkcatalan/textures/inv_item_underpants.tga deleted file mode 100644 index e712f9c5d..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_underpants.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/inv_item_undershirt.tga b/indra/newview/skins/darkcatalan/textures/inv_item_undershirt.tga deleted file mode 100644 index c7b4aae78..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/inv_item_undershirt.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/lag_status_critical.tga b/indra/newview/skins/darkcatalan/textures/lag_status_critical.tga deleted file mode 100644 index bbc71d9e7..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/lag_status_critical.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/lag_status_good.tga b/indra/newview/skins/darkcatalan/textures/lag_status_good.tga deleted file mode 100644 index 680ba90f1..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/lag_status_good.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/lag_status_warning.tga b/indra/newview/skins/darkcatalan/textures/lag_status_warning.tga deleted file mode 100644 index 13ce3cc39..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/lag_status_warning.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/legend.tga b/indra/newview/skins/darkcatalan/textures/legend.tga deleted file mode 100644 index 0dbb8fda4..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/legend.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/lightgray.tga b/indra/newview/skins/darkcatalan/textures/lightgray.tga deleted file mode 100644 index 2063d685a..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/lightgray.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_avatar_16.tga b/indra/newview/skins/darkcatalan/textures/map_avatar_16.tga deleted file mode 100644 index ce129e359..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_avatar_16.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_avatar_32.tga b/indra/newview/skins/darkcatalan/textures/map_avatar_32.tga deleted file mode 100644 index aebeab409..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_avatar_32.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_avatar_8.tga b/indra/newview/skins/darkcatalan/textures/map_avatar_8.tga deleted file mode 100644 index 28552f223..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_avatar_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_avatar_you_32.tga b/indra/newview/skins/darkcatalan/textures/map_avatar_you_32.tga deleted file mode 100644 index 782207efd..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_avatar_you_32.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_avatar_you_8.tga b/indra/newview/skins/darkcatalan/textures/map_avatar_you_8.tga deleted file mode 100644 index 61f319fd9..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_avatar_you_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_event.tga b/indra/newview/skins/darkcatalan/textures/map_event.tga deleted file mode 100644 index c229b379a..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_event.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_event_mature.tga b/indra/newview/skins/darkcatalan/textures/map_event_mature.tga deleted file mode 100644 index 61c879bc9..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_event_mature.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_home.tga b/indra/newview/skins/darkcatalan/textures/map_home.tga deleted file mode 100644 index 7478de371..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_home.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_infohub.tga b/indra/newview/skins/darkcatalan/textures/map_infohub.tga deleted file mode 100644 index d0134fa5f..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_telehub.tga b/indra/newview/skins/darkcatalan/textures/map_telehub.tga deleted file mode 100644 index ef63a3eb7..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_telehub.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_track_16.tga b/indra/newview/skins/darkcatalan/textures/map_track_16.tga deleted file mode 100644 index 451ce24cf..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_track_16.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/map_track_8.tga b/indra/newview/skins/darkcatalan/textures/map_track_8.tga deleted file mode 100644 index 53425ff45..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/map_track_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/media_icon.tga b/indra/newview/skins/darkcatalan/textures/media_icon.tga deleted file mode 100644 index 289520cde..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/media_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/minimize.tga b/indra/newview/skins/darkcatalan/textures/minimize.tga deleted file mode 100644 index a21fd9148..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/minimize.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/minimize_inactive.tga b/indra/newview/skins/darkcatalan/textures/minimize_inactive.tga deleted file mode 100644 index fcd62aa35..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/minimize_inactive.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/minimize_pressed.tga b/indra/newview/skins/darkcatalan/textures/minimize_pressed.tga deleted file mode 100644 index 0061dd5f5..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/minimize_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/missing_asset.tga b/indra/newview/skins/darkcatalan/textures/missing_asset.tga deleted file mode 100644 index 9a43f4db5..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/missing_asset.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/music_icon.tga b/indra/newview/skins/darkcatalan/textures/music_icon.tga deleted file mode 100644 index aeaff02e0..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/music_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/mute_icon.tga b/indra/newview/skins/darkcatalan/textures/mute_icon.tga deleted file mode 100644 index 879b9e618..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/notify_caution_icon.tga b/indra/newview/skins/darkcatalan/textures/notify_caution_icon.tga deleted file mode 100644 index 48c76ad91..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/notify_caution_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/propertyline.tga b/indra/newview/skins/darkcatalan/textures/propertyline.tga deleted file mode 100644 index 0c504eea7..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/propertyline.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/restore.tga b/indra/newview/skins/darkcatalan/textures/restore.tga deleted file mode 100644 index 87910e288..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/restore.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/restore_inactive.tga b/indra/newview/skins/darkcatalan/textures/restore_inactive.tga deleted file mode 100644 index dbbec7ea1..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/restore_inactive.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/restore_pressed.tga b/indra/newview/skins/darkcatalan/textures/restore_pressed.tga deleted file mode 100644 index 1922ca881..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/restore_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/scrollbutton_down_in_blue.tga b/indra/newview/skins/darkcatalan/textures/scrollbutton_down_in_blue.tga deleted file mode 100644 index 5e7379950..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/scrollbutton_down_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/scrollbutton_left_in_blue.tga b/indra/newview/skins/darkcatalan/textures/scrollbutton_left_in_blue.tga deleted file mode 100644 index 480842a3b..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/scrollbutton_left_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/scrollbutton_right_in_blue.tga b/indra/newview/skins/darkcatalan/textures/scrollbutton_right_in_blue.tga deleted file mode 100644 index 6d7f13bfc..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/scrollbutton_right_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/scrollbutton_up_in_blue.tga b/indra/newview/skins/darkcatalan/textures/scrollbutton_up_in_blue.tga deleted file mode 100644 index 4c6a8fe41..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/scrollbutton_up_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/slim_icon_16_viewer.tga b/indra/newview/skins/darkcatalan/textures/slim_icon_16_viewer.tga deleted file mode 100644 index 552181d36..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/slim_icon_16_viewer.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/sm_rounded_corners_simple.tga b/indra/newview/skins/darkcatalan/textures/sm_rounded_corners_simple.tga deleted file mode 100644 index 85157e461..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/sm_rounded_corners_simple.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/smicon_warn.tga b/indra/newview/skins/darkcatalan/textures/smicon_warn.tga deleted file mode 100644 index 90ccaa07e..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/smicon_warn.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/spacer24.tga b/indra/newview/skins/darkcatalan/textures/spacer24.tga deleted file mode 100644 index c7cab6b38..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/spacer35.tga b/indra/newview/skins/darkcatalan/textures/spacer35.tga deleted file mode 100644 index b88bc6680..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_busy.tga b/indra/newview/skins/darkcatalan/textures/status_busy.tga deleted file mode 100644 index 7743d9c7b..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_busy.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_health.tga b/indra/newview/skins/darkcatalan/textures/status_health.tga deleted file mode 100644 index 3d5f455fc..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_health.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_money.tga b/indra/newview/skins/darkcatalan/textures/status_money.tga deleted file mode 100644 index d5be31fc6..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_money.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_no_build.tga b/indra/newview/skins/darkcatalan/textures/status_no_build.tga deleted file mode 100644 index 8e471e185..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_no_build.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_no_fly.tga b/indra/newview/skins/darkcatalan/textures/status_no_fly.tga deleted file mode 100644 index cde2700ab..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_no_fly.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_no_push.tga b/indra/newview/skins/darkcatalan/textures/status_no_push.tga deleted file mode 100644 index 5ccbfa50f..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_no_push.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_no_scripts.tga b/indra/newview/skins/darkcatalan/textures/status_no_scripts.tga deleted file mode 100644 index 52ecdb1b8..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_no_scripts.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_no_voice.tga b/indra/newview/skins/darkcatalan/textures/status_no_voice.tga deleted file mode 100644 index 4ab4498cb..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_no_voice.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_script_debug.tga b/indra/newview/skins/darkcatalan/textures/status_script_debug.tga deleted file mode 100644 index 6fca61483..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_script_debug.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_search.tga b/indra/newview/skins/darkcatalan/textures/status_search.tga deleted file mode 100644 index 3ac10c476..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_search.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_search_btn.png b/indra/newview/skins/darkcatalan/textures/status_search_btn.png deleted file mode 100644 index e648ba849..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_search_btn.png and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_search_btn_pressed.png b/indra/newview/skins/darkcatalan/textures/status_search_btn_pressed.png deleted file mode 100644 index ec4254f4d..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_search_btn_pressed.png and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/status_voice.tga b/indra/newview/skins/darkcatalan/textures/status_voice.tga deleted file mode 100644 index 4ab4498cb..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/status_voice.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tab_background_darkpurple.tga b/indra/newview/skins/darkcatalan/textures/tab_background_darkpurple.tga deleted file mode 100644 index 8169f9869..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tab_background_darkpurple.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tab_background_lightgrey.tga b/indra/newview/skins/darkcatalan/textures/tab_background_lightgrey.tga deleted file mode 100644 index c2f8818f7..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tab_background_lightgrey.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tab_background_purple.tga b/indra/newview/skins/darkcatalan/textures/tab_background_purple.tga deleted file mode 100644 index aa01b3cb6..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tab_background_purple.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tabarea.tga b/indra/newview/skins/darkcatalan/textures/tabarea.tga deleted file mode 100644 index 5517aebfc..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tearoff_pressed.tga b/indra/newview/skins/darkcatalan/textures/tearoff_pressed.tga deleted file mode 100644 index 620d109de..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tearoff_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/tearoffbox.tga b/indra/newview/skins/darkcatalan/textures/tearoffbox.tga deleted file mode 100644 index 0670d2e91..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/tearoffbox.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/textures.xml b/indra/newview/skins/darkcatalan/textures/textures.xml index 2c4b0cbea..48fcecbfe 100644 --- a/indra/newview/skins/darkcatalan/textures/textures.xml +++ b/indra/newview/skins/darkcatalan/textures/textures.xml @@ -1,382 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/indra/newview/skins/darkcatalan/textures/uv_test2.tga b/indra/newview/skins/darkcatalan/textures/uv_test2.tga deleted file mode 100644 index a16000d1e..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/uv_test2.tga and /dev/null differ diff --git a/indra/newview/skins/darkcatalan/textures/white.tga b/indra/newview/skins/darkcatalan/textures/white.tga deleted file mode 100644 index 9fe68631c..000000000 Binary files a/indra/newview/skins/darkcatalan/textures/white.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/alpha_gradient.tga b/indra/newview/skins/darkgred/textures/alpha_gradient.tga deleted file mode 100644 index 6fdba25d4..000000000 Binary files a/indra/newview/skins/darkgred/textures/alpha_gradient.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/circle.tga b/indra/newview/skins/darkgred/textures/circle.tga deleted file mode 100644 index d7097e3a3..000000000 Binary files a/indra/newview/skins/darkgred/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/color_swatch_alpha.tga b/indra/newview/skins/darkgred/textures/color_swatch_alpha.tga deleted file mode 100644 index 814a004e6..000000000 Binary files a/indra/newview/skins/darkgred/textures/color_swatch_alpha.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/crosshairs.tga b/indra/newview/skins/darkgred/textures/crosshairs.tga deleted file mode 100644 index ac4d63dc5..000000000 Binary files a/indra/newview/skins/darkgred/textures/crosshairs.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/direction_arrow.tga b/indra/newview/skins/darkgred/textures/direction_arrow.tga deleted file mode 100644 index f3ef1068c..000000000 Binary files a/indra/newview/skins/darkgred/textures/direction_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/ff_edit_mine.tga b/indra/newview/skins/darkgred/textures/ff_edit_mine.tga deleted file mode 100644 index 8f0c35b98..000000000 Binary files a/indra/newview/skins/darkgred/textures/ff_edit_mine.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/ff_edit_theirs.tga b/indra/newview/skins/darkgred/textures/ff_edit_theirs.tga deleted file mode 100644 index 005ada2de..000000000 Binary files a/indra/newview/skins/darkgred/textures/ff_edit_theirs.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/icn_clear_lineeditor.tga b/indra/newview/skins/darkgred/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c6..000000000 Binary files a/indra/newview/skins/darkgred/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/icn_scrollbar.tga b/indra/newview/skins/darkgred/textures/icn_scrollbar.tga deleted file mode 100644 index a19a8a5d1..000000000 Binary files a/indra/newview/skins/darkgred/textures/icn_scrollbar.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/map_avatar_above_8.tga b/indra/newview/skins/darkgred/textures/map_avatar_above_8.tga deleted file mode 100644 index 193428e53..000000000 Binary files a/indra/newview/skins/darkgred/textures/map_avatar_above_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/map_avatar_below_8.tga b/indra/newview/skins/darkgred/textures/map_avatar_below_8.tga deleted file mode 100644 index 9e14bfab9..000000000 Binary files a/indra/newview/skins/darkgred/textures/map_avatar_below_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/propertyline.tga b/indra/newview/skins/darkgred/textures/propertyline.tga deleted file mode 100644 index 0c504eea7..000000000 Binary files a/indra/newview/skins/darkgred/textures/propertyline.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/tabarea.tga b/indra/newview/skins/darkgred/textures/tabarea.tga deleted file mode 100644 index 5517aebfc..000000000 Binary files a/indra/newview/skins/darkgred/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/darkgred/textures/textures.xml b/indra/newview/skins/darkgred/textures/textures.xml deleted file mode 100644 index 451b70062..000000000 --- a/indra/newview/skins/darkgred/textures/textures.xml +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/darkgreen/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/darkgreen/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e379309..000000000 Binary files a/indra/newview/skins/darkgreen/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/circle.tga b/indra/newview/skins/darkgreen/textures/circle.tga deleted file mode 100644 index d7097e3a3..000000000 Binary files a/indra/newview/skins/darkgreen/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/folder_arrow.tga b/indra/newview/skins/darkgreen/textures/folder_arrow.tga deleted file mode 100644 index 77d470731..000000000 Binary files a/indra/newview/skins/darkgreen/textures/folder_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef3..000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa..000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1..000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0..000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f946..000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad34..000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_clear_lineeditor.tga b/indra/newview/skins/darkgreen/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c6..000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/icn_scrollbar.tga b/indra/newview/skins/darkgreen/textures/icn_scrollbar.tga deleted file mode 100644 index a19a8a5d1..000000000 Binary files a/indra/newview/skins/darkgreen/textures/icn_scrollbar.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/mute_icon.tga b/indra/newview/skins/darkgreen/textures/mute_icon.tga deleted file mode 100644 index 879b9e618..000000000 Binary files a/indra/newview/skins/darkgreen/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/spacer24.tga b/indra/newview/skins/darkgreen/textures/spacer24.tga deleted file mode 100644 index c7cab6b38..000000000 Binary files a/indra/newview/skins/darkgreen/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/spacer35.tga b/indra/newview/skins/darkgreen/textures/spacer35.tga deleted file mode 100644 index b88bc6680..000000000 Binary files a/indra/newview/skins/darkgreen/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/tabarea.tga b/indra/newview/skins/darkgreen/textures/tabarea.tga deleted file mode 100644 index 5517aebfc..000000000 Binary files a/indra/newview/skins/darkgreen/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/darkgreen/textures/textures.xml b/indra/newview/skins/darkgreen/textures/textures.xml deleted file mode 100644 index 451b70062..000000000 --- a/indra/newview/skins/darkgreen/textures/textures.xml +++ /dev/null @@ -1,389 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/indra/newview/skins/darkorange/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga b/indra/newview/skins/darkorange/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga deleted file mode 100644 index fb6dac0c3..000000000 Binary files a/indra/newview/skins/darkorange/textures/3c18c87e-5f50-14e2-e744-f44734aa365f.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga b/indra/newview/skins/darkorange/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga deleted file mode 100644 index 55e379309..000000000 Binary files a/indra/newview/skins/darkorange/textures/5748decc-f629-461c-9a36-a35a221fe21f.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga b/indra/newview/skins/darkorange/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga deleted file mode 100644 index 010c748c2..000000000 Binary files a/indra/newview/skins/darkorange/textures/7dabc040-ec13-2309-ddf7-4f161f6de2f4.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga b/indra/newview/skins/darkorange/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga deleted file mode 100644 index e0656c901..000000000 Binary files a/indra/newview/skins/darkorange/textures/9cad3e6d-2d6d-107d-f8ab-5ba272b5bfe1.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/account_id_green.tga b/indra/newview/skins/darkorange/textures/account_id_green.tga deleted file mode 100644 index 9be215eed..000000000 Binary files a/indra/newview/skins/darkorange/textures/account_id_green.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/account_id_orange.tga b/indra/newview/skins/darkorange/textures/account_id_orange.tga deleted file mode 100644 index 6b41e8663..000000000 Binary files a/indra/newview/skins/darkorange/textures/account_id_orange.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/active_speakers.tga b/indra/newview/skins/darkorange/textures/active_speakers.tga deleted file mode 100644 index 02d3643d7..000000000 Binary files a/indra/newview/skins/darkorange/textures/active_speakers.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/active_voice_tab.tga b/indra/newview/skins/darkorange/textures/active_voice_tab.tga deleted file mode 100644 index 2d0dfaabc..000000000 Binary files a/indra/newview/skins/darkorange/textures/active_voice_tab.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/alpha_gradient.tga b/indra/newview/skins/darkorange/textures/alpha_gradient.tga deleted file mode 100644 index 6fdba25d4..000000000 Binary files a/indra/newview/skins/darkorange/textures/alpha_gradient.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/alpha_gradient_2d.j2c b/indra/newview/skins/darkorange/textures/alpha_gradient_2d.j2c deleted file mode 100644 index 5de5a80a6..000000000 Binary files a/indra/newview/skins/darkorange/textures/alpha_gradient_2d.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/arrow_down.tga b/indra/newview/skins/darkorange/textures/arrow_down.tga deleted file mode 100644 index 81dc9d3b6..000000000 Binary files a/indra/newview/skins/darkorange/textures/arrow_down.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/arrow_up.tga b/indra/newview/skins/darkorange/textures/arrow_up.tga deleted file mode 100644 index 22195cf7f..000000000 Binary files a/indra/newview/skins/darkorange/textures/arrow_up.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/avatar_gone.tga b/indra/newview/skins/darkorange/textures/avatar_gone.tga deleted file mode 100644 index e5c2c070b..000000000 Binary files a/indra/newview/skins/darkorange/textures/avatar_gone.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/avatar_new.tga b/indra/newview/skins/darkorange/textures/avatar_new.tga deleted file mode 100644 index 854b70c32..000000000 Binary files a/indra/newview/skins/darkorange/textures/avatar_new.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/avatar_thumb_bkgrnd.j2c b/indra/newview/skins/darkorange/textures/avatar_thumb_bkgrnd.j2c deleted file mode 100644 index 555551ba1..000000000 Binary files a/indra/newview/skins/darkorange/textures/avatar_thumb_bkgrnd.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/avatar_typing.tga b/indra/newview/skins/darkorange/textures/avatar_typing.tga deleted file mode 100644 index 2c549025d..000000000 Binary files a/indra/newview/skins/darkorange/textures/avatar_typing.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/badge_error.j2c b/indra/newview/skins/darkorange/textures/badge_error.j2c deleted file mode 100644 index e8f3da507..000000000 Binary files a/indra/newview/skins/darkorange/textures/badge_error.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/badge_note.j2c b/indra/newview/skins/darkorange/textures/badge_note.j2c deleted file mode 100644 index 1ab5233fa..000000000 Binary files a/indra/newview/skins/darkorange/textures/badge_note.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/badge_ok.j2c b/indra/newview/skins/darkorange/textures/badge_ok.j2c deleted file mode 100644 index f85b880f1..000000000 Binary files a/indra/newview/skins/darkorange/textures/badge_ok.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/badge_warn.j2c b/indra/newview/skins/darkorange/textures/badge_warn.j2c deleted file mode 100644 index 26437ca42..000000000 Binary files a/indra/newview/skins/darkorange/textures/badge_warn.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/black.tga b/indra/newview/skins/darkorange/textures/black.tga deleted file mode 100644 index e69be0893..000000000 Binary files a/indra/newview/skins/darkorange/textures/black.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/checkbox_disabled_false.tga b/indra/newview/skins/darkorange/textures/checkbox_disabled_false.tga deleted file mode 100644 index 16c239227..000000000 Binary files a/indra/newview/skins/darkorange/textures/checkbox_disabled_false.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/checkbox_disabled_true.tga b/indra/newview/skins/darkorange/textures/checkbox_disabled_true.tga deleted file mode 100644 index 04a8d516f..000000000 Binary files a/indra/newview/skins/darkorange/textures/checkbox_disabled_true.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/checkbox_enabled_false.tga b/indra/newview/skins/darkorange/textures/checkbox_enabled_false.tga deleted file mode 100644 index a604a4409..000000000 Binary files a/indra/newview/skins/darkorange/textures/checkbox_enabled_false.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/checkbox_enabled_true.tga b/indra/newview/skins/darkorange/textures/checkbox_enabled_true.tga deleted file mode 100644 index 4a1b504ea..000000000 Binary files a/indra/newview/skins/darkorange/textures/checkbox_enabled_true.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/checkerboard_transparency_bg.png b/indra/newview/skins/darkorange/textures/checkerboard_transparency_bg.png deleted file mode 100644 index fe06d38ef..000000000 Binary files a/indra/newview/skins/darkorange/textures/checkerboard_transparency_bg.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/circle.tga b/indra/newview/skins/darkorange/textures/circle.tga deleted file mode 100644 index d7097e3a3..000000000 Binary files a/indra/newview/skins/darkorange/textures/circle.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/close_in_blue.tga b/indra/newview/skins/darkorange/textures/close_in_blue.tga deleted file mode 100644 index 8200eba32..000000000 Binary files a/indra/newview/skins/darkorange/textures/close_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/close_inactive_blue.tga b/indra/newview/skins/darkorange/textures/close_inactive_blue.tga deleted file mode 100644 index 191c5d3e8..000000000 Binary files a/indra/newview/skins/darkorange/textures/close_inactive_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/closebox.tga b/indra/newview/skins/darkorange/textures/closebox.tga deleted file mode 100644 index 294d4fb24..000000000 Binary files a/indra/newview/skins/darkorange/textures/closebox.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/cloud-particle.j2c b/indra/newview/skins/darkorange/textures/cloud-particle.j2c deleted file mode 100644 index 6c03bf6d0..000000000 Binary files a/indra/newview/skins/darkorange/textures/cloud-particle.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/color_swatch_alpha.tga b/indra/newview/skins/darkorange/textures/color_swatch_alpha.tga deleted file mode 100644 index 814a004e6..000000000 Binary files a/indra/newview/skins/darkorange/textures/color_swatch_alpha.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/combobox_arrow.tga b/indra/newview/skins/darkorange/textures/combobox_arrow.tga deleted file mode 100644 index ad08f32bb..000000000 Binary files a/indra/newview/skins/darkorange/textures/combobox_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/crosshairs.tga b/indra/newview/skins/darkorange/textures/crosshairs.tga deleted file mode 100644 index ac4d63dc5..000000000 Binary files a/indra/newview/skins/darkorange/textures/crosshairs.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/darkgray.tga b/indra/newview/skins/darkorange/textures/darkgray.tga deleted file mode 100644 index 2063d685a..000000000 Binary files a/indra/newview/skins/darkorange/textures/darkgray.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/direction_arrow.tga b/indra/newview/skins/darkorange/textures/direction_arrow.tga deleted file mode 100644 index f3ef1068c..000000000 Binary files a/indra/newview/skins/darkorange/textures/direction_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/down_arrow.png b/indra/newview/skins/darkorange/textures/down_arrow.png deleted file mode 100644 index d376d980d..000000000 Binary files a/indra/newview/skins/darkorange/textures/down_arrow.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/eye_button_active.tga b/indra/newview/skins/darkorange/textures/eye_button_active.tga deleted file mode 100644 index 014f785a7..000000000 Binary files a/indra/newview/skins/darkorange/textures/eye_button_active.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/eye_button_inactive.tga b/indra/newview/skins/darkorange/textures/eye_button_inactive.tga deleted file mode 100644 index 8666f0bbe..000000000 Binary files a/indra/newview/skins/darkorange/textures/eye_button_inactive.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/folder_arrow.tga b/indra/newview/skins/darkorange/textures/folder_arrow.tga deleted file mode 100644 index 77d470731..000000000 Binary files a/indra/newview/skins/darkorange/textures/folder_arrow.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/foot_shadow.j2c b/indra/newview/skins/darkorange/textures/foot_shadow.j2c deleted file mode 100644 index f9ce9da7d..000000000 Binary files a/indra/newview/skins/darkorange/textures/foot_shadow.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl0.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl0.tga deleted file mode 100644 index 35846cef3..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl0.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl1.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl1.tga deleted file mode 100644 index 1f9f564fa..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl2.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl2.tga deleted file mode 100644 index b2e5609f1..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-dot-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing1.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-typing1.tga deleted file mode 100644 index 3706c96e0..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing1.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing2.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-typing2.tga deleted file mode 100644 index 0d127f946..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing2.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing3.tga b/indra/newview/skins/darkorange/textures/icn_active-speakers-typing3.tga deleted file mode 100644 index 031b3ad34..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_active-speakers-typing3.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_clear_lineeditor.tga b/indra/newview/skins/darkorange/textures/icn_clear_lineeditor.tga deleted file mode 100644 index 8cd8310c6..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_clear_lineeditor.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_rounded-text-field.tga b/indra/newview/skins/darkorange/textures/icn_rounded-text-field.tga deleted file mode 100644 index 7da504f93..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_rounded-text-field.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice-call-end.tga b/indra/newview/skins/darkorange/textures/icn_voice-call-end.tga deleted file mode 100644 index 2da4e856b..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice-call-end.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice-call-start.tga b/indra/newview/skins/darkorange/textures/icn_voice-call-start.tga deleted file mode 100644 index 07701cb5a..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice-call-start.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice-groupfocus.tga b/indra/newview/skins/darkorange/textures/icn_voice-groupfocus.tga deleted file mode 100644 index 9f48d4609..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice-groupfocus.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice-localchat.tga b/indra/newview/skins/darkorange/textures/icn_voice-localchat.tga deleted file mode 100644 index 7cf267eaf..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice-localchat.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice-pvtfocus.tga b/indra/newview/skins/darkorange/textures/icn_voice-pvtfocus.tga deleted file mode 100644 index abadb09aa..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice-pvtfocus.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice_ptt-off.tga b/indra/newview/skins/darkorange/textures/icn_voice_ptt-off.tga deleted file mode 100644 index 15ecbdff9..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice_ptt-off.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl1.tga b/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl1.tga deleted file mode 100644 index ae72af131..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl1.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl2.tga b/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl2.tga deleted file mode 100644 index 4dfc2dd29..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl2.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl3.tga b/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl3.tga deleted file mode 100644 index 018b0bef4..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on-lvl3.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on.tga b/indra/newview/skins/darkorange/textures/icn_voice_ptt-on.tga deleted file mode 100644 index 9eb643110..000000000 Binary files a/indra/newview/skins/darkorange/textures/icn_voice_ptt-on.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_auction.tga b/indra/newview/skins/darkorange/textures/icon_auction.tga deleted file mode 100644 index d121833b4..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_auction.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_day_cycle.tga b/indra/newview/skins/darkorange/textures/icon_day_cycle.tga deleted file mode 100644 index 2d5dee1e9..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_day_cycle.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_diurnal.tga b/indra/newview/skins/darkorange/textures/icon_diurnal.tga deleted file mode 100644 index fc720c826..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_diurnal.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_event.tga b/indra/newview/skins/darkorange/textures/icon_event.tga deleted file mode 100644 index 7805dbce6..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_event.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_event_mature.tga b/indra/newview/skins/darkorange/textures/icon_event_mature.tga deleted file mode 100644 index 61c879bc9..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_event_mature.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_for_sale.tga b/indra/newview/skins/darkorange/textures/icon_for_sale.tga deleted file mode 100644 index 455b1aeb1..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_for_sale.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_group.tga b/indra/newview/skins/darkorange/textures/icon_group.tga deleted file mode 100644 index 22122d6cf..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_group.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_groupnotice.tga b/indra/newview/skins/darkorange/textures/icon_groupnotice.tga deleted file mode 100644 index edf2c6180..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_groupnotice.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_groupnoticeinventory.tga b/indra/newview/skins/darkorange/textures/icon_groupnoticeinventory.tga deleted file mode 100644 index f31390632..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_groupnoticeinventory.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_lock.tga b/indra/newview/skins/darkorange/textures/icon_lock.tga deleted file mode 100644 index 23521aa11..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_lock.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_place.tga b/indra/newview/skins/darkorange/textures/icon_place.tga deleted file mode 100644 index 2170c9849..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_place.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/icon_popular.tga b/indra/newview/skins/darkorange/textures/icon_popular.tga deleted file mode 100644 index f1165b8aa..000000000 Binary files a/indra/newview/skins/darkorange/textures/icon_popular.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_folder_trash.tga b/indra/newview/skins/darkorange/textures/inv_folder_trash.tga deleted file mode 100644 index 54043e9cf..000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_folder_trash.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_animation.tga b/indra/newview/skins/darkorange/textures/inv_item_animation.tga deleted file mode 100644 index 2b12b2809..000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_animation.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_attach.tga b/indra/newview/skins/darkorange/textures/inv_item_attach.tga deleted file mode 100644 index 053899332..000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_attach.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_callingcard_offline.tga b/indra/newview/skins/darkorange/textures/inv_item_callingcard_offline.tga deleted file mode 100644 index 44222d306..000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_callingcard_offline.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_callingcard_online.tga b/indra/newview/skins/darkorange/textures/inv_item_callingcard_online.tga deleted file mode 100644 index 42be4d2e1..000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_callingcard_online.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_gesture.tga b/indra/newview/skins/darkorange/textures/inv_item_gesture.tga deleted file mode 100644 index 52ac90c90..000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_gesture.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/inv_item_notecard.tga b/indra/newview/skins/darkorange/textures/inv_item_notecard.tga deleted file mode 100644 index 2534d1b2a..000000000 Binary files a/indra/newview/skins/darkorange/textures/inv_item_notecard.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/lag_status_critical.tga b/indra/newview/skins/darkorange/textures/lag_status_critical.tga deleted file mode 100644 index bbc71d9e7..000000000 Binary files a/indra/newview/skins/darkorange/textures/lag_status_critical.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/lag_status_good.tga b/indra/newview/skins/darkorange/textures/lag_status_good.tga deleted file mode 100644 index 680ba90f1..000000000 Binary files a/indra/newview/skins/darkorange/textures/lag_status_good.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/lag_status_warning.tga b/indra/newview/skins/darkorange/textures/lag_status_warning.tga deleted file mode 100644 index 13ce3cc39..000000000 Binary files a/indra/newview/skins/darkorange/textures/lag_status_warning.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/legend.tga b/indra/newview/skins/darkorange/textures/legend.tga deleted file mode 100644 index 0dbb8fda4..000000000 Binary files a/indra/newview/skins/darkorange/textures/legend.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/lightgray.tga b/indra/newview/skins/darkorange/textures/lightgray.tga deleted file mode 100644 index 2063d685a..000000000 Binary files a/indra/newview/skins/darkorange/textures/lightgray.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_avatar_16.tga b/indra/newview/skins/darkorange/textures/map_avatar_16.tga deleted file mode 100644 index ce129e359..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_avatar_16.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_avatar_8.tga b/indra/newview/skins/darkorange/textures/map_avatar_8.tga deleted file mode 100644 index 28552f223..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_avatar_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_avatar_above_8.tga b/indra/newview/skins/darkorange/textures/map_avatar_above_8.tga deleted file mode 100644 index 193428e53..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_avatar_above_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_avatar_below_8.tga b/indra/newview/skins/darkorange/textures/map_avatar_below_8.tga deleted file mode 100644 index 9e14bfab9..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_avatar_below_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_avatar_you_8.tga b/indra/newview/skins/darkorange/textures/map_avatar_you_8.tga deleted file mode 100644 index 61f319fd9..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_avatar_you_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_event.tga b/indra/newview/skins/darkorange/textures/map_event.tga deleted file mode 100644 index c229b379a..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_event.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_event_mature.tga b/indra/newview/skins/darkorange/textures/map_event_mature.tga deleted file mode 100644 index 61c879bc9..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_event_mature.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_home.tga b/indra/newview/skins/darkorange/textures/map_home.tga deleted file mode 100644 index 7478de371..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_home.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_infohub.tga b/indra/newview/skins/darkorange/textures/map_infohub.tga deleted file mode 100644 index d0134fa5f..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_infohub.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_telehub.tga b/indra/newview/skins/darkorange/textures/map_telehub.tga deleted file mode 100644 index ef63a3eb7..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_telehub.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_track_16.tga b/indra/newview/skins/darkorange/textures/map_track_16.tga deleted file mode 100644 index 451ce24cf..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_track_16.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/map_track_8.tga b/indra/newview/skins/darkorange/textures/map_track_8.tga deleted file mode 100644 index 53425ff45..000000000 Binary files a/indra/newview/skins/darkorange/textures/map_track_8.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/minimize.tga b/indra/newview/skins/darkorange/textures/minimize.tga deleted file mode 100644 index a21fd9148..000000000 Binary files a/indra/newview/skins/darkorange/textures/minimize.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/minimize_inactive.tga b/indra/newview/skins/darkorange/textures/minimize_inactive.tga deleted file mode 100644 index fcd62aa35..000000000 Binary files a/indra/newview/skins/darkorange/textures/minimize_inactive.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/minimize_pressed.tga b/indra/newview/skins/darkorange/textures/minimize_pressed.tga deleted file mode 100644 index 0061dd5f5..000000000 Binary files a/indra/newview/skins/darkorange/textures/minimize_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/missing_asset.tga b/indra/newview/skins/darkorange/textures/missing_asset.tga deleted file mode 100644 index 9a43f4db5..000000000 Binary files a/indra/newview/skins/darkorange/textures/missing_asset.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/mute_icon.tga b/indra/newview/skins/darkorange/textures/mute_icon.tga deleted file mode 100644 index 879b9e618..000000000 Binary files a/indra/newview/skins/darkorange/textures/mute_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/noentrylines.j2c b/indra/newview/skins/darkorange/textures/noentrylines.j2c deleted file mode 100644 index 93ec17659..000000000 Binary files a/indra/newview/skins/darkorange/textures/noentrylines.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/noentrypasslines.j2c b/indra/newview/skins/darkorange/textures/noentrypasslines.j2c deleted file mode 100644 index 800c46696..000000000 Binary files a/indra/newview/skins/darkorange/textures/noentrypasslines.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/notify_caution_icon.tga b/indra/newview/skins/darkorange/textures/notify_caution_icon.tga deleted file mode 100644 index abc23d1d7..000000000 Binary files a/indra/newview/skins/darkorange/textures/notify_caution_icon.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/notify_next.png b/indra/newview/skins/darkorange/textures/notify_next.png deleted file mode 100644 index 7b4aba9d3..000000000 Binary files a/indra/newview/skins/darkorange/textures/notify_next.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/pixiesmall.j2c b/indra/newview/skins/darkorange/textures/pixiesmall.j2c deleted file mode 100644 index a1ff64014..000000000 Binary files a/indra/newview/skins/darkorange/textures/pixiesmall.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/propertyline.tga b/indra/newview/skins/darkorange/textures/propertyline.tga deleted file mode 100644 index 0c504eea7..000000000 Binary files a/indra/newview/skins/darkorange/textures/propertyline.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/ptt_lock_off.tga b/indra/newview/skins/darkorange/textures/ptt_lock_off.tga deleted file mode 100644 index 09c479807..000000000 Binary files a/indra/newview/skins/darkorange/textures/ptt_lock_off.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/ptt_lock_on.tga b/indra/newview/skins/darkorange/textures/ptt_lock_on.tga deleted file mode 100644 index dfb8ce284..000000000 Binary files a/indra/newview/skins/darkorange/textures/ptt_lock_on.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/radio_active_false.tga b/indra/newview/skins/darkorange/textures/radio_active_false.tga deleted file mode 100644 index 963037392..000000000 Binary files a/indra/newview/skins/darkorange/textures/radio_active_false.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/radio_active_true.tga b/indra/newview/skins/darkorange/textures/radio_active_true.tga deleted file mode 100644 index f49297fd2..000000000 Binary files a/indra/newview/skins/darkorange/textures/radio_active_true.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/radio_inactive_false.tga b/indra/newview/skins/darkorange/textures/radio_inactive_false.tga deleted file mode 100644 index 9f9589e64..000000000 Binary files a/indra/newview/skins/darkorange/textures/radio_inactive_false.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/radio_inactive_true.tga b/indra/newview/skins/darkorange/textures/radio_inactive_true.tga deleted file mode 100644 index ca69cc6b5..000000000 Binary files a/indra/newview/skins/darkorange/textures/radio_inactive_true.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/resize_handle_bottom_right_blue.tga b/indra/newview/skins/darkorange/textures/resize_handle_bottom_right_blue.tga deleted file mode 100644 index f47aacfa4..000000000 Binary files a/indra/newview/skins/darkorange/textures/resize_handle_bottom_right_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/restore.tga b/indra/newview/skins/darkorange/textures/restore.tga deleted file mode 100644 index 87910e288..000000000 Binary files a/indra/newview/skins/darkorange/textures/restore.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/restore_inactive.tga b/indra/newview/skins/darkorange/textures/restore_inactive.tga deleted file mode 100644 index dbbec7ea1..000000000 Binary files a/indra/newview/skins/darkorange/textures/restore_inactive.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/restore_pressed.tga b/indra/newview/skins/darkorange/textures/restore_pressed.tga deleted file mode 100644 index 1922ca881..000000000 Binary files a/indra/newview/skins/darkorange/textures/restore_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/rounded_square.j2c b/indra/newview/skins/darkorange/textures/rounded_square.j2c deleted file mode 100644 index c8bb572fa..000000000 Binary files a/indra/newview/skins/darkorange/textures/rounded_square.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/rounded_square_soft.j2c b/indra/newview/skins/darkorange/textures/rounded_square_soft.j2c deleted file mode 100644 index 56e56c1ec..000000000 Binary files a/indra/newview/skins/darkorange/textures/rounded_square_soft.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/script_error.j2c b/indra/newview/skins/darkorange/textures/script_error.j2c deleted file mode 100644 index 893cb642e..000000000 Binary files a/indra/newview/skins/darkorange/textures/script_error.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_down_in_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_down_in_blue.tga deleted file mode 100644 index 5e7379950..000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_down_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_down_out_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_down_out_blue.tga deleted file mode 100644 index c5cf9bf9f..000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_down_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_left_in_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_left_in_blue.tga deleted file mode 100644 index 480842a3b..000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_left_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_left_out_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_left_out_blue.tga deleted file mode 100644 index 71aad797b..000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_left_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_right_in_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_right_in_blue.tga deleted file mode 100644 index 6d7f13bfc..000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_right_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_right_out_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_right_out_blue.tga deleted file mode 100644 index 0edc59af3..000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_right_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_up_in_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_up_in_blue.tga deleted file mode 100644 index 4c6a8fe41..000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_up_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/scrollbutton_up_out_blue.tga b/indra/newview/skins/darkorange/textures/scrollbutton_up_out_blue.tga deleted file mode 100644 index 5cd5dff46..000000000 Binary files a/indra/newview/skins/darkorange/textures/scrollbutton_up_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/silhouette.j2c b/indra/newview/skins/darkorange/textures/silhouette.j2c deleted file mode 100644 index 3859d4cb3..000000000 Binary files a/indra/newview/skins/darkorange/textures/silhouette.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_dark.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_dark.png deleted file mode 100644 index fc102a014..000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_dark.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_default.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_default.png deleted file mode 100644 index e22b1c164..000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_default.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_emerald.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_emerald.png deleted file mode 100644 index f2ab49e6d..000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_emerald.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_gred.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_gred.png deleted file mode 100644 index d60584743..000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_gred.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_pslgreen.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_pslgreen.png deleted file mode 100644 index 3eb7263d6..000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_pslgreen.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_pslpurple.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_pslpurple.png deleted file mode 100644 index 877514d8c..000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_pslpurple.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_ruby.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_ruby.png deleted file mode 100644 index 944b51985..000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_ruby.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_saphire.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_saphire.png deleted file mode 100644 index 2ee896780..000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_saphire.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/skin_thumbnail_silver.png b/indra/newview/skins/darkorange/textures/skin_thumbnail_silver.png deleted file mode 100644 index 51f4cceb0..000000000 Binary files a/indra/newview/skins/darkorange/textures/skin_thumbnail_silver.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/slim_icon_16_viewer.tga b/indra/newview/skins/darkorange/textures/slim_icon_16_viewer.tga deleted file mode 100644 index 552181d36..000000000 Binary files a/indra/newview/skins/darkorange/textures/slim_icon_16_viewer.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/sm_rounded_corners_simple.tga b/indra/newview/skins/darkorange/textures/sm_rounded_corners_simple.tga deleted file mode 100644 index 85157e461..000000000 Binary files a/indra/newview/skins/darkorange/textures/sm_rounded_corners_simple.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/smicon_warn.tga b/indra/newview/skins/darkorange/textures/smicon_warn.tga deleted file mode 100644 index 90ccaa07e..000000000 Binary files a/indra/newview/skins/darkorange/textures/smicon_warn.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spacer24.tga b/indra/newview/skins/darkorange/textures/spacer24.tga deleted file mode 100644 index c7cab6b38..000000000 Binary files a/indra/newview/skins/darkorange/textures/spacer24.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spacer35.tga b/indra/newview/skins/darkorange/textures/spacer35.tga deleted file mode 100644 index b88bc6680..000000000 Binary files a/indra/newview/skins/darkorange/textures/spacer35.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spin_down_in_blue.tga b/indra/newview/skins/darkorange/textures/spin_down_in_blue.tga deleted file mode 100644 index b9eb36ba9..000000000 Binary files a/indra/newview/skins/darkorange/textures/spin_down_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spin_down_out_blue.tga b/indra/newview/skins/darkorange/textures/spin_down_out_blue.tga deleted file mode 100644 index c9cb5e8bf..000000000 Binary files a/indra/newview/skins/darkorange/textures/spin_down_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spin_up_in_blue.tga b/indra/newview/skins/darkorange/textures/spin_up_in_blue.tga deleted file mode 100644 index b604b8843..000000000 Binary files a/indra/newview/skins/darkorange/textures/spin_up_in_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/spin_up_out_blue.tga b/indra/newview/skins/darkorange/textures/spin_up_out_blue.tga deleted file mode 100644 index 4e3941e45..000000000 Binary files a/indra/newview/skins/darkorange/textures/spin_up_out_blue.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/startup_logo.j2c b/indra/newview/skins/darkorange/textures/startup_logo.j2c deleted file mode 100644 index d1b991f17..000000000 Binary files a/indra/newview/skins/darkorange/textures/startup_logo.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_busy.tga b/indra/newview/skins/darkorange/textures/status_busy.tga deleted file mode 100644 index 7743d9c7b..000000000 Binary files a/indra/newview/skins/darkorange/textures/status_busy.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_health.tga b/indra/newview/skins/darkorange/textures/status_health.tga deleted file mode 100644 index 3d5f455fc..000000000 Binary files a/indra/newview/skins/darkorange/textures/status_health.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_money.tga b/indra/newview/skins/darkorange/textures/status_money.tga deleted file mode 100644 index d5be31fc6..000000000 Binary files a/indra/newview/skins/darkorange/textures/status_money.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_script_debug.tga b/indra/newview/skins/darkorange/textures/status_script_debug.tga deleted file mode 100644 index 6fca61483..000000000 Binary files a/indra/newview/skins/darkorange/textures/status_script_debug.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_search.tga b/indra/newview/skins/darkorange/textures/status_search.tga deleted file mode 100644 index 3ac10c476..000000000 Binary files a/indra/newview/skins/darkorange/textures/status_search.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_search_btn.png b/indra/newview/skins/darkorange/textures/status_search_btn.png deleted file mode 100644 index e648ba849..000000000 Binary files a/indra/newview/skins/darkorange/textures/status_search_btn.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_search_btn_pressed.png b/indra/newview/skins/darkorange/textures/status_search_btn_pressed.png deleted file mode 100644 index ec4254f4d..000000000 Binary files a/indra/newview/skins/darkorange/textures/status_search_btn_pressed.png and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/status_voice.tga b/indra/newview/skins/darkorange/textures/status_voice.tga deleted file mode 100644 index 4ab4498cb..000000000 Binary files a/indra/newview/skins/darkorange/textures/status_voice.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tab_background_darkpurple.tga b/indra/newview/skins/darkorange/textures/tab_background_darkpurple.tga deleted file mode 100644 index 8169f9869..000000000 Binary files a/indra/newview/skins/darkorange/textures/tab_background_darkpurple.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tab_background_lightgrey.tga b/indra/newview/skins/darkorange/textures/tab_background_lightgrey.tga deleted file mode 100644 index c2f8818f7..000000000 Binary files a/indra/newview/skins/darkorange/textures/tab_background_lightgrey.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tab_background_purple.tga b/indra/newview/skins/darkorange/textures/tab_background_purple.tga deleted file mode 100644 index aa01b3cb6..000000000 Binary files a/indra/newview/skins/darkorange/textures/tab_background_purple.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tabarea.tga b/indra/newview/skins/darkorange/textures/tabarea.tga deleted file mode 100644 index 5517aebfc..000000000 Binary files a/indra/newview/skins/darkorange/textures/tabarea.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tearoff_pressed.tga b/indra/newview/skins/darkorange/textures/tearoff_pressed.tga deleted file mode 100644 index 620d109de..000000000 Binary files a/indra/newview/skins/darkorange/textures/tearoff_pressed.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/tearoffbox.tga b/indra/newview/skins/darkorange/textures/tearoffbox.tga deleted file mode 100644 index 0670d2e91..000000000 Binary files a/indra/newview/skins/darkorange/textures/tearoffbox.tga and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/textures.xml b/indra/newview/skins/darkorange/textures/textures.xml index 41fe7a9f9..48fcecbfe 100644 --- a/indra/newview/skins/darkorange/textures/textures.xml +++ b/indra/newview/skins/darkorange/textures/textures.xml @@ -1,386 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/indra/newview/skins/darkorange/textures/uv_test1.j2c b/indra/newview/skins/darkorange/textures/uv_test1.j2c deleted file mode 100644 index 3d5b54179..000000000 Binary files a/indra/newview/skins/darkorange/textures/uv_test1.j2c and /dev/null differ diff --git a/indra/newview/skins/darkorange/textures/white.tga b/indra/newview/skins/darkorange/textures/white.tga deleted file mode 100644 index 9fe68631c..000000000 Binary files a/indra/newview/skins/darkorange/textures/white.tga and /dev/null differ diff --git a/indra/newview/skins/default/textures/skin_thumbnail_default.png b/indra/newview/skins/default/textures/skin_thumbnail_default.png deleted file mode 100644 index e22b1c164..000000000 Binary files a/indra/newview/skins/default/textures/skin_thumbnail_default.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/skin_thumbnail_silver.png b/indra/newview/skins/default/textures/skin_thumbnail_silver.png deleted file mode 100644 index 51f4cceb0..000000000 Binary files a/indra/newview/skins/default/textures/skin_thumbnail_silver.png and /dev/null differ diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml index 6ec647776..5917069bc 100644 --- a/indra/newview/skins/default/textures/textures.xml +++ b/indra/newview/skins/default/textures/textures.xml @@ -1,107 +1,251 @@ + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - + - + - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - @@ -114,8 +258,8 @@ - + @@ -123,9 +267,7 @@ - - @@ -135,48 +277,51 @@ + - - + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - - - - + + @@ -207,224 +352,93 @@ - - - - - - - + + + + + + + + + + + + + + - + + - + + + + + + + - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml index 54f2fbd43..4e4716e42 100644 --- a/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml +++ b/indra/newview/skins/default/xui/de/panel_preferences_graphics1.xml @@ -38,10 +38,10 @@ Ultra Higher Quality diff --git a/indra/newview/skins/default/xui/en-us/panel_notifications_channel.xml b/indra/newview/skins/default/xui/en-us/panel_notifications_channel.xml index a5e734b12..beee9c329 100644 --- a/indra/newview/skins/default/xui/en-us/panel_notifications_channel.xml +++ b/indra/newview/skins/default/xui/en-us/panel_notifications_channel.xml @@ -16,5 +16,5 @@ -