diff options
434 files changed, 15782 insertions, 20137 deletions
@@ -74,4 +74,6 @@ glob:indra/newview/filters.xml glob:indra/newview/avatar_icons_cache.txt glob:indra/newview/avatar_lad.log glob:*.diff -#*.rej +indra/newview/pilot.txt +indra/newview/pilot.xml +*.rej diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake index 472f271fa8..ac9e717c82 100755 --- a/indra/cmake/00-Common.cmake +++ b/indra/cmake/00-Common.cmake @@ -61,6 +61,7 @@ if (WINDOWS) add_definitions( /DLL_WINDOWS=1 + /DNOMINMAX /DDOM_DYNAMIC /DUNICODE /D_UNICODE diff --git a/indra/llappearance/llavatarappearance.cpp b/indra/llappearance/llavatarappearance.cpp index 3bb759d458..35d1a8b247 100644 --- a/indra/llappearance/llavatarappearance.cpp +++ b/indra/llappearance/llavatarappearance.cpp @@ -36,8 +36,8 @@ #include "llavatarappearancedefines.h" #include "llavatarjointmesh.h" #include "imageids.h" -#include "lldir.h" #include "lldeleteutils.h" +#include "lldir.h" #include "llpolymorph.h" #include "llpolymesh.h" #include "llpolyskeletaldistortion.h" diff --git a/indra/llappearance/llavatarjointmesh.cpp b/indra/llappearance/llavatarjointmesh.cpp index 4a5cff1dc3..753805b314 100644 --- a/indra/llappearance/llavatarjointmesh.cpp +++ b/indra/llappearance/llavatarjointmesh.cpp @@ -117,7 +117,6 @@ BOOL LLSkinJoint::setupSkinJoint( LLAvatarJoint *joint) //----------------------------------------------------------------------------- BOOL LLAvatarJointMesh::sPipelineRender = FALSE; -EAvatarRenderPass LLAvatarJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE; U32 LLAvatarJointMesh::sClothingMaskImageName = 0; LLColor4 LLAvatarJointMesh::sClothingInnerColor; diff --git a/indra/llappearance/llavatarjointmesh.h b/indra/llappearance/llavatarjointmesh.h index 6486932cdf..5980b29b46 100644 --- a/indra/llappearance/llavatarjointmesh.h +++ b/indra/llappearance/llavatarjointmesh.h @@ -82,7 +82,6 @@ public: static BOOL sPipelineRender; //RN: this is here for testing purposes static U32 sClothingMaskImageName; - static EAvatarRenderPass sRenderPass; static LLColor4 sClothingInnerColor; public: diff --git a/indra/llappearance/llpolymorph.cpp b/indra/llappearance/llpolymorph.cpp index 8a17819083..d40dfadfc8 100644 --- a/indra/llappearance/llpolymorph.cpp +++ b/indra/llappearance/llpolymorph.cpp @@ -35,6 +35,7 @@ #include "llxmltree.h" #include "llendianswizzle.h" #include "llpolymesh.h" +#include "llfasttimer.h" //#include "../tools/imdebug/imdebug.h" diff --git a/indra/llappearance/llpolyskeletaldistortion.cpp b/indra/llappearance/llpolyskeletaldistortion.cpp index 4ba16691c2..a98a11b357 100644 --- a/indra/llappearance/llpolyskeletaldistortion.cpp +++ b/indra/llappearance/llpolyskeletaldistortion.cpp @@ -29,18 +29,11 @@ //----------------------------------------------------------------------------- #include "llpreprocessor.h" #include "llerrorlegacy.h" -//#include "llcommon.h" -//#include "llmemory.h" #include "llavatarappearance.h" #include "llavatarjoint.h" #include "llpolymorph.h" -//#include "llviewercontrol.h" -//#include "llxmltree.h" -//#include "llvoavatar.h" #include "llwearable.h" -//#include "lldir.h" -//#include "llvolume.h" -//#include "llendianswizzle.h" +#include "llfasttimer.h" #include "llpolyskeletaldistortion.h" diff --git a/indra/llappearance/lltexlayer.cpp b/indra/llappearance/lltexlayer.cpp index f951a982e5..f65829febe 100644 --- a/indra/llappearance/lltexlayer.cpp +++ b/indra/llappearance/lltexlayer.cpp @@ -38,11 +38,13 @@ #include "llvfs.h" #include "lltexlayerparams.h" #include "lltexturemanagerbridge.h" +#include "lllocaltextureobject.h" #include "../llui/llui.h" #include "llwearable.h" #include "llwearabledata.h" #include "llvertexbuffer.h" #include "llviewervisualparam.h" +#include "llfasttimer.h" //#include "../tools/imdebug/imdebug.h" diff --git a/indra/llappearance/lltexlayerparams.cpp b/indra/llappearance/lltexlayerparams.cpp index 6aae9a8cc1..674e8c3c06 100644 --- a/indra/llappearance/lltexlayerparams.cpp +++ b/indra/llappearance/lltexlayerparams.cpp @@ -35,6 +35,7 @@ #include "lltexturemanagerbridge.h" #include "../llui/llui.h" #include "llwearable.h" +#include "llfasttimer.h" //----------------------------------------------------------------------------- // LLTexLayerParam diff --git a/indra/llappearance/llwearable.h b/indra/llappearance/llwearable.h index 6f5a1e14e8..8c2a1721b7 100644 --- a/indra/llappearance/llwearable.h +++ b/indra/llappearance/llwearable.h @@ -32,12 +32,12 @@ #include "llpermissions.h" #include "llsaleinfo.h" #include "llwearabletype.h" -#include "lllocaltextureobject.h" class LLMD5; class LLVisualParam; class LLTexGlobalColorInfo; class LLTexGlobalColor; +class LLLocalTextureObject; class LLAvatarAppearance; // Abstract class. @@ -116,7 +116,7 @@ public: protected: typedef std::map<S32, LLLocalTextureObject*> te_map_t; void syncImages(te_map_t &src, te_map_t &dst); - void destroyTextures(); + void destroyTextures(); void createVisualParams(LLAvatarAppearance *avatarp); void createLayers(S32 te, LLAvatarAppearance *avatarp); BOOL getNextPopulatedLine(std::istream& input_stream, char* buffer, U32 buffer_size); diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index 6c97a64ed7..bcff03ceaa 100755 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -40,6 +40,7 @@ #include "vorbis/codec.h" #include "vorbis/vorbisfile.h" +#include <iterator> extern LLAudioEngine *gAudiop; diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp index 85cf1cd3f5..045b4abf50 100755 --- a/indra/llcharacter/llcharacter.cpp +++ b/indra/llcharacter/llcharacter.cpp @@ -32,6 +32,7 @@ #include "llcharacter.h" #include "llstring.h" +#include "llfasttimer.h" #define SKEL_HEADER "Linden Skeleton 1.0" diff --git a/indra/llcharacter/lleditingmotion.cpp b/indra/llcharacter/lleditingmotion.cpp index 0d0b85ba60..ff7ad1c289 100755 --- a/indra/llcharacter/lleditingmotion.cpp +++ b/indra/llcharacter/lleditingmotion.cpp @@ -232,7 +232,7 @@ BOOL LLEditingMotion::onUpdate(F32 time, U8* joint_mask) mIKSolver.solve(); // use blending... - F32 slerp_amt = LLCriticalDamp::getInterpolant(TARGET_LAG_HALF_LIFE); + F32 slerp_amt = LLSmoothInterpolation::getInterpolant(TARGET_LAG_HALF_LIFE); shoulderRot = slerp(slerp_amt, mShoulderJoint.getRotation(), shoulderRot); elbowRot = slerp(slerp_amt, mElbowJoint.getRotation(), elbowRot); diff --git a/indra/llcharacter/llheadrotmotion.cpp b/indra/llcharacter/llheadrotmotion.cpp index 15a58a8389..4a8af2f00c 100755 --- a/indra/llcharacter/llheadrotmotion.cpp +++ b/indra/llcharacter/llheadrotmotion.cpp @@ -182,8 +182,8 @@ BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask) LLQuaternion currentRootRotWorld = mRootJoint->getWorldRotation(); LLQuaternion currentInvRootRotWorld = ~currentRootRotWorld; - F32 head_slerp_amt = LLCriticalDamp::getInterpolant(HEAD_LOOKAT_LAG_HALF_LIFE); - F32 torso_slerp_amt = LLCriticalDamp::getInterpolant(TORSO_LOOKAT_LAG_HALF_LIFE); + F32 head_slerp_amt = LLSmoothInterpolation::getInterpolant(HEAD_LOOKAT_LAG_HALF_LIFE); + F32 torso_slerp_amt = LLSmoothInterpolation::getInterpolant(TORSO_LOOKAT_LAG_HALF_LIFE); LLVector3* targetPos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint"); diff --git a/indra/llcharacter/lljoint.h b/indra/llcharacter/lljoint.h index 2b1e2005c6..07374b7814 100755 --- a/indra/llcharacter/lljoint.h +++ b/indra/llcharacter/lljoint.h @@ -31,6 +31,7 @@ // Header Files //----------------------------------------------------------------------------- #include <string> +#include <list> #include "linked_lists.h" #include "v3math.h" diff --git a/indra/llcharacter/llkeyframemotion.cpp b/indra/llcharacter/llkeyframemotion.cpp index c6f45bffa2..831a0a6719 100755 --- a/indra/llcharacter/llkeyframemotion.cpp +++ b/indra/llcharacter/llkeyframemotion.cpp @@ -1031,11 +1031,11 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8 if (constraint->mSharedData->mChainLength != 0 && dist_vec_squared(root_pos, target_pos) * 0.95f > constraint->mTotalLength * constraint->mTotalLength) { - constraint->mWeight = lerp(constraint->mWeight, 0.f, LLCriticalDamp::getInterpolant(0.1f)); + constraint->mWeight = LLSmoothInterpolation::lerp(constraint->mWeight, 0.f, 0.1f); } else { - constraint->mWeight = lerp(constraint->mWeight, 1.f, LLCriticalDamp::getInterpolant(0.3f)); + constraint->mWeight = LLSmoothInterpolation::lerp(constraint->mWeight, 1.f, 0.3f); } F32 weight = constraint->mWeight * ((shared_data->mEaseOutStopTime == 0.f) ? 1.f : @@ -1082,9 +1082,9 @@ void LLKeyframeMotion::applyConstraint(JointConstraint* constraint, F32 time, U8 // convert intermediate joint positions to world coordinates positions[joint_num] = ( constraint->mPositions[joint_num] * mPelvisp->getWorldRotation()) + mPelvisp->getWorldPosition(); F32 time_constant = 1.f / clamp_rescale(constraint->mFixupDistanceRMS, 0.f, 0.5f, 0.2f, 8.f); -// llinfos << "Interpolant " << LLCriticalDamp::getInterpolant(time_constant, FALSE) << " and fixup distance " << constraint->mFixupDistanceRMS << " on " << mCharacter->findCollisionVolume(shared_data->mSourceConstraintVolume)->getName() << llendl; +// llinfos << "Interpolant " << LLSmoothInterpolation::getInterpolant(time_constant, FALSE) << " and fixup distance " << constraint->mFixupDistanceRMS << " on " << mCharacter->findCollisionVolume(shared_data->mSourceConstraintVolume)->getName() << llendl; positions[joint_num] = lerp(positions[joint_num], kinematic_position, - LLCriticalDamp::getInterpolant(time_constant, FALSE)); + LLSmoothInterpolation::getInterpolant(time_constant, FALSE)); } S32 iteration_count; diff --git a/indra/llcharacter/llkeyframewalkmotion.cpp b/indra/llcharacter/llkeyframewalkmotion.cpp index d52eb89a5c..e188b06c03 100755 --- a/indra/llcharacter/llkeyframewalkmotion.cpp +++ b/indra/llcharacter/llkeyframewalkmotion.cpp @@ -258,7 +258,7 @@ BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask) // but this will cause the animation playback rate calculation below to // kick in too slowly and sometimes start playing the animation in reverse. - //mPelvisOffset -= PELVIS_COMPENSATION_WIEGHT * (foot_slip_vector * world_to_avatar_rot);//lerp(LLVector3::zero, -1.f * (foot_slip_vector * world_to_avatar_rot), LLCriticalDamp::getInterpolant(0.1f)); + //mPelvisOffset -= PELVIS_COMPENSATION_WIEGHT * (foot_slip_vector * world_to_avatar_rot);//lerp(LLVector3::zero, -1.f * (foot_slip_vector * world_to_avatar_rot), LLSmoothInterpolation::getInterpolant(0.1f)); ////F32 drift_comp_max = DRIFT_COMP_MAX_TOTAL * (llclamp(speed, 0.f, DRIFT_COMP_MAX_SPEED) / DRIFT_COMP_MAX_SPEED); //F32 drift_comp_max = DRIFT_COMP_MAX_TOTAL; @@ -287,7 +287,7 @@ BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask) F32 desired_speed_multiplier = llclamp(speed / foot_speed, min_speed_multiplier, ANIM_SPEED_MAX); // blend towards new speed adjustment value - F32 new_speed_adjust = lerp(mAdjustedSpeed, desired_speed_multiplier, LLCriticalDamp::getInterpolant(SPEED_ADJUST_TIME_CONSTANT)); + F32 new_speed_adjust = LLSmoothInterpolation::lerp(mAdjustedSpeed, desired_speed_multiplier, SPEED_ADJUST_TIME_CONSTANT); // limit that rate at which the speed adjustment changes F32 speedDelta = llclamp(new_speed_adjust - mAdjustedSpeed, -SPEED_ADJUST_MAX_SEC * delta_time, SPEED_ADJUST_MAX_SEC * delta_time); @@ -305,8 +305,8 @@ BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask) { // standing/turning // damp out speed adjustment to 0 - mAnimSpeed = lerp(mAnimSpeed, 1.f, LLCriticalDamp::getInterpolant(0.2f)); - //mPelvisOffset = lerp(mPelvisOffset, LLVector3::zero, LLCriticalDamp::getInterpolant(0.2f)); + mAnimSpeed = LLSmoothInterpolation::lerp(mAnimSpeed, 1.f, 0.2f); + //mPelvisOffset = lerp(mPelvisOffset, LLVector3::zero, LLSmoothInterpolation::getInterpolant(0.2f)); } // broadcast walk speed change @@ -383,7 +383,7 @@ BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask) F32 target_roll = llclamp(ang_vel.mV[VZ], -4.f, 4.f) * roll_factor; // roll is critically damped interpolation between current roll and angular velocity-derived target roll - mRoll = lerp(mRoll, target_roll, LLCriticalDamp::getInterpolant(0.1f)); + mRoll = LLSmoothInterpolation::lerp(mRoll, target_roll, LLUnit<LLUnits::Milliseconds, F32>(100)); LLQuaternion roll(mRoll, LLVector3(0.f, 0.f, 1.f)); mPelvisState->setRotation(roll); diff --git a/indra/llcharacter/llmotion.cpp b/indra/llcharacter/llmotion.cpp index 2551f125d0..af2e10220a 100755 --- a/indra/llcharacter/llmotion.cpp +++ b/indra/llcharacter/llmotion.cpp @@ -73,7 +73,7 @@ void LLMotion::fadeOut() { if (mFadeWeight > 0.01f) { - mFadeWeight = lerp(mFadeWeight, 0.f, LLCriticalDamp::getInterpolant(0.15f)); + mFadeWeight = lerp(mFadeWeight, 0.f, LLSmoothInterpolation::getInterpolant(0.15f)); } else { @@ -88,7 +88,7 @@ void LLMotion::fadeIn() { if (mFadeWeight < 0.99f) { - mFadeWeight = lerp(mFadeWeight, 1.f, LLCriticalDamp::getInterpolant(0.15f)); + mFadeWeight = lerp(mFadeWeight, 1.f, LLSmoothInterpolation::getInterpolant(0.15f)); } else { diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index e9fb91ad73..d1c605451a 100755 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -30,6 +30,7 @@ #include "linden_common.h" #include "llmotioncontroller.h" +#include "llfasttimer.h" #include "llkeyframemotion.h" #include "llmath.h" #include "lltimer.h" diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h index 52eaf557b1..2bd5271c4f 100755 --- a/indra/llcharacter/llmotioncontroller.h +++ b/indra/llcharacter/llmotioncontroller.h @@ -34,7 +34,6 @@ #include <map> #include <deque> -#include "lluuidhashmap.h" #include "llmotion.h" #include "llpose.h" #include "llframetimer.h" diff --git a/indra/llcharacter/lltargetingmotion.cpp b/indra/llcharacter/lltargetingmotion.cpp index 489aef923c..633c1d51eb 100755 --- a/indra/llcharacter/lltargetingmotion.cpp +++ b/indra/llcharacter/lltargetingmotion.cpp @@ -106,7 +106,7 @@ BOOL LLTargetingMotion::onActivate() //----------------------------------------------------------------------------- BOOL LLTargetingMotion::onUpdate(F32 time, U8* joint_mask) { - F32 slerp_amt = LLCriticalDamp::getInterpolant(TORSO_TARGET_HALF_LIFE); + F32 slerp_amt = LLSmoothInterpolation::getInterpolant(TORSO_TARGET_HALF_LIFE); LLVector3 target; LLVector3* lookAtPoint = (LLVector3*)mCharacter->getAnimationData("LookAtPoint"); diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 3a4a8facc2..bf99a4c3a0 100755 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -75,8 +75,10 @@ set(llcommon_SOURCE_FILES llmetrics.cpp llmetricperformancetester.cpp llmortician.cpp + llmutex.cpp lloptioninterface.cpp llptrto.cpp + llpredicate.cpp llprocess.cpp llprocessor.cpp llqueuedthread.cpp @@ -90,7 +92,6 @@ set(llcommon_SOURCE_FILES llsdutil.cpp llsecondlifeurls.cpp llsingleton.cpp - llstat.cpp llstacktrace.cpp llstreamqueue.cpp llstreamtools.cpp @@ -98,14 +99,15 @@ set(llcommon_SOURCE_FILES llstringtable.cpp llsys.cpp llthread.cpp + llthreadlocalstorage.cpp llthreadsafequeue.cpp lltimer.cpp + lltrace.cpp + lltracerecording.cpp + lltracethreadrecorder.cpp lluri.cpp lluuid.cpp llworkerthread.cpp - metaclass.cpp - metaproperty.cpp - reflective.cpp timing.cpp u64.cpp ) @@ -115,7 +117,6 @@ set(llcommon_HEADER_FILES bitpack.h ctype_workaround.h - doublelinkedlist.h fix_macros.h imageids.h indra_constants.h @@ -129,7 +130,6 @@ set(llcommon_HEADER_FILES llapp.h llapr.h llassettype.h - llassoclist.h llavatarconstants.h llbase32.h llbase64.h @@ -143,18 +143,14 @@ set(llcommon_HEADER_FILES llcriticaldamp.h llcursortypes.h lldarray.h - lldarrayptr.h lldate.h lldefs.h lldependencies.h lldeleteutils.h lldepthstack.h lldictionary.h - lldlinked.h lldoubledispatch.h - lldqueueptr.h llendianswizzle.h - llenum.h llerror.h llerrorcontrol.h llerrorlegacy.h @@ -178,18 +174,15 @@ set(llcommon_HEADER_FILES llhash.h llheartbeat.h llhttpstatuscodes.h - llindexedqueue.h llinitparam.h llinstancetracker.h llkeythrottle.h - lllazy.h llleap.h llleaplistener.h lllistenerwrapper.h lllinkedqueue.h llliveappconfig.h lllivefile.h - lllocalidhashmap.h lllog.h lllslconstants.h llmap.h @@ -199,15 +192,15 @@ set(llcommon_HEADER_FILES llmetrics.h llmetricperformancetester.h llmortician.h + llmutex.h llnametable.h lloptioninterface.h llpointer.h + llpredicate.h llpreprocessor.h llpriqueuemap.h llprocess.h llprocessor.h - llptrskiplist.h - llptrskipmap.h llptrto.h llqueuedthread.h llrand.h @@ -224,12 +217,7 @@ set(llcommon_HEADER_FILES llsecondlifeurls.h llsimplehash.h llsingleton.h - llskiplist.h - llskipmap.h - llsortedvector.h - llstack.h llstacktrace.h - llstat.h llstatenums.h llstl.h llstreamqueue.h @@ -239,22 +227,21 @@ set(llcommon_HEADER_FILES llstringtable.h llsys.h llthread.h + llthreadlocalstorage.h llthreadsafequeue.h lltimer.h + lltrace.h + lltracerecording.h + lltracethreadrecorder.h lltreeiterators.h - lltypeinfolookup.h + llunit.h lluri.h lluuid.h - lluuidhashmap.h llversionserver.h + llwin32headers.h + llwin32headerslean.h llworkerthread.h ll_template_cast.h - metaclass.h - metaclasst.h - metaproperty.h - metapropertyt.h - reflective.h - reflectivet.h roles_constants.h stdenums.h stdtypes.h @@ -326,7 +313,6 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(llerror "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}") - LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}") LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}") @@ -334,7 +320,7 @@ if (LL_TESTS) LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lltreeiterators "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lluri "" "${test_libs}") - LL_ADD_INTEGRATION_TEST(reflection "" "${test_libs}") + LL_ADD_INTEGRATION_TEST(llunits "" "${test_libs}") LL_ADD_INTEGRATION_TEST(stringize "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lleventdispatcher "" "${test_libs}") LL_ADD_INTEGRATION_TEST(lleventcoro "" "${test_libs};${BOOST_CONTEXT_LIBRARY}") diff --git a/indra/llcommon/doublelinkedlist.h b/indra/llcommon/doublelinkedlist.h deleted file mode 100755 index 0aeaa69df3..0000000000 --- a/indra/llcommon/doublelinkedlist.h +++ /dev/null @@ -1,1397 +0,0 @@ -/** - * @file doublelinkedlist.h - * @brief Provides a standard doubly linked list for fun and profit. - * - * $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_DOUBLELINKEDLIST_H -#define LL_DOUBLELINKEDLIST_H - -#include "llerror.h" -#include "llrand.h" - -// node that actually contains the data -template <class DATA_TYPE> class LLDoubleLinkedNode -{ -public: - DATA_TYPE *mDatap; - LLDoubleLinkedNode *mNextp; - LLDoubleLinkedNode *mPrevp; - - -public: - // assign the mDatap pointer - LLDoubleLinkedNode(DATA_TYPE *data); - - // destructor does not, by default, destroy associated data - // however, the mDatap must be NULL to ensure that we aren't causing memory leaks - ~LLDoubleLinkedNode(); - - // delete associated data and NULL out pointer - void deleteData(); - - // remove associated data and NULL out pointer - void removeData(); -}; - - -const U32 LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH = 4; - -template <class DATA_TYPE> class LLDoubleLinkedList -{ -private: - LLDoubleLinkedNode<DATA_TYPE> mHead; // head node - LLDoubleLinkedNode<DATA_TYPE> mTail; // tail node - LLDoubleLinkedNode<DATA_TYPE> *mQueuep; // The node in the batter's box - LLDoubleLinkedNode<DATA_TYPE> *mCurrentp; // The node we're talking about - - // The state stack allows nested exploration of the LLDoubleLinkedList - // but should be used with great care - LLDoubleLinkedNode<DATA_TYPE> *mQueuepStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH]; - LLDoubleLinkedNode<DATA_TYPE> *mCurrentpStack[LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH]; - U32 mStateStackDepth; - U32 mCount; - - // mInsertBefore is a pointer to a user-set function that returns - // TRUE if "first" should be located before "second" - // NOTE: mInsertBefore() should never return TRUE when ("first" == "second") - // or never-ending loops can occur - BOOL (*mInsertBefore)(DATA_TYPE *first, DATA_TYPE *second); - -public: - LLDoubleLinkedList(); - - // destructor destroys list and nodes, but not data in nodes - ~LLDoubleLinkedList(); - - // put data into a node and stick it at the front of the list - // set mCurrentp to mQueuep - void addData(DATA_TYPE *data); - - // put data into a node and stick it at the end of the list - // set mCurrentp to mQueuep - void addDataAtEnd(DATA_TYPE *data); - - S32 getLength() const; - // search the list starting at mHead.mNextp and remove the link with mDatap == data - // set mCurrentp to mQueuep - // return TRUE if found, FALSE if not found - BOOL removeData(const DATA_TYPE *data); - - // search the list starting at mHead.mNextp and delete the link with mDatap == data - // set mCurrentp to mQueuep - // return TRUE if found, FALSE if not found - BOOL deleteData(DATA_TYPE *data); - - // remove all nodes from the list and delete the associated data - void deleteAllData(); - - // remove all nodes from the list but do not delete data - void removeAllNodes(); - - BOOL isEmpty(); - - // check to see if data is in list - // set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep - // return TRUE if found, FALSE if not found - BOOL checkData(const DATA_TYPE *data); - - // NOTE: This next two funtions are only included here - // for those too familiar with the LLLinkedList template class. - // They are depreciated. resetList() is unecessary while - // getCurrentData() is identical to getNextData() and has - // a misleading name. - // - // The recommended way to loop through a list is as follows: - // - // datap = list.getFirstData(); - // while (datap) - // { - // /* do stuff */ - // datap = list.getNextData(); - // } - - // place mQueuep on mHead node - void resetList(); - - // return the data currently pointed to, - // set mCurrentp to that node and bump mQueuep down the list - // NOTE: this function is identical to getNextData() - DATA_TYPE *getCurrentData(); - - - // reset the list and return the data currently pointed to, - // set mCurrentp to that node and bump mQueuep down the list - DATA_TYPE *getFirstData(); - - - // reset the list and return the data at position n, set mCurentp - // to that node and bump mQueuep down the list - // Note: n=0 will behave like getFirstData() - DATA_TYPE *getNthData(U32 n); - - // reset the list and return the last data in it, - // set mCurrentp to that node and bump mQueuep up the list - DATA_TYPE *getLastData(); - - // return data in mQueuep, - // set mCurrentp mQueuep and bump mQueuep down the list - DATA_TYPE *getNextData(); - - // return the data in mQueuep, - // set mCurrentp to mQueuep and bump mQueuep up the list - DATA_TYPE *getPreviousData(); - - // remove the Node at mCurrentp - // set mCurrentp to mQueuep - void removeCurrentData(); - - // delete the Node at mCurrentp - // set mCurrentp to mQueuep - void deleteCurrentData(); - - // remove the Node at mCurrentp and insert it into newlist - // set mCurrentp to mQueuep - void moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist); - - // insert the node in front of mCurrentp - // set mCurrentp to mQueuep - void insertNode(LLDoubleLinkedNode<DATA_TYPE> *node); - - // insert the data in front of mCurrentp - // set mCurrentp to mQueuep - void insertData(DATA_TYPE *data); - - // if mCurrentp has a previous node then : - // * swaps mCurrentp with its previous - // * set mCurrentp to mQueuep - // (convenient for forward bubble-sort) - // otherwise does nothing - void swapCurrentWithPrevious(); - - // if mCurrentp has a next node then : - // * swaps mCurrentp with its next - // * set mCurrentp to mQueuep - // (convenient for backwards bubble-sort) - // otherwise does nothing - void swapCurrentWithNext(); - - // move mCurrentp to the front of the list - // set mCurrentp to mQueuep - void moveCurrentToFront(); - - // move mCurrentp to the end of the list - // set mCurrentp to mQueuep - void moveCurrentToEnd(); - - // set mInsertBefore - void setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second)); - - // add data in front of first node for which mInsertBefore(datap, node->mDatap) returns TRUE - // set mCurrentp to mQueuep - BOOL addDataSorted(DATA_TYPE *datap); - - // sort the list using bubble-sort - // Yes, this is a different name than the same function in LLLinkedList. - // When it comes time for a name consolidation hopefully this one will win. - BOOL bubbleSort(); - - // does a single bubble sort pass on the list - BOOL lazyBubbleSort(); - - // returns TRUE if state successfully pushed (state stack not full) - BOOL pushState(); - - // returns TRUE if state successfully popped (state stack not empty) - BOOL popState(); - - // empties the state stack - void clearStateStack(); - - // randomly move the the links in the list for debug or (Discordian) purposes - // sets mCurrentp and mQueuep to top of list - void scramble(); - -private: - // add node to beginning of list - // set mCurrentp to mQueuep - void addNode(LLDoubleLinkedNode<DATA_TYPE> *node); - - // add node to end of list - // set mCurrentp to mQueuep - void addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node); -}; - -//#endif - -//////////////////////////////////////////////////////////////////////////////////////////// - -// doublelinkedlist.cpp -// LLDoubleLinkedList template class implementation file. -// Provides a standard doubly linked list for fun and profit. -// -// Copyright 2001, Linden Research, Inc. - -//#include "llerror.h" -//#include "doublelinkedlist.h" - -////////////////////////////////////////////////////////////////////////////////////////// -// LLDoubleLinkedNode -////////////////////////////////////////////////////////////////////////////////////////// - - -// assign the mDatap pointer -template <class DATA_TYPE> -LLDoubleLinkedNode<DATA_TYPE>::LLDoubleLinkedNode(DATA_TYPE *data) : - mDatap(data), mNextp(NULL), mPrevp(NULL) -{ -} - - -// destructor does not, by default, destroy associated data -// however, the mDatap must be NULL to ensure that we aren't causing memory leaks -template <class DATA_TYPE> -LLDoubleLinkedNode<DATA_TYPE>::~LLDoubleLinkedNode() -{ - if (mDatap) - { - llerror("Attempting to call LLDoubleLinkedNode destructor with a non-null mDatap!", 1); - } -} - - -// delete associated data and NULL out pointer -template <class DATA_TYPE> -void LLDoubleLinkedNode<DATA_TYPE>::deleteData() -{ - delete mDatap; - mDatap = NULL; -} - - -template <class DATA_TYPE> -void LLDoubleLinkedNode<DATA_TYPE>::removeData() -{ - mDatap = NULL; -} - - -////////////////////////////////////////////////////////////////////////////////////// -// LLDoubleLinkedList -////////////////////////////////////////////////////////////////////////////////////// - -// <------- up ------- -// -// mCurrentp -// mQueuep | -// | | -// | | -// .------. .------. .------. .------. -// | |---->| |---->| |----->| |-----> NULL -// NULL <-----| |<----| |<----| |<-----| | -// _'------' '------' '------' '------:_ -// .------. /| | | |\ .------. -// NULL <-----|mHead |/ | mQueuep \|mTail |-----> NULL -// | | mCurrentp | | -// '------' '------' -// -------- down ---------> - -template <class DATA_TYPE> -LLDoubleLinkedList<DATA_TYPE>::LLDoubleLinkedList() -: mHead(NULL), mTail(NULL), mQueuep(NULL) -{ - mCurrentp = mHead.mNextp; - mQueuep = mHead.mNextp; - mStateStackDepth = 0; - mCount = 0; - mInsertBefore = NULL; -} - - -// destructor destroys list and nodes, but not data in nodes -template <class DATA_TYPE> -LLDoubleLinkedList<DATA_TYPE>::~LLDoubleLinkedList() -{ - removeAllNodes(); -} - - -// put data into a node and stick it at the front of the list -// doesn't change mCurrentp nor mQueuep -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::addData(DATA_TYPE *data) -{ - // don't allow NULL to be passed to addData - if (!data) - { - llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0); - } - - // make the new node - LLDoubleLinkedNode<DATA_TYPE> *temp = new LLDoubleLinkedNode<DATA_TYPE> (data); - - // add the node to the front of the list - temp->mPrevp = NULL; - temp->mNextp = mHead.mNextp; - mHead.mNextp = temp; - - // if there's something in the list, fix its back pointer - if (temp->mNextp) - { - temp->mNextp->mPrevp = temp; - } - // otherwise, fix the tail of the list - else - { - mTail.mPrevp = temp; - } - - mCount++; -} - - -// put data into a node and stick it at the end of the list -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::addDataAtEnd(DATA_TYPE *data) -{ - // don't allow NULL to be passed to addData - if (!data) - { - llerror("NULL pointer passed to LLDoubleLinkedList::addData()", 0); - } - - // make the new node - LLDoubleLinkedNode<DATA_TYPE> *nodep = new LLDoubleLinkedNode<DATA_TYPE>(data); - - addNodeAtEnd(nodep); - mCount++; -} - - -// search the list starting at mHead.mNextp and remove the link with mDatap == data -// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data -// return TRUE if found, FALSE if not found -template <class DATA_TYPE> -BOOL LLDoubleLinkedList<DATA_TYPE>::removeData(const DATA_TYPE *data) -{ - BOOL b_found = FALSE; - // don't allow NULL to be passed to addData - if (!data) - { - llerror("NULL pointer passed to LLDoubleLinkedList::removeData()", 0); - } - - mCurrentp = mHead.mNextp; - - while (mCurrentp) - { - if (mCurrentp->mDatap == data) - { - b_found = TRUE; - - // if there is a next one, fix it - if (mCurrentp->mNextp) - { - mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp; - } - else // we are at end of list - { - mTail.mPrevp = mCurrentp->mPrevp; - } - - // if there is a previous one, fix it - if (mCurrentp->mPrevp) - { - mCurrentp->mPrevp->mNextp = mCurrentp->mNextp; - } - else // we are at beginning of list - { - mHead.mNextp = mCurrentp->mNextp; - } - - // remove the node - mCurrentp->removeData(); - delete mCurrentp; - mCount--; - break; - } - mCurrentp = mCurrentp->mNextp; - } - - // reset the list back to where it was - if (mCurrentp == mQueuep) - { - mCurrentp = mQueuep = NULL; - } - else - { - mCurrentp = mQueuep; - } - - return b_found; -} - - -// search the list starting at mHead.mNextp and delete the link with mDatap == data -// set mCurrentp to mQueuep, or NULL if mQueuep points to node with mDatap == data -// return TRUE if found, FALSE if not found -template <class DATA_TYPE> -BOOL LLDoubleLinkedList<DATA_TYPE>::deleteData(DATA_TYPE *data) -{ - BOOL b_found = FALSE; - // don't allow NULL to be passed to addData - if (!data) - { - llerror("NULL pointer passed to LLDoubleLinkedList::deleteData()", 0); - } - - mCurrentp = mHead.mNextp; - - while (mCurrentp) - { - if (mCurrentp->mDatap == data) - { - b_found = TRUE; - - // if there is a next one, fix it - if (mCurrentp->mNextp) - { - mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp; - } - else // we are at end of list - { - mTail.mPrevp = mCurrentp->mPrevp; - } - - // if there is a previous one, fix it - if (mCurrentp->mPrevp) - { - mCurrentp->mPrevp->mNextp = mCurrentp->mNextp; - } - else // we are at beginning of list - { - mHead.mNextp = mCurrentp->mNextp; - } - - // remove the node - mCurrentp->deleteData(); - delete mCurrentp; - mCount--; - break; - } - mCurrentp = mCurrentp->mNextp; - } - - // reset the list back to where it was - if (mCurrentp == mQueuep) - { - mCurrentp = mQueuep = NULL; - } - else - { - mCurrentp = mQueuep; - } - - return b_found; -} - - -// remove all nodes from the list and delete the associated data -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::deleteAllData() -{ - mCurrentp = mHead.mNextp; - - while (mCurrentp) - { - mQueuep = mCurrentp->mNextp; - mCurrentp->deleteData(); - delete mCurrentp; - mCurrentp = mQueuep; - } - - // reset mHead and mQueuep - mHead.mNextp = NULL; - mTail.mPrevp = NULL; - mCurrentp = mHead.mNextp; - mQueuep = mHead.mNextp; - mStateStackDepth = 0; - mCount = 0; -} - - -// remove all nodes from the list but do not delete associated data -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::removeAllNodes() -{ - mCurrentp = mHead.mNextp; - - while (mCurrentp) - { - mQueuep = mCurrentp->mNextp; - mCurrentp->removeData(); - delete mCurrentp; - mCurrentp = mQueuep; - } - - // reset mHead and mCurrentp - mHead.mNextp = NULL; - mTail.mPrevp = NULL; - mCurrentp = mHead.mNextp; - mQueuep = mHead.mNextp; - mStateStackDepth = 0; - mCount = 0; -} - -template <class DATA_TYPE> -S32 LLDoubleLinkedList<DATA_TYPE>::getLength() const -{ -// U32 length = 0; -// for (LLDoubleLinkedNode<DATA_TYPE>* temp = mHead.mNextp; temp != NULL; temp = temp->mNextp) -// { -// length++; -// } - return mCount; -} - -// check to see if data is in list -// set mCurrentp and mQueuep to the target of search if found, otherwise set mCurrentp to mQueuep -// return TRUE if found, FALSE if not found -template <class DATA_TYPE> -BOOL LLDoubleLinkedList<DATA_TYPE>::checkData(const DATA_TYPE *data) -{ - mCurrentp = mHead.mNextp; - - while (mCurrentp) - { - if (mCurrentp->mDatap == data) - { - mQueuep = mCurrentp; - return TRUE; - } - mCurrentp = mCurrentp->mNextp; - } - - mCurrentp = mQueuep; - return FALSE; -} - -// NOTE: This next two funtions are only included here -// for those too familiar with the LLLinkedList template class. -// They are depreciated. resetList() is unecessary while -// getCurrentData() is identical to getNextData() and has -// a misleading name. -// -// The recommended way to loop through a list is as follows: -// -// datap = list.getFirstData(); -// while (datap) -// { -// /* do stuff */ -// datap = list.getNextData(); -// } - - // place mCurrentp and mQueuep on first node - template <class DATA_TYPE> - void LLDoubleLinkedList<DATA_TYPE>::resetList() - { - mCurrentp = mHead.mNextp; - mQueuep = mHead.mNextp; - mStateStackDepth = 0; - } - - - // return the data currently pointed to, - // set mCurrentp to that node and bump mQueuep down the list - template <class DATA_TYPE> - DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getCurrentData() - { - if (mQueuep) - { - mCurrentp = mQueuep; - mQueuep = mQueuep->mNextp; - return mCurrentp->mDatap; - } - else - { - return NULL; - } - } - - -// reset the list and return the data currently pointed to, -// set mCurrentp to that node and bump mQueuep down the list -template <class DATA_TYPE> -DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getFirstData() -{ - mQueuep = mHead.mNextp; - mCurrentp = mQueuep; - if (mQueuep) - { - mQueuep = mQueuep->mNextp; - return mCurrentp->mDatap; - } - else - { - return NULL; - } -} - - -// reset the list and return the data at position n, set mCurentp -// to that node and bump mQueuep down the list -// Note: n=0 will behave like getFirstData() -template <class DATA_TYPE> -DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNthData(U32 n) -{ - mCurrentp = mHead.mNextp; - - if (mCurrentp) - { - for (U32 i=0; i<n; i++) - { - mCurrentp = mCurrentp->mNextp; - if (!mCurrentp) - { - break; - } - } - } - - if (mCurrentp) - { - // bump mQueuep down the list - mQueuep = mCurrentp->mNextp; - return mCurrentp->mDatap; - } - else - { - mQueuep = NULL; - return NULL; - } -} - - -// reset the list and return the last data in it, -// set mCurrentp to that node and bump mQueuep up the list -template <class DATA_TYPE> -DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getLastData() -{ - mQueuep = mTail.mPrevp; - mCurrentp = mQueuep; - if (mQueuep) - { - mQueuep = mQueuep->mPrevp; - return mCurrentp->mDatap; - } - else - { - return NULL; - } -} - - -// return the data in mQueuep, -// set mCurrentp to mQueuep and bump mQueuep down the list -template <class DATA_TYPE> -DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getNextData() -{ - if (mQueuep) - { - mCurrentp = mQueuep; - mQueuep = mQueuep->mNextp; - return mCurrentp->mDatap; - } - else - { - return NULL; - } -} - - -// return the data in mQueuep, -// set mCurrentp to mQueuep and bump mQueuep up the list -template <class DATA_TYPE> -DATA_TYPE* LLDoubleLinkedList<DATA_TYPE>::getPreviousData() -{ - if (mQueuep) - { - mCurrentp = mQueuep; - mQueuep = mQueuep->mPrevp; - return mCurrentp->mDatap; - } - else - { - return NULL; - } -} - - -// remove the Node at mCurrentp -// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep) -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::removeCurrentData() -{ - if (mCurrentp) - { - // if there is a next one, fix it - if (mCurrentp->mNextp) - { - mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp; - } - else // otherwise we are at end of list - { - mTail.mPrevp = mCurrentp->mPrevp; - } - - // if there is a previous one, fix it - if (mCurrentp->mPrevp) - { - mCurrentp->mPrevp->mNextp = mCurrentp->mNextp; - } - else // otherwise we are at beginning of list - { - mHead.mNextp = mCurrentp->mNextp; - } - - // remove the node - mCurrentp->removeData(); - delete mCurrentp; - mCount--; - - // check for redundant pointing - if (mCurrentp == mQueuep) - { - mCurrentp = mQueuep = NULL; - } - else - { - mCurrentp = mQueuep; - } - } -} - - -// delete the Node at mCurrentp -// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep) -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::deleteCurrentData() -{ - if (mCurrentp) - { - // remove the node - // if there is a next one, fix it - if (mCurrentp->mNextp) - { - mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp; - } - else // otherwise we are at end of list - { - mTail.mPrevp = mCurrentp->mPrevp; - } - - // if there is a previous one, fix it - if (mCurrentp->mPrevp) - { - mCurrentp->mPrevp->mNextp = mCurrentp->mNextp; - } - else // otherwise we are at beginning of list - { - mHead.mNextp = mCurrentp->mNextp; - } - - // remove the LLDoubleLinkedNode - mCurrentp->deleteData(); - delete mCurrentp; - mCount--; - - // check for redundant pointing - if (mCurrentp == mQueuep) - { - mCurrentp = mQueuep = NULL; - } - else - { - mCurrentp = mQueuep; - } - } -} - - -// remove the Node at mCurrentp and insert it into newlist -// set mCurrentp to mQueuep, or NULL if (mCurrentp == mQueuep) -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::moveCurrentData(LLDoubleLinkedList<DATA_TYPE> *newlist) -{ - if (mCurrentp) - { - // remove the node - // if there is a next one, fix it - if (mCurrentp->mNextp) - { - mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp; - } - else // otherwise we are at end of list - { - mTail.mPrevp = mCurrentp->mPrevp; - } - - // if there is a previous one, fix it - if (mCurrentp->mPrevp) - { - mCurrentp->mPrevp->mNextp = mCurrentp->mNextp; - } - else // otherwise we are at beginning of list - { - mHead.mNextp = mCurrentp->mNextp; - } - - // move the node to the new list - newlist->addNode(mCurrentp); - - // check for redundant pointing - if (mCurrentp == mQueuep) - { - mCurrentp = mQueuep = NULL; - } - else - { - mCurrentp = mQueuep; - } - } -} - - -// Inserts the node previous to mCurrentp -// set mCurrentp to mQueuep -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::insertNode(LLDoubleLinkedNode<DATA_TYPE> *nodep) -{ - // don't allow pointer to NULL to be passed - if (!nodep) - { - llerror("NULL pointer passed to LLDoubleLinkedList::insertNode()", 0); - } - if (!nodep->mDatap) - { - llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0); - } - - if (mCurrentp) - { - if (mCurrentp->mPrevp) - { - nodep->mPrevp = mCurrentp->mPrevp; - nodep->mNextp = mCurrentp; - mCurrentp->mPrevp->mNextp = nodep; - mCurrentp->mPrevp = nodep; - } - else // at beginning of list - { - nodep->mPrevp = NULL; - nodep->mNextp = mCurrentp; - mHead.mNextp = nodep; - mCurrentp->mPrevp = nodep; - } - mCurrentp = mQueuep; - } - else // add to front of list - { - addNode(nodep); - } -} - - -// insert the data in front of mCurrentp -// set mCurrentp to mQueuep -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::insertData(DATA_TYPE *data) -{ - if (!data) - { - llerror("NULL data pointer passed to LLDoubleLinkedList::insertNode()", 0); - } - LLDoubleLinkedNode<DATA_TYPE> *node = new LLDoubleLinkedNode<DATA_TYPE>(data); - insertNode(node); - mCount++; -} - - -// if mCurrentp has a previous node then : -// * swaps mCurrentp with its previous -// * set mCurrentp to mQueuep -// otherwise does nothing -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithPrevious() -{ - if (mCurrentp) - { - if (mCurrentp->mPrevp) - { - // Pull mCurrentp out of list - mCurrentp->mPrevp->mNextp = mCurrentp->mNextp; - if (mCurrentp->mNextp) - { - mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp; - } - else // mCurrentp was at end of list - { - mTail.mPrevp = mCurrentp->mPrevp; - } - - // Fix mCurrentp's pointers - mCurrentp->mNextp = mCurrentp->mPrevp; - mCurrentp->mPrevp = mCurrentp->mNextp->mPrevp; - mCurrentp->mNextp->mPrevp = mCurrentp; - - if (mCurrentp->mPrevp) - { - // Fix the backward pointer of mCurrentp's new previous - mCurrentp->mPrevp->mNextp = mCurrentp; - } - else // mCurrentp is now at beginning of list - { - mHead.mNextp = mCurrentp; - } - - // Set the list back to the way it was - mCurrentp = mQueuep; - } - } -} - - -// if mCurrentp has a next node then : -// * swaps mCurrentp with its next -// * set mCurrentp to mQueuep -// otherwise does nothing -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::swapCurrentWithNext() -{ - if (mCurrentp) - { - if (mCurrentp->mNextp) - { - // Pull mCurrentp out of list - mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp; - if (mCurrentp->mPrevp) - { - mCurrentp->mPrevp->mNextp = mCurrentp->mNextp; - } - else // mCurrentp was at beginning of list - { - mHead.mNextp = mCurrentp->mNextp; - } - - // Fix mCurrentp's pointers - mCurrentp->mPrevp = mCurrentp->mNextp; - mCurrentp->mNextp = mCurrentp->mPrevp->mNextp; - mCurrentp->mPrevp->mNextp = mCurrentp; - - if (mCurrentp->mNextp) - { - // Fix the back pointer of mCurrentp's new next - mCurrentp->mNextp->mPrevp = mCurrentp; - } - else // mCurrentp is now at end of list - { - mTail.mPrevp = mCurrentp; - } - - // Set the list back to the way it was - mCurrentp = mQueuep; - } - } -} - -// move mCurrentp to the front of the list -// set mCurrentp to mQueuep -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToFront() -{ - if (mCurrentp) - { - // if there is a previous one, fix it - if (mCurrentp->mPrevp) - { - mCurrentp->mPrevp->mNextp = mCurrentp->mNextp; - } - else // otherwise we are at beginning of list - { - // check for redundant pointing - if (mCurrentp == mQueuep) - { - mCurrentp = mQueuep = NULL; - } - else - { - mCurrentp = mQueuep; - } - return; - } - - // if there is a next one, fix it - if (mCurrentp->mNextp) - { - mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp; - } - else // otherwise we are at end of list - { - mTail.mPrevp = mCurrentp->mPrevp; - } - - // add mCurrentp to beginning of list - mCurrentp->mNextp = mHead.mNextp; - mHead.mNextp->mPrevp = mCurrentp; // mHead.mNextp MUST be valid, - // or the list had only one node - // and we would have returned already - mCurrentp->mPrevp = NULL; - mHead.mNextp = mCurrentp; - - // check for redundant pointing - if (mCurrentp == mQueuep) - { - mCurrentp = mQueuep = NULL; - } - else - { - mCurrentp = mQueuep; - } - } - -} - -// move mCurrentp to the end of the list -// set mCurrentp to mQueuep -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::moveCurrentToEnd() -{ - if (mCurrentp) - { - // if there is a next one, fix it - if (mCurrentp->mNextp) - { - mCurrentp->mNextp->mPrevp = mCurrentp->mPrevp; - } - else // otherwise we are at end of list and we're done - { - // check for redundant pointing - if (mCurrentp == mQueuep) - { - mCurrentp = mQueuep = NULL; - } - else - { - mCurrentp = mQueuep; - } - return; - } - - // if there is a previous one, fix it - if (mCurrentp->mPrevp) - { - mCurrentp->mPrevp->mNextp = mCurrentp->mNextp; - } - else // otherwise we are at beginning of list - { - mHead.mNextp = mCurrentp->mNextp; - } - - // add mCurrentp to end of list - mCurrentp->mPrevp = mTail.mPrevp; - mTail.mPrevp->mNextp = mCurrentp; // mTail.mPrevp MUST be valid, - // or the list had only one node - // and we would have returned already - mCurrentp->mNextp = NULL; - mTail.mPrevp = mCurrentp; - - // check for redundant pointing - if (mCurrentp == mQueuep) - { - mCurrentp = mQueuep = NULL; - } - else - { - mCurrentp = mQueuep; - } - } -} - - -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::setInsertBefore(BOOL (*insert_before)(DATA_TYPE *first, DATA_TYPE *second) ) -{ - mInsertBefore = insert_before; -} - - -// add data in front of the first node for which mInsertBefore(datap, node->mDatap) returns TRUE -// set mCurrentp to mQueuep -template <class DATA_TYPE> -BOOL LLDoubleLinkedList<DATA_TYPE>::addDataSorted(DATA_TYPE *datap) -{ - // don't allow NULL to be passed to addData() - if (!datap) - { - llerror("NULL pointer passed to LLDoubleLinkedList::addDataSorted()", 0); - } - - // has mInsertBefore not been set? - if (!mInsertBefore) - { - addData(datap); - return FALSE; - } - - // is the list empty? - if (!mHead.mNextp) - { - addData(datap); - return TRUE; - } - - // Note: this step has been added so that the behavior of LLDoubleLinkedList - // is as rigorous as the LLLinkedList class about adding duplicate nodes. - // Duplicate nodes can cause a problem when sorting if mInsertBefore(foo, foo) - // returns TRUE. However, if mInsertBefore(foo, foo) returns FALSE, then there - // shouldn't be any reason to exclude duplicate nodes (as we do here). - if (checkData(datap)) - { - return FALSE; - } - - mCurrentp = mHead.mNextp; - while (mCurrentp) - { - // check to see if datap is already in the list - if (datap == mCurrentp->mDatap) - { - return FALSE; - } - else if (mInsertBefore(datap, mCurrentp->mDatap)) - { - insertData(datap); - return TRUE; - } - mCurrentp = mCurrentp->mNextp; - } - - addDataAtEnd(datap); - return TRUE; -} - - -// bubble-sort until sorted and return TRUE if anything was sorted -// leaves mQueuep pointing at last node that was swapped with its mNextp -// -// NOTE: if you find this function looping for really long times, then you -// probably need to check your implementation of mInsertBefore(a,b) and make -// sure it does not return TRUE when (a == b)! -template <class DATA_TYPE> -BOOL LLDoubleLinkedList<DATA_TYPE>::bubbleSort() -{ - BOOL b_swapped = FALSE; - U32 count = 0; - while (lazyBubbleSort()) - { - b_swapped = TRUE; - if (count++ > 0x7FFFFFFF) - { - llwarning("LLDoubleLinkedList::bubbleSort() : too many passes...", 1); - llwarning(" make sure the mInsertBefore(a, b) does not return TRUE for a == b", 1); - break; - } - } - return b_swapped; -} - - -// do a single bubble-sort pass and return TRUE if anything was sorted -// leaves mQueuep pointing at last node that was swapped with its mNextp -template <class DATA_TYPE> -BOOL LLDoubleLinkedList<DATA_TYPE>::lazyBubbleSort() -{ - // has mInsertBefore been set? - if (!mInsertBefore) - { - return FALSE; - } - - // is list empty? - mCurrentp = mHead.mNextp; - if (!mCurrentp) - { - return FALSE; - } - - BOOL b_swapped = FALSE; - - // the sort will exit after 0x7FFFFFFF nodes or the end of the list, whichever is first - S32 length = 0x7FFFFFFF; - S32 count = 0; - - while (mCurrentp && mCurrentp->mNextp && count<length) - { - if (mInsertBefore(mCurrentp->mNextp->mDatap, mCurrentp->mDatap)) - { - b_swapped = TRUE; - mQueuep = mCurrentp; - swapCurrentWithNext(); // sets mCurrentp to mQueuep - } - count++; - mCurrentp = mCurrentp->mNextp; - } - - return b_swapped; -} - - -template <class DATA_TYPE> -BOOL LLDoubleLinkedList<DATA_TYPE>::pushState() -{ - if (mStateStackDepth < LLDOUBLE_LINKED_LIST_STATE_STACK_DEPTH) - { - *(mQueuepStack + mStateStackDepth) = mQueuep; - *(mCurrentpStack + mStateStackDepth) = mCurrentp; - mStateStackDepth++; - return TRUE; - } - return FALSE; -} - - -template <class DATA_TYPE> -BOOL LLDoubleLinkedList<DATA_TYPE>::popState() -{ - if (mStateStackDepth > 0) - { - mStateStackDepth--; - mQueuep = *(mQueuepStack + mStateStackDepth); - mCurrentp = *(mCurrentpStack + mStateStackDepth); - return TRUE; - } - return FALSE; -} - - -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::clearStateStack() -{ - mStateStackDepth = 0; -} - -////////////////////////////////////////////////////////////////////////////////////////// -// private members -////////////////////////////////////////////////////////////////////////////////////////// - -// add node to beginning of list -// set mCurrentp to mQueuep -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::addNode(LLDoubleLinkedNode<DATA_TYPE> *nodep) -{ - // add the node to the front of the list - nodep->mPrevp = NULL; - nodep->mNextp = mHead.mNextp; - mHead.mNextp = nodep; - - // if there's something in the list, fix its back pointer - if (nodep->mNextp) - { - nodep->mNextp->mPrevp = nodep; - } - else // otherwise fix the tail node - { - mTail.mPrevp = nodep; - } - - mCurrentp = mQueuep; -} - - -// add node to end of list -// set mCurrentp to mQueuep -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::addNodeAtEnd(LLDoubleLinkedNode<DATA_TYPE> *node) -{ - // add the node to the end of the list - node->mNextp = NULL; - node->mPrevp = mTail.mPrevp; - mTail.mPrevp = node; - - // if there's something in the list, fix its back pointer - if (node->mPrevp) - { - node->mPrevp->mNextp = node; - } - else // otherwise fix the head node - { - mHead.mNextp = node; - } - - mCurrentp = mQueuep; -} - - -// randomly move nodes in the list for DEBUG (or Discordian) purposes -// sets mCurrentp and mQueuep to top of list -template <class DATA_TYPE> -void LLDoubleLinkedList<DATA_TYPE>::scramble() -{ - S32 random_number; - DATA_TYPE *datap = getFirstData(); - while(datap) - { - random_number = ll_rand(5); - - if (0 == random_number) - { - removeCurrentData(); - addData(datap); - } - else if (1 == random_number) - { - removeCurrentData(); - addDataAtEnd(datap); - } - else if (2 == random_number) - { - swapCurrentWithPrevious(); - } - else if (3 == random_number) - { - swapCurrentWithNext(); - } - datap = getNextData(); - } - mQueuep = mHead.mNextp; - mCurrentp = mQueuep; -} - -template <class DATA_TYPE> -BOOL LLDoubleLinkedList<DATA_TYPE>::isEmpty() -{ - return (mCount == 0); -} - - -#endif diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index d1c44c9403..47fa70614f 100755 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -29,6 +29,7 @@ #include "linden_common.h" #include "llapr.h" #include "apr_dso.h" +#include "llthreadlocalstorage.h" apr_pool_t *gAPRPoolp = NULL; // Global APR memory pool LLVolatileAPRPool *LLAPRFile::sAPRFilePoolp = NULL ; //global volatile APR memory pool. @@ -37,12 +38,15 @@ apr_thread_mutex_t *gCallStacksLogMutexp = NULL; const S32 FULL_VOLATILE_APR_POOL = 1024 ; //number of references to LLVolatileAPRPool +bool gAPRInitialized = false; + void ll_init_apr() { + // Initialize APR and create the global pool + apr_initialize(); + if (!gAPRPoolp) { - // Initialize APR and create the global pool - apr_initialize(); apr_pool_create(&gAPRPoolp, NULL); // Initialize the logging mutex @@ -52,13 +56,23 @@ void ll_init_apr() if(!LLAPRFile::sAPRFilePoolp) { - LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE) ; + LLAPRFile::sAPRFilePoolp = new LLVolatileAPRPool(FALSE); } + + LLThreadLocalPointerBase::initAllThreadLocalStorage(); + gAPRInitialized = true; } +bool ll_apr_is_initialized() +{ + return gAPRInitialized; +} + void ll_cleanup_apr() { + gAPRInitialized = false; + LL_INFOS("APR") << "Cleaning up APR" << LL_ENDL; if (gLogMutexp) @@ -77,6 +91,9 @@ void ll_cleanup_apr() apr_thread_mutex_destroy(gCallStacksLogMutexp); gCallStacksLogMutexp = NULL; } + + LLThreadLocalPointerBase::destroyAllThreadLocalStorage(); + if (gAPRPoolp) { apr_pool_destroy(gAPRPoolp); @@ -84,7 +101,7 @@ void ll_cleanup_apr() } if (LLAPRFile::sAPRFilePoolp) { - delete LLAPRFile::sAPRFilePoolp ; + delete LLAPRFile::sAPRFilePoolp ; LLAPRFile::sAPRFilePoolp = NULL ; } apr_terminate(); diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index 752574c65d..e9b13c5919 100755 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -32,28 +32,34 @@ #if LL_LINUX || LL_SOLARIS #include <sys/param.h> // Need PATH_MAX in APR headers... #endif -#if LL_WINDOWS - // Limit Windows API to small and manageable set. - // If you get undefined symbols, find the appropriate - // Windows header file and include that in your .cpp file. - #define WIN32_LEAN_AND_MEAN - #include <winsock2.h> - #include <windows.h> -#endif #include <boost/noncopyable.hpp> - +#include "llwin32headerslean.h" #include "apr_thread_proc.h" #include "apr_thread_mutex.h" #include "apr_getopt.h" #include "apr_signal.h" #include "apr_atomic.h" + #include "llstring.h" extern LL_COMMON_API apr_thread_mutex_t* gLogMutexp; extern apr_thread_mutex_t* gCallStacksLogMutexp; struct apr_dso_handle_t; +/** + * @brief Function which appropriately logs error or remains quiet on + * APR_SUCCESS. + * @return Returns <code>true</code> if status is an error condition. + */ +bool LL_COMMON_API ll_apr_warn_status(apr_status_t status); +/// There's a whole other APR error-message function if you pass a DSO handle. +bool LL_COMMON_API ll_apr_warn_status(apr_status_t status, apr_dso_handle_t* handle); + +void LL_COMMON_API ll_apr_assert_status(apr_status_t status); +void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle); + +extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool /** * @brief initialize the common apr constructs -- apr itself, the @@ -66,6 +72,9 @@ void LL_COMMON_API ll_init_apr(); */ void LL_COMMON_API ll_cleanup_apr(); +bool LL_COMMON_API ll_apr_is_initialized(); + + // //LL apr_pool //manage apr_pool_t, destroy allocated apr_pool in the destruction function. @@ -163,14 +172,17 @@ public: LLAtomic32<Type>(Type x) {apr_atomic_set32(&mData, apr_uint32_t(x)); }; ~LLAtomic32<Type>() {}; - operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); } + operator const Type() { return get(); } Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); } void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); } void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); } Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++ - Type operator --(int) { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise) + Type operator ++() { apr_atomic_inc32(&mData); return get(); } // ++Type + Type operator --(int) { const Type result(get()); apr_atomic_dec32(&mData); return result; } // Type-- + Type operator --() { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise) private: + const Type get() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); } apr_uint32_t mData; }; @@ -257,18 +269,5 @@ public: //******************************************************************************************************************************* }; -/** - * @brief Function which appropriately logs error or remains quiet on - * APR_SUCCESS. - * @return Returns <code>true</code> if status is an error condition. - */ -bool LL_COMMON_API ll_apr_warn_status(apr_status_t status); -/// There's a whole other APR error-message function if you pass a DSO handle. -bool LL_COMMON_API ll_apr_warn_status(apr_status_t status, apr_dso_handle_t* handle); - -void LL_COMMON_API ll_apr_assert_status(apr_status_t status); -void LL_COMMON_API ll_apr_assert_status(apr_status_t status, apr_dso_handle_t* handle); - -extern "C" LL_COMMON_API apr_pool_t* gAPRPoolp; // Global APR memory pool #endif // LL_LLAPR_H diff --git a/indra/llcommon/llassoclist.h b/indra/llcommon/llassoclist.h deleted file mode 100755 index 2950504155..0000000000 --- a/indra/llcommon/llassoclist.h +++ /dev/null @@ -1,296 +0,0 @@ -/** - * @file llassoclist.h - * @brief LLAssocList class header file - * - * $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_LLASSOCLIST_H -#define LL_LLASSOCLIST_H - -//------------------------------------------------------------------------ -// LLAssocList is an associative list container class. -// -// The implementation is a single linked list. -// Both index and value objects are stored by value (not reference). -// If pointer values are specified for index and/or value, this -// container does NOT assume ownership of the referenced objects, -// and does NOT delete() them on removal or destruction of the container. -// -// Note that operations are generally not optimized, and may of them -// are O(n) complexity. -//------------------------------------------------------------------------ - -#include <iostream> - -template<class INDEX_TYPE, class VALUE_TYPE> -class LLAssocList -{ -private: - // internal list node type - class Node - { - public: - Node(const INDEX_TYPE &index, const VALUE_TYPE &value, Node *next) - { - mIndex = index; - mValue = value; - mNext = next; - } - ~Node() { } - INDEX_TYPE mIndex; - VALUE_TYPE mValue; - Node *mNext; - }; - - // head of the linked list - Node *mHead; - -public: - // Constructor - LLAssocList() - { - mHead = NULL; - } - - // Destructor - ~LLAssocList() - { - removeAll(); - } - - // Returns TRUE if list is empty. - BOOL isEmpty() - { - return (mHead == NULL); - } - - // Returns the number of items in the list. - U32 length() - { - U32 count = 0; - for ( Node *node = mHead; - node; - node = node->mNext ) - { - count++; - } - return count; - } - - // Removes item with the specified index. - BOOL remove( const INDEX_TYPE &index ) - { - if (!mHead) - return FALSE; - - if (mHead->mIndex == index) - { - Node *node = mHead; - mHead = mHead->mNext; - delete node; - return TRUE; - } - - for ( Node *prev = mHead; - prev->mNext; - prev = prev->mNext ) - { - if (prev->mNext->mIndex == index) - { - Node *node = prev->mNext; - prev->mNext = prev->mNext->mNext; - delete node; - return TRUE; - } - } - return FALSE; - } - - // Removes all items from the list. - void removeAll() - { - while ( mHead ) - { - Node *node = mHead; - mHead = mHead->mNext; - delete node; - } - } - - // Adds a new item to the head of the list, - // removing any existing item with same index. - void addToHead( const INDEX_TYPE &index, const VALUE_TYPE &value ) - { - remove(index); - Node *node = new Node(index, value, mHead); - mHead = node; - } - - // Adds a new item to the end of the list, - // removing any existing item with the same index. - void addToTail( const INDEX_TYPE &index, const VALUE_TYPE &value ) - { - remove(index); - Node *node = new Node(index, value, NULL); - if (!mHead) - { - mHead = node; - return; - } - for ( Node *prev=mHead; - prev; - prev=prev->mNext ) - { - if (!prev->mNext) - { - prev->mNext=node; - return; - } - } - } - - // Sets the value of a specified index. - // If index does not exist, a new value will be added only if - // 'addIfNotFound' is set to TRUE. - // Returns TRUE if successful. - BOOL setValue( const INDEX_TYPE &index, const VALUE_TYPE &value, BOOL addIfNotFound=FALSE ) - { - VALUE_TYPE *valueP = getValue(index); - if (valueP) - { - *valueP = value; - return TRUE; - } - if (!addIfNotFound) - return FALSE; - addToTail(index, value); - return TRUE; - } - - // Sets the ith value in the list. - // A new value will NOT be addded, if the ith value does not exist. - // Returns TRUE if successful. - BOOL setValueAt( U32 i, const VALUE_TYPE &value ) - { - VALUE_TYPE *valueP = getValueAt(i); - if (valueP) - { - *valueP = value; - return TRUE; - } - return FALSE; - } - - // Returns a pointer to the value for the specified index, - // or NULL if no item found. - VALUE_TYPE *getValue( const INDEX_TYPE &index ) - { - for ( Node *node = mHead; - node; - node = node->mNext ) - { - if (node->mIndex == index) - return &node->mValue; - } - return NULL; - } - - // Returns a pointer to the ith value in the list, or - // NULL if i is not valid. - VALUE_TYPE *getValueAt( U32 i ) - { - U32 count = 0; - for ( Node *node = mHead; - node; - node = node->mNext ) - { - if (count == i) - return &node->mValue; - count++; - } - return NULL; - } - - // Returns a pointer to the index for the specified index, - // or NULL if no item found. - INDEX_TYPE *getIndex( const INDEX_TYPE &index ) - { - for ( Node *node = mHead; - node; - node = node->mNext ) - { - if (node->mIndex == index) - return &node->mIndex; - } - return NULL; - } - - // Returns a pointer to the ith index in the list, or - // NULL if i is not valid. - INDEX_TYPE *getIndexAt( U32 i ) - { - U32 count = 0; - for ( Node *node = mHead; - node; - node = node->mNext ) - { - if (count == i) - return &node->mIndex; - count++; - } - return NULL; - } - - // Returns a pointer to the value for the specified index, - // or NULL if no item found. - VALUE_TYPE *operator[](const INDEX_TYPE &index) - { - return getValue(index); - } - - // Returns a pointer to the ith value in the list, or - // NULL if i is not valid. - VALUE_TYPE *operator[](U32 i) - { - return getValueAt(i); - } - - // Prints the list contents to the specified stream. - friend std::ostream &operator<<( std::ostream &os, LLAssocList &map ) - { - os << "{"; - for ( Node *node = map.mHead; - node; - node = node->mNext ) - { - os << "<" << node->mIndex << ", " << node->mValue << ">"; - if (node->mNext) - os << ", "; - } - os << "}"; - - return os; - } -}; - -#endif // LL_LLASSOCLIST_H diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 8be9e4f4de..c720df7555 100755 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -29,6 +29,7 @@ #include "llmemory.h" #include "llthread.h" +#include "lltrace.h" //static BOOL LLCommon::sAprInitialized = FALSE; @@ -44,15 +45,13 @@ void LLCommon::initClass() } LLTimer::initClass(); LLThreadSafeRefCount::initThreadSafeRefCount(); -// LLWorkerThread::initClass(); -// LLFrameCallbackManager::initClass(); + LLTrace::init(); } //static void LLCommon::cleanupClass() { -// LLFrameCallbackManager::cleanupClass(); -// LLWorkerThread::cleanupClass(); + LLTrace::cleanup(); LLThreadSafeRefCount::cleanupThreadSafeRefCount(); LLTimer::cleanupClass(); if (sAprInitialized) diff --git a/indra/llcommon/llcriticaldamp.cpp b/indra/llcommon/llcriticaldamp.cpp index 87d79b1ee0..2f013fe255 100755 --- a/indra/llcommon/llcriticaldamp.cpp +++ b/indra/llcommon/llcriticaldamp.cpp @@ -27,18 +27,38 @@ #include "linden_common.h" #include "llcriticaldamp.h" +#include <algorithm> //----------------------------------------------------------------------------- // static members //----------------------------------------------------------------------------- -LLFrameTimer LLCriticalDamp::sInternalTimer; -std::map<F32, F32> LLCriticalDamp::sInterpolants; -F32 LLCriticalDamp::sTimeDelta; +LLFrameTimer LLSmoothInterpolation::sInternalTimer; +std::vector<LLSmoothInterpolation::Interpolant> LLSmoothInterpolation::sInterpolants; +F32 LLSmoothInterpolation::sTimeDelta; + +// helper functors +struct LLSmoothInterpolation::CompareTimeConstants +{ + bool operator()(const F32& a, const LLSmoothInterpolation::Interpolant& b) const + { + return a < b.mTimeScale; + } + + bool operator()(const LLSmoothInterpolation::Interpolant& a, const F32& b) const + { + return a.mTimeScale < b; // bottom of a is higher than bottom of b + } + + bool operator()(const LLSmoothInterpolation::Interpolant& a, const LLSmoothInterpolation::Interpolant& b) const + { + return a.mTimeScale < b.mTimeScale; // bottom of a is higher than bottom of b + } +}; //----------------------------------------------------------------------------- -// LLCriticalDamp() +// LLSmoothInterpolation() //----------------------------------------------------------------------------- -LLCriticalDamp::LLCriticalDamp() +LLSmoothInterpolation::LLSmoothInterpolation() { sTimeDelta = 0.f; } @@ -47,43 +67,54 @@ LLCriticalDamp::LLCriticalDamp() //----------------------------------------------------------------------------- // updateInterpolants() //----------------------------------------------------------------------------- -void LLCriticalDamp::updateInterpolants() +void LLSmoothInterpolation::updateInterpolants() { sTimeDelta = sInternalTimer.getElapsedTimeAndResetF32(); - F32 time_constant; - - for (std::map<F32, F32>::iterator iter = sInterpolants.begin(); - iter != sInterpolants.end(); iter++) + for (S32 i = 0; i < sInterpolants.size(); i++) { - time_constant = iter->first; - F32 new_interpolant = 1.f - pow(2.f, -sTimeDelta / time_constant); - new_interpolant = llclamp(new_interpolant, 0.f, 1.f); - sInterpolants[time_constant] = new_interpolant; + Interpolant& interp = sInterpolants[i]; + interp.mInterpolant = calcInterpolant(interp.mTimeScale); } } //----------------------------------------------------------------------------- // getInterpolant() //----------------------------------------------------------------------------- -F32 LLCriticalDamp::getInterpolant(const F32 time_constant, BOOL use_cache) +F32 LLSmoothInterpolation::getInterpolant(LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache) { if (time_constant == 0.f) { return 1.f; } - if (use_cache && sInterpolants.count(time_constant)) + if (use_cache) { - return sInterpolants[time_constant]; + interpolant_vec_t::iterator find_it = std::lower_bound(sInterpolants.begin(), sInterpolants.end(), time_constant.value(), CompareTimeConstants()); + if (find_it != sInterpolants.end() && find_it->mTimeScale == time_constant) + { + return find_it->mInterpolant; + } + else + { + Interpolant interp; + interp.mTimeScale = time_constant.value(); + interp.mInterpolant = calcInterpolant(time_constant.value()); + sInterpolants.insert(find_it, interp); + return interp.mInterpolant; + } } - - F32 interpolant = 1.f - pow(2.f, -sTimeDelta / time_constant); - interpolant = llclamp(interpolant, 0.f, 1.f); - if (use_cache) + else { - sInterpolants[time_constant] = interpolant; + return calcInterpolant(time_constant.value()); + } +} - return interpolant; +//----------------------------------------------------------------------------- +// calcInterpolant() +//----------------------------------------------------------------------------- +F32 LLSmoothInterpolation::calcInterpolant(F32 time_constant) +{ + return llclamp(1.f - powf(2.f, -sTimeDelta / time_constant), 0.f, 1.f); } diff --git a/indra/llcommon/llcriticaldamp.h b/indra/llcommon/llcriticaldamp.h index 52f052ae25..ab5d4ba6e2 100755 --- a/indra/llcommon/llcriticaldamp.h +++ b/indra/llcommon/llcriticaldamp.h @@ -28,26 +28,46 @@ #ifndef LL_LLCRITICALDAMP_H #define LL_LLCRITICALDAMP_H -#include <map> +#include <vector> #include "llframetimer.h" +#include "llunit.h" -class LL_COMMON_API LLCriticalDamp +class LL_COMMON_API LLSmoothInterpolation { public: - LLCriticalDamp(); + LLSmoothInterpolation(); // MANIPULATORS static void updateInterpolants(); // ACCESSORS - static F32 getInterpolant(const F32 time_constant, BOOL use_cache = TRUE); + static F32 getInterpolant(LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache = true); -protected: + template<typename T> + static T lerp(T a, T b, LLUnit<LLUnits::Seconds, F32> time_constant, bool use_cache = true) + { + F32 interpolant = getInterpolant(time_constant, use_cache); + return ((a * (1.f - interpolant)) + + (b * interpolant)); + } + +protected: + static F32 calcInterpolant(F32 time_constant); + + struct CompareTimeConstants; static LLFrameTimer sInternalTimer; // frame timer for calculating deltas - static std::map<F32, F32> sInterpolants; + struct Interpolant + { + F32 mTimeScale; + F32 mInterpolant; + }; + typedef std::vector<Interpolant> interpolant_vec_t; + static interpolant_vec_t sInterpolants; static F32 sTimeDelta; }; +typedef LLSmoothInterpolation LLCriticalDamp; + #endif // LL_LLCRITICALDAMP_H diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 030ef6a3c7..2efe39e158 100755 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -39,6 +39,7 @@ #include "lltimer.h" #include "llstring.h" +#include "llfasttimer.h" static const F64 DATE_EPOCH = 0.0; @@ -48,18 +49,15 @@ static const F64 LL_APR_USEC_PER_SEC = 1000000.0; LLDate::LLDate() : mSecondsSinceEpoch(DATE_EPOCH) -{ -} +{} LLDate::LLDate(const LLDate& date) : mSecondsSinceEpoch(date.mSecondsSinceEpoch) -{ -} +{} -LLDate::LLDate(F64 seconds_since_epoch) : - mSecondsSinceEpoch(seconds_since_epoch) -{ -} +LLDate::LLDate(LLUnit<LLUnits::Seconds, F64> seconds_since_epoch) : + mSecondsSinceEpoch(seconds_since_epoch.value()) +{} LLDate::LLDate(const std::string& iso8601_date) { diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 7ff8b550ad..b62a846147 100755 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -33,6 +33,7 @@ #include <string> #include "stdtypes.h" +#include "llunit.h" /** * @class LLDate @@ -56,9 +57,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(LLUnit<LLUnits::Seconds, F64> seconds_since_epoch); /** * @brief Construct a date from a string representation diff --git a/indra/llcommon/lldefs.h b/indra/llcommon/lldefs.h index 5a4b8325f4..d57b9dccff 100755 --- a/indra/llcommon/lldefs.h +++ b/indra/llcommon/lldefs.h @@ -244,5 +244,8 @@ inline void llswap(LLDATATYPE& lhs, LLDATATYPE& rhs) rhs = tmp; } +#define LL_GLUE_IMPL(x, y) x##y +#define LL_GLUE_TOKENS(x, y) LL_GLUE_IMPL(x, y) + #endif // LL_LLDEFS_H diff --git a/indra/llcommon/lldeleteutils.h b/indra/llcommon/lldeleteutils.h deleted file mode 100755 index f250dc3028..0000000000 --- a/indra/llcommon/lldeleteutils.h +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file lldeleteutils.h - * @brief Utility functions to simplify some common pointer-munging idioms. - * - * $LicenseInfo:firstyear=2009&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_DELETE_UTILS_H -#define LL_DELETE_UTILS_H - -// Simple utility functions to eventually replace the common 2-line -// idiom scattered throughout the viewer codebase. Note that where -// possible we would rather be using smart pointers of some sort. - -template <class T> -inline void deleteAndClear(T*& ptr) -{ - delete ptr; - ptr = NULL; -} - -template <class T> -inline void deleteAndClearArray(T*& array_ptr) -{ - delete[] array_ptr; - array_ptr = NULL; -} - -#endif diff --git a/indra/llcommon/lldepthstack.h b/indra/llcommon/lldepthstack.h index d9db54efc7..ac435a30fa 100755 --- a/indra/llcommon/lldepthstack.h +++ b/indra/llcommon/lldepthstack.h @@ -27,17 +27,20 @@ #ifndef LL_LLDEPTHSTACK_H #define LL_LLDEPTHSTACK_H -#include "linked_lists.h" +#include "llstl.h" template <class DATA_TYPE> class LLDepthStack { private: - LLLinkedList<DATA_TYPE> mStack; + std::deque<DATA_TYPE*> mStack; U32 mCurrentDepth; U32 mMaxDepth; public: - LLDepthStack() : mCurrentDepth(0), mMaxDepth(0) {} + LLDepthStack() + : mCurrentDepth(0), mMaxDepth(0) + {} + ~LLDepthStack() {} void setDepth(U32 depth) @@ -54,24 +57,27 @@ public: { if (mCurrentDepth < mMaxDepth) { - mStack.addData(data); + mStack.push_back(data); mCurrentDepth++; } else { // the last item falls off stack and is deleted - mStack.getLastData(); - mStack.deleteCurrentData(); - mStack.addData(data); + if (!mStack.empty()) + { + mStack.pop_front(); + } + mStack.push_back(data); } } DATA_TYPE *pop() { - DATA_TYPE *tempp = mStack.getFirstData(); - if (tempp) + DATA_TYPE *tempp = NULL; + if (!mStack.empty()) { - mStack.removeCurrentData(); + tempp = mStack.back(); + mStack.pop_back(); mCurrentDepth--; } return tempp; @@ -79,20 +85,20 @@ public: DATA_TYPE *check() { - DATA_TYPE *tempp = mStack.getFirstData(); - return tempp; + return mStack.empty() ? NULL : mStack.back(); } void deleteAllData() { mCurrentDepth = 0; - mStack.deleteAllData(); + std::for_each(mStack.begin(), mStack.end(), DeletePointer()); + mStack.clear(); } void removeAllNodes() { mCurrentDepth = 0; - mStack.removeAllNodes(); + mStack.clear(); } }; diff --git a/indra/llcommon/lldlinked.h b/indra/llcommon/lldlinked.h deleted file mode 100755 index 3f7c197be7..0000000000 --- a/indra/llcommon/lldlinked.h +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @file lldlinked.h - * @brief Declaration of the LLDLinked class. - * - * $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_LLDLINKED_H -#define LL_LLDLINKED_H - -template <class Type> class LLDLinked -{ - LLDLinked* mNextp; - LLDLinked* mPrevp; -public: - - Type* getNext() { return (Type*)mNextp; } - Type* getPrev() { return (Type*)mPrevp; } - Type* getFirst() { return (Type*)mNextp; } - - void init() - { - mNextp = mPrevp = NULL; - } - - void unlink() - { - if (mPrevp) mPrevp->mNextp = mNextp; - if (mNextp) mNextp->mPrevp = mPrevp; - } - - LLDLinked() { mNextp = mPrevp = NULL; } - virtual ~LLDLinked() { unlink(); } - - virtual void deleteAll() - { - Type *curp = getFirst(); - while(curp) - { - Type *nextp = curp->getNext(); - curp->unlink(); - delete curp; - curp = nextp; - } - } - - void relink(Type &after) - { - LLDLinked *afterp = (LLDLinked*)&after; - afterp->mPrevp = this; - mNextp = afterp; - } - - virtual void append(Type& after) - { - LLDLinked *afterp = (LLDLinked*)&after; - afterp->mPrevp = this; - afterp->mNextp = mNextp; - if (mNextp) mNextp->mPrevp = afterp; - mNextp = afterp; - } - - virtual void insert(Type& before) - { - LLDLinked *beforep = (LLDLinked*)&before; - beforep->mNextp = this; - beforep->mPrevp = mPrevp; - if (mPrevp) mPrevp->mNextp = beforep; - mPrevp = beforep; - } - - virtual void put(Type& obj) { append(obj); } -}; - -#endif diff --git a/indra/llcommon/lldqueueptr.h b/indra/llcommon/lldqueueptr.h deleted file mode 100755 index 9fe08191e1..0000000000 --- a/indra/llcommon/lldqueueptr.h +++ /dev/null @@ -1,352 +0,0 @@ -/** - * @file lldqueueptr.h - * @brief LLDynamicQueuePtr declaration - * - * $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_LLDQUEUEPTR_H -#define LL_LLDQUEUEPTR_H - -template <class Type> -class LLDynamicQueuePtr -{ -public: - enum - { - OKAY = 0, - FAIL = -1 - }; - - LLDynamicQueuePtr(const S32 size=8); - ~LLDynamicQueuePtr(); - - void init(); - void destroy(); - void reset(); - void reallocate(U32 newsize); - - // ACCESSORS - const Type& get(const S32 index) const; // no bounds checking - Type& get(const S32 index); // no bounds checking - const Type& operator [] (const S32 index) const { return get(index); } - Type& operator [] (const S32 index) { return get(index); } - S32 find(const Type &obj) const; - - S32 count() const { return (mLastObj >= mFirstObj ? mLastObj - mFirstObj : mLastObj + mMaxObj - mFirstObj); } - S32 getMax() const { return mMaxObj; } - S32 getFirst() const { return mFirstObj; } - S32 getLast () const { return mLastObj; } - - // MANIPULATE - S32 push(const Type &obj); // add to end of Queue, returns index from start - S32 pull( Type &obj); // pull from Queue, returns index from start - - S32 remove (S32 index); // remove by index - S32 removeObj(const Type &obj); // remove by object - -protected: - S32 mFirstObj, mLastObj, mMaxObj; - Type* mMemory; - -public: - - void print() - { - /* - Convert this to llinfos if it's intended to be used - djs 08/30/02 - - printf("Printing from %d to %d (of %d): ",mFirstObj, mLastObj, mMaxObj); - - if (mFirstObj <= mLastObj) - { - for (S32 i=mFirstObj;i<mLastObj;i++) - { - printf("%d ",mMemory[i]); - } - } - else - { - for (S32 i=mFirstObj;i<mMaxObj;i++) - { - printf("%d ",mMemory[i]); - } - for (i=0;i<mLastObj;i++) - { - printf("%d ",mMemory[i]); - } - } - printf("\n"); - */ - } - -}; - - -//-------------------------------------------------------- -// LLDynamicQueuePtrPtr implementation -//-------------------------------------------------------- - - -template <class Type> -inline LLDynamicQueuePtr<Type>::LLDynamicQueuePtr(const S32 size) -{ - init(); - reallocate(size); -} - -template <class Type> -inline LLDynamicQueuePtr<Type>::~LLDynamicQueuePtr() -{ - destroy(); -} - -template <class Type> -inline void LLDynamicQueuePtr<Type>::init() -{ - mFirstObj = 0; - mLastObj = 0; - mMaxObj = 0; - mMemory = NULL; -} - -template <class Type> -inline void LLDynamicQueuePtr<Type>::reallocate(U32 newsize) -{ - if (newsize) - { - if (mFirstObj > mLastObj && newsize > mMaxObj) - { - Type* new_memory = new Type[newsize]; - - llassert(new_memory); - - S32 _count = count(); - S32 i, m = 0; - for (i=mFirstObj; i < mMaxObj; i++) - { - new_memory[m++] = mMemory[i]; - } - for (i=0; i <=mLastObj; i++) - { - new_memory[m++] = mMemory[i]; - } - - delete[] mMemory; - mMemory = new_memory; - - mFirstObj = 0; - mLastObj = _count; - } - else - { - Type* new_memory = new Type[newsize]; - - llassert(new_memory); - - S32 i, m = 0; - for (i=0; i < mLastObj; i++) - { - new_memory[m++] = mMemory[i]; - } - delete[] mMemory; - mMemory = new_memory; - } - } - else if (mMemory) - { - delete[] mMemory; - mMemory = NULL; - } - - mMaxObj = newsize; -} - -template <class Type> -inline void LLDynamicQueuePtr<Type>::destroy() -{ - reset(); - delete[] mMemory; - mMemory = NULL; -} - - -template <class Type> -void LLDynamicQueuePtr<Type>::reset() -{ - for (S32 i=0; i < mMaxObj; i++) - { - get(i) = NULL; // unrefs for pointers - } - - mFirstObj = 0; - mLastObj = 0; -} - - -template <class Type> -inline S32 LLDynamicQueuePtr<Type>::find(const Type &obj) const -{ - S32 i; - if (mFirstObj <= mLastObj) - { - for ( i = mFirstObj; i < mLastObj; i++ ) - { - if (mMemory[i] == obj) - { - return i; - } - } - } - else - { - for ( i = mFirstObj; i < mMaxObj; i++ ) - { - if (mMemory[i] == obj) - { - return i; - } - } - for ( i = 0; i < mLastObj; i++ ) - { - if (mMemory[i] == obj) - { - return i; - } - } - } - - return FAIL; -} - -template <class Type> -inline S32 LLDynamicQueuePtr<Type>::remove(S32 i) -{ - if (mFirstObj > mLastObj) - { - if (i >= mFirstObj && i < mMaxObj) - { - while( i > mFirstObj) - { - mMemory[i] = mMemory[i-1]; - i--; - } - mMemory[mFirstObj] = NULL; - mFirstObj++; - if (mFirstObj >= mMaxObj) mFirstObj = 0; - - return count(); - } - else if (i < mLastObj && i >= 0) - { - while(i < mLastObj) - { - mMemory[i] = mMemory[i+1]; - i++; - } - mMemory[mLastObj] = NULL; - mLastObj--; - if (mLastObj < 0) mLastObj = mMaxObj-1; - - return count(); - } - } - else if (i <= mLastObj && i >= mFirstObj) - { - while(i < mLastObj) - { - mMemory[i] = mMemory[i+1]; - i++; - } - mMemory[mLastObj] = NULL; - mLastObj--; - if (mLastObj < 0) mLastObj = mMaxObj-1; - - return count(); - } - - - return FAIL; -} - -template <class Type> -inline S32 LLDynamicQueuePtr<Type>::removeObj(const Type& obj) -{ - S32 ind = find(obj); - if (ind >= 0) - { - return remove(ind); - } - return FAIL; -} - -template <class Type> -inline S32 LLDynamicQueuePtr<Type>::push(const Type &obj) -{ - if (mMaxObj - count() <= 1) - { - reallocate(mMaxObj * 2); - } - - mMemory[mLastObj++] = obj; - - if (mLastObj >= mMaxObj) - { - mLastObj = 0; - } - - return count(); -} - -template <class Type> -inline S32 LLDynamicQueuePtr<Type>::pull(Type &obj) -{ - obj = NULL; - - if (count() < 1) return -1; - - obj = mMemory[mFirstObj]; - mMemory[mFirstObj] = NULL; - - mFirstObj++; - - if (mFirstObj >= mMaxObj) - { - mFirstObj = 0; - } - - return count(); -} - -template <class Type> -inline const Type& LLDynamicQueuePtr<Type>::get(const S32 i) const -{ - return mMemory[i]; -} - -template <class Type> -inline Type& LLDynamicQueuePtr<Type>::get(const S32 i) -{ - return mMemory[i]; -} - - -#endif // LL_LLDQUEUEPTR_H diff --git a/indra/llcommon/llenum.h b/indra/llcommon/llenum.h deleted file mode 100755 index f57b2bc0b5..0000000000 --- a/indra/llcommon/llenum.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file llenum.h - * @author Tom Yedwab - * @brief Utility class for storing enum value <-> string lookup. - * - * $LicenseInfo:firstyear=2006&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_LLENUM_H -#define LL_LLENUM_H - -class LLEnum -{ -public: - typedef std::pair<const std::string, const U32> enum_t; - enum - { - UNDEFINED = 0xffffffff, - }; - - LLEnum(const enum_t values_array[], const U32 length) - { - for (U32 i=0; i<length; ++i) - { - mEnumMap.insert(values_array[i]); - if (values_array[i].second >= mEnumArray.size()) - { - mEnumArray.resize(values_array[i].second+1); - } - mEnumArray[values_array[i].second] = values_array[i].first; - } - } - - U32 operator[](std::string str) - { - std::map<const std::string, const U32>::iterator itor; - itor = mEnumMap.find(str); - if (itor != mEnumMap.end()) - { - return itor->second; - } - return UNDEFINED; - } - - const std::string operator[](U32 index) - { - if (index < mEnumArray.size()) - { - return mEnumArray[index]; - } - return ""; - } - -private: - std::map<const std::string, const U32> mEnumMap; - std::vector<std::string> mEnumArray; -}; - -#endif // LL_LLENUM_H diff --git a/indra/llcommon/llerrorlegacy.h b/indra/llcommon/llerrorlegacy.h index 37cee579cd..097a533b1a 100755 --- a/indra/llcommon/llerrorlegacy.h +++ b/indra/llcommon/llerrorlegacy.h @@ -29,6 +29,7 @@ #define LL_LLERRORLEGACY_H #include "llpreprocessor.h" +#include <boost/static_assert.hpp> /* LEGACY -- DO NOT USE THIS STUFF ANYMORE @@ -111,6 +112,14 @@ const int LL_ERR_PRICE_MISMATCH = -23018; #define llverify(func) do {if (func) {}} while(0) #endif +#ifdef LL_WINDOWS +#define llstatic_assert(func, msg) static_assert(func, msg) +#define llstatic_assert_template(type, func, msg) static_assert(func, msg) +#else +#define llstatic_assert(func, msg) BOOST_STATIC_ASSERT(func) +#define llstatic_assert_template(type, func, msg) BOOST_STATIC_ASSERT(sizeof(type) != 0 && func); +#endif + // handy compile-time assert - enforce those template parameters! #define cassert(expn) typedef char __C_ASSERT__[(expn)?1:-1] /* Flawfinder: ignore */ //XXX: used in two places in llcommon/llskipmap.h diff --git a/indra/llcommon/llevents.cpp b/indra/llcommon/llevents.cpp index 0855180dcd..1c928b3db8 100755 --- a/indra/llcommon/llevents.cpp +++ b/indra/llcommon/llevents.cpp @@ -41,7 +41,6 @@ #include <algorithm> // std headers #include <typeinfo> -#include <cassert> #include <cmath> #include <cctype> // external library headers diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index 9b15804e97..dfc72bd2ce 100755 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -32,8 +32,13 @@ #include "llsingleton.h" #include "lltreeiterators.h" #include "llsdserialize.h" +#include "llunit.h" +#include "llsd.h" +#include "lltracerecording.h" +#include "lltracethreadrecorder.h" #include <boost/bind.hpp> +#include <queue> #if LL_WINDOWS @@ -49,37 +54,36 @@ #error "architecture not supported" #endif +namespace LLTrace +{ + ////////////////////////////////////////////////////////////////////////////// // statics -S32 LLFastTimer::sCurFrameIndex = -1; -S32 LLFastTimer::sLastFrameIndex = -1; -U64 LLFastTimer::sLastFrameTime = LLFastTimer::getCPUClockCount64(); -bool LLFastTimer::sPauseHistory = 0; -bool LLFastTimer::sResetHistory = 0; -LLFastTimer::CurTimerData LLFastTimer::sCurTimerData; -BOOL LLFastTimer::sLog = FALSE; -std::string LLFastTimer::sLogName = ""; -BOOL LLFastTimer::sMetricLog = FALSE; -LLMutex* LLFastTimer::sLogLock = NULL; -std::queue<LLSD> LLFastTimer::sLogQueue; +bool TimeBlock::sLog = false; +std::string TimeBlock::sLogName = ""; +bool TimeBlock::sMetricLog = false; #if LL_LINUX || LL_SOLARIS -U64 LLFastTimer::sClockResolution = 1000000000; // Nanosecond resolution +U64 TimeBlock::sClockResolution = 1000000000; // Nanosecond resolution #else -U64 LLFastTimer::sClockResolution = 1000000; // Microsecond resolution +U64 TimeBlock::sClockResolution = 1000000; // Microsecond resolution #endif +static LLMutex* sLogLock = NULL; +static std::queue<LLSD> sLogQueue; + + // FIXME: move these declarations to the relevant modules // helper functions -typedef LLTreeDFSPostIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_bottom_up_iterator_t; +typedef LLTreeDFSPostIter<TimeBlock, TimeBlock::child_const_iter> timer_tree_bottom_up_iterator_t; -static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(LLFastTimer::NamedTimer& id) +static timer_tree_bottom_up_iterator_t begin_timer_tree_bottom_up(TimeBlock& id) { return timer_tree_bottom_up_iterator_t(&id, - boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1), - boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1)); + boost::bind(boost::mem_fn(&TimeBlock::beginChildren), _1), + boost::bind(boost::mem_fn(&TimeBlock::endChildren), _1)); } static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up() @@ -87,14 +91,14 @@ static timer_tree_bottom_up_iterator_t end_timer_tree_bottom_up() return timer_tree_bottom_up_iterator_t(); } -typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_dfs_iterator_t; +typedef LLTreeDFSIter<TimeBlock, TimeBlock::child_const_iter> timer_tree_dfs_iterator_t; -static timer_tree_dfs_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id) +static timer_tree_dfs_iterator_t begin_timer_tree(TimeBlock& id) { return timer_tree_dfs_iterator_t(&id, - boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1), - boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1)); + boost::bind(boost::mem_fn(&TimeBlock::beginChildren), _1), + boost::bind(boost::mem_fn(&TimeBlock::endChildren), _1)); } static timer_tree_dfs_iterator_t end_timer_tree() @@ -102,90 +106,48 @@ static timer_tree_dfs_iterator_t end_timer_tree() return timer_tree_dfs_iterator_t(); } -// factory class that creates NamedTimers via static DeclareTimer objects -class NamedTimerFactory : public LLSingleton<NamedTimerFactory> -{ -public: - NamedTimerFactory() - : mTimerRoot(NULL) - {} - /*virtual */ void initSingleton() +// sort child timers by name +struct SortTimerByName +{ + bool operator()(const TimeBlock* i1, const TimeBlock* i2) { - mTimerRoot = new LLFastTimer::NamedTimer("root"); - mRootFrameState.setNamedTimer(mTimerRoot); - mTimerRoot->setFrameState(&mRootFrameState); - mTimerRoot->mParent = mTimerRoot; - mTimerRoot->setCollapsed(false); - mRootFrameState.mParent = &mRootFrameState; + return i1->getName() < i2->getName(); } +}; - ~NamedTimerFactory() +TimeBlock& TimeBlock::getRootTimeBlock() { - std::for_each(mTimers.begin(), mTimers.end(), DeletePairedPointer()); - - delete mTimerRoot; + static TimeBlock root_timer("root", true, NULL); + return root_timer; } - LLFastTimer::NamedTimer& createNamedTimer(const std::string& name, LLFastTimer::FrameState* state) +void TimeBlock::pushLog(LLSD log) { - LLFastTimer::NamedTimer* timer = new LLFastTimer::NamedTimer(name); - timer->setFrameState(state); - timer->setParent(mTimerRoot); - mTimers.insert(std::make_pair(name, timer)); + LLMutexLock lock(sLogLock); - return *timer; + sLogQueue.push(log); } - LLFastTimer::NamedTimer* getTimerByName(const std::string& name) - { - timer_map_t::iterator found_it = mTimers.find(name); - if (found_it != mTimers.end()) - { - return found_it->second; - } - return NULL; - } - - LLFastTimer::NamedTimer* getRootTimer() { return mTimerRoot; } - - typedef std::multimap<std::string, LLFastTimer::NamedTimer*> timer_map_t; - timer_map_t::iterator beginTimers() { return mTimers.begin(); } - timer_map_t::iterator endTimers() { return mTimers.end(); } - S32 timerCount() { return mTimers.size(); } - -private: - timer_map_t mTimers; - - LLFastTimer::NamedTimer* mTimerRoot; - LLFastTimer::FrameState mRootFrameState; -}; - -LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name, bool open ) -: mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState)) +void TimeBlock::setLogLock(LLMutex* lock) { - mTimer.setCollapsed(!open); + sLogLock = lock; } -LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name) -: mTimer(NamedTimerFactory::instance().createNamedTimer(name, &mFrameState)) -{ -} //static #if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) -U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer +U64 TimeBlock::countsPerSecond() { - return sClockResolution >> 8; + return sClockResolution; } #else // windows or x86-mac or x86-linux or x86-solaris -U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer +U64 TimeBlock::countsPerSecond() { #if LL_FASTTIMER_USE_RDTSC || !LL_WINDOWS //getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz - static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0); + static LLUnit<LLUnits::Hertz, U64> sCPUClockFrequency = LLProcessorInfo().getCPUFrequency(); - // we drop the low-order byte in our timers, so report a lower frequency #else // If we're not using RDTSC, each fasttimer tick is just a performance counter tick. // Not redefining the clock frequency itself (in llprocessor.cpp/calculate_cpu_frequency()) @@ -198,269 +160,189 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer firstcall = false; } #endif - return sCPUClockFrequency >> 8; + return sCPUClockFrequency.value(); } #endif -LLFastTimer::FrameState::FrameState() -: mActiveCount(0), - mCalls(0), - mSelfTimeCounter(0), - mParent(NULL), - mLastCaller(NULL), - mMoveUpTree(false) -{} - - -LLFastTimer::NamedTimer::NamedTimer(const std::string& name) -: mName(name), - mCollapsed(true), - mParent(NULL), - mTotalTimeCounter(0), - mCountAverage(0), - mCallAverage(0), - mNeedsSorting(false), - mFrameState(NULL) -{ - mCountHistory = new U32[HISTORY_NUM]; - memset(mCountHistory, 0, sizeof(U32) * HISTORY_NUM); - mCallHistory = new U32[HISTORY_NUM]; - memset(mCallHistory, 0, sizeof(U32) * HISTORY_NUM); -} - -LLFastTimer::NamedTimer::~NamedTimer() -{ - delete[] mCountHistory; - delete[] mCallHistory; -} - -std::string LLFastTimer::NamedTimer::getToolTip(S32 history_idx) -{ - F64 ms_multiplier = 1000.0 / (F64)LLFastTimer::countsPerSecond(); - if (history_idx < 0) - { - // by default, show average number of call - return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getCountAverage() * ms_multiplier), (S32)getCallAverage()); - } - else - { - return llformat("%s (%d ms, %d calls)", getName().c_str(), (S32)(getHistoricalCount(history_idx) * ms_multiplier), (S32)getHistoricalCalls(history_idx)); - } -} - -void LLFastTimer::NamedTimer::setParent(NamedTimer* parent) -{ - llassert_always(parent != this); - llassert_always(parent != NULL); - - if (mParent) - { - // subtract our accumulated from previous parent - for (S32 i = 0; i < HISTORY_NUM; i++) - { - mParent->mCountHistory[i] -= mCountHistory[i]; - } - - // subtract average timing from previous parent - mParent->mCountAverage -= mCountAverage; - - std::vector<NamedTimer*>& children = mParent->getChildren(); - std::vector<NamedTimer*>::iterator found_it = std::find(children.begin(), children.end(), this); - if (found_it != children.end()) - { - children.erase(found_it); - } - } - - mParent = parent; - if (parent) - { - getFrameState().mParent = &parent->getFrameState(); - parent->getChildren().push_back(this); - parent->mNeedsSorting = true; - } -} - -S32 LLFastTimer::NamedTimer::getDepth() +TimeBlock::TimeBlock(const char* name, bool open, TimeBlock* parent) +: TraceType<TimeBlockAccumulator>(name), + mCollapsed(true) { - S32 depth = 0; - NamedTimer* timerp = mParent; - while(timerp) - { - depth++; - if (timerp->getParent() == timerp) break; - timerp = timerp->mParent; - } - return depth; + setCollapsed(!open); } -// static -void LLFastTimer::NamedTimer::processTimes() +TimeBlockTreeNode& TimeBlock::getTreeNode() const { - if (sCurFrameIndex < 0) return; - - buildHierarchy(); - accumulateTimings(); + TimeBlockTreeNode* nodep = LLTrace::get_thread_recorder()->getTimeBlockTreeNode(getIndex()); + llassert(nodep); + return *nodep; } -// sort child timers by name -struct SortTimerByName -{ - bool operator()(const LLFastTimer::NamedTimer* i1, const LLFastTimer::NamedTimer* i2) - { - return i1->getName() < i2->getName(); - } -}; +static LLFastTimer::DeclareTimer FTM_PROCESS_TIMES("Process FastTimer Times"); +// not thread safe, so only call on main thread //static -void LLFastTimer::NamedTimer::buildHierarchy() +void TimeBlock::processTimes() { - if (sCurFrameIndex < 0 ) return; + LLFastTimer _(FTM_PROCESS_TIMES); + get_clock_count(); // good place to calculate clock frequency + U64 cur_time = getCPUClockCount64(); // set up initial tree + for (LLInstanceTracker<TimeBlock>::instance_iter begin_it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(), it = begin_it; + it != end_it; + ++it) { - for (instance_iter it = beginInstances(); it != endInstances(); ++it) + TimeBlock& timer = *it; + if (&timer == &TimeBlock::getRootTimeBlock()) continue; + + // bootstrap tree construction by attaching to last timer to be on stack + // when this timer was called + if (timer.getParent() == &TimeBlock::getRootTimeBlock()) { - NamedTimer& timer = *it; - if (&timer == NamedTimerFactory::instance().getRootTimer()) continue; + TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator(); - // bootstrap tree construction by attaching to last timer to be on stack - // when this timer was called - if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer()) + if (accumulator->mLastCaller) { - timer.setParent(timer.getFrameState().mLastCaller->mTimer); - // no need to push up tree on first use, flag can be set spuriously - timer.getFrameState().mMoveUpTree = false; + timer.setParent(accumulator->mLastCaller); + accumulator->mParent = accumulator->mLastCaller; } + // no need to push up tree on first use, flag can be set spuriously + accumulator->mMoveUpTree = false; } } - // bump timers up tree if they've been flagged as being in the wrong place + // bump timers up tree if they have been flagged as being in the wrong place // do this in a bottom up order to promote descendants first before promoting ancestors // this preserves partial order derived from current frame's observations - for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer()); + for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(TimeBlock::getRootTimeBlock()); it != end_timer_tree_bottom_up(); ++it) { - NamedTimer* timerp = *it; - // skip root timer - if (timerp == NamedTimerFactory::instance().getRootTimer()) continue; + TimeBlock* timerp = *it; - if (timerp->getFrameState().mMoveUpTree) + // sort timers by time last called, so call graph makes sense + TimeBlockTreeNode& tree_node = timerp->getTreeNode(); + if (tree_node.mNeedsSorting) { - // since ancestors have already been visited, reparenting won't affect tree traversal - //step up tree, bringing our descendants with us - LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() << - " to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL; - timerp->setParent(timerp->getParent()->getParent()); - timerp->getFrameState().mMoveUpTree = false; - - // don't bubble up any ancestors until descendants are done bubbling up - it.skipAncestors(); + std::sort(tree_node.mChildren.begin(), tree_node.mChildren.end(), SortTimerByName()); } - } - // sort timers by time last called, so call graph makes sense - for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer()); - it != end_timer_tree(); - ++it) - { - NamedTimer* timerp = (*it); - if (timerp->mNeedsSorting) + // skip root timer + if (timerp != &TimeBlock::getRootTimeBlock()) { - std::sort(timerp->getChildren().begin(), timerp->getChildren().end(), SortTimerByName()); + TimeBlockAccumulator* accumulator = timerp->getPrimaryAccumulator(); + + if (accumulator->mMoveUpTree) + { + // since ancestors have already been visited, re-parenting won't affect tree traversal + //step up tree, bringing our descendants with us + LL_DEBUGS("FastTimers") << "Moving " << timerp->getName() << " from child of " << timerp->getParent()->getName() << + " to child of " << timerp->getParent()->getParent()->getName() << LL_ENDL; + timerp->setParent(timerp->getParent()->getParent()); + accumulator->mParent = timerp->getParent(); + accumulator->mMoveUpTree = false; + + // don't bubble up any ancestors until descendants are done bubbling up + // as ancestors may call this timer only on certain paths, so we want to resolve + // child-most block locations before their parents + it.skipAncestors(); + } } - timerp->mNeedsSorting = false; } -} - -//static -void LLFastTimer::NamedTimer::accumulateTimings() -{ - U32 cur_time = getCPUClockCount32(); // walk up stack of active timers and accumulate current time while leaving timing structures active - LLFastTimer* cur_timer = sCurTimerData.mCurTimer; - // root defined by parent pointing to self - CurTimerData* cur_data = &sCurTimerData; - while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer) + BlockTimerStackRecord* stack_record = ThreadTimerStack::getInstance(); + BlockTimer* cur_timer = stack_record->mActiveTimer; + TimeBlockAccumulator* accumulator = stack_record->mTimeBlock->getPrimaryAccumulator(); + + while(cur_timer + && cur_timer->mParentTimerData.mActiveTimer != cur_timer) // root defined by parent pointing to self { - U32 cumulative_time_delta = cur_time - cur_timer->mStartTime; - U32 self_time_delta = cumulative_time_delta - cur_data->mChildTime; - cur_data->mChildTime = 0; - cur_timer->mFrameState->mSelfTimeCounter += self_time_delta; + U64 cumulative_time_delta = cur_time - cur_timer->mStartTime; + accumulator->mTotalTimeCounter += cumulative_time_delta - (accumulator->mTotalTimeCounter - cur_timer->mBlockStartTotalTimeCounter); + accumulator->mSelfTimeCounter += cumulative_time_delta - stack_record->mChildTime; + stack_record->mChildTime = 0; + cur_timer->mStartTime = cur_time; + cur_timer->mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter; - cur_data = &cur_timer->mLastTimerData; - cur_data->mChildTime += cumulative_time_delta; + stack_record = &cur_timer->mParentTimerData; + accumulator = stack_record->mTimeBlock->getPrimaryAccumulator(); + cur_timer = stack_record->mActiveTimer; - cur_timer = cur_timer->mLastTimerData.mCurTimer; + stack_record->mChildTime += cumulative_time_delta; } - // traverse tree in DFS post order, or bottom up - for(timer_tree_bottom_up_iterator_t it = begin_timer_tree_bottom_up(*NamedTimerFactory::instance().getRootTimer()); - it != end_timer_tree_bottom_up(); + // reset for next frame + for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), + end_it = LLInstanceTracker<TimeBlock>::endInstances(); + it != end_it; ++it) { - NamedTimer* timerp = (*it); - timerp->mTotalTimeCounter = timerp->getFrameState().mSelfTimeCounter; - for (child_const_iter child_it = timerp->beginChildren(); child_it != timerp->endChildren(); ++child_it) + TimeBlock& timer = *it; + TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator(); + + accumulator->mLastCaller = NULL; + accumulator->mMoveUpTree = false; + } +} + + +std::vector<TimeBlock*>::iterator TimeBlock::beginChildren() { - timerp->mTotalTimeCounter += (*child_it)->mTotalTimeCounter; + return getTreeNode().mChildren.begin(); } - S32 cur_frame = sCurFrameIndex; - if (cur_frame >= 0) +std::vector<TimeBlock*>::iterator TimeBlock::endChildren() { - // update timer history - int hidx = cur_frame % HISTORY_NUM; + return getTreeNode().mChildren.end(); +} - timerp->mCountHistory[hidx] = timerp->mTotalTimeCounter; - timerp->mCountAverage = ((U64)timerp->mCountAverage * cur_frame + timerp->mTotalTimeCounter) / (cur_frame+1); - timerp->mCallHistory[hidx] = timerp->getFrameState().mCalls; - timerp->mCallAverage = ((U64)timerp->mCallAverage * cur_frame + timerp->getFrameState().mCalls) / (cur_frame+1); - } - } +std::vector<TimeBlock*>& TimeBlock::getChildren() +{ + return getTreeNode().mChildren; } // static -void LLFastTimer::NamedTimer::resetFrame() +void TimeBlock::logStats() { + // get ready for next frame if (sLog) { //output current frame counts to performance log static S32 call_count = 0; if (call_count % 100 == 0) { - LL_DEBUGS("FastTimers") << "countsPerSecond (32 bit): " << countsPerSecond() << LL_ENDL; - LL_DEBUGS("FastTimers") << "get_clock_count (64 bit): " << get_clock_count() << llendl; + LL_DEBUGS("FastTimers") << "countsPerSecond: " << countsPerSecond() << LL_ENDL; LL_DEBUGS("FastTimers") << "LLProcessorInfo().getCPUFrequency() " << LLProcessorInfo().getCPUFrequency() << LL_ENDL; LL_DEBUGS("FastTimers") << "getCPUClockCount32() " << getCPUClockCount32() << LL_ENDL; LL_DEBUGS("FastTimers") << "getCPUClockCount64() " << getCPUClockCount64() << LL_ENDL; - LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64())/((F64)LLProcessorInfo().getCPUFrequency()*1000000.0) << LL_ENDL; + LL_DEBUGS("FastTimers") << "elapsed sec " << ((F64)getCPUClockCount64()) / (LLUnit<LLUnits::Hertz, F64>(LLProcessorInfo().getCPUFrequency())) << LL_ENDL; } call_count++; - F64 iclock_freq = 1000.0 / countsPerSecond(); // good place to calculate clock frequency - - F64 total_time = 0; + LLUnit<LLUnits::Seconds, F64> total_time(0); LLSD sd; { - for (instance_iter it = beginInstances(); it != endInstances(); ++it) + for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), + end_it = LLInstanceTracker<TimeBlock>::endInstances(); + it != end_it; + ++it) { - NamedTimer& timer = *it; - FrameState& info = timer.getFrameState(); - sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq); - sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls; + TimeBlock& timer = *it; + LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording(); + sd[timer.getName()]["Time"] = (LLSD::Real) (frame_recording.getLastRecording().getSum(timer).value()); + sd[timer.getName()]["Calls"] = (LLSD::Integer) (frame_recording.getLastRecording().getSum(timer.callCount())); // computing total time here because getting the root timer's getCountHistory // doesn't work correctly on the first frame - total_time = total_time + info.mSelfTimeCounter * iclock_freq; + total_time += frame_recording.getLastRecording().getSum(timer); } } - sd["Total"]["Time"] = (LLSD::Real) total_time; + sd["Total"]["Time"] = (LLSD::Real) total_time.value(); sd["Total"]["Calls"] = (LLSD::Integer) 1; { @@ -469,168 +351,44 @@ void LLFastTimer::NamedTimer::resetFrame() } } - // reset for next frame - for (instance_iter it = beginInstances(); it != endInstances(); ++it) - { - NamedTimer& timer = *it; - - FrameState& info = timer.getFrameState(); - info.mSelfTimeCounter = 0; - info.mCalls = 0; - info.mLastCaller = NULL; - info.mMoveUpTree = false; - // update parent pointer in timer state struct - if (timer.mParent) - { - info.mParent = &timer.mParent->getFrameState(); - } - } } //static -void LLFastTimer::NamedTimer::reset() -{ - resetFrame(); // reset frame data - - // walk up stack of active timers and reset start times to current time - // effectively zeroing out any accumulated time - U32 cur_time = getCPUClockCount32(); - - // root defined by parent pointing to self - CurTimerData* cur_data = &sCurTimerData; - LLFastTimer* cur_timer = cur_data->mCurTimer; - while(cur_timer && cur_timer->mLastTimerData.mCurTimer != cur_timer) - { - cur_timer->mStartTime = cur_time; - cur_data->mChildTime = 0; - - cur_data = &cur_timer->mLastTimerData; - cur_timer = cur_data->mCurTimer; - } - - // reset all history - { - for (instance_iter it = beginInstances(); it != endInstances(); ++it) - { - NamedTimer& timer = *it; - if (&timer != NamedTimerFactory::instance().getRootTimer()) - { - timer.setParent(NamedTimerFactory::instance().getRootTimer()); - } - - timer.mCountAverage = 0; - timer.mCallAverage = 0; - memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM); - memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM); - } - } - - sLastFrameIndex = 0; - sCurFrameIndex = 0; -} - -U32 LLFastTimer::NamedTimer::getHistoricalCount(S32 history_index) const +void TimeBlock::dumpCurTimes() { - S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM; - return mCountHistory[history_idx]; -} - -U32 LLFastTimer::NamedTimer::getHistoricalCalls(S32 history_index ) const -{ - S32 history_idx = (getLastFrameIndex() + history_index) % LLFastTimer::NamedTimer::HISTORY_NUM; - return mCallHistory[history_idx]; -} - -LLFastTimer::FrameState& LLFastTimer::NamedTimer::getFrameState() const -{ - return *mFrameState; -} - -std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::beginChildren() -{ - return mChildren.begin(); -} - -std::vector<LLFastTimer::NamedTimer*>::const_iterator LLFastTimer::NamedTimer::endChildren() -{ - return mChildren.end(); -} - -std::vector<LLFastTimer::NamedTimer*>& LLFastTimer::NamedTimer::getChildren() -{ - return mChildren; -} - -// static -LLFastTimer::NamedTimer& LLFastTimer::NamedTimer::getRootNamedTimer() -{ - return *NamedTimerFactory::instance().getRootTimer(); -} - -//static -void LLFastTimer::nextFrame() -{ - countsPerSecond(); // good place to calculate clock frequency - U64 frame_time = getCPUClockCount64(); - if ((frame_time - sLastFrameTime) >> 8 > 0xffffffff) - { - llinfos << "Slow frame, fast timers inaccurate" << llendl; - } - - if (!sPauseHistory) - { - NamedTimer::processTimes(); - sLastFrameIndex = sCurFrameIndex++; - } - - // get ready for next frame - NamedTimer::resetFrame(); - sLastFrameTime = frame_time; -} - -//static -void LLFastTimer::dumpCurTimes() -{ - // accumulate timings, etc. - NamedTimer::processTimes(); - - F64 clock_freq = (F64)countsPerSecond(); - F64 iclock_freq = 1000.0 / clock_freq; // clock_ticks -> milliseconds + LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording(); + LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording(); // walk over timers in depth order and output timings - for(timer_tree_dfs_iterator_t it = begin_timer_tree(*NamedTimerFactory::instance().getRootTimer()); + for(timer_tree_dfs_iterator_t it = begin_timer_tree(TimeBlock::getRootTimeBlock()); it != end_timer_tree(); ++it) { - NamedTimer* timerp = (*it); - F64 total_time_ms = ((F64)timerp->getHistoricalCount(0) * iclock_freq); + TimeBlock* timerp = (*it); + LLUnit<LLUnits::Seconds, F64> total_time_ms = last_frame_recording.getSum(*timerp); + U32 num_calls = last_frame_recording.getSum(timerp->callCount()); + // Don't bother with really brief times, keep output concise if (total_time_ms < 0.1) continue; std::ostringstream out_str; - for (S32 i = 0; i < timerp->getDepth(); i++) + TimeBlock* parent_timerp = timerp; + while(parent_timerp && parent_timerp != parent_timerp->getParent()) { out_str << "\t"; + parent_timerp = parent_timerp->getParent(); } - out_str << timerp->getName() << " " - << std::setprecision(3) << total_time_ms << " ms, " - << timerp->getHistoricalCalls(0) << " calls"; + << std::setprecision(3) << total_time_ms.as<LLUnits::Milliseconds>().value() << " ms, " + << num_calls << " calls"; llinfos << out_str.str() << llendl; } } //static -void LLFastTimer::reset() -{ - NamedTimer::reset(); -} - - -//static -void LLFastTimer::writeLog(std::ostream& os) +void TimeBlock::writeLog(std::ostream& os) { while (!sLogQueue.empty()) { @@ -641,22 +399,62 @@ void LLFastTimer::writeLog(std::ostream& os) } } -//static -const LLFastTimer::NamedTimer* LLFastTimer::getTimerByName(const std::string& name) +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// TimeBlockAccumulator +////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +TimeBlockAccumulator::TimeBlockAccumulator() +: mTotalTimeCounter(0), + mSelfTimeCounter(0), + mStartTotalTimeCounter(0), + mCalls(0), + mLastCaller(NULL), + mActiveCount(0), + mMoveUpTree(false), + mParent(NULL) +{} + +void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other, bool append ) { - return NamedTimerFactory::instance().getTimerByName(name); + // we can't merge two unrelated time block samples, as that will screw with the nested timings + // due to the call hierarchy of each thread + llassert(append); + mTotalTimeCounter += other.mTotalTimeCounter - other.mStartTotalTimeCounter; + mSelfTimeCounter += other.mSelfTimeCounter; + mCalls += other.mCalls; + mLastCaller = other.mLastCaller; + mActiveCount = other.mActiveCount; + mMoveUpTree = other.mMoveUpTree; + mParent = other.mParent; } -LLFastTimer::LLFastTimer(LLFastTimer::FrameState* state) -: mFrameState(state) +void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other ) { - U32 start_time = getCPUClockCount32(); - mStartTime = start_time; - mFrameState->mActiveCount++; - LLFastTimer::sCurTimerData.mCurTimer = this; - LLFastTimer::sCurTimerData.mFrameState = mFrameState; - LLFastTimer::sCurTimerData.mChildTime = 0; - mLastTimerData = LLFastTimer::sCurTimerData; + mCalls = 0; + mSelfTimeCounter = 0; + + if (other) + { + mStartTotalTimeCounter = other->mTotalTimeCounter; + mTotalTimeCounter = mStartTotalTimeCounter; + + mLastCaller = other->mLastCaller; + mActiveCount = other->mActiveCount; + mMoveUpTree = other->mMoveUpTree; + mParent = other->mParent; + } + else +{ + mStartTotalTimeCounter = mTotalTimeCounter; + } +} + +LLUnit<LLUnits::Seconds, F64> BlockTimer::getElapsedTime() +{ + U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime; + + return (F64)total_time / (F64)TimeBlock::countsPerSecond(); } +} // namespace LLTrace diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 81c4b78775..20514d1638 100755 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -28,216 +28,98 @@ #define LL_FASTTIMER_H #include "llinstancetracker.h" +#include "lltrace.h" #define FAST_TIMER_ON 1 -#define DEBUG_FAST_TIMER_THREADS 1 +#define LL_FASTTIMER_USE_RDTSC 1 class LLMutex; -#include <queue> -#include "llsd.h" - -#define LL_FASTTIMER_USE_RDTSC 1 - +namespace LLTrace +{ -LL_COMMON_API void assert_main_thread(); +struct BlockTimerStackRecord +{ + class BlockTimer* mActiveTimer; + class TimeBlock* mTimeBlock; + U64 mChildTime; +}; -class LL_COMMON_API LLFastTimer +class ThreadTimerStack +: public BlockTimerStackRecord, + public LLThreadLocalSingleton<ThreadTimerStack> { -public: - class NamedTimer; + friend class LLThreadLocalSingleton<ThreadTimerStack>; + ThreadTimerStack() + {} - struct LL_COMMON_API FrameState - { - FrameState(); - void setNamedTimer(NamedTimer* timerp) { mTimer = timerp; } - - U32 mSelfTimeCounter; - U32 mCalls; - FrameState* mParent; // info for caller timer - FrameState* mLastCaller; // used to bootstrap tree construction - NamedTimer* mTimer; - U16 mActiveCount; // number of timers with this ID active on stack - bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame - }; - - // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances - class LL_COMMON_API NamedTimer - : public LLInstanceTracker<NamedTimer> +public: + ThreadTimerStack& operator=(const BlockTimerStackRecord& other) { - friend class DeclareTimer; - public: - ~NamedTimer(); - - enum { HISTORY_NUM = 300 }; - - const std::string& getName() const { return mName; } - NamedTimer* getParent() const { return mParent; } - void setParent(NamedTimer* parent); - S32 getDepth(); - std::string getToolTip(S32 history_index = -1); - - typedef std::vector<NamedTimer*>::const_iterator child_const_iter; - child_const_iter beginChildren(); - child_const_iter endChildren(); - std::vector<NamedTimer*>& getChildren(); - - void setCollapsed(bool collapsed) { mCollapsed = collapsed; } - bool getCollapsed() const { return mCollapsed; } - - U32 getCountAverage() const { return mCountAverage; } - U32 getCallAverage() const { return mCallAverage; } - - U32 getHistoricalCount(S32 history_index = 0) const; - U32 getHistoricalCalls(S32 history_index = 0) const; - - static NamedTimer& getRootNamedTimer(); - - void setFrameState(FrameState* state) { mFrameState = state; state->setNamedTimer(this); } - FrameState& getFrameState() const; - - private: - friend class LLFastTimer; - friend class NamedTimerFactory; - - // - // methods - // - NamedTimer(const std::string& name); - // recursive call to gather total time from children - static void accumulateTimings(); - - // updates cumulative times and hierarchy, - // can be called multiple times in a frame, at any point - static void processTimes(); - - static void buildHierarchy(); - static void resetFrame(); - static void reset(); - - // - // members - // - FrameState* mFrameState; + BlockTimerStackRecord::operator=(other); + return *this; + } +}; - std::string mName; +class BlockTimer +{ +public: + friend class TimeBlock; + typedef BlockTimer self_t; + typedef class TimeBlock DeclareTimer; - U32 mTotalTimeCounter; + BlockTimer(TimeBlock& timer); + ~BlockTimer(); - U32 mCountAverage; - U32 mCallAverage; + LLUnit<LLUnits::Seconds, F64> getElapsedTime(); - U32* mCountHistory; - U32* mCallHistory; +private: - // tree structure - NamedTimer* mParent; // NamedTimer of caller(parent) - std::vector<NamedTimer*> mChildren; - bool mCollapsed; // don't show children - bool mNeedsSorting; // sort children whenever child added - }; + U64 mStartTime; + U64 mBlockStartTotalTimeCounter; + BlockTimerStackRecord mParentTimerData; +}; - // used to statically declare a new named timer - class LL_COMMON_API DeclareTimer - : public LLInstanceTracker<DeclareTimer> - { - friend class LLFastTimer; - public: - DeclareTimer(const std::string& name, bool open); - DeclareTimer(const std::string& name); +// stores a "named" timer instance to be reused via multiple BlockTimer stack instances +class TimeBlock +: public TraceType<TimeBlockAccumulator>, + public LLInstanceTracker<TimeBlock> +{ +public: + TimeBlock(const char* name, bool open = false, TimeBlock* parent = &getRootTimeBlock()); - NamedTimer& getNamedTimer() { return mTimer; } + TimeBlockTreeNode& getTreeNode() const; + TimeBlock* getParent() const { return getTreeNode().getParent(); } + void setParent(TimeBlock* parent) { getTreeNode().setParent(parent); } - private: - FrameState mFrameState; - NamedTimer& mTimer; - }; + typedef std::vector<TimeBlock*>::iterator child_iter; + typedef std::vector<TimeBlock*>::const_iterator child_const_iter; + child_iter beginChildren(); + child_iter endChildren(); + std::vector<TimeBlock*>& getChildren(); -public: - LLFastTimer(LLFastTimer::FrameState* state); + void setCollapsed(bool collapsed) { mCollapsed = collapsed; } + bool getCollapsed() const { return mCollapsed; } - LL_FORCE_INLINE LLFastTimer(LLFastTimer::DeclareTimer& timer) - : mFrameState(&timer.mFrameState) + TraceType<TimeBlockAccumulator::CallCountFacet>& callCount() { -#if FAST_TIMER_ON - LLFastTimer::FrameState* frame_state = mFrameState; - mStartTime = getCPUClockCount32(); - - frame_state->mActiveCount++; - frame_state->mCalls++; - // keep current parent as long as it is active when we are - frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0); - - LLFastTimer::CurTimerData* cur_timer_data = &LLFastTimer::sCurTimerData; - mLastTimerData = *cur_timer_data; - cur_timer_data->mCurTimer = this; - cur_timer_data->mFrameState = frame_state; - cur_timer_data->mChildTime = 0; -#endif -#if DEBUG_FAST_TIMER_THREADS -#if !LL_RELEASE - assert_main_thread(); -#endif -#endif + return static_cast<TraceType<TimeBlockAccumulator::CallCountFacet>&>(*(TraceType<TimeBlockAccumulator>*)this); } - LL_FORCE_INLINE ~LLFastTimer() + TraceType<TimeBlockAccumulator::SelfTimeFacet>& selfTime() { -#if FAST_TIMER_ON - LLFastTimer::FrameState* frame_state = mFrameState; - U32 total_time = getCPUClockCount32() - mStartTime; - - frame_state->mSelfTimeCounter += total_time - LLFastTimer::sCurTimerData.mChildTime; - frame_state->mActiveCount--; - - // store last caller to bootstrap tree creation - // do this in the destructor in case of recursion to get topmost caller - frame_state->mLastCaller = mLastTimerData.mFrameState; - - // we are only tracking self time, so subtract our total time delta from parents - mLastTimerData.mChildTime += total_time; - - LLFastTimer::sCurTimerData = mLastTimerData; -#endif + return static_cast<TraceType<TimeBlockAccumulator::SelfTimeFacet>&>(*(TraceType<TimeBlockAccumulator>*)this); } -public: - static LLMutex* sLogLock; - static std::queue<LLSD> sLogQueue; - static BOOL sLog; - static BOOL sMetricLog; - static std::string sLogName; - static bool sPauseHistory; - static bool sResetHistory; - - // call this once a frame to reset timers - static void nextFrame(); + static TimeBlock& getRootTimeBlock(); + static void pushLog(LLSD sd); + static void setLogLock(LLMutex* mutex); + static void writeLog(std::ostream& os); // dumps current cumulative frame stats to log // call nextFrame() to reset timers static void dumpCurTimes(); - // call this to reset timer hierarchy, averages, etc. - static void reset(); - - static U64 countsPerSecond(); - static S32 getLastFrameIndex() { return sLastFrameIndex; } - static S32 getCurFrameIndex() { return sCurFrameIndex; } - - static void writeLog(std::ostream& os); - static const NamedTimer* getTimerByName(const std::string& name); - - struct CurTimerData - { - LLFastTimer* mCurTimer; - FrameState* mFrameState; - U32 mChildTime; - }; - static CurTimerData sCurTimerData; - -private: - - ////////////////////////////////////////////////////////////////////////////// // // Important note: These implementations must be FAST! @@ -260,14 +142,14 @@ private: //#undef _interlockedbittestandset //#undef _interlockedbittestandreset - //inline U32 LLFastTimer::getCPUClockCount32() + //inline U32 TimeBlock::getCPUClockCount32() //{ // U64 time_stamp = __rdtsc(); // return (U32)(time_stamp >> 8); //} // //// return full timer value, *not* shifted by 8 bits - //inline U64 LLFastTimer::getCPUClockCount64() + //inline U64 TimeBlock::getCPUClockCount64() //{ // return __rdtsc(); //} @@ -307,7 +189,7 @@ private: } #else - //LL_COMMON_API U64 get_clock_count(); // in lltimer.cpp + //U64 get_clock_count(); // in lltimer.cpp // These use QueryPerformanceCounter, which is arguably fine and also works on AMD architectures. static U32 getCPUClockCount32() { @@ -374,18 +256,71 @@ private: #endif - static U64 sClockResolution; + static U64 countsPerSecond(); - static S32 sCurFrameIndex; - static S32 sLastFrameIndex; - static U64 sLastFrameTime; + // updates cumulative times and hierarchy, + // can be called multiple times in a frame, at any point + static void processTimes(); - U32 mStartTime; - LLFastTimer::FrameState* mFrameState; - LLFastTimer::CurTimerData mLastTimerData; + // call this once a frame to periodically log timers + static void logStats(); + bool mCollapsed; // don't show children + + // statics + static std::string sLogName; + static bool sMetricLog, + sLog; + static U64 sClockResolution; }; -typedef class LLFastTimer LLFastTimer; +LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer) +{ +#if FAST_TIMER_ON + BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists(); + TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator(); + accumulator->mActiveCount++; + mBlockStartTotalTimeCounter = accumulator->mTotalTimeCounter; + // keep current parent as long as it is active when we are + accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0); + + // store top of stack + mParentTimerData = *cur_timer_data; + // push new information + cur_timer_data->mActiveTimer = this; + cur_timer_data->mTimeBlock = &timer; + cur_timer_data->mChildTime = 0; + + mStartTime = TimeBlock::getCPUClockCount64(); +#endif +} + +LL_FORCE_INLINE BlockTimer::~BlockTimer() +{ +#if FAST_TIMER_ON + U64 total_time = TimeBlock::getCPUClockCount64() - mStartTime; + BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists(); + TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator(); + + accumulator->mCalls++; + accumulator->mTotalTimeCounter += total_time - (accumulator->mTotalTimeCounter - mBlockStartTotalTimeCounter); + accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime; + accumulator->mActiveCount--; + + // store last caller to bootstrap tree creation + // do this in the destructor in case of recursion to get topmost caller + accumulator->mLastCaller = mParentTimerData.mTimeBlock; + + // we are only tracking self time, so subtract our total time delta from parents + mParentTimerData.mChildTime += total_time; + + //pop stack + *cur_timer_data = mParentTimerData; +#endif +} + +} + +typedef LLTrace::BlockTimer LLFastTimer; #endif // LL_LLFASTTIMER_H diff --git a/indra/llcommon/llfile.cpp b/indra/llcommon/llfile.cpp index 864b6e6975..40a57c2ae4 100755 --- a/indra/llcommon/llfile.cpp +++ b/indra/llcommon/llfile.cpp @@ -28,7 +28,7 @@ */ #if LL_WINDOWS -#include <windows.h> +#include "llwin32headerslean.h" #include <stdlib.h> // Windows errno #else #include <errno.h> @@ -848,7 +848,7 @@ llifstream::llifstream() : _M_filebuf(), #endif // explicit -llifstream::llifstream(const std::string& _Filename, +llifstream::llifstream(const std::string& _Filename, ios_base::openmode _Mode) : _M_filebuf(), #if LL_WINDOWS std::istream(&_M_filebuf) diff --git a/indra/llcommon/llfindlocale.cpp b/indra/llcommon/llfindlocale.cpp index cd7c0c7c09..f019bd0c64 100755 --- a/indra/llcommon/llfindlocale.cpp +++ b/indra/llcommon/llfindlocale.cpp @@ -33,7 +33,7 @@ #include <ctype.h> #ifdef WIN32 -#include <windows.h> +#include "llwin32headers.h" #include <winnt.h> #endif diff --git a/indra/llcommon/llindexedqueue.h b/indra/llcommon/llindexedqueue.h deleted file mode 100755 index aa2675d87d..0000000000 --- a/indra/llcommon/llindexedqueue.h +++ /dev/null @@ -1,155 +0,0 @@ -/** - * @file llindexedqueue.h - * @brief An indexed FIFO queue, where only one element with each key - * can be in the queue. - * - * $LicenseInfo:firstyear=2003&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_LLINDEXEDQUEUE_H -#define LL_LLINDEXEDQUEUE_H - -// An indexed FIFO queue, where only one element with each key can be in the queue. -// This is ONLY used in the interest list, you'll probably want to review this code -// carefully if you want to use it elsewhere - Doug - -template <typename Type> -class LLIndexedQueue -{ -protected: - typedef std::deque<Type> type_deque; - type_deque mQueue; - std::set<Type> mKeySet; - -public: - LLIndexedQueue() {} - - // move_if_there is an O(n) operation - bool push_back(const Type &value, bool move_if_there = false) - { - if (mKeySet.find(value) != mKeySet.end()) - { - // Already on the queue - if (move_if_there) - { - // Remove the existing entry. - typename type_deque::iterator it; - for (it = mQueue.begin(); it != mQueue.end(); ++it) - { - if (*it == value) - { - break; - } - } - - // This HAS to succeed, otherwise there's a serious bug in the keyset implementation - // (although this isn't thread safe, at all) - - mQueue.erase(it); - } - else - { - // We're not moving it, leave it alone - return false; - } - } - else - { - // Doesn't exist, add it to the key set - mKeySet.insert(value); - } - - mQueue.push_back(value); - - // We succeeded in adding the new element. - return true; - } - - bool push_front(const Type &value, bool move_if_there = false) - { - if (mKeySet.find(value) != mKeySet.end()) - { - // Already on the queue - if (move_if_there) - { - // Remove the existing entry. - typename type_deque::iterator it; - for (it = mQueue.begin(); it != mQueue.end(); ++it) - { - if (*it == value) - { - break; - } - } - - // This HAS to succeed, otherwise there's a serious bug in the keyset implementation - // (although this isn't thread safe, at all) - - mQueue.erase(it); - } - else - { - // We're not moving it, leave it alone - return false; - } - } - else - { - // Doesn't exist, add it to the key set - mKeySet.insert(value); - } - - mQueue.push_front(value); - return true; - } - - void pop() - { - Type value = mQueue.front(); - mKeySet.erase(value); - mQueue.pop_front(); - } - - Type &front() - { - return mQueue.front(); - } - - S32 size() const - { - return mQueue.size(); - } - - bool empty() const - { - return mQueue.empty(); - } - - void clear() - { - // Clear out all elements on the queue - mQueue.clear(); - mKeySet.clear(); - } -}; - -#endif // LL_LLINDEXEDQUEUE_H diff --git a/indra/llcommon/llinitparam.cpp b/indra/llcommon/llinitparam.cpp index 89c831d296..dbd4eba7a0 100755 --- a/indra/llcommon/llinitparam.cpp +++ b/indra/llcommon/llinitparam.cpp @@ -28,10 +28,17 @@ #include "linden_common.h" #include "llinitparam.h" +#include "llformat.h" namespace LLInitParam { + + predicate_rule_t default_parse_rules() + { + return ll_make_predicate(PROVIDED) && !ll_make_predicate(EMPTY); + } + // // Param // @@ -196,6 +203,9 @@ namespace LLInitParam bool BaseBlock::validateBlock(bool emit_errors) const { + // only validate block when it hasn't already passed validation with current data + if (!mValidated) + { const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it) { @@ -209,11 +219,18 @@ namespace LLInitParam return false; } } - return true; + mValidated = true; + } + return mValidated; } - void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const + bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const LLInitParam::BaseBlock* diff_block) const { + bool serialized = false; + if (!predicate_rule.check(ll_make_predicate(PROVIDED, isProvided()))) + { + return false; + } // named param is one like LLView::Params::follows // unnamed param is like LLView::Params::rect - implicit const BlockDescriptor& block_data = mostDerivedBlockDescriptor(); @@ -225,10 +242,10 @@ namespace LLInitParam param_handle_t param_handle = (*it)->mParamHandle; const Param* param = getParamFromHandle(param_handle); ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc; - if (serialize_func) + if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided()))) { const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - serialize_func(*param, parser, name_stack, diff_param); + serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param); } } @@ -239,7 +256,7 @@ namespace LLInitParam param_handle_t param_handle = it->second->mParamHandle; const Param* param = getParamFromHandle(param_handle); ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc; - if (serialize_func && param->anyProvided()) + if (serialize_func && predicate_rule.check(ll_make_predicate(PROVIDED, param->anyProvided()))) { // Ensure this param has not already been serialized // Prevents <rect> from being serialized as its own tag. @@ -264,10 +281,17 @@ namespace LLInitParam name_stack.push_back(std::make_pair(it->first, !duplicate)); const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL; - serialize_func(*param, parser, name_stack, diff_param); + serialized |= serialize_func(*param, parser, name_stack, predicate_rule, diff_param); name_stack.pop_back(); } } + + if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY))) + { + serialized |= parser.writeValue(Flag(), name_stack); + } + // was anything serialized in this block? + return serialized; } bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index ae836645b9..a32557b4ac 100755 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -29,14 +29,15 @@ #define LL_LLPARAM_H #include <vector> +#include <list> #include <boost/function.hpp> #include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_enum.hpp> #include <boost/unordered_map.hpp> -#include <boost/shared_ptr.hpp> #include "llerror.h" #include "llstl.h" +#include "llpredicate.h" namespace LLTypeTags { @@ -195,6 +196,8 @@ namespace LLInitParam return mValue; } + bool isValid() const { return true; } + protected: T mValue; }; @@ -209,13 +212,11 @@ namespace LLInitParam typedef T value_t; ParamValue() - : T(), - mValidated(false) + : T() {} ParamValue(const default_value_t& other) - : T(other), - mValidated(false) + : T(other) {} void setValue(const value_t& val) @@ -232,9 +233,6 @@ namespace LLInitParam { return *this; } - - protected: - mutable bool mValidated; // lazy validation flag }; @@ -497,25 +495,25 @@ namespace LLInitParam virtual ~Parser(); template <typename T> bool readValue(T& param, typename boost::disable_if<boost::is_enum<T> >::type* dummy = 0) - { + { parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); if (found_it != mParserReadFuncs->end()) - { + { return found_it->second(*this, (void*)¶m); - } - - return false; } + return false; + } + template <typename T> bool readValue(T& param, typename boost::enable_if<boost::is_enum<T> >::type* dummy = 0) - { + { parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); if (found_it != mParserReadFuncs->end()) - { + { return found_it->second(*this, (void*)¶m); - } + } else - { + { found_it = mParserReadFuncs->find(&typeid(S32)); if (found_it != mParserReadFuncs->end()) { @@ -579,6 +577,19 @@ namespace LLInitParam class Param; + enum ESerializePredicates + { + PROVIDED, + REQUIRED, + VALID, + HAS_DEFAULT_VALUE, + EMPTY + }; + + typedef LLPredicate::Rule<ESerializePredicates> predicate_rule_t; + + predicate_rule_t default_parse_rules(); + // various callbacks and constraints associated with an individual param struct LL_COMMON_API ParamDescriptor { @@ -589,7 +600,7 @@ namespace LLInitParam typedef bool(*merge_func_t)(Param&, const Param&, bool); typedef bool(*deserialize_func_t)(Param&, Parser&, Parser::name_stack_range_t&, bool); - typedef void(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const Param* diff_param); + typedef bool(*serialize_func_t)(const Param&, Parser&, Parser::name_stack_t&, const predicate_rule_t rules, const Param* diff_param); typedef void(*inspect_func_t)(const Param&, Parser&, Parser::name_stack_t&, S32 min_count, S32 max_count); typedef bool(*validation_func_t)(const Param*); @@ -617,7 +628,7 @@ namespace LLInitParam UserData* mUserData; }; - typedef boost::shared_ptr<ParamDescriptor> ParamDescriptorPtr; + typedef ParamDescriptor* ParamDescriptorPtr; // each derived Block class keeps a static data structure maintaining offsets to various params class LL_COMMON_API BlockDescriptor @@ -829,12 +840,28 @@ namespace LLInitParam LOG_CLASS(BaseBlock); friend class Param; + BaseBlock() + : mValidated(false), + mParamProvided(false) + {} + virtual ~BaseBlock() {} bool submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent=false); param_handle_t getHandleFromParam(const Param* param) const; bool validateBlock(bool emit_errors = true) const; + bool isProvided() const + { + return mParamProvided; + } + + bool isValid() const + { + return validateBlock(false); + } + + Param* getParamFromHandle(const param_handle_t param_handle) { if (param_handle == 0) return NULL; @@ -852,10 +879,19 @@ namespace LLInitParam void addSynonym(Param& param, const std::string& synonym); // Blocks can override this to do custom tracking of changes - virtual void paramChanged(const Param& changed_param, bool user_provided) {} + virtual void paramChanged(const Param& changed_param, bool user_provided) + { + if (user_provided) + { + // a child param has been explicitly changed + // so *some* aspect of this block is now provided + mValidated = false; + mParamProvided = true; + } + } bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name); - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; + bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t rule, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const; virtual const BlockDescriptor& mostDerivedBlockDescriptor() const { return getBlockDescriptor(); } @@ -893,6 +929,9 @@ namespace LLInitParam return mergeBlock(block_data, source, overwrite); } + mutable bool mValidated; // lazy validation flag + bool mParamProvided; + private: const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const; }; @@ -986,6 +1025,8 @@ namespace LLInitParam bool isProvided() const { return Param::anyProvided(); } + bool isValid() const { return true; } + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { self_t& typed_param = static_cast<self_t&>(param); @@ -1014,10 +1055,23 @@ namespace LLInitParam return false; } - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param) { + bool serialized = false; const self_t& typed_param = static_cast<const self_t&>(param); - if (!typed_param.isProvided()) return; + const self_t* diff_typed_param = static_cast<const self_t*>(diff_param); + + LLPredicate::Value<ESerializePredicates> predicate; + if (diff_typed_param && ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue())) + { + predicate.set(HAS_DEFAULT_VALUE); + } + + predicate.set(VALID, typed_param.isValid()); + predicate.set(PROVIDED, typed_param.anyProvided()); + predicate.set(EMPTY, false); + + if (!predicate_rule.check(predicate)) return false; if (!name_stack.empty()) { @@ -1030,25 +1084,27 @@ namespace LLInitParam if (!key.empty()) { - if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key)) + if (!diff_typed_param || !ParamCompare<std::string>::equals(diff_typed_param->getValueName(), key)) { - parser.writeValue(key, name_stack); + serialized = parser.writeValue(key, name_stack); } } // then try to serialize value directly - else if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), static_cast<const self_t*>(diff_param)->getValue())) + else if (!diff_typed_param || ParamCompare<T>::equals(typed_param.getValue(), diff_typed_param->getValue())) { - if (!parser.writeValue(typed_param.getValue(), name_stack)) + serialized = parser.writeValue(typed_param.getValue(), name_stack); + if (!serialized) { std::string calculated_key = typed_param.calcValueName(typed_param.getValue()); if (calculated_key.size() - && (!diff_param + && (!diff_typed_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), calculated_key))) { - parser.writeValue(calculated_key, name_stack); + serialized = parser.writeValue(calculated_key, name_stack); } } } + return serialized; } static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) @@ -1113,19 +1169,19 @@ namespace LLInitParam }; // parameter that is a block - template <typename T, typename NAME_VALUE_LOOKUP> - class TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> + template <typename BLOCK_T, typename NAME_VALUE_LOOKUP> + class TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> : public Param, public NAME_VALUE_LOOKUP::type_value_t { protected: - typedef ParamValue<typename LLTypeTags::Sorted<T>::value_t> param_value_t; - typedef typename param_value_t::default_value_t default_value_t; - typedef TypedParam<T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> self_t; - typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; + typedef ParamValue<typename LLTypeTags::Sorted<BLOCK_T>::value_t> param_value_t; + typedef typename param_value_t::default_value_t default_value_t; + typedef TypedParam<BLOCK_T, NAME_VALUE_LOOKUP, false, IS_A_BLOCK> self_t; + typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; public: using named_value_t::operator(); - typedef typename param_value_t::value_t value_t; + typedef typename param_value_t::value_t value_t; TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) : Param(block_descriptor.mCurrentBlockPtr), @@ -1148,11 +1204,11 @@ namespace LLInitParam if(named_value_t::valueNamesExist() && parser.readValue(name) && named_value_t::getValueFromName(name, typed_param.getValue())) - { - typed_param.setValueName(name); - typed_param.setProvided(); - return true; - } + { + typed_param.setValueName(name); + typed_param.setProvided(); + return true; + } } if(typed_param.deserializeBlock(parser, name_stack_range, new_name)) @@ -1166,10 +1222,16 @@ namespace LLInitParam return false; } - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param) { const self_t& typed_param = static_cast<const self_t&>(param); - if (!typed_param.isProvided()) return; + + LLPredicate::Value<ESerializePredicates> predicate; + + predicate.set(VALID, typed_param.isValid()); + predicate.set(PROVIDED, typed_param.anyProvided()); + + if (!predicate_rule.check(predicate)) return false; if (!name_stack.empty()) { @@ -1182,12 +1244,15 @@ namespace LLInitParam if (!diff_param || !ParamCompare<std::string>::equals(static_cast<const self_t*>(diff_param)->getValueName(), key)) { parser.writeValue(key, name_stack); + return true; } } else { - typed_param.serializeBlock(parser, name_stack, static_cast<const self_t*>(diff_param)); + return typed_param.serializeBlock(parser, name_stack, predicate_rule, static_cast<const self_t*>(diff_param)); } + + return false; } static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) @@ -1209,13 +1274,12 @@ namespace LLInitParam // *and* the block as a whole validates bool isProvided() const { - // only validate block when it hasn't already passed validation with current data - if (Param::anyProvided() && !param_value_t::mValidated) - { - // a sub-block is "provided" when it has been filled in enough to be valid - param_value_t::mValidated = param_value_t::validateBlock(false); - } - return Param::anyProvided() && param_value_t::mValidated; + return Param::anyProvided() && isValid(); + } + + bool isValid() const + { + return param_value_t::isValid(); } // assign block contents to this param-that-is-a-block @@ -1223,9 +1287,6 @@ namespace LLInitParam { setValue(val); named_value_t::clearValueName(); - // force revalidation of block - // next call to isProvided() will update provision status based on validity - param_value_t::mValidated = false; setProvided(flag_as_provided); } @@ -1242,9 +1303,6 @@ namespace LLInitParam if (user_provided) { - // a child param has been explicitly changed - // so *some* aspect of this block is now provided - param_value_t::mValidated = false; setProvided(); named_value_t::clearValueName(); } @@ -1296,13 +1354,13 @@ namespace LLInitParam }; // list of non-block parameters - template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> - class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> + template <typename MULTI_VALUE_T, typename NAME_VALUE_LOOKUP> + class TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, NOT_BLOCK> : public Param { protected: - typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; - typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t> param_value_t; + typedef TypedParam<MULTI_VALUE_T, NAME_VALUE_LOOKUP, true, NOT_BLOCK> self_t; + typedef ParamValue<typename LLTypeTags::Sorted<MULTI_VALUE_T>::value_t> param_value_t; typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t; typedef container_t default_value_t; typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; @@ -1311,7 +1369,9 @@ namespace LLInitParam typedef typename param_value_t::value_t value_t; TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr) + : Param(block_descriptor.mCurrentBlockPtr), + mMinCount(min_count), + mMaxCount(max_count) { std::copy(value.begin(), value.end(), std::back_inserter(mValues)); @@ -1322,7 +1382,13 @@ namespace LLInitParam } } - bool isProvided() const { return Param::anyProvided(); } + bool isProvided() const { return Param::anyProvided() && isValid(); } + + bool isValid() const + { + size_t num_elements = numValidElements(); + return mMinCount < num_elements && num_elements < mMaxCount; + } static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { @@ -1337,7 +1403,7 @@ namespace LLInitParam } // no further names in stack, attempt to parse value now - if (name_stack_range.first == name_stack_range.second) + if (new_name_stack_range.first == new_name_stack_range.second) { std::string name; @@ -1359,10 +1425,20 @@ namespace LLInitParam return false; } - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param) { + bool serialized = false; const self_t& typed_param = static_cast<const self_t&>(param); - if (!typed_param.isProvided()) return; + if (!typed_param.isProvided()) return false; + + LLPredicate::Value<ESerializePredicates> predicate; + + predicate.set(REQUIRED, typed_param.mMinCount > 0); + predicate.set(VALID, typed_param.isValid()); + predicate.set(PROVIDED, typed_param.anyProvided()); + predicate.set(EMPTY, typed_param.mValues.empty()); + + if (!predicate_rule.check(predicate)) return false; for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); it != end_it; @@ -1378,7 +1454,11 @@ namespace LLInitParam if (!value_written) { std::string calculated_key = it->calcValueName(it->getValue()); - if (!parser.writeValue(calculated_key, name_stack)) + if (parser.writeValue(calculated_key, name_stack)) + { + serialized = true; + } + else { break; } @@ -1386,19 +1466,23 @@ namespace LLInitParam } else { - if(!parser.writeValue(key, name_stack)) + if(parser.writeValue(key, name_stack)) + { + serialized = true; + } + else { break; } } - - name_stack.pop_back(); } + + return serialized; } static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) { - parser.inspectValue<VALUE_TYPE>(name_stack, min_count, max_count, NULL); + parser.inspectValue<MULTI_VALUE_T>(name_stack, min_count, max_count, NULL); if (named_value_t::getPossibleValues()) { parser.inspectValue<std::string>(name_stack, min_count, max_count, named_value_t::getPossibleValues()); @@ -1453,7 +1537,7 @@ namespace LLInitParam bool empty() const { return mValues.empty(); } size_t size() const { return mValues.size(); } - U32 numValidElements() const + size_t numValidElements() const { return mValues.size(); } @@ -1483,6 +1567,8 @@ namespace LLInitParam } container_t mValues; + size_t mMinCount, + mMaxCount; private: void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) @@ -1500,13 +1586,13 @@ namespace LLInitParam }; // list of block parameters - template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP> - class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> + template <typename MULTI_BLOCK_T, typename NAME_VALUE_LOOKUP> + class TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> : public Param { protected: - typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> self_t; - typedef ParamValue<typename LLTypeTags::Sorted<VALUE_TYPE>::value_t> param_value_t; + typedef TypedParam<MULTI_BLOCK_T, NAME_VALUE_LOOKUP, true, IS_A_BLOCK> self_t; + typedef ParamValue<typename LLTypeTags::Sorted<MULTI_BLOCK_T>::value_t> param_value_t; typedef typename std::vector<typename NAME_VALUE_LOOKUP::type_value_t> container_t; typedef typename NAME_VALUE_LOOKUP::type_value_t named_value_t; typedef container_t default_value_t; @@ -1516,7 +1602,9 @@ namespace LLInitParam typedef typename param_value_t::value_t value_t; TypedParam(BlockDescriptor& block_descriptor, const char* name, const default_value_t& value, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count) - : Param(block_descriptor.mCurrentBlockPtr) + : Param(block_descriptor.mCurrentBlockPtr), + mMinCount(min_count), + mMaxCount(max_count) { std::copy(value.begin(), value.end(), back_inserter(mValues)); @@ -1526,7 +1614,14 @@ namespace LLInitParam } } - bool isProvided() const { return Param::anyProvided(); } + bool isProvided() const { return Param::anyProvided() && isValid(); } + + bool isValid() const + { + size_t num_elements = numValidElements(); + return mMinCount < num_elements && num_elements < mMaxCount; + } + static bool deserializeParam(Param& param, Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) { @@ -1549,7 +1644,7 @@ namespace LLInitParam } param_value_t& value = typed_param.mValues.back(); - if (name_stack_range.first == name_stack_range.second) + if (new_name_stack_range.first == new_name_stack_range.second) { // try to parse a known named value std::string name; @@ -1559,6 +1654,10 @@ namespace LLInitParam { typed_param.mValues.back().setValueName(name); typed_param.setProvided(); + if (new_array_value) + { + name_stack_range.first->second = false; + } return true; } } @@ -1583,10 +1682,19 @@ namespace LLInitParam return false; } - static void serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const Param* diff_param) + static bool serializeParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const Param* diff_param) { + bool serialized = false; const self_t& typed_param = static_cast<const self_t&>(param); - if (!typed_param.isProvided()) return; + if (!typed_param.isProvided()) return false; + LLPredicate::Value<ESerializePredicates> predicate; + + predicate.set(REQUIRED, typed_param.mMinCount > 0); + predicate.set(VALID, typed_param.isValid()); + predicate.set(PROVIDED, typed_param.anyProvided()); + predicate.set(EMPTY, typed_param.mValues.empty()); + + if (!predicate_rule.check(predicate)) return false; for (const_iterator it = typed_param.mValues.begin(), end_it = typed_param.mValues.end(); it != end_it; @@ -1597,17 +1705,24 @@ namespace LLInitParam std::string key = it->getValueName(); if (!key.empty()) { - parser.writeValue(key, name_stack); + serialized |= parser.writeValue(key, name_stack); } // Not parsed via named values, write out value directly - // NOTE: currently we don't worry about removing default values in Multiple + // NOTE: currently we don't do diffing of Multiples else { - it->serializeBlock(parser, name_stack, NULL); + serialized = it->serializeBlock(parser, name_stack, predicate_rule, NULL); } name_stack.pop_back(); } + + if (!serialized && predicate_rule.check(ll_make_predicate(EMPTY))) + { + serialized |= parser.writeValue(Flag(), name_stack); + } + + return serialized; } static void inspectParam(const Param& param, Parser& parser, Parser::name_stack_t& name_stack, S32 min_count, S32 max_count) @@ -1670,14 +1785,14 @@ namespace LLInitParam bool empty() const { return mValues.empty(); } size_t size() const { return mValues.size(); } - U32 numValidElements() const + size_t numValidElements() const { - U32 count = 0; + size_t count = 0; for (const_iterator it = mValues.begin(), end_it = mValues.end(); it != end_it; ++it) { - if(it->validateBlock(false)) count++; + if(it->isValid()) count++; } return count; } @@ -1709,6 +1824,8 @@ namespace LLInitParam } container_t mValues; + size_t mMinCount, + mMaxCount; private: void init( BlockDescriptor &block_descriptor, ParamDescriptor::validation_func_t validate_func, S32 min_count, S32 max_count, const char* name ) @@ -2015,7 +2132,7 @@ namespace LLInitParam static bool validate(const Param* paramp) { - U32 num_valid = ((super_t*)paramp)->numValidElements(); + size_t num_valid = ((super_t*)paramp)->numValidElements(); return RANGE::minCount <= num_valid && num_valid <= RANGE::maxCount; } }; @@ -2158,13 +2275,11 @@ namespace LLInitParam typedef T default_value_t; ParamValue() - : mValue(), - mValidated(false) + : mValue() {} ParamValue(const default_value_t& value) - : mValue(value), - mValidated(false) + : mValue(value) {} void setValue(const value_t& val) @@ -2191,18 +2306,18 @@ namespace LLInitParam return mValue.deserializeBlock(p, name_stack_range, new_name); } - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const + bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const { const BaseBlock* base_block = diff_block ? &(diff_block->mValue) : NULL; - mValue.serializeBlock(p, name_stack, base_block); + return mValue.serializeBlock(p, name_stack, predicate_rule, base_block); } bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const - { + { return mValue.inspectBlock(p, name_stack, min_count, max_count); - } + } bool mergeBlockParam(bool source_provided, bool dst_provided, BlockDescriptor& block_data, const self_t& source, bool overwrite) { @@ -2212,9 +2327,7 @@ namespace LLInitParam // clear away what is there and take the new stuff as a whole resetToDefault(); return mValue.mergeBlock(block_data, source.getValue(), overwrite); - } - - + } return mValue.mergeBlock(block_data, source.getValue(), overwrite); } @@ -2223,14 +2336,17 @@ namespace LLInitParam return mValue.validateBlock(emit_errors); } + bool isValid() const + { + return validateBlock(false); + } + static BlockDescriptor& getBlockDescriptor() { return value_t::getBlockDescriptor(); } - mutable bool mValidated; // lazy validation flag - private: void resetToDefault() { @@ -2251,15 +2367,13 @@ namespace LLInitParam typedef T default_value_t; ParamValue() - : mValue(), - mValidated(false) + : mValue() { mCurParam = getBlockDescriptor().mAllParams.begin(); } ParamValue(const default_value_t& value) - : mValue(value), - mValidated(false) + : mValue(value) { mCurParam = getBlockDescriptor().mAllParams.begin(); } @@ -2284,7 +2398,7 @@ namespace LLInitParam if (new_name) { mCurParam = getBlockDescriptor().mAllParams.begin(); - } + } if (name_stack_range.first == name_stack_range.second && mCurParam != getBlockDescriptor().mAllParams.end()) { @@ -2296,7 +2410,7 @@ namespace LLInitParam if (deserialize_func && paramp && deserialize_func(*paramp, p, name_stack_range, new_name)) - { + { ++mCurParam; return true; } @@ -2304,19 +2418,19 @@ namespace LLInitParam { return false; } - } + } else { return mValue.deserializeBlock(p, name_stack_range, new_name); } } - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const + bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const { const BaseBlock* base_block = diff_block ? &(diff_block->mValue) : NULL; - mValue.serializeBlock(p, name_stack, base_block); + return mValue.serializeBlock(p, name_stack, predicate_rule, base_block); } bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const @@ -2334,13 +2448,16 @@ namespace LLInitParam return mValue.validateBlock(emit_errors); } + bool isValid() const + { + return validateBlock(false); + } + static BlockDescriptor& getBlockDescriptor() { return value_t::getBlockDescriptor(); } - mutable bool mValidated; // lazy validation flag - private: BlockDescriptor::all_params_list_t::iterator mCurParam; @@ -2358,16 +2475,14 @@ namespace LLInitParam typedef T default_value_t; ParamValue() - : T(), - mValidated(false) + : T() {} ParamValue(const default_value_t& value) - : T(value.getValue()), - mValidated(false) + : T(value.getValue()) {} - mutable bool mValidated; // lazy validation flag + bool isValid() const { return true; } }; template<typename T, typename BLOCK_T> @@ -2380,18 +2495,15 @@ namespace LLInitParam typedef LazyValue<T> default_value_t; ParamValue() - : mValue(), - mValidated(false) + : mValue() {} ParamValue(const default_value_t& other) - : mValue(other), - mValidated(false) + : mValue(other) {} ParamValue(const T& value) - : mValue(value), - mValidated(false) + : mValue(value) {} void setValue(const value_t& val) @@ -2414,14 +2526,14 @@ namespace LLInitParam return mValue.get().deserializeBlock(p, name_stack_range, new_name); } - void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const self_t* diff_block = NULL) const + bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const self_t* diff_block = NULL) const { - if (mValue.empty()) return; + if (mValue.empty()) return false; const BaseBlock* base_block = (diff_block && !diff_block->mValue.empty()) ? &(diff_block->mValue.get().getValue()) : NULL; - mValue.get().serializeBlock(p, name_stack, base_block); + return mValue.get().serializeBlock(p, name_stack, predicate_rule, base_block); } bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const @@ -2433,26 +2545,29 @@ namespace LLInitParam { return source.mValue.empty() || mValue.get().mergeBlock(block_data, source.getValue(), overwrite); } - + bool validateBlock(bool emit_errors = true) const { return mValue.empty() || mValue.get().validateBlock(emit_errors); } + bool isValid() const + { + return validateBlock(false); + } + static BlockDescriptor& getBlockDescriptor() { return value_t::getBlockDescriptor(); } - mutable bool mValidated; // lazy validation flag - private: LazyValue<T> mValue; }; template<typename T, typename BLOCK_T> class ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> - { + { typedef ParamValue <BaseBlock::Lazy<T, NOT_BLOCK>, BLOCK_T> self_t; public: @@ -2460,18 +2575,15 @@ namespace LLInitParam typedef LazyValue<T> default_value_t; ParamValue() - : mValue(), - mValidated(false) + : mValue() {} ParamValue(const default_value_t& other) - : mValue(other), - mValidated(false) + : mValue(other) {} ParamValue(const T& value) - : mValue(value), - mValidated(false) + : mValue(value) {} void setValue(const value_t& val) @@ -2489,7 +2601,10 @@ namespace LLInitParam return mValue.get().getValue(); } - mutable bool mValidated; // lazy validation flag + bool isValid() const + { + return true; + } private: LazyValue<T> mValue; @@ -2504,12 +2619,10 @@ namespace LLInitParam typedef LLSD default_value_t; ParamValue() - : mValidated(false) {} ParamValue(const default_value_t& other) - : mValue(other), - mValidated(false) + : mValue(other) {} void setValue(const value_t& val) { mValue = val; } @@ -2519,16 +2632,13 @@ namespace LLInitParam // block param interface LL_COMMON_API bool deserializeBlock(Parser& p, Parser::name_stack_range_t& name_stack_range, bool new_name); - LL_COMMON_API void serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const; + LL_COMMON_API bool serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const; bool inspectBlock(Parser& p, Parser::name_stack_t name_stack = Parser::name_stack_t(), S32 min_count = 0, S32 max_count = S32_MAX) const { //TODO: implement LLSD params as schema type Any return true; } - protected: - mutable bool mValidated; // lazy validation flag - private: static void serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack); @@ -2547,18 +2657,17 @@ namespace LLInitParam BLOCK_AUTHORITATIVE // mValue is derived from the block parameters, which are authoritative } EValueAge; - typedef ParamValue<T> derived_t; - typedef CustomParamValue<T> self_t; - typedef Block<derived_t> block_t; + typedef TypeValues<T> derived_t; + typedef CustomParamValue<T> self_t; + typedef Block<ParamValue<T> > block_t; typedef T default_value_t; - typedef T value_t; + typedef T value_t; typedef void baseblock_base_class_t; CustomParamValue(const default_value_t& value = T()) : mValue(value), - mValueAge(VALUE_AUTHORITATIVE), - mValidated(false) + mValueAge(VALUE_AUTHORITATIVE) {} bool deserializeBlock(Parser& parser, Parser::name_stack_range_t& name_stack_range, bool new_name) @@ -2580,16 +2689,30 @@ namespace LLInitParam return typed_param.BaseBlock::deserializeBlock(parser, name_stack_range, new_name); } - void serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const BaseBlock* diff_block = NULL) const + bool serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const predicate_rule_t predicate_rule, const BaseBlock* diff_block = NULL) const { const derived_t& typed_param = static_cast<const derived_t&>(*this); const derived_t* diff_param = static_cast<const derived_t*>(diff_block); + //std::string key = typed_param.getValueName(); + + //// first try to write out name of name/value pair + //if (!key.empty()) + //{ + // if (!diff_param || !ParamCompare<std::string>::equals(diff_param->getValueName(), key)) + // { + // return parser.writeValue(key, name_stack); + // } + //} // then try to serialize value directly if (!diff_param || !ParamCompare<T>::equals(typed_param.getValue(), diff_param->getValue())) { - if (!parser.writeValue(typed_param.getValue(), name_stack)) + if (parser.writeValue(typed_param.getValue(), name_stack)) + { + return true; + } + else { //RN: *always* serialize provided components of BlockValue (don't pass diff_param on), // since these tend to be viewed as the constructor arguments for the value T. It seems @@ -2606,14 +2729,15 @@ namespace LLInitParam // and serialize those params derived_t copy(typed_param); copy.updateBlockFromValue(true); - copy.block_t::serializeBlock(parser, name_stack, NULL); + return copy.block_t::serializeBlock(parser, name_stack, predicate_rule, NULL); } else { - block_t::serializeBlock(parser, name_stack, NULL); + return block_t::serializeBlock(parser, name_stack, predicate_rule, NULL); } } } + return false; } bool validateBlock(bool emit_errors = true) const @@ -2705,8 +2829,6 @@ namespace LLInitParam return block_t::mergeBlock(block_data, source, overwrite); } - mutable bool mValidated; // lazy validation flag - private: mutable T mValue; mutable EValueAge mValueAge; diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp index 5dc3ea5d7b..7ff8324fe3 100755 --- a/indra/llcommon/llinstancetracker.cpp +++ b/indra/llcommon/llinstancetracker.cpp @@ -27,23 +27,25 @@ #include "linden_common.h" // associated header #include "llinstancetracker.h" +#include "llapr.h" + // STL headers // std headers // external library headers // other Linden headers -//static -void * & LLInstanceTrackerBase::getInstances(std::type_info const & info) +void LLInstanceTrackerBase::StaticBase::incrementDepth() +{ + apr_atomic_inc32(&sIterationNestDepth); +} + +void LLInstanceTrackerBase::StaticBase::decrementDepth() { - typedef std::map<std::string, void *> InstancesMap; - static InstancesMap instances; + apr_atomic_dec32(&sIterationNestDepth); +} - // std::map::insert() is just what we want here. You attempt to insert a - // (key, value) pair. If the specified key doesn't yet exist, it inserts - // the pair and returns a std::pair of (iterator, true). If the specified - // key DOES exist, insert() simply returns (iterator, false). One lookup - // handles both cases. - return instances.insert(InstancesMap::value_type(info.name(), - InstancesMap::mapped_type())) - .first->second; +U32 LLInstanceTrackerBase::StaticBase::getDepth() +{ + apr_uint32_t data = apr_atomic_read32(&sIterationNestDepth); + return data; } diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 1eab270e3c..c8e1d9cd84 100755 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -46,22 +46,6 @@ class LL_COMMON_API LLInstanceTrackerBase { protected: - /// Get a process-unique void* pointer slot for the specified type_info - static void * & getInstances(std::type_info const & info); - - /// Find or create a STATICDATA instance for the specified TRACKED class. - /// STATICDATA must be default-constructible. - template<typename STATICDATA, class TRACKED> - static STATICDATA& getStatic() - { - void *& instances = getInstances(typeid(TRACKED)); - if (! instances) - { - instances = new STATICDATA; - } - return *static_cast<STATICDATA*>(instances); - } - /// It's not essential to derive your STATICDATA (for use with /// getStatic()) from StaticBase; it's just that both known /// implementations do. @@ -70,15 +54,21 @@ protected: StaticBase(): sIterationNestDepth(0) {} - S32 sIterationNestDepth; + + void incrementDepth(); + void decrementDepth(); + U32 getDepth(); + private: + U32 sIterationNestDepth; }; }; /// This mix-in class adds support for tracking all instances of the specified class parameter T /// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup /// If KEY is not provided, then instances are stored in a simple set -/// @NOTE: see explicit specialization below for default KEY==T* case -template<typename T, typename KEY = T*> +/// @NOTE: see explicit specialization below for default KEY==void case +/// @NOTE: this class is not thread-safe unless used as read-only +template<typename T, typename KEY = void> class LLInstanceTracker : public LLInstanceTrackerBase { typedef LLInstanceTracker<T, KEY> MyT; @@ -87,7 +77,7 @@ class LLInstanceTracker : public LLInstanceTrackerBase { InstanceMap sMap; }; - static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); } + static StaticData& getStatic() { static StaticData sData; return sData;} static InstanceMap& getMap_() { return getStatic().sMap; } public: @@ -99,12 +89,12 @@ public: instance_iter(const typename InstanceMap::iterator& it) : mIterator(it) { - ++getStatic().sIterationNestDepth; + getStatic().incrementDepth(); } ~instance_iter() { - --getStatic().sIterationNestDepth; + getStatic().decrementDepth(); } @@ -131,20 +121,20 @@ public: typedef boost::iterator_facade<key_iter, KEY, boost::forward_traversal_tag> super_t; key_iter(typename InstanceMap::iterator it) - : mIterator(it) + : mIterator(it) { - ++getStatic().sIterationNestDepth; + getStatic().incrementDepth(); } key_iter(const key_iter& other) - : mIterator(other.mIterator) + : mIterator(other.mIterator) { - ++getStatic().sIterationNestDepth; + getStatic().incrementDepth(); } ~key_iter() { - --getStatic().sIterationNestDepth; + getStatic().decrementDepth(); } @@ -182,7 +172,10 @@ public: return instance_iter(getMap_().end()); } - static S32 instanceCount() { return getMap_().size(); } + static S32 instanceCount() + { + return getMap_().size(); + } static key_iter beginKeys() { @@ -203,7 +196,7 @@ protected: virtual ~LLInstanceTracker() { // it's unsafe to delete instances of this type while all instances are being iterated over. - llassert_always(getStatic().sIterationNestDepth == 0); + llassert_always(getStatic().getDepth() == 0); remove_(); } virtual void setKey(KEY key) { remove_(); add_(key); } @@ -227,18 +220,18 @@ private: KEY mInstanceKey; }; -/// explicit specialization for default case where KEY is T* +/// explicit specialization for default case where KEY is void /// use a simple std::set<T*> template<typename T> -class LLInstanceTracker<T, T*> : public LLInstanceTrackerBase +class LLInstanceTracker<T, void> : public LLInstanceTrackerBase { - typedef LLInstanceTracker<T, T*> MyT; + typedef LLInstanceTracker<T, void> MyT; typedef typename std::set<T*> InstanceSet; struct StaticData: public StaticBase { InstanceSet sSet; }; - static StaticData& getStatic() { return LLInstanceTrackerBase::getStatic<StaticData, MyT>(); } + static StaticData& getStatic() { static StaticData sData; return sData; } static InstanceSet& getSet_() { return getStatic().sSet; } public: @@ -265,18 +258,18 @@ public: instance_iter(const typename InstanceSet::iterator& it) : mIterator(it) { - ++getStatic().sIterationNestDepth; + getStatic().incrementDepth(); } instance_iter(const instance_iter& other) : mIterator(other.mIterator) { - ++getStatic().sIterationNestDepth; + getStatic().incrementDepth(); } ~instance_iter() { - --getStatic().sIterationNestDepth; + getStatic().decrementDepth(); } private: @@ -309,7 +302,7 @@ protected: virtual ~LLInstanceTracker() { // it's unsafe to delete instances of this type while all instances are being iterated over. - llassert_always(getStatic().sIterationNestDepth == 0); + llassert_always(getStatic().getDepth() == 0); getSet_().erase(static_cast<T*>(this)); } diff --git a/indra/llcommon/lllazy.cpp b/indra/llcommon/lllazy.cpp deleted file mode 100755 index 29fa040387..0000000000 --- a/indra/llcommon/lllazy.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @file lllazy.cpp - * @author Nat Goodspeed - * @date 2009-01-28 - * @brief Implementation for lllazy. - * - * $LicenseInfo:firstyear=2009&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$ - */ - -// Precompiled header -#include "linden_common.h" -// associated header -#include "lllazy.h" -// STL headers -// std headers -// external library headers -// other Linden headers - -// lllazy.h is presently header-only. This file exists only because our CMake -// test macro ADD_BUILD_TEST requires it. -int dummy = 0; diff --git a/indra/llcommon/lllazy.h b/indra/llcommon/lllazy.h deleted file mode 100755 index 5f3bbce79e..0000000000 --- a/indra/llcommon/lllazy.h +++ /dev/null @@ -1,399 +0,0 @@ -/** - * @file lllazy.h - * @author Nat Goodspeed - * @date 2009-01-22 - * @brief Lazy instantiation of specified type. Useful in conjunction with - * Michael Feathers's "Extract and Override Getter" ("Working - * Effectively with Legacy Code", p. 352). - * - * Quoting his synopsis of steps on p.355: - * - * 1. Identify the object you need a getter for. - * 2. Extract all of the logic needed to create the object into a getter. - * 3. Replace all uses of the object with calls to the getter, and initialize - * the reference that holds the object to null in all constructors. - * 4. Add the first-time logic to the getter so that the object is constructed - * and assigned to the reference whenever the reference is null. - * 5. Subclass the class and override the getter to provide an alternative - * object for testing. - * - * It's the second half of bullet 3 (3b, as it were) that bothers me. I find - * it all too easy to imagine adding pointer initializers to all but one - * constructor... the one not exercised by my tests. That suggested using - * (e.g.) boost::scoped_ptr<MyObject> so you don't have to worry about - * destroying it either. - * - * However, introducing additional machinery allows us to encapsulate bullet 4 - * as well. - * - * $LicenseInfo:firstyear=2009&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$ - */ - -#if ! defined(LL_LLLAZY_H) -#define LL_LLLAZY_H - -#include <boost/function.hpp> -#include <boost/scoped_ptr.hpp> -#include <boost/lambda/construct.hpp> -#include <stdexcept> - -/// LLLazyCommon simply factors out of LLLazy<T> things that don't depend on -/// its template parameter. -class LLLazyCommon -{ -public: - /** - * This exception is thrown if you try to replace an LLLazy<T>'s factory - * (or T* instance) after it already has an instance in hand. Since T - * might well be stateful, we can't know the effect of silently discarding - * and replacing an existing instance, so we disallow it. This facility is - * intended for testing, and in a test scenario we can definitely control - * that. - */ - struct InstanceChange: public std::runtime_error - { - InstanceChange(const std::string& what): std::runtime_error(what) {} - }; - -protected: - /** - * InstanceChange might be appropriate in a couple of different LLLazy<T> - * methods. Factor out the common logic. - */ - template <typename PTR> - static void ensureNoInstance(const PTR& ptr) - { - if (ptr) - { - // Too late: we've already instantiated the lazy object. We don't - // know whether it's stateful or not, so it's not safe to discard - // the existing instance in favor of a replacement. - throw InstanceChange("Too late to replace LLLazy instance"); - } - } -}; - -/** - * LLLazy<T> is useful when you have an outer class Outer that you're trying - * to bring under unit test, that contains a data member difficult to - * instantiate in a test harness. Typically the data member's class Inner has - * many thorny dependencies. Feathers generally advocates "Extract and - * Override Factory Method" (p. 350). But in C++, you can't call a derived - * class override of a virtual method from the derived class constructor, - * which limits applicability of "Extract and Override Factory Method." For - * such cases Feathers presents "Extract and Override Getter" (p. 352). - * - * So we'll assume that your class Outer contains a member like this: - * @code - * Inner mInner; - * @endcode - * - * LLLazy<Inner> can be used to replace this member. You can directly declare: - * @code - * LLLazy<Inner> mInner; - * @endcode - * and change references to mInner accordingly. - * - * (Alternatively, you can add a base class of the form - * <tt>LLLazyBase<Inner></tt>. This is discussed further in the LLLazyBase<T> - * documentation.) - * - * LLLazy<T> binds a <tt>boost::scoped_ptr<T></tt> and a factory functor - * returning T*. You can either bind that functor explicitly or let it default - * to the expression <tt>new T()</tt>. - * - * As long as LLLazy<T> remains unreferenced, its T remains uninstantiated. - * The first time you use get(), <tt>operator*()</tt> or <tt>operator->()</tt> - * it will instantiate its T and thereafter behave like a pointer to it. - * - * Thus, any existing reference to <tt>mInner.member</tt> should be replaced - * with <tt>mInner->member</tt>. Any simple reference to @c mInner should be - * replaced by <tt>*mInner</tt>. - * - * (If the original declaration was a pointer initialized in Outer's - * constructor, e.g. <tt>Inner* mInner</tt>, so much the better. In that case - * you should be able to drop in <tt>LLLazy<Inner></tt> without much change.) - * - * The support for "Extract and Override Getter" lies in the fact that you can - * replace the factory functor -- or provide an explicit T*. Presumably this - * is most useful from a test subclass -- which suggests that your @c mInner - * member should be @c protected. - * - * Note that <tt>boost::lambda::new_ptr<T>()</tt> makes a dandy factory - * functor, for either the set() method or LLLazy<T>'s constructor. If your T - * requires constructor arguments, use an expression more like - * <tt>boost::lambda::bind(boost::lambda::new_ptr<T>(), arg1, arg2, ...)</tt>. - * - * Of course the point of replacing the functor is to substitute a class that, - * though referenced as Inner*, is not an Inner; presumably this is a testing - * subclass of Inner (e.g. TestInner). Thus your test subclass TestOuter for - * the containing class Outer will contain something like this: - * @code - * class TestOuter: public Outer - * { - * public: - * TestOuter() - * { - * // mInner must be 'protected' rather than 'private' - * mInner.set(boost::lambda::new_ptr<TestInner>()); - * } - * ... - * }; - * @endcode - */ -template <typename T> -class LLLazy: public LLLazyCommon -{ -public: - /// Any nullary functor returning T* will work as a Factory - typedef boost::function<T* ()> Factory; - - /// The default LLLazy constructor uses <tt>new T()</tt> as its Factory - LLLazy(): - mFactory(boost::lambda::new_ptr<T>()) - {} - - /// Bind an explicit Factory functor - LLLazy(const Factory& factory): - mFactory(factory) - {} - - /// Reference T, instantiating it if this is the first access - const T& get() const - { - if (! mInstance) - { - // use the bound Factory functor - mInstance.reset(mFactory()); - } - return *mInstance; - } - - /// non-const get() - T& get() - { - return const_cast<T&>(const_cast<const LLLazy<T>*>(this)->get()); - } - - /// operator*() is equivalent to get() - const T& operator*() const { return get(); } - /// operator*() is equivalent to get() - T& operator*() { return get(); } - - /** - * operator->() must return (something resembling) T*. It's tempting to - * return the underlying boost::scoped_ptr<T>, but that would require - * breaking out the lazy-instantiation logic from get() into a common - * private method. Assume the pointer used for operator->() access is very - * short-lived. - */ - const T* operator->() const { return &get(); } - /// non-const operator->() - T* operator->() { return &get(); } - - /// set(Factory). This will throw InstanceChange if mInstance has already - /// been set. - void set(const Factory& factory) - { - ensureNoInstance(mInstance); - mFactory = factory; - } - - /// set(T*). This will throw InstanceChange if mInstance has already been - /// set. - void set(T* instance) - { - ensureNoInstance(mInstance); - mInstance.reset(instance); - } - -private: - Factory mFactory; - // Consider an LLLazy<T> member of a class we're accessing by const - // reference. We want to allow even const methods to touch the LLLazy<T> - // member. Hence the actual pointer must be mutable because such access - // might assign it. - mutable boost::scoped_ptr<T> mInstance; -}; - -#if (! defined(__GNUC__)) || (__GNUC__ > 3) || (__GNUC__ == 3 && __GNUC_MINOR__ > 3) -// Not gcc at all, or a gcc more recent than gcc 3.3 -#define GCC33 0 -#else -#define GCC33 1 -#endif - -/** - * LLLazyBase<T> wraps LLLazy<T>, giving you an alternative way to replace - * <tt>Inner mInner;</tt>. Instead of coding <tt>LLLazy<Inner> mInner</tt>, - * you can add LLLazyBase<Inner> to your Outer class's bases, e.g.: - * @code - * class Outer: public LLLazyBase<Inner> - * { - * ... - * }; - * @endcode - * - * This gives you @c public get() and @c protected set() methods without - * having to make your LLLazy<Inner> member @c protected. The tradeoff is that - * you must access the wrapped LLLazy<Inner> using get() and set() rather than - * with <tt>operator*()</tt> or <tt>operator->()</tt>. - * - * This mechanism can be used for more than one member, but only if they're of - * different types. That is, you can replace: - * @code - * DifficultClass mDifficult; - * AwkwardType mAwkward; - * @endcode - * with: - * @code - * class Outer: public LLLazyBase<DifficultClass>, public LLLazyBase<AwkwardType> - * { - * ... - * }; - * @endcode - * but for a situation like this: - * @code - * DifficultClass mMainDifficult, mAuxDifficult; - * @endcode - * you should directly embed LLLazy<DifficultClass> (q.v.). - * - * For multiple LLLazyBase bases, e.g. the <tt>LLLazyBase<DifficultClass>, - * LLLazyBase<AwkwardType></tt> example above, access the relevant get()/set() - * as (e.g.) <tt>LLLazyBase<DifficultClass>::get()</tt>. (This is why you - * can't have multiple LLLazyBase<T> of the same T.) For a bit of syntactic - * sugar, please see getLazy()/setLazy(). - */ -template <typename T> -class LLLazyBase -{ -public: - /// invoke default LLLazy constructor - LLLazyBase() {} - /// make wrapped LLLazy bind an explicit Factory - LLLazyBase(const typename LLLazy<T>::Factory& factory): - mInstance(factory) - {} - - /// access to LLLazy::get() - T& get() { return *mInstance; } - /// access to LLLazy::get() - const T& get() const { return *mInstance; } - -protected: - // see getLazy()/setLazy() - #if (! GCC33) - template <typename T2, class MYCLASS> friend T2& getLazy(MYCLASS* this_); - template <typename T2, class MYCLASS> friend const T2& getLazy(const MYCLASS* this_); - #else // gcc 3.3 - template <typename T2, class MYCLASS> friend T2& getLazy(const MYCLASS* this_); - #endif // gcc 3.3 - template <typename T2, class MYCLASS> friend void setLazy(MYCLASS* this_, T2* instance); - template <typename T2, class MYCLASS> - friend void setLazy(MYCLASS* this_, const typename LLLazy<T2>::Factory& factory); - - /// access to LLLazy::set(Factory) - void set(const typename LLLazy<T>::Factory& factory) - { - mInstance.set(factory); - } - - /// access to LLLazy::set(T*) - void set(T* instance) - { - mInstance.set(instance); - } - -private: - LLLazy<T> mInstance; -}; - -/** - * @name getLazy()/setLazy() - * Suppose you have something like the following: - * @code - * class Outer: public LLLazyBase<DifficultClass>, public LLLazyBase<AwkwardType> - * { - * ... - * }; - * @endcode - * - * Your methods can reference the @c DifficultClass instance using - * <tt>LLLazyBase<DifficultClass>::get()</tt>, which is admittedly a bit ugly. - * Alternatively, you can write <tt>getLazy<DifficultClass>(this)</tt>, which - * is somewhat more straightforward to read. - * - * Similarly, - * @code - * LLLazyBase<DifficultClass>::set(new TestDifficultClass()); - * @endcode - * could instead be written: - * @code - * setLazy<DifficultClass>(this, new TestDifficultClass()); - * @endcode - * - * @note - * I wanted to provide getLazy() and setLazy() without explicitly passing @c - * this. That would imply making them methods on a base class rather than free - * functions. But if <tt>LLLazyBase<T></tt> derives normally from (say) @c - * LLLazyGrandBase providing those methods, then unqualified getLazy() would - * be ambiguous: you'd have to write <tt>LLLazyBase<T>::getLazy<T>()</tt>, - * which is even uglier than <tt>LLLazyBase<T>::get()</tt>, and therefore - * pointless. You can make the compiler not care which @c LLLazyGrandBase - * instance you're talking about by making @c LLLazyGrandBase a @c virtual - * base class of @c LLLazyBase. But in that case, - * <tt>LLLazyGrandBase::getLazy<T>()</tt> can't access - * <tt>LLLazyBase<T>::get()</tt>! - * - * We want <tt>getLazy<T>()</tt> to access <tt>LLLazyBase<T>::get()</tt> as if - * in the lexical context of some subclass method. Ironically, free functions - * let us do that better than methods on a @c virtual base class -- but that - * implies passing @c this explicitly. So be it. - */ -//@{ -#if (! GCC33) -template <typename T, class MYCLASS> -T& getLazy(MYCLASS* this_) { return this_->LLLazyBase<T>::get(); } -template <typename T, class MYCLASS> -const T& getLazy(const MYCLASS* this_) { return this_->LLLazyBase<T>::get(); } -#else // gcc 3.3 -// For const-correctness, we really should have two getLazy() variants: one -// accepting const MYCLASS* and returning const T&, the other accepting -// non-const MYCLASS* and returning non-const T&. This works fine on the Mac -// (gcc 4.0.1) and Windows (MSVC 8.0), but fails on our Linux 32-bit Debian -// Sarge stations (gcc 3.3.5). Since I really don't know how to beat that aging -// compiler over the head to make it do the right thing, I'm going to have to -// move forward with the wrong thing: a single getLazy() function that accepts -// const MYCLASS* and returns non-const T&. -template <typename T, class MYCLASS> -T& getLazy(const MYCLASS* this_) { return const_cast<MYCLASS*>(this_)->LLLazyBase<T>::get(); } -#endif // gcc 3.3 -template <typename T, class MYCLASS> -void setLazy(MYCLASS* this_, T* instance) { this_->LLLazyBase<T>::set(instance); } -template <typename T, class MYCLASS> -void setLazy(MYCLASS* this_, const typename LLLazy<T>::Factory& factory) -{ - this_->LLLazyBase<T>::set(factory); -} -//@} - -#endif /* ! defined(LL_LLLAZY_H) */ diff --git a/indra/llcommon/llleap.cpp b/indra/llcommon/llleap.cpp index 0a57ef1c48..84d2a12f65 100755 --- a/indra/llcommon/llleap.cpp +++ b/indra/llcommon/llleap.cpp @@ -394,7 +394,7 @@ public: LLProcess::WritePipe& childin(mChild->getWritePipe(LLProcess::STDIN)); LLEventPump& mainloop(LLEventPumps::instance().obtain("mainloop")); LLSD nop; - F64 until(LLTimer::getElapsedSeconds() + 2); + F64 until = (LLTimer::getElapsedSeconds() + 2).value(); while (childin.size() && LLTimer::getElapsedSeconds() < until) { mainloop.post(nop); diff --git a/indra/llcommon/lllocalidhashmap.h b/indra/llcommon/lllocalidhashmap.h deleted file mode 100755 index 8f4f91a560..0000000000 --- a/indra/llcommon/lllocalidhashmap.h +++ /dev/null @@ -1,895 +0,0 @@ -/** - * @file lllocalidhashmap.h - * @brief Map specialized for dealing with local ids - * - * $LicenseInfo:firstyear=2003&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_LLLOCALIDHASHMAP_H -#define LL_LLLOCALIDHASHMAP_H - -#include "stdtypes.h" -#include "llerror.h" - -const S32 MAX_ITERS = 4; -// LocalID hash map - -// -// LLLocalIDHashNode -// - -template <class DATA, int SIZE> -class LLLocalIDHashNode -{ -public: - LLLocalIDHashNode(); - -public: - S32 mCount; - U32 mKey[SIZE]; - DATA mData[SIZE]; - LLLocalIDHashNode<DATA, SIZE> *mNextNodep; -}; - - -// -// LLLocalIDHashNode implementation -// -template <class DATA, int SIZE> -LLLocalIDHashNode<DATA, SIZE>::LLLocalIDHashNode() -{ - mCount = 0; - mNextNodep = NULL; -} - -// -// LLLocalIDHashMapIter -// -template <class DATA_TYPE, int SIZE> -class LLLocalIDHashMap; - -template <class DATA_TYPE, int SIZE> -class LLLocalIDHashMapIter -{ -public: - LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp); - ~LLLocalIDHashMapIter(); - - void setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp); - inline void first(); - inline void next(); - inline DATA_TYPE& current(); // *NOTE: Deprecate? Phoenix 2005-04-15 - inline BOOL done() const; - inline S32 currentBin() const; - inline void setBin(S32 bin); - - DATA_TYPE& operator*() const - { - return mCurHashNodep->mData[mCurHashNodeKey]; - } - DATA_TYPE* operator->() const - { - return &(operator*()); - } - - LLLocalIDHashMap<DATA_TYPE, SIZE> *mHashMapp; - LLLocalIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep; - - S32 mCurHashMapNodeNum; - S32 mCurHashNodeKey; - - DATA_TYPE mNull; - - S32 mIterID; -}; - - - -template <class DATA_TYPE, int SIZE> -class LLLocalIDHashMap -{ -public: - friend class LLLocalIDHashMapIter<DATA_TYPE, SIZE>; - - LLLocalIDHashMap(); // DO NOT use this unless you explicitly setNull, or the data type constructs a "null" - // object by default - // basic constructor including sorter - LLLocalIDHashMap(const DATA_TYPE &null_data); - // Hack, this should really be a const ref, but I'm not doing it that way because the sim - // usually uses pointers. - ~LLLocalIDHashMap(); - - inline DATA_TYPE &get(const U32 local_id); - inline BOOL check(const U32 local_id) const; - inline DATA_TYPE &set(const U32 local_id, const DATA_TYPE data); - inline BOOL remove(const U32 local_id); - void removeAll(); - - void setNull(const DATA_TYPE data) { mNull = data; } - - inline S32 getLength() const; // Warning, NOT O(1!) - - void dumpIter(); - void dumpBin(U32 bin); - -protected: - // Only used by the iterator. - void addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter); - void removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter); - - // Remove the item and shift all items afterward down the list, - // fixing up iterators as we go. - BOOL removeWithShift(const U32 local_id); - -protected: - LLLocalIDHashNode<DATA_TYPE, SIZE> mNodes[256]; - - S32 mIterCount; - LLLocalIDHashMapIter<DATA_TYPE, SIZE> *mIters[MAX_ITERS]; - - DATA_TYPE mNull; -}; - - -// -// LLLocalIDHashMap implementation -// - -template <class DATA_TYPE, int SIZE> -LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap() -: mIterCount(0), - mNull() -{ - S32 i; - for (i = 0; i < MAX_ITERS; i++) - { - mIters[i] = NULL; - } -} - -template <class DATA_TYPE, int SIZE> -LLLocalIDHashMap<DATA_TYPE, SIZE>::LLLocalIDHashMap(const DATA_TYPE &null_data) -: mIterCount(0), - mNull(null_data) -{ - S32 i; - for (i = 0; i < MAX_ITERS; i++) - { - mIters[i] = NULL; - } -} - -template <class DATA_TYPE, int SIZE> -LLLocalIDHashMap<DATA_TYPE, SIZE>::~LLLocalIDHashMap() -{ - S32 i; - for (i = 0; i < MAX_ITERS; i++) - { - if (mIters[i]) - { - mIters[i]->mHashMapp = NULL; - mIterCount--; - } - } - removeAll(); -} - -template <class DATA_TYPE, int SIZE> -void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeAll() -{ - S32 bin; - for (bin = 0; bin < 256; bin++) - { - LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin]; - - BOOL first = TRUE; - do // First node guaranteed to be there - { - S32 i; - const S32 count = nodep->mCount; - - // Iterate through all members of this node - for (i = 0; i < count; i++) - { - nodep->mData[i] = mNull; - } - - nodep->mCount = 0; - // Done with all objects in this node, go to the next. - - LLLocalIDHashNode<DATA_TYPE, SIZE>* curp = nodep; - nodep = nodep->mNextNodep; - - // Delete the node if it's not the first node - if (first) - { - first = FALSE; - curp->mNextNodep = NULL; - } - else - { - delete curp; - } - } while (nodep); - } -} - -template <class DATA_TYPE, int SIZE> -void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpIter() -{ - std::cout << "Hash map with " << mIterCount << " iterators" << std::endl; - - std::cout << "Hash Map Iterators:" << std::endl; - S32 i; - for (i = 0; i < MAX_ITERS; i++) - { - if (mIters[i]) - { - llinfos << i << " " << mIters[i]->mCurHashNodep << " " << mIters[i]->mCurHashNodeKey << llendl; - } - else - { - llinfos << i << "null" << llendl; - } - } -} - -template <class DATA_TYPE, int SIZE> -void LLLocalIDHashMap<DATA_TYPE, SIZE>::dumpBin(U32 bin) -{ - std::cout << "Dump bin " << bin << std::endl; - - LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin]; - S32 node = 0; - do // First node guaranteed to be there. - { - std::cout << "Bin " << bin - << " node " << node - << " count " << nodep->mCount - << " contains " << std::flush; - - S32 i; - for (i = 0; i < nodep->mCount; i++) - { - std::cout << nodep->mData[i] << " " << std::flush; - } - - std::cout << std::endl; - - nodep = nodep->mNextNodep; - node++; - } while (nodep); -} - -template <class DATA_TYPE, int SIZE> -inline S32 LLLocalIDHashMap<DATA_TYPE, SIZE>::getLength() const -{ - S32 count = 0; - S32 bin; - for (bin = 0; bin < 256; bin++) - { - const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin]; - while (nodep) - { - count += nodep->mCount; - nodep = nodep->mNextNodep; - } - } - return count; -} - -template <class DATA_TYPE, int SIZE> -inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::get(const U32 local_id) -{ - LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff]; - - do // First node guaranteed to be there - { - S32 i; - const S32 count = nodep->mCount; - - // Iterate through all members of this node - for (i = 0; i < count; i++) - { - if (nodep->mKey[i] == local_id) - { - // We found it. - return nodep->mData[i]; - } - } - - // Done with all objects in this node, go to the next. - nodep = nodep->mNextNodep; - } while (nodep); - - return mNull; -} - - -template <class DATA_TYPE, int SIZE> -inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::check(const U32 local_id) const -{ - const LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff]; - - do // First node guaranteed to be there - { - S32 i; - const S32 count = nodep->mCount; - - // Iterate through all members of this node - for (i = 0; i < count; i++) - { - if (nodep->mKey[i] == local_id) - { - // We found it. - return TRUE; - } - } - - // Done with all objects in this node, go to the next. - nodep = nodep->mNextNodep; - } while (nodep); - - // Didn't find anything - return FALSE; -} - - -template <class DATA_TYPE, int SIZE> -inline DATA_TYPE &LLLocalIDHashMap<DATA_TYPE, SIZE>::set(const U32 local_id, const DATA_TYPE data) -{ - // Set is just like a normal find, except that if we find a match - // we replace it with the input value. - // If we don't find a match, we append to the end of the list. - - LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[local_id & 0xff]; - - while (1) - { - const S32 count = nodep->mCount; - - S32 i; - for (i = 0; i < count; i++) - { - if (nodep->mKey[i] == local_id) - { - // We found a match for this key, replace the data with - // the incoming data. - nodep->mData[i] = data; - return nodep->mData[i]; - } - } - if (!nodep->mNextNodep) - { - // We've iterated through all of the keys without finding a match - if (i < SIZE) - { - // There's still some space on this node, append - // the key and data to it. - nodep->mKey[i] = local_id; - nodep->mData[i] = data; - nodep->mCount++; - - return nodep->mData[i]; - } - else - { - // This node is full, append a new node to the end. - nodep->mNextNodep = new LLLocalIDHashNode<DATA_TYPE, SIZE>; - nodep->mNextNodep->mKey[0] = local_id; - nodep->mNextNodep->mData[0] = data; - nodep->mNextNodep->mCount = 1; - - return nodep->mNextNodep->mData[0]; - } - } - - // No match on this node, go to the next - nodep = nodep->mNextNodep; - } -} - - -template <class DATA_TYPE, int SIZE> -inline BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::remove(const U32 local_id) -{ - // Remove is the trickiest operation. - // What we want to do is swap the last element of the last - // node if we find the one that we want to remove, but we have - // to deal with deleting the node from the tail if it's empty, but - // NOT if it's the only node left. - - const S32 node_index = local_id & 0xff; - - LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index]; - - // A modification of the standard search algorithm. - do // First node guaranteed to be there - { - const S32 count = nodep->mCount; - - S32 i; - for (i = 0; i < count; i++) - { - if (nodep->mKey[i] == local_id) - { - // If we're removing the item currently pointed to by one - // or more iterators, we can just swap in the last item - // and back the iterator(s) up by one. - // Otherwise, we need to do a slow and safe shift of all - // items back to one position to fill the hole and fix up - // all iterators we find. - BOOL need_shift = FALSE; - S32 cur_iter; - if (mIterCount) - { - for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++) - { - if (mIters[cur_iter]) - { - // We only care if the hash map node is on the one - // that we're working on. If it's before, we've already - // traversed it, if it's after, changing the order doesn't - // matter. - if (mIters[cur_iter]->mCurHashMapNodeNum == node_index) - { - if ((mIters[cur_iter]->mCurHashNodep == nodep) - && (mIters[cur_iter]->mCurHashNodeKey == i)) - { - // it's on the one we're deleting, we'll - // fix the iterator quickly below. - } - else - { - // We're trying to remove an item on this - // iterator's chain that this - // iterator doesn't point to! We need to do - // the slow remove-and-shift-down case. - need_shift = TRUE; - } - } - } - } - } - - // Removing an item that isn't pointed to by all iterators - if (need_shift) - { - return removeWithShift(local_id); - } - - // Fix the iterators that point to this node/i pair, the - // one we're deleting - for (cur_iter = 0; cur_iter < MAX_ITERS; cur_iter++) - { - if (mIters[cur_iter]) - { - // We only care if the hash map node is on the one - // that we're working on. If it's before, we've already - // traversed it, if it's after, changing the order doesn't - // matter. - if (mIters[cur_iter]->mCurHashMapNodeNum == node_index) - { - if ((mIters[cur_iter]->mCurHashNodep == nodep) - && (mIters[cur_iter]->mCurHashNodeKey == i)) - { - // We can handle the case where we're deleting - // the element we're on trivially (sort of). - if (nodep->mCount > 1) - { - // If we're not going to delete this node, - // it's OK. - mIters[cur_iter]->mCurHashNodeKey--; - } - else - { - // We're going to delete this node, because this - // is the last element on it. - - // Find the next node, and then back up one. - mIters[cur_iter]->next(); - mIters[cur_iter]->mCurHashNodeKey--; - } - } - } - } - } - - // We found the node that we want to remove. - // Find the last (and next-to-last) node, and the index of the last - // element. We could conceviably start from the node we're on, - // but that makes it more complicated, this is easier. - - LLLocalIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[node_index]; - LLLocalIDHashNode<DATA_TYPE, SIZE> *lastp = prevp; - - // Find the last and next-to-last - while (lastp->mNextNodep) - { - prevp = lastp; - lastp = lastp->mNextNodep; - } - - // First, swap in the last to the current location. - nodep->mKey[i] = lastp->mKey[lastp->mCount - 1]; - nodep->mData[i] = lastp->mData[lastp->mCount - 1]; - - // Now, we delete the entry - lastp->mCount--; - lastp->mData[lastp->mCount] = mNull; - - if (!lastp->mCount) - { - // We deleted the last element! - if (lastp != &mNodes[local_id & 0xff]) - { - // Only blitz the node if it's not the head - // Set the previous node to point to NULL, then - // blitz the empty last node - prevp->mNextNodep = NULL; - delete lastp; - } - } - - return TRUE; - } - } - - // Iterate to the next node, we've scanned all the entries in this one. - nodep = nodep->mNextNodep; - } while (nodep); - - return FALSE; -} - -template <class DATA_TYPE, int SIZE> -BOOL LLLocalIDHashMap<DATA_TYPE, SIZE>::removeWithShift(const U32 local_id) -{ - const S32 node_index = local_id & 0xFF; - LLLocalIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[node_index]; - LLLocalIDHashNode<DATA_TYPE, SIZE>* prevp = NULL; - BOOL found = FALSE; - - do // First node guaranteed to be there - { - const S32 count = nodep->mCount; - S32 i; - for (i = 0; i < count; i++) - { - if (nodep->mKey[i] == local_id) - { - // Found the item. Start shifting items from later - // in the list over this item. - found = TRUE; - } - - if (found) - { - // If there is an iterator on this node, we need to - // back it up. - S32 cur_iter; - for (cur_iter = 0; cur_iter <MAX_ITERS; cur_iter++) - { - LLLocalIDHashMapIter<DATA_TYPE, SIZE>* iter; - iter = mIters[cur_iter]; - // If an iterator is on this node,i pair, then back it up. - if (iter - && iter->mCurHashMapNodeNum == node_index - && iter->mCurHashNodep == nodep - && iter->mCurHashNodeKey == i) - { - if (i > 0) - { - // Don't need to move iterator nodep, since - // we're in the same node. - iter->mCurHashNodeKey--; - } - else if (prevp) - { - // need to go the previous node, last item - iter->mCurHashNodep = prevp; - iter->mCurHashNodeKey = prevp->mCount - 1; - } - else - { - // we're on the first item in the list, but - // need to go back anyhow. - - // BUG: If this deletion empties the list, - // iter->done() will be wrong until - // iter->next() is called. - iter->mCurHashNodeKey = -1; - } - } - } - - // Copy data from the next position into this position. - if (i < count-1) - { - // we're not on the last item in the node, - // so we can copy within the node - nodep->mKey[i] = nodep->mKey[i+1]; - nodep->mData[i] = nodep->mData[i+1]; - } - else if (nodep->mNextNodep) - { - // we're on the last item in the node, - // but there's a next node we can copy from - nodep->mKey[i] = nodep->mNextNodep->mKey[0]; - nodep->mData[i] = nodep->mNextNodep->mData[0]; - } - else - { - // We're on the last position in the list. - // No one to copy from. Replace with nothing. - nodep->mKey[i] = 0; - nodep->mData[i] = mNull; - } - } - } - - // Last node in chain, so delete the last node - if (found - && !nodep->mNextNodep) - { - // delete the last item off the last node - nodep->mCount--; - - if (nodep->mCount == 0) - { - // We deleted the last element! - if (nodep != &mNodes[node_index]) - { - // Always have a prevp if we're not the head. - llassert(prevp); - - // Only blitz the node if it's not the head - // Set the previous node to point to NULL, then - // blitz the empty last node - prevp->mNextNodep = NULL; - delete nodep; - nodep = NULL; - } - } - - // Deleted last item in chain, so we're done. - return found; - } - - prevp = nodep; - nodep = nodep->mNextNodep; - } while (nodep); - - return found; -} - -template <class DATA_TYPE, int SIZE> -void LLLocalIDHashMap<DATA_TYPE, SIZE>::removeIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter) -{ - S32 i; - for (i = 0; i < MAX_ITERS; i++) - { - if (mIters[i] == iter) - { - mIters[i] = NULL; - mIterCount--; - return; - } - } - llerrs << "Iterator " << iter << " not found for removal in hash map!" << llendl; -} - -template <class DATA_TYPE, int SIZE> -void LLLocalIDHashMap<DATA_TYPE, SIZE>::addIter(LLLocalIDHashMapIter<DATA_TYPE, SIZE> *iter) -{ - S32 i; - for (i = 0; i < MAX_ITERS; i++) - { - if (mIters[i] == NULL) - { - mIters[i] = iter; - mIterCount++; - return; - } - } - llerrs << "More than " << MAX_ITERS << " iterating over a map simultaneously!" << llendl; -} - - - -// -// LLLocalIDHashMapIter Implementation -// -template <class DATA_TYPE, int SIZE> -LLLocalIDHashMapIter<DATA_TYPE, SIZE>::LLLocalIDHashMapIter(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp) -{ - mHashMapp = NULL; - setMap(hash_mapp); -} - -template <class DATA_TYPE, int SIZE> -LLLocalIDHashMapIter<DATA_TYPE, SIZE>::~LLLocalIDHashMapIter() -{ - if (mHashMapp) - { - mHashMapp->removeIter(this); - } -} - -template <class DATA_TYPE, int SIZE> -void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setMap(LLLocalIDHashMap<DATA_TYPE, SIZE> *hash_mapp) -{ - if (mHashMapp) - { - mHashMapp->removeIter(this); - } - mHashMapp = hash_mapp; - if (mHashMapp) - { - mHashMapp->addIter(this); - } - - mCurHashNodep = NULL; - mCurHashMapNodeNum = -1; - mCurHashNodeKey = 0; -} - -template <class DATA_TYPE, int SIZE> -inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::first() -{ - // Iterate through until we find the first non-empty node; - S32 i; - for (i = 0; i < 256; i++) - { - if (mHashMapp->mNodes[i].mCount) - { - - mCurHashNodep = &mHashMapp->mNodes[i]; - mCurHashMapNodeNum = i; - mCurHashNodeKey = 0; - //return mCurHashNodep->mData[0]; - return; - } - } - - // Completely empty! - mCurHashNodep = NULL; - //return mNull; - return; -} - -template <class DATA_TYPE, int SIZE> -inline BOOL LLLocalIDHashMapIter<DATA_TYPE, SIZE>::done() const -{ - return mCurHashNodep ? FALSE : TRUE; -} - -template <class DATA_TYPE, int SIZE> -inline S32 LLLocalIDHashMapIter<DATA_TYPE, SIZE>::currentBin() const -{ - if ( (mCurHashMapNodeNum > 255) - ||(mCurHashMapNodeNum < 0)) - { - return 0; - } - else - { - return mCurHashMapNodeNum; - } -} - -template <class DATA_TYPE, int SIZE> -inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::setBin(S32 bin) -{ - // Iterate through until we find the first non-empty node; - S32 i; - bin = llclamp(bin, 0, 255); - for (i = bin; i < 256; i++) - { - if (mHashMapp->mNodes[i].mCount) - { - - mCurHashNodep = &mHashMapp->mNodes[i]; - mCurHashMapNodeNum = i; - mCurHashNodeKey = 0; - return; - } - } - for (i = 0; i < bin; i++) - { - if (mHashMapp->mNodes[i].mCount) - { - - mCurHashNodep = &mHashMapp->mNodes[i]; - mCurHashMapNodeNum = i; - mCurHashNodeKey = 0; - return; - } - } - // Completely empty! - mCurHashNodep = NULL; -} - -template <class DATA_TYPE, int SIZE> -inline DATA_TYPE &LLLocalIDHashMapIter<DATA_TYPE, SIZE>::current() -{ - if (!mCurHashNodep) - { - return mNull; - } - return mCurHashNodep->mData[mCurHashNodeKey]; -} - -template <class DATA_TYPE, int SIZE> -inline void LLLocalIDHashMapIter<DATA_TYPE, SIZE>::next() -{ - // No current entry, this iterator is done - if (!mCurHashNodep) - { - //return mNull; - return; - } - - // Go to the next element - mCurHashNodeKey++; - if (mCurHashNodeKey < mCurHashNodep->mCount) - { - // We're not done with this node, return the current element - //return mCurHashNodep->mData[mCurHashNodeKey]; - return; - } - - // Done with this node, move to the next - mCurHashNodep = mCurHashNodep->mNextNodep; - if (mCurHashNodep) - { - // Return the first element - mCurHashNodeKey = 0; - //return mCurHashNodep->mData[0]; - return; - } - - // Find the next non-empty node (keyed on the first byte) - mCurHashMapNodeNum++; - - S32 i; - for (i = mCurHashMapNodeNum; i < 256; i++) - { - if (mHashMapp->mNodes[i].mCount) - { - // We found one that wasn't empty - mCurHashNodep = &mHashMapp->mNodes[i]; - mCurHashMapNodeNum = i; - mCurHashNodeKey = 0; - //return mCurHashNodep->mData[0]; - return; - } - } - - // OK, we're done, nothing else to iterate - mCurHashNodep = NULL; - mHashMapp->mIterCount--; // Decrement since we're safe to do removes now - //return mNull; - return; -} - -#endif // LL_LLLOCALIDHASHMAP_H diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 1409c55d1c..ed80af36d8 100755 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -76,7 +76,6 @@ documentation and/or software. #include "llmd5.h" -#include <cassert> #include <iostream> // cerr // how many bytes to grab at a time when checking files diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index 70ad10ad55..c6b02df939 100755 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -32,7 +32,6 @@ //#endif #if defined(LL_WINDOWS) -//# include <windows.h> # include <psapi.h> #elif defined(LL_DARWIN) # include <sys/types.h> diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index e725bdd9fa..95500753e4 100755 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -27,6 +27,9 @@ #define LLMEMORY_H #include "linden_common.h" +#if !LL_WINDOWS +#include <stdint.h> +#endif class LLMutex ; @@ -36,6 +39,20 @@ 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 + inline void* ll_aligned_malloc( size_t size, int align ) { void* mem = malloc( size + (align - 1) + sizeof(void*) ); diff --git a/indra/llcommon/llmetricperformancetester.cpp b/indra/llcommon/llmetricperformancetester.cpp index 731e58bd20..fd89cb818a 100755 --- a/indra/llcommon/llmetricperformancetester.cpp +++ b/indra/llcommon/llmetricperformancetester.cpp @@ -29,9 +29,9 @@ #include "indra_constants.h" #include "llerror.h" #include "llsdserialize.h" -#include "llstat.h" #include "lltreeiterators.h" #include "llmetricperformancetester.h" +#include "llfasttimer.h" //---------------------------------------------------------------------------------------------- // LLMetricPerformanceTesterBasic : static methods and testers management @@ -91,7 +91,7 @@ LLMetricPerformanceTesterBasic* LLMetricPerformanceTesterBasic::getTester(std::s // Return TRUE if this metric is requested or if the general default "catch all" metric is requested BOOL LLMetricPerformanceTesterBasic::isMetricLogRequested(std::string name) { - return (LLFastTimer::sMetricLog && ((LLFastTimer::sLogName == name) || (LLFastTimer::sLogName == DEFAULT_METRIC_NAME))); + return (LLTrace::TimeBlock::sMetricLog && ((LLTrace::TimeBlock::sLogName == name) || (LLTrace::TimeBlock::sLogName == DEFAULT_METRIC_NAME))); } /*static*/ @@ -194,8 +194,7 @@ void LLMetricPerformanceTesterBasic::preOutputTestResults(LLSD* sd) void LLMetricPerformanceTesterBasic::postOutputTestResults(LLSD* sd) { - LLMutexLock lock(LLFastTimer::sLogLock); - LLFastTimer::sLogQueue.push((*sd)); + LLTrace::TimeBlock::pushLog(*sd); } void LLMetricPerformanceTesterBasic::outputTestResults() diff --git a/indra/llcommon/llmortician.h b/indra/llcommon/llmortician.h index 319955ef93..9517e2db5e 100755 --- a/indra/llcommon/llmortician.h +++ b/indra/llcommon/llmortician.h @@ -28,6 +28,7 @@ #define LLMORTICIAN_H #include "stdtypes.h" +#include <list> class LL_COMMON_API LLMortician { diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp new file mode 100644 index 0000000000..ad0287c6d5 --- /dev/null +++ b/indra/llcommon/llmutex.cpp @@ -0,0 +1,179 @@ +/** + * @file llmutex.cpp + * + * $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 "linden_common.h" +#include "llapr.h" + +#include "apr_portable.h" + +#include "llmutex.h" +#include "llthread.h" + +//============================================================================ + +LLMutex::LLMutex(apr_pool_t *poolp) : + mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD) +{ + //if (poolp) + //{ + // mIsLocalPool = FALSE; + // mAPRPoolp = poolp; + //} + //else + { + mIsLocalPool = TRUE; + apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread + } + apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp); +} + + +LLMutex::~LLMutex() +{ +#if MUTEX_DEBUG + //bad assertion, the subclass LLSignal might be "locked", and that's OK + //llassert_always(!isLocked()); // better not be locked! +#endif + if (ll_apr_is_initialized()) + { + apr_thread_mutex_destroy(mAPRMutexp); + if (mIsLocalPool) + { + apr_pool_destroy(mAPRPoolp); + } + } + mAPRMutexp = NULL; +} + + +void LLMutex::lock() +{ + if(isSelfLocked()) + { //redundant lock + mCount++; + return; + } + + apr_thread_mutex_lock(mAPRMutexp); + +#if MUTEX_DEBUG + // Have to have the lock before we can access the debug info + U32 id = LLThread::currentID(); + if (mIsLocked[id] != FALSE) + llerrs << "Already locked in Thread: " << id << llendl; + mIsLocked[id] = TRUE; +#endif + + mLockingThread = LLThread::currentID(); +} + +void LLMutex::unlock() +{ + if (mCount > 0) + { //not the root unlock + mCount--; + return; + } + +#if MUTEX_DEBUG + // Access the debug info while we have the lock + U32 id = LLThread::currentID(); + if (mIsLocked[id] != TRUE) + llerrs << "Not locked in Thread: " << id << llendl; + mIsLocked[id] = FALSE; +#endif + + mLockingThread = NO_THREAD; + apr_thread_mutex_unlock(mAPRMutexp); +} + +bool LLMutex::isLocked() +{ + apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp); + if (APR_STATUS_IS_EBUSY(status)) + { + return true; + } + else + { + apr_thread_mutex_unlock(mAPRMutexp); + return false; + } +} + +bool LLMutex::isSelfLocked() +{ + return mLockingThread == LLThread::currentID(); +} + +U32 LLMutex::lockingThread() const +{ + return mLockingThread; +} + +//============================================================================ + +LLCondition::LLCondition(apr_pool_t *poolp) : + LLMutex(poolp) +{ + // base class (LLMutex) has already ensured that mAPRPoolp is set up. + + apr_thread_cond_create(&mAPRCondp, mAPRPoolp); +} + + +LLCondition::~LLCondition() +{ + apr_thread_cond_destroy(mAPRCondp); + mAPRCondp = NULL; +} + + +void LLCondition::wait() +{ + if (!isLocked()) + { //mAPRMutexp MUST be locked before calling apr_thread_cond_wait + apr_thread_mutex_lock(mAPRMutexp); +#if MUTEX_DEBUG + // avoid asserts on destruction in non-release builds + U32 id = LLThread::currentID(); + mIsLocked[id] = TRUE; +#endif + } + apr_thread_cond_wait(mAPRCondp, mAPRMutexp); +} + +void LLCondition::signal() +{ + apr_thread_cond_signal(mAPRCondp); +} + +void LLCondition::broadcast() +{ + apr_thread_cond_broadcast(mAPRCondp); +} + + +//============================================================================ diff --git a/indra/llcommon/llmutex.h b/indra/llcommon/llmutex.h new file mode 100644 index 0000000000..cbde4c47a9 --- /dev/null +++ b/indra/llcommon/llmutex.h @@ -0,0 +1,101 @@ +/** + * @file llmutex.h + * @brief Base classes for mutex and condition handling. + * + * $LicenseInfo:firstyear=2004&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_LLMUTEX_H +#define LL_LLMUTEX_H + +#include "llapr.h" +#include "apr_thread_cond.h" + +//============================================================================ + +#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO) + +class LL_COMMON_API LLMutex +{ +public: + typedef enum + { + NO_THREAD = 0xFFFFFFFF + } e_locking_thread; + + LLMutex(apr_pool_t *apr_poolp = NULL); // NULL pool constructs a new pool for the mutex + virtual ~LLMutex(); + + void lock(); // blocks + void unlock(); + bool isLocked(); // non-blocking, but does do a lock/unlock so not free + bool isSelfLocked(); //return true if locked in a same thread + U32 lockingThread() const; //get ID of locking thread + +protected: + apr_thread_mutex_t *mAPRMutexp; + mutable U32 mCount; + mutable U32 mLockingThread; + + apr_pool_t *mAPRPoolp; + BOOL mIsLocalPool; + +#if MUTEX_DEBUG + std::map<U32, BOOL> mIsLocked; +#endif +}; + +// Actually a condition/mutex pair (since each condition needs to be associated with a mutex). +class LL_COMMON_API LLCondition : public LLMutex +{ +public: + LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well. + ~LLCondition(); + + void wait(); // blocks + void signal(); + void broadcast(); + +protected: + apr_thread_cond_t *mAPRCondp; +}; + +class LLMutexLock +{ +public: + LLMutexLock(LLMutex* mutex) + { + mMutex = mutex; + + if(mMutex) + mMutex->lock(); + } + ~LLMutexLock() + { + if(mMutex) + mMutex->unlock(); + } +private: + LLMutex* mMutex; +}; + +#endif // LL_LLTHREAD_H diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h index 88c09c8dca..e640ffd595 100755 --- a/indra/llcommon/llpointer.h +++ b/indra/llcommon/llpointer.h @@ -97,24 +97,13 @@ public: LLPointer<Type>& operator =(Type* ptr) { - if( mPointer != ptr ) - { - unref(); - mPointer = ptr; - ref(); - } - + assign(ptr); return *this; } LLPointer<Type>& operator =(const LLPointer<Type>& ptr) { - if( mPointer != ptr.mPointer ) - { - unref(); - mPointer = ptr.mPointer; - ref(); - } + assign(ptr); return *this; } @@ -122,12 +111,7 @@ public: template<typename Subclass> LLPointer<Type>& operator =(const LLPointer<Subclass>& ptr) { - if( mPointer != ptr.get() ) - { - unref(); - mPointer = ptr.get(); - ref(); - } + assign(ptr.get()); return *this; } @@ -144,6 +128,16 @@ protected: void ref(); void unref(); #else + + void assign(const LLPointer<Type>& ptr) + { + if( mPointer != ptr.mPointer ) + { + unref(); + mPointer = ptr.mPointer; + ref(); + } + } void ref() { if (mPointer) @@ -156,9 +150,9 @@ protected: { if (mPointer) { - Type *tempp = mPointer; + Type *temp = mPointer; mPointer = NULL; - tempp->unref(); + temp->unref(); if (mPointer != NULL) { llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; @@ -171,4 +165,40 @@ protected: Type* mPointer; }; +template<typename Type> +class LLCopyOnWritePointer : public LLPointer<Type> +{ +public: + typedef LLCopyOnWritePointer<Type> self_t; + typedef LLPointer<Type> pointer_t; + + LLCopyOnWritePointer() + {} + + LLCopyOnWritePointer(Type* ptr) + : LLPointer<Type>(ptr) + {} + + LLCopyOnWritePointer(LLPointer<Type>& ptr) + : LLPointer<Type>(ptr) + {} + + Type* write() + { + makeUnique(); + return pointer_t::mPointer; + } + + void makeUnique() + { + if (pointer_t::notNull() && pointer_t::mPointer->getNumRefs() > 1) + { + *(pointer_t*)(this) = new Type(*pointer_t::mPointer); + } + } + + const Type* operator->() const { return pointer_t::mPointer; } + const Type& operator*() const { return *pointer_t::mPointer; } +}; + #endif diff --git a/indra/llui/llfunctorregistry.cpp b/indra/llcommon/llpredicate.cpp index 8003324973..1278948e24 100755..100644 --- a/indra/llui/llfunctorregistry.cpp +++ b/indra/llcommon/llpredicate.cpp @@ -1,7 +1,6 @@ -/** - * @file llfunctorregistry.cpp - * @author Kent Quirk - * @brief Maintains a registry of named callback functors taking a single LLSD parameter +/** + * @file llpredicate.cpp + * @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions * * $LicenseInfo:firstyear=2008&license=viewerlgpl$ * Second Life Viewer Source Code @@ -23,11 +22,20 @@ * * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ - **/ - + */ #include "linden_common.h" -#include "llfunctorregistry.h" -// This is a default functor always resident in the system. -// It's used whenever a functor isn't found in the registry, so that -// we at least log the data relating to the user response. +#include "llpredicate.h" + +namespace LLPredicate +{ + const U32 cPredicateFlagsFromEnum[5] = + { + 0xAAAAaaaa, // 10101010101010101010101010101010 + 0xCCCCcccc, // 11001100110011001100110011001100 + 0xF0F0F0F0, // 11110000111100001111000011110000 + 0xFF00FF00, // 11111111000000001111111100000000 + 0xFFFF0000 // 11111111111111110000000000000000 + }; +} + diff --git a/indra/llcommon/llpredicate.h b/indra/llcommon/llpredicate.h new file mode 100644 index 0000000000..a0e970a799 --- /dev/null +++ b/indra/llcommon/llpredicate.h @@ -0,0 +1,210 @@ +/** + * @file llpredicate.h + * @brief abstraction for filtering objects by predicates, with arbitrary boolean expressions + * + * $LicenseInfo:firstyear=2008&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_LLPREDICATE_H +#define LL_LLPREDICATE_H + +#include "llerror.h" + +namespace LLPredicate +{ + template<typename ENUM> class Rule; + + extern const U32 cPredicateFlagsFromEnum[5]; + + template<typename ENUM> + class Value + { + public: + typedef U32 predicate_flag_t; + static const S32 cMaxEnum = 5; + + Value(ENUM e, bool predicate_value = true) + : mPredicateFlags(predicate_value ? cPredicateFlagsFromEnum[e] : ~cPredicateFlagsFromEnum[e]) + { + llassert(0 <= e && e < cMaxEnum); + } + + Value() + : mPredicateFlags(0xFFFFffff) + {} + + Value operator!() const + { + Value new_value; + new_value.mPredicateFlags = ~mPredicateFlags; + return new_value; + } + + Value operator &&(const Value other) const + { + Value new_value; + new_value.mPredicateFlags = mPredicateFlags & other.mPredicateFlags; + return new_value; + } + + Value operator ||(const Value other) const + { + Value new_value; + new_value.mPredicateFlags = mPredicateFlags | other.mPredicateFlags; + return new_value; + } + + void set(ENUM e, bool value = true) + { + llassert(0 <= e && e < cMaxEnum); + predicate_flag_t flags_to_modify; + predicate_flag_t mask = cPredicateFlagsFromEnum[e]; + if (value) + { // add predicate "e" to flags that don't contain it already + flags_to_modify = (mPredicateFlags & ~mask); + // clear flags not containing e + mPredicateFlags &= mask; + // add back flags shifted to contain e + mPredicateFlags |= flags_to_modify << (0x1 << e); + } + else + { // remove predicate "e" from flags that contain it + flags_to_modify = (mPredicateFlags & mask); + // clear flags containing e + mPredicateFlags &= ~mask; + // add back flags shifted to not contain e + mPredicateFlags |= flags_to_modify >> (0x1 << e); + } + } + + void forget(ENUM e) + { + set(e, true); + U32 flags_with_predicate = mPredicateFlags; + set(e, false); + // ambiguous value is result of adding and removing predicate at the same time! + mPredicateFlags |= flags_with_predicate; + } + + bool allSet() const + { + return mPredicateFlags == ~0; + } + + bool noneSet() const + { + return mPredicateFlags == 0; + } + + bool someSet() const + { + return mPredicateFlags != 0; + } + + private: + predicate_flag_t mPredicateFlags; + }; + + template<typename ENUM> + class Rule + { + public: + Rule(ENUM value) + : mRule(value) + {} + + Rule(const Value<ENUM> other) + : mRule(other) + {} + + Rule() + {} + + void require(ENUM e) + { + mRule.set(e, require); + } + + void allow(ENUM e) + { + mRule.forget(e); + } + + bool check(const Value<ENUM> value) const + { + return (mRule && value).someSet(); + } + + bool requires(const Value<ENUM> value) const + { + return (mRule && value).someSet() && (!mRule && value).noneSet(); + } + + bool isAmbivalent(const Value<ENUM> value) const + { + return (mRule && value).someSet() && (!mRule && value).someSet(); + } + + bool acceptsAll() const + { + return mRule.allSet(); + } + + bool acceptsNone() const + { + return mRule.noneSet(); + } + + Rule operator!() const + { + Rule new_rule; + new_rule.mRule = !mRule; + return new_rule; + } + + Rule operator &&(const Rule other) const + { + Rule new_rule; + new_rule.mRule = mRule && other.mRule; + return new_rule; + } + + Rule operator ||(const Rule other) const + { + Rule new_rule; + new_rule.mRule = mRule || other.mRule; + return new_rule; + } + + private: + Value<ENUM> mRule; + }; +} + +template<typename ENUM> +LLPredicate::Value<ENUM> ll_make_predicate(ENUM e, bool predicate_value = true) +{ + return LLPredicate::Value<ENUM>(e, predicate_value); +} + + +#endif // LL_LLPREDICATE_H diff --git a/indra/llcommon/llprocess.h b/indra/llcommon/llprocess.h index d711ce2f74..43ccadc412 100755 --- a/indra/llcommon/llprocess.h +++ b/indra/llcommon/llprocess.h @@ -29,6 +29,7 @@ #include "llinitparam.h" #include "llsdparam.h" +#include "llwin32headerslean.h" #include "apr_thread_proc.h" #include <boost/shared_ptr.hpp> #include <boost/ptr_container/ptr_vector.hpp> @@ -38,8 +39,7 @@ #include <stdexcept> #if LL_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include <windows.h> // HANDLE (eye roll) +#include "llwin32headerslean.h" // for HANDLE #elif LL_LINUX #if defined(Status) #undef Status diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index fd8f603d21..5ddfa6fcef 100755 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -32,9 +32,7 @@ //#include <memory> #if LL_WINDOWS -# define WIN32_LEAN_AND_MEAN -# include <winsock2.h> -# include <windows.h> +# include "llwin32headerslean.h" # define _interlockedbittestandset _renamed_interlockedbittestandset # define _interlockedbittestandreset _renamed_interlockedbittestandreset # include <intrin.h> @@ -877,7 +875,7 @@ LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) LLProcessorInfo::~LLProcessorInfo() {} -F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } +LLUnitImplicit<LLUnits::Megahertz, F64> LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); } bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); } diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 6364d3c8bb..fbd427f484 100755 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -27,6 +27,8 @@ #ifndef LLPROCESSOR_H #define LLPROCESSOR_H +#include "llunit.h" + class LLProcessorInfoImpl; class LL_COMMON_API LLProcessorInfo @@ -35,7 +37,7 @@ public: LLProcessorInfo(); ~LLProcessorInfo(); - F64 getCPUFrequency() const; + LLUnitImplicit<LLUnits::Megahertz, F64> getCPUFrequency() const; bool hasSSE() const; bool hasSSE2() const; bool hasAltivec() const; diff --git a/indra/llcommon/llptrskiplist.h b/indra/llcommon/llptrskiplist.h deleted file mode 100755 index 67c7cde352..0000000000 --- a/indra/llcommon/llptrskiplist.h +++ /dev/null @@ -1,724 +0,0 @@ -/** - * @file llptrskiplist.h - * @brief Skip list implementation. - * - * $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_LLPTRSKIPLIST_H -#define LL_LLPTRSKIPLIST_H - -#include "llerror.h" -#include "llrand.h" -//#include "vmath.h" -#include "llrand.h" - -///////////////////////////////////////////// -// -// LLPtrSkipList implementation - skip list for pointers to objects -// - -template <class DATA_TYPE, S32 BINARY_DEPTH = 8> -class LLPtrSkipList -{ -public: - friend class LLPtrSkipNode; - - // basic constructor - LLPtrSkipList(); - // basic constructor including sorter - LLPtrSkipList(BOOL (*insert_first)(DATA_TYPE *first, DATA_TYPE *second), - BOOL (*equals)(DATA_TYPE *first, DATA_TYPE *second)); - ~LLPtrSkipList(); - - inline void setInsertFirst(BOOL (*insert_first)(const DATA_TYPE *first, const DATA_TYPE *second)); - inline void setEquals(BOOL (*equals)(const DATA_TYPE *first, const DATA_TYPE *second)); - - inline BOOL addData(DATA_TYPE *data); - - inline BOOL checkData(const DATA_TYPE *data); - - inline S32 getLength(); // returns number of items in the list - NOT constant time! - - inline BOOL removeData(const DATA_TYPE *data); - - // note that b_sort is ignored - inline BOOL moveData(const DATA_TYPE *data, LLPtrSkipList *newlist, BOOL b_sort); - - inline BOOL moveCurrentData(LLPtrSkipList *newlist, BOOL b_sort); - - // resort -- use when the value we're sorting by changes - /* IW 12/6/02 - This doesn't work! - Instead, remove the data BEFORE you change it - Then re-insert it after you change it - BOOL resortData(DATA_TYPE *data) - */ - - // remove all nodes from the list but do not delete data - inline void removeAllNodes(); - - inline BOOL deleteData(const DATA_TYPE *data); - - // remove all nodes from the list and delete data - inline void deleteAllData(); - - // place mCurrentp on first node - inline void resetList(); - - // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp - inline DATA_TYPE *getCurrentData(); - - // same as getCurrentData() but a more intuitive name for the operation - inline DATA_TYPE *getNextData(); - - // remove the Node at mCurentOperatingp - // leave mCurrentp and mCurentOperatingp on the next entry - inline void removeCurrentData(); - - // delete the Node at mCurentOperatingp - // leave mCurrentp and mCurentOperatingp on the next entry - inline void deleteCurrentData(); - - // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp - inline DATA_TYPE *getFirstData(); - - // TRUE if nodes are not in sorted order - inline BOOL corrupt(); - -protected: - class LLPtrSkipNode - { - public: - LLPtrSkipNode() - : mData(NULL) - { - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mForward[i] = NULL; - } - } - - LLPtrSkipNode(DATA_TYPE *data) - : mData(data) - { - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mForward[i] = NULL; - } - } - - ~LLPtrSkipNode() - { - if (mData) - { - llerror("Attempting to call LLPtrSkipNode destructor with a non-null mDatap!", 1); - } - } - - // delete associated data and NULLs out pointer - void deleteData() - { - delete mData; - mData = NULL; - } - - // NULLs out pointer - void removeData() - { - mData = NULL; - } - - DATA_TYPE *mData; - LLPtrSkipNode *mForward[BINARY_DEPTH]; - }; - - static BOOL defaultEquals(const DATA_TYPE *first, const DATA_TYPE *second) - { - return first == second; - } - - - LLPtrSkipNode mHead; - LLPtrSkipNode *mUpdate[BINARY_DEPTH]; - LLPtrSkipNode *mCurrentp; - LLPtrSkipNode *mCurrentOperatingp; - S32 mLevel; - BOOL (*mInsertFirst)(const DATA_TYPE *first, const DATA_TYPE *second); - BOOL (*mEquals)(const DATA_TYPE *first, const DATA_TYPE *second); -}; - - -// basic constructor -template <class DATA_TYPE, S32 BINARY_DEPTH> -LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::LLPtrSkipList() - : mInsertFirst(NULL), mEquals(defaultEquals) -{ - if (BINARY_DEPTH < 2) - { - llerrs << "Trying to create skip list with too little depth, " - "must be 2 or greater" << llendl; - } - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mUpdate[i] = NULL; - } - mLevel = 1; - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -// basic constructor including sorter -template <class DATA_TYPE, S32 BINARY_DEPTH> -LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::LLPtrSkipList(BOOL (*insert_first)(DATA_TYPE *first, DATA_TYPE *second), - BOOL (*equals)(DATA_TYPE *first, DATA_TYPE *second)) - :mInsertFirst(insert_first), mEquals(equals) -{ - if (BINARY_DEPTH < 2) - { - llerrs << "Trying to create skip list with too little depth, " - "must be 2 or greater" << llendl; - } - mLevel = 1; - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mHead.mForward[i] = NULL; - mUpdate[i] = NULL; - } - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::~LLPtrSkipList() -{ - removeAllNodes(); -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::setInsertFirst(BOOL (*insert_first)(const DATA_TYPE *first, const DATA_TYPE *second)) -{ - mInsertFirst = insert_first; -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::setEquals(BOOL (*equals)(const DATA_TYPE *first, const DATA_TYPE *second)) -{ - mEquals = equals; -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::addData(DATA_TYPE *data) -{ - S32 level; - LLPtrSkipNode *current = &mHead; - LLPtrSkipNode *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mData, data))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mData < data)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - // now add the new node - S32 newlevel; - for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++) - { - if (ll_frand() < 0.5f) - break; - } - - LLPtrSkipNode *snode = new LLPtrSkipNode(data); - - if (newlevel > mLevel) - { - mHead.mForward[mLevel] = NULL; - mUpdate[mLevel] = &mHead; - mLevel = newlevel; - } - - for (level = 0; level < newlevel; level++) - { - snode->mForward[level] = mUpdate[level]->mForward[level]; - mUpdate[level]->mForward[level] = snode; - } - return TRUE; -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::checkData(const DATA_TYPE *data) -{ - S32 level; - LLPtrSkipNode *current = &mHead; - LLPtrSkipNode *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mData, data))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mData < data)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - if (current) - { - return mEquals(current->mData, data); - } - else - { - return FALSE; - } -} - -// returns number of items in the list -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline S32 LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getLength() -{ - U32 length = 0; - for (LLPtrSkipNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0]) - { - length++; - } - return length; -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeData(const DATA_TYPE *data) -{ - S32 level; - LLPtrSkipNode *current = &mHead; - LLPtrSkipNode *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mData, data))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mData < data)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - if (!current) - { - // empty list or beyond the end! - return FALSE; - } - - // is this the one we want? - if (!mEquals(current->mData, data)) - { - // nope! - return FALSE; - } - else - { - // yes it is! change pointers as required - for (level = 0; level < mLevel; level++) - { - if (mUpdate[level]->mForward[level] != current) - { - // cool, we've fixed all the pointers! - break; - } - mUpdate[level]->mForward[level] = current->mForward[level]; - } - - // clean up cuurent - current->removeData(); - delete current; - - // clean up mHead - while ( (mLevel > 1) - &&(!mHead.mForward[mLevel - 1])) - { - mLevel--; - } - } - return TRUE; -} - -// note that b_sort is ignored -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::moveData(const DATA_TYPE *data, LLPtrSkipList *newlist, BOOL b_sort) -{ - BOOL removed = removeData(data); - BOOL added = newlist->addData(data); - return removed && added; -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::moveCurrentData(LLPtrSkipList *newlist, BOOL b_sort) -{ - if (mCurrentOperatingp) - { - mCurrentp = mCurrentOperatingp->mForward[0]; - BOOL removed = removeData(mCurrentOperatingp); - BOOL added = newlist->addData(mCurrentOperatingp); - mCurrentOperatingp = mCurrentp; - return removed && added; - } - return FALSE; -} - -// resort -- use when the value we're sorting by changes -/* IW 12/6/02 - This doesn't work! - Instead, remove the data BEFORE you change it - Then re-insert it after you change it -BOOL resortData(DATA_TYPE *data) -{ - removeData(data); - addData(data); -} -*/ - -// remove all nodes from the list but do not delete data -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeAllNodes() -{ - LLPtrSkipNode *temp; - // reset mCurrentp - mCurrentp = *(mHead.mForward); - - while (mCurrentp) - { - temp = mCurrentp->mForward[0]; - mCurrentp->removeData(); - delete mCurrentp; - mCurrentp = temp; - } - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mHead.mForward[i] = NULL; - mUpdate[i] = NULL; - } - - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteData(const DATA_TYPE *data) -{ - S32 level; - LLPtrSkipNode *current = &mHead; - LLPtrSkipNode *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mData, data))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mData < data)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - if (!current) - { - // empty list or beyond the end! - return FALSE; - } - - // is this the one we want? - if (!mEquals(current->mData, data)) - { - // nope! - return FALSE; - } - else - { - // do we need to fix current or currentop? - if (current == mCurrentp) - { - mCurrentp = current->mForward[0]; - } - - if (current == mCurrentOperatingp) - { - mCurrentOperatingp = current->mForward[0]; - } - - // yes it is! change pointers as required - for (level = 0; level < mLevel; level++) - { - if (mUpdate[level]->mForward[level] != current) - { - // cool, we've fixed all the pointers! - break; - } - mUpdate[level]->mForward[level] = current->mForward[level]; - } - - // clean up cuurent - current->deleteData(); - delete current; - - // clean up mHead - while ( (mLevel > 1) - &&(!mHead.mForward[mLevel - 1])) - { - mLevel--; - } - } - return TRUE; -} - -// remove all nodes from the list and delete data -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteAllData() -{ - LLPtrSkipNode *temp; - // reset mCurrentp - mCurrentp = *(mHead.mForward); - - while (mCurrentp) - { - temp = mCurrentp->mForward[0]; - mCurrentp->deleteData(); - delete mCurrentp; - mCurrentp = temp; - } - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mHead.mForward[i] = NULL; - mUpdate[i] = NULL; - } - - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -// place mCurrentp on first node -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::resetList() -{ - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getCurrentData() -{ - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = *mCurrentp->mForward; - return mCurrentOperatingp->mData; - } - else - { - //return NULL; // causes compile warning - return 0; // equivalent, but no warning - } -} - -// same as getCurrentData() but a more intuitive name for the operation -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getNextData() -{ - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = *mCurrentp->mForward; - return mCurrentOperatingp->mData; - } - else - { - //return NULL; // causes compile warning - return 0; // equivalent, but no warning - } -} - -// remove the Node at mCurentOperatingp -// leave mCurrentp and mCurentOperatingp on the next entry -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::removeCurrentData() -{ - if (mCurrentOperatingp) - { - removeData(mCurrentOperatingp->mData); - } -} - -// delete the Node at mCurentOperatingp -// leave mCurrentp and mCurentOperatingp on the next entry -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::deleteCurrentData() -{ - if (mCurrentOperatingp) - { - deleteData(mCurrentOperatingp->mData); - } -} - -// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE *LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::getFirstData() -{ - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mData; - } - else - { - //return NULL; // causes compile warning - return 0; // equivalent, but no warning - } -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipList<DATA_TYPE, BINARY_DEPTH>::corrupt() -{ - LLPtrSkipNode *previous = mHead.mForward[0]; - - // Empty lists are not corrupt. - if (!previous) return FALSE; - - LLPtrSkipNode *current = previous->mForward[0]; - while(current) - { - if (!mInsertFirst(previous->mData, current->mData)) - { - // prev shouldn't be in front of cur! - return TRUE; - } - current = current->mForward[0]; - } - return FALSE; -} - -#endif diff --git a/indra/llcommon/llptrskipmap.h b/indra/llcommon/llptrskipmap.h deleted file mode 100755 index 94bc71ec55..0000000000 --- a/indra/llcommon/llptrskipmap.h +++ /dev/null @@ -1,1239 +0,0 @@ -/** - * @file llptrskipmap.h - * @brief Just like a LLSkipMap, but since it's pointers, you can call - * deleteAllData - * - * $LicenseInfo:firstyear=2003&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_LLPTRSKIPMAP_H -#define LL_LLPTRSKIPMAP_H - -#include "llerror.h" -#include "llrand.h" - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH = 8> -class LLPtrSkipMapNode -{ -public: - LLPtrSkipMapNode() - { - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mForward[i] = NULL; - } - - U8 *zero = (U8 *)&mIndex; - - for (i = 0; i < (S32)sizeof(INDEX_T); i++) - { - *(zero + i) = 0; - } - - zero = (U8 *)&mData; - - for (i = 0; i < (S32)sizeof(DATA_T); i++) - { - *(zero + i) = 0; - } - } - - LLPtrSkipMapNode(const INDEX_T &index) - : mIndex(index) - { - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mForward[i] = NULL; - } - - U8 *zero = (U8 *)&mData; - - for (i = 0; i < (S32)sizeof(DATA_T); i++) - { - *(zero + i) = 0; - } - } - - LLPtrSkipMapNode(const INDEX_T &index, DATA_T datap) - : mIndex(index) - { - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mForward[i] = NULL; - } - - mData = datap; - } - - ~LLPtrSkipMapNode() - { - } - - // delete associated data and NULLs out pointer - void deleteData() - { - delete mData; - mData = 0; - } - - // NULLs out pointer - void removeData() - { - mData = 0; - } - - INDEX_T mIndex; - DATA_T mData; - LLPtrSkipMapNode *mForward[BINARY_DEPTH]; - -private: - // Disallow copying of LLPtrSkipMapNodes by not implementing these methods. - LLPtrSkipMapNode(const LLPtrSkipMapNode &); - LLPtrSkipMapNode &operator=(const LLPtrSkipMapNode &rhs); -}; - -//--------------------------------------------------------------------------- - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH = 8> -class LLPtrSkipMap -{ -public: - typedef BOOL (*compare)(const DATA_T& first, const DATA_T& second); - typedef compare insert_func; - typedef compare equals_func; - - void init(); - - // basic constructor - LLPtrSkipMap(); - - // basic constructor including sorter - LLPtrSkipMap(insert_func insert_first, equals_func equals); - - ~LLPtrSkipMap(); - - void setInsertFirst(insert_func insert_first); - void setEquals(equals_func equals); - - DATA_T &addData(const INDEX_T &index, DATA_T datap); - DATA_T &addData(const INDEX_T &index); - DATA_T &getData(const INDEX_T &index); - DATA_T &operator[](const INDEX_T &index); - - // If index present, returns data. - // If index not present, adds <index,NULL> and returns NULL. - DATA_T &getData(const INDEX_T &index, BOOL &b_new_entry); - - // returns data entry before and after index - BOOL getInterval(const INDEX_T &index, INDEX_T &index_before, INDEX_T &index_after, - DATA_T &data_before, DATA_T &data_after ); - - // Returns TRUE if data present in map. - BOOL checkData(const INDEX_T &index); - - // Returns TRUE if key is present in map. This is useful if you - // are potentially storing NULL pointers in the map - BOOL checkKey(const INDEX_T &index); - - // If there, returns the data. - // If not, returns NULL. - // Never adds entries to the map. - DATA_T getIfThere(const INDEX_T &index); - - INDEX_T reverseLookup(const DATA_T datap); - - // returns number of items in the list - S32 getLength(); // WARNING! getLength is O(n), not O(1)! - - BOOL removeData(const INDEX_T &index); - BOOL deleteData(const INDEX_T &index); - - // remove all nodes from the list but do not delete data - void removeAllData(); - void deleteAllData(); - - // place mCurrentp on first node - void resetList(); - - // return the data currently pointed to - DATA_T getCurrentDataWithoutIncrement(); - - // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp - DATA_T getCurrentData(); - - // same as getCurrentData() but a more intuitive name for the operation - DATA_T getNextData(); - - INDEX_T getNextKey(); - - // return the key currently pointed to - INDEX_T getCurrentKeyWithoutIncrement(); - - // remove the Node at mCurentOperatingp - // leave mCurrentp and mCurentOperatingp on the next entry - void removeCurrentData(); - - void deleteCurrentData(); - - // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp - DATA_T getFirstData(); - - INDEX_T getFirstKey(); - - static BOOL defaultEquals(const INDEX_T &first, const INDEX_T &second) - { - return first == second; - } - -private: - // don't generate implicit copy constructor or copy assignment - LLPtrSkipMap(const LLPtrSkipMap &); - LLPtrSkipMap &operator=(const LLPtrSkipMap &); - -private: - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mUpdate[BINARY_DEPTH]; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mCurrentp; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *mCurrentOperatingp; - S32 mLevel; - BOOL (*mInsertFirst)(const INDEX_T &first, const INDEX_T &second); - BOOL (*mEquals)(const INDEX_T &first, const INDEX_T &second); - S32 mNumberOfSteps; -}; - -////////////////////////////////////////////////// -// -// LLPtrSkipMap implementation -// -// - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap() - : mInsertFirst(NULL), - mEquals(defaultEquals), - mNumberOfSteps(0) -{ - if (BINARY_DEPTH < 2) - { - llerrs << "Trying to create skip list with too little depth, " - "must be 2 or greater" << llendl; - } - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mUpdate[i] = NULL; - } - mLevel = 1; - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::LLPtrSkipMap(insert_func insert_first, - equals_func equals) -: mInsertFirst(insert_first), - mEquals(equals), - mNumberOfSteps(0) -{ - if (BINARY_DEPTH < 2) - { - llerrs << "Trying to create skip list with too little depth, " - "must be 2 or greater" << llendl; - } - mLevel = 1; - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mHead.mForward[i] = NULL; - mUpdate[i] = NULL; - } - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::~LLPtrSkipMap() -{ - removeAllData(); -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::setInsertFirst(insert_func insert_first) -{ - mInsertFirst = insert_first; -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::setEquals(equals_func equals) -{ - mEquals = equals; -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::addData(const INDEX_T &index, DATA_T datap) -{ - S32 level; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - // replace the existing data if a node is already there - if ( (current) - &&(mEquals(current->mIndex, index))) - { - current->mData = datap; - return current->mData; - } - - // now add the new node - S32 newlevel; - for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++) - { - if (ll_frand() < 0.5f) - { - break; - } - } - - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode - = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index, datap); - - if (newlevel > mLevel) - { - mHead.mForward[mLevel] = NULL; - mUpdate[mLevel] = &mHead; - mLevel = newlevel; - } - - for (level = 0; level < newlevel; level++) - { - snode->mForward[level] = mUpdate[level]->mForward[level]; - mUpdate[level]->mForward[level] = snode; - } - return snode->mData; -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::addData(const INDEX_T &index) -{ - S32 level; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - // now add the new node - S32 newlevel; - for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++) - { - if (ll_frand() < 0.5f) - break; - } - - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode - = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index); - - if (newlevel > mLevel) - { - mHead.mForward[mLevel] = NULL; - mUpdate[mLevel] = &mHead; - mLevel = newlevel; - } - - for (level = 0; level < newlevel; level++) - { - snode->mForward[level] = mUpdate[level]->mForward[level]; - mUpdate[level]->mForward[level] = snode; - } - return snode->mData; -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getData(const INDEX_T &index) -{ - S32 level; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - - mNumberOfSteps = 0; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - mNumberOfSteps++; - - if ( (current) - &&(mEquals(current->mIndex, index))) - { - - return current->mData; - } - - // now add the new node - S32 newlevel; - for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++) - { - if (ll_frand() < 0.5f) - break; - } - - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *snode - = new LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>(index); - - if (newlevel > mLevel) - { - mHead.mForward[mLevel] = NULL; - mUpdate[mLevel] = &mHead; - mLevel = newlevel; - } - - for (level = 0; level < newlevel; level++) - { - snode->mForward[level] = mUpdate[level]->mForward[level]; - mUpdate[level]->mForward[level] = snode; - } - - return snode->mData; -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getInterval(const INDEX_T &index, - INDEX_T &index_before, - INDEX_T &index_after, - DATA_T &data_before, - DATA_T &data_after) -{ - S32 level; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - - mNumberOfSteps = 0; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - - BOOL both_found = TRUE; - - if (current != &mHead) - { - index_before = current->mIndex; - data_before = current->mData; - } - else - { - data_before = 0; - index_before = 0; - both_found = FALSE; - } - - // we're now just in front of where we want to be . . . take one step forward - mNumberOfSteps++; - current = *current->mForward; - - if (current) - { - data_after = current->mData; - index_after = current->mIndex; - } - else - { - data_after = 0; - index_after = 0; - both_found = FALSE; - } - - return both_found; -} - - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::operator[](const INDEX_T &index) -{ - - return getData(index); -} - -// If index present, returns data. -// If index not present, adds <index,NULL> and returns NULL. -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline DATA_T &LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getData(const INDEX_T &index, BOOL &b_new_entry) -{ - S32 level; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - - mNumberOfSteps = 0; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - mNumberOfSteps++; - current = *current->mForward; - - if ( (current) - &&(mEquals(current->mIndex, index))) - { - - return current->mData; - } - b_new_entry = TRUE; - addData(index); - - return current->mData; -} - -// Returns TRUE if data present in map. -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::checkData(const INDEX_T &index) -{ - S32 level; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - if (current) - { - // Gets rid of some compiler ambiguity for the LLPointer<> templated class. - if (current->mData) - { - return mEquals(current->mIndex, index); - } - } - - return FALSE; -} - -// Returns TRUE if key is present in map. This is useful if you -// are potentially storing NULL pointers in the map -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::checkKey(const INDEX_T &index) -{ - S32 level; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - if (current) - { - return mEquals(current->mIndex, index); - } - - return FALSE; -} - -// If there, returns the data. -// If not, returns NULL. -// Never adds entries to the map. -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getIfThere(const INDEX_T &index) -{ - S32 level; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - - mNumberOfSteps = 0; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - mNumberOfSteps++; - current = *current->mForward; - - if (current) - { - if (mEquals(current->mIndex, index)) - { - return current->mData; - } - } - - // Avoid Linux compiler warning on returning NULL. - return (DATA_T)0; -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::reverseLookup(const DATA_T datap) -{ - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - - while (current) - { - if (datap == current->mData) - { - - return current->mIndex; - } - current = *current->mForward; - } - - // not found! return NULL - return INDEX_T(); -} - -// returns number of items in the list -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline S32 LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getLength() -{ - U32 length = 0; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH>* temp; - for (temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0]) - { - length++; - } - - return length; -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeData(const INDEX_T &index) -{ - S32 level; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - if (!current) - { - // empty list or beyond the end! - - return FALSE; - } - - // is this the one we want? - if (!mEquals(current->mIndex, index)) - { - // nope! - - return FALSE; - } - else - { - // do we need to fix current or currentop? - if (current == mCurrentp) - { - mCurrentp = *current->mForward; - } - - if (current == mCurrentOperatingp) - { - mCurrentOperatingp = *current->mForward; - } - // yes it is! change pointers as required - for (level = 0; level < mLevel; level++) - { - if (*((*(mUpdate + level))->mForward + level) != current) - { - // cool, we've fixed all the pointers! - break; - } - *((*(mUpdate + level))->mForward + level) = *(current->mForward + level); - } - - // clean up cuurent - current->removeData(); - delete current; - - // clean up mHead - while ( (mLevel > 1) - &&(!*(mHead.mForward + mLevel - 1))) - { - mLevel--; - } - } - - return TRUE; -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline BOOL LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteData(const INDEX_T &index) -{ - S32 level; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *current = &mHead; - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - if (!current) - { - // empty list or beyond the end! - - return FALSE; - } - - // is this the one we want? - if (!mEquals(current->mIndex, index)) - { - // nope! - - return FALSE; - } - else - { - // do we need to fix current or currentop? - if (current == mCurrentp) - { - mCurrentp = *current->mForward; - } - - if (current == mCurrentOperatingp) - { - mCurrentOperatingp = *current->mForward; - } - // yes it is! change pointers as required - for (level = 0; level < mLevel; level++) - { - if (*((*(mUpdate + level))->mForward + level) != current) - { - // cool, we've fixed all the pointers! - break; - } - *((*(mUpdate + level))->mForward + level) = *(current->mForward + level); - } - - // clean up cuurent - current->deleteData(); - delete current; - - // clean up mHead - while ( (mLevel > 1) - &&(!*(mHead.mForward + mLevel - 1))) - { - mLevel--; - } - } - - return TRUE; -} - -// remove all nodes from the list but do not delete data -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeAllData() -{ - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - // reset mCurrentp - mCurrentp = *(mHead.mForward); - - while (mCurrentp) - { - temp = mCurrentp->mForward[0]; - mCurrentp->removeData(); - delete mCurrentp; - mCurrentp = temp; - } - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mHead.mForward[i] = NULL; - mUpdate[i] = NULL; - } - - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteAllData() -{ - LLPtrSkipMapNode<INDEX_T, DATA_T, BINARY_DEPTH> *temp; - // reset mCurrentp - mCurrentp = *(mHead.mForward); - - while (mCurrentp) - { - temp = mCurrentp->mForward[0]; - mCurrentp->deleteData(); - delete mCurrentp; - mCurrentp = temp; - } - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mHead.mForward[i] = NULL; - mUpdate[i] = NULL; - } - - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -// place mCurrentp on first node -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::resetList() -{ - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - - -// return the data currently pointed to -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentDataWithoutIncrement() -{ - if (mCurrentOperatingp) - { - return mCurrentOperatingp->mData; - } - else - { - //return NULL; // causes warning - return (DATA_T)0; // equivalent, but no warning - } -} - -// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentData() -{ - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mData; - } - else - { - //return NULL; // causes warning - return (DATA_T)0; // equivalent, but no warning - } -} - -// same as getCurrentData() but a more intuitive name for the operation -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getNextData() -{ - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mData; - } - else - { - //return NULL; // causes compile warning - return (DATA_T)0; // equivalent, but removes warning - } -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getNextKey() -{ - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mIndex; - } - else - { - return mHead.mIndex; - } -} - -// return the key currently pointed to -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getCurrentKeyWithoutIncrement() -{ - if (mCurrentOperatingp) - { - return mCurrentOperatingp->mIndex; - } - else - { - //return NULL; // causes compile warning - return (INDEX_T)0; // equivalent, but removes warning - } -} - - -// remove the Node at mCurentOperatingp -// leave mCurrentp and mCurentOperatingp on the next entry -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::removeCurrentData() -{ - if (mCurrentOperatingp) - { - removeData(mCurrentOperatingp->mIndex); - } -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline void LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::deleteCurrentData() -{ - if (mCurrentOperatingp) - { - deleteData(mCurrentOperatingp->mIndex); - } -} - -// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline DATA_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getFirstData() -{ - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mData; - } - else - { - //return NULL; // causes compile warning - return (DATA_T)0; // equivalent, but removes warning - } -} - -template <class INDEX_T, class DATA_T, S32 BINARY_DEPTH> -inline INDEX_T LLPtrSkipMap<INDEX_T, DATA_T, BINARY_DEPTH>::getFirstKey() -{ - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mIndex; - } - else - { - return mHead.mIndex; - } -} - -#endif diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index abf47a0f57..4339f203db 100755 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -28,6 +28,7 @@ #include "llstl.h" #include "lltimer.h" // ms_sleep() +#include "lltracethreadrecorder.h" //============================================================================ @@ -134,8 +135,8 @@ S32 LLQueuedThread::updateQueue(F32 max_time_ms) pending = getPending(); if(pending > 0) { - unpause(); - } + unpause(); + } } else { @@ -403,6 +404,7 @@ S32 LLQueuedThread::processNextRequest() QueuedRequest *req; // Get next request from pool lockData(); + while(1) { req = NULL; @@ -467,10 +469,11 @@ S32 LLQueuedThread::processNextRequest() ms_sleep(1); // sleep the thread a little } } + + LLTrace::get_thread_recorder()->pushToMaster(); } S32 pending = getPending(); - return pending; } @@ -499,6 +502,7 @@ void LLQueuedThread::run() if (isQuitting()) { + LLTrace::get_thread_recorder()->pushToMaster(); endThread(); break; } @@ -507,8 +511,9 @@ void LLQueuedThread::run() threadedUpdate(); - int res = processNextRequest(); - if (res == 0) + int pending_work = processNextRequest(); + + if (pending_work == 0) { mIdleThread = TRUE; ms_sleep(1); diff --git a/indra/llcommon/llregistry.h b/indra/llcommon/llregistry.h index bb0d60247e..c8ec0a0bc0 100755 --- a/indra/llcommon/llregistry.h +++ b/indra/llcommon/llregistry.h @@ -29,7 +29,6 @@ #include <list> -#include <boost/type_traits.hpp> #include "llsingleton.h" #include "llstl.h" @@ -47,12 +46,11 @@ template <typename KEY, typename VALUE, typename COMPARATOR = LLRegistryDefaultC class LLRegistry { public: - typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t; - typedef typename boost::add_reference<typename boost::add_const<KEY>::type>::type ref_const_key_t; - typedef typename boost::add_reference<typename boost::add_const<VALUE>::type>::type ref_const_value_t; - typedef typename boost::add_reference<VALUE>::type ref_value_t; - typedef typename boost::add_pointer<typename boost::add_const<VALUE>::type>::type ptr_const_value_t; - typedef typename boost::add_pointer<VALUE>::type ptr_value_t; + typedef LLRegistry<KEY, VALUE, COMPARATOR> registry_t; + typedef const KEY& ref_const_key_t; + typedef const VALUE& ref_const_value_t; + typedef const VALUE* ptr_const_value_t; + typedef VALUE* ptr_value_t; class Registrar { diff --git a/indra/llcommon/llsdparam.cpp b/indra/llcommon/llsdparam.cpp index 9f4460a988..50815b2cc6 100755 --- a/indra/llcommon/llsdparam.cpp +++ b/indra/llcommon/llsdparam.cpp @@ -102,13 +102,13 @@ void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool //readSDValues(sd, block); } -void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block) +void LLParamSDParser::writeSDImpl(LLSD& sd, const LLInitParam::BaseBlock& block, const LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block) { mNameStack.clear(); mWriteRootSD = &sd; name_stack_t name_stack; - block.serializeBlock(*this, name_stack); + block.serializeBlock(*this, name_stack, rules, diff_block); } /*virtual*/ std::string LLParamSDParser::getCurrentElementName() @@ -299,6 +299,7 @@ void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd) LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t(); readSDValues(cb, sd, stack); } + namespace LLInitParam { // LLSD specialization @@ -329,13 +330,14 @@ namespace LLInitParam p.writeValue<LLSD::String>(sd.asString(), name_stack); } - void ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const + bool ParamValue<LLSD, NOT_BLOCK>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack_range, const predicate_rule_t predicate_rule, const BaseBlock* diff_block) const { // attempt to write LLSD out directly - if (!p.writeValue<LLSD>(mValue, name_stack)) + if (!p.writeValue<LLSD>(mValue, name_stack_range)) { // otherwise read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc) - LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack); + LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, name_stack_range); } + return true; } } diff --git a/indra/llcommon/llsdparam.h b/indra/llcommon/llsdparam.h index 6ef5debd7b..7cfc265c62 100755 --- a/indra/llcommon/llsdparam.h +++ b/indra/llcommon/llsdparam.h @@ -30,6 +30,7 @@ #include "llinitparam.h" #include "boost/function.hpp" +#include "llfasttimer.h" struct LL_COMMON_API LLParamSDParserUtilities { @@ -50,11 +51,28 @@ typedef LLInitParam::Parser parser_t; public: LLParamSDParser(); void readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent = false); - void writeSD(LLSD& sd, const LLInitParam::BaseBlock& block); + template<typename BLOCK> + void writeSD(LLSD& sd, + const BLOCK& block, + const LLInitParam::predicate_rule_t rules = LLInitParam::default_parse_rules(), + const LLInitParam::BaseBlock* diff_block = NULL) + { + if (!diff_block + && !rules.isAmbivalent(LLInitParam::HAS_DEFAULT_VALUE)) + { + diff_block = &LLInitParam::defaultValue<BLOCK>(); + } + writeSDImpl(sd, block, rules, diff_block); + } /*virtual*/ std::string getCurrentElementName(); private: + void writeSDImpl(LLSD& sd, + const LLInitParam::BaseBlock& block, + const LLInitParam::predicate_rule_t, + const LLInitParam::BaseBlock* diff_block); + void submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack); template<typename T> diff --git a/indra/llcommon/llsingleton.cpp b/indra/llcommon/llsingleton.cpp index eb8e2c9456..9b49e52377 100755 --- a/indra/llcommon/llsingleton.cpp +++ b/indra/llcommon/llsingleton.cpp @@ -28,5 +28,4 @@ #include "llsingleton.h" -std::map<std::string, void *> * LLSingletonRegistry::sSingletonMap = NULL; diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 49d99f2cd0..b9cb8e3d41 100755 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -30,38 +30,6 @@ #include <typeinfo> #include <boost/noncopyable.hpp> -/// @brief A global registry of all singletons to prevent duplicate allocations -/// across shared library boundaries -class LL_COMMON_API LLSingletonRegistry { - private: - typedef std::map<std::string, void *> TypeMap; - static TypeMap * sSingletonMap; - - static void checkInit() - { - if(sSingletonMap == NULL) - { - sSingletonMap = new TypeMap(); - } - } - - public: - template<typename T> static void * & get() - { - std::string name(typeid(T).name()); - - checkInit(); - - // the first entry of the pair returned by insert will be either the existing - // iterator matching our key, or the newly inserted NULL initialized entry - // see "Insert element" in http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html - TypeMap::iterator result = - sSingletonMap->insert(std::make_pair(name, (void*)NULL)).first; - - return result->second; - } -}; - // LLSingleton implements the getInstance() method part of the Singleton // pattern. It can't make the derived class constructors protected, though, so // you have to do that yourself. @@ -99,22 +67,30 @@ private: INITIALIZED, DELETED } EInitState; + + static DERIVED_TYPE* constructSingleton() + { + return new DERIVED_TYPE(); + } // stores pointer to singleton instance - // and tracks initialization state of singleton - struct SingletonInstanceData + struct SingletonLifetimeManager { - EInitState mInitState; - DERIVED_TYPE* mSingletonInstance; - - SingletonInstanceData() - : mSingletonInstance(NULL), - mInitState(UNINITIALIZED) - {} - - ~SingletonInstanceData() + SingletonLifetimeManager() + { + construct(); + } + + static void construct() { - if (mInitState != DELETED) + sData.mInitState = CONSTRUCTING; + sData.mInstance = constructSingleton(); + sData.mInitState = INITIALIZING; + } + + ~SingletonLifetimeManager() + { + if (sData.mInitState != DELETED) { deleteSingleton(); } @@ -124,9 +100,8 @@ private: public: virtual ~LLSingleton() { - SingletonInstanceData& data = getData(); - data.mSingletonInstance = NULL; - data.mInitState = DELETED; + sData.mInstance = NULL; + sData.mInitState = DELETED; } /** @@ -151,50 +126,49 @@ public: */ static void deleteSingleton() { - delete getData().mSingletonInstance; - getData().mSingletonInstance = NULL; - getData().mInitState = DELETED; + delete sData.mInstance; + sData.mInstance = NULL; + sData.mInitState = DELETED; } - static SingletonInstanceData& getData() - { - // this is static to cache the lookup results - static void * & registry = LLSingletonRegistry::get<DERIVED_TYPE>(); - - // *TODO - look into making this threadsafe - if(NULL == registry) - { - static SingletonInstanceData data; - registry = &data; - } - - return *static_cast<SingletonInstanceData *>(registry); - } static DERIVED_TYPE* getInstance() { - SingletonInstanceData& data = getData(); + static SingletonLifetimeManager sLifeTimeMgr; - if (data.mInitState == CONSTRUCTING) + switch (sData.mInitState) { + case UNINITIALIZED: + // should never be uninitialized at this point + llassert(false); + return NULL; + case CONSTRUCTING: llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl; - } - - if (data.mInitState == DELETED) - { + return NULL; + case INITIALIZING: + // go ahead and flag ourselves as initialized so we can be reentrant during initialization + sData.mInitState = INITIALIZED; + // initialize singleton after constructing it so that it can reference other singletons which in turn depend on it, + // thus breaking cyclic dependencies + sData.mInstance->initSingleton(); + return sData.mInstance; + case INITIALIZED: + return sData.mInstance; + case DELETED: llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl; + SingletonLifetimeManager::construct(); + // same as first time construction + sData.mInitState = INITIALIZED; + sData.mInstance->initSingleton(); + return sData.mInstance; } - - if (!data.mSingletonInstance) - { - data.mInitState = CONSTRUCTING; - data.mSingletonInstance = new DERIVED_TYPE(); - data.mInitState = INITIALIZING; - data.mSingletonInstance->initSingleton(); - data.mInitState = INITIALIZED; - } - - return data.mSingletonInstance; + + return NULL; + } + + static DERIVED_TYPE* getIfExists() + { + return sData.mInstance; } // Reference version of getInstance() @@ -208,18 +182,31 @@ public: // Use this to avoid accessing singletons before the can safely be constructed static bool instanceExists() { - return getData().mInitState == INITIALIZED; + return sData.mInitState == INITIALIZED; } // Has this singleton already been deleted? // Use this to avoid accessing singletons from a static object's destructor static bool destroyed() { - return getData().mInitState == DELETED; + return sData.mInitState == DELETED; } private: + virtual void initSingleton() {} + + struct SingletonData + { + // explicitly has a default constructor so that member variables are zero initialized in BSS + // and only changed by singleton logic, not constructor running during startup + EInitState mInitState; + DERIVED_TYPE* mInstance; + }; + static SingletonData sData; }; +template<typename T> +typename LLSingleton<T>::SingletonData LLSingleton<T>::sData; + #endif diff --git a/indra/llcommon/llskiplist.h b/indra/llcommon/llskiplist.h deleted file mode 100755 index ed132381f9..0000000000 --- a/indra/llcommon/llskiplist.h +++ /dev/null @@ -1,517 +0,0 @@ -/** - * @file llskiplist.h - * @brief skip list implementation - * - * $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_LLSKIPLIST_H -#define LL_LLSKIPLIST_H - -#include "llrand.h" -#include "llrand.h" - -// NOTA BENE: Insert first needs to be < NOT <= -// Binary depth must be >= 2 -template <class DATA_TYPE, S32 BINARY_DEPTH = 10> -class LLSkipList -{ -public: - typedef BOOL (*compare)(const DATA_TYPE& first, const DATA_TYPE& second); - typedef compare insert_func; - typedef compare equals_func; - - void init(); - - // basic constructor - LLSkipList(); - - // basic constructor including sorter - LLSkipList(insert_func insert_first, equals_func equals); - ~LLSkipList(); - - inline void setInsertFirst(insert_func insert_first); - inline void setEquals(equals_func equals); - - inline BOOL addData(const DATA_TYPE& data); - inline BOOL checkData(const DATA_TYPE& data); - - // returns number of items in the list - inline S32 getLength() const; // NOT a constant time operation, traverses entire list! - - inline BOOL moveData(const DATA_TYPE& data, LLSkipList *newlist); - - inline BOOL removeData(const DATA_TYPE& data); - - // remove all nodes from the list but do not delete data - inline void removeAllNodes(); - - // place mCurrentp on first node - inline void resetList(); - - // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp - inline DATA_TYPE getCurrentData(); - - // same as getCurrentData() but a more intuitive name for the operation - inline DATA_TYPE getNextData(); - - // remove the Node at mCurentOperatingp - // leave mCurrentp and mCurentOperatingp on the next entry - inline void removeCurrentData(); - - // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp - inline DATA_TYPE getFirstData(); - - class LLSkipNode - { - public: - LLSkipNode() - : mData(0) - { - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mForward[i] = NULL; - } - } - - LLSkipNode(DATA_TYPE data) - : mData(data) - { - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mForward[i] = NULL; - } - } - - ~LLSkipNode() - { - } - - DATA_TYPE mData; - LLSkipNode *mForward[BINARY_DEPTH]; - - private: - // Disallow copying of LLSkipNodes by not implementing these methods. - LLSkipNode(const LLSkipNode &); - LLSkipNode &operator=(const LLSkipNode &); - }; - - static BOOL defaultEquals(const DATA_TYPE& first, const DATA_TYPE& second) - { - return first == second; - } - -private: - LLSkipNode mHead; - LLSkipNode *mUpdate[BINARY_DEPTH]; - LLSkipNode *mCurrentp; - LLSkipNode *mCurrentOperatingp; - S32 mLevel; - insert_func mInsertFirst; - equals_func mEquals; - -private: - // Disallow copying of LLSkipNodes by not implementing these methods. - LLSkipList(const LLSkipList &); - LLSkipList &operator=(const LLSkipList &); -}; - - -/////////////////////// -// -// Implementation -// - - -// Binary depth must be >= 2 -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::init() -{ - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mHead.mForward[i] = NULL; - mUpdate[i] = NULL; - } - mLevel = 1; - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - - -// basic constructor -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::LLSkipList() -: mInsertFirst(NULL), - mEquals(defaultEquals) -{ - init(); -} - -// basic constructor including sorter -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::LLSkipList(insert_func insert, - equals_func equals) -: mInsertFirst(insert), - mEquals(equals) -{ - init(); -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline LLSkipList<DATA_TYPE, BINARY_DEPTH>::~LLSkipList() -{ - removeAllNodes(); -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::setInsertFirst(insert_func insert_first) -{ - mInsertFirst = insert_first; -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::setEquals(equals_func equals) -{ - mEquals = equals; -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::addData(const DATA_TYPE& data) -{ - S32 level; - LLSkipNode *current = &mHead; - LLSkipNode *temp; - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mData, data))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mData < data)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - // now add the new node - S32 newlevel; - for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++) - { - if (ll_frand() < 0.5f) - break; - } - - LLSkipNode *snode = new LLSkipNode(data); - - if (newlevel > mLevel) - { - mHead.mForward[mLevel] = NULL; - mUpdate[mLevel] = &mHead; - mLevel = newlevel; - } - - for (level = 0; level < newlevel; level++) - { - snode->mForward[level] = mUpdate[level]->mForward[level]; - mUpdate[level]->mForward[level] = snode; - } - return TRUE; -} - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::checkData(const DATA_TYPE& data) -{ - S32 level; - LLSkipNode *current = &mHead; - LLSkipNode *temp; - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mData, data))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mData < data)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - - if (current) - { - return mEquals(current->mData, data); - } - - return FALSE; -} - -// returns number of items in the list -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline S32 LLSkipList<DATA_TYPE, BINARY_DEPTH>::getLength() const -{ - U32 length = 0; - for (LLSkipNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0]) - { - length++; - } - return length; -} - - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::moveData(const DATA_TYPE& data, LLSkipList *newlist) -{ - BOOL removed = removeData(data); - BOOL added = newlist->addData(data); - return removed && added; -} - - -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeData(const DATA_TYPE& data) -{ - S32 level; - LLSkipNode *current = &mHead; - LLSkipNode *temp; - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mData, data))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mData < data)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - - if (!current) - { - // empty list or beyond the end! - return FALSE; - } - - // is this the one we want? - if (!mEquals(current->mData, data)) - { - // nope! - return FALSE; - } - else - { - // do we need to fix current or currentop? - if (current == mCurrentp) - { - mCurrentp = current->mForward[0]; - } - - if (current == mCurrentOperatingp) - { - mCurrentOperatingp = current->mForward[0]; - } - // yes it is! change pointers as required - for (level = 0; level < mLevel; level++) - { - if (mUpdate[level]->mForward[level] != current) - { - // cool, we've fixed all the pointers! - break; - } - mUpdate[level]->mForward[level] = current->mForward[level]; - } - - // clean up cuurent - delete current; - - // clean up mHead - while ( (mLevel > 1) - &&(!mHead.mForward[mLevel - 1])) - { - mLevel--; - } - } - return TRUE; -} - -// remove all nodes from the list but do not delete data -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeAllNodes() -{ - LLSkipNode *temp; - // reset mCurrentp - mCurrentp = *(mHead.mForward); - - while (mCurrentp) - { - temp = mCurrentp->mForward[0]; - delete mCurrentp; - mCurrentp = temp; - } - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mHead.mForward[i] = NULL; - mUpdate[i] = NULL; - } - - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -// place mCurrentp on first node -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::resetList() -{ - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getCurrentData() -{ - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mData; - } - else - { - //return NULL; // causes compile warning - return (DATA_TYPE)0; // equivalent, but no warning - } -} - -// same as getCurrentData() but a more intuitive name for the operation -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getNextData() -{ - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mData; - } - else - { - //return NULL; // causes compile warning - return (DATA_TYPE)0; // equivalent, but no warning - } -} - -// remove the Node at mCurentOperatingp -// leave mCurrentp and mCurentOperatingp on the next entry -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipList<DATA_TYPE, BINARY_DEPTH>::removeCurrentData() -{ - if (mCurrentOperatingp) - { - removeData(mCurrentOperatingp->mData); - } -} - -// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp -template <class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE LLSkipList<DATA_TYPE, BINARY_DEPTH>::getFirstData() -{ - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mData; - } - else - { - //return NULL; // causes compile warning - return (DATA_TYPE)0; // equivalent, but no warning - } -} - - -#endif diff --git a/indra/llcommon/llskipmap.h b/indra/llcommon/llskipmap.h deleted file mode 100755 index 49ff2928d1..0000000000 --- a/indra/llcommon/llskipmap.h +++ /dev/null @@ -1,1022 +0,0 @@ -/** - * @file llskipmap.h - * @brief Associative container based on the skiplist algorithm. - * - * $LicenseInfo:firstyear=2003&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_LLSKIPMAP_H -#define LL_LLSKIPMAP_H - -#include "llerror.h" - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH = 8> -class LLSkipMap -{ -public: - // basic constructor - LLSkipMap(); - - // basic constructor including sorter - LLSkipMap(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second), - BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second)); - - ~LLSkipMap(); - - void setInsertFirst(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second)); - void setEquals(BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second)); - - DATA_TYPE &addData(const INDEX_TYPE &index, DATA_TYPE datap); - DATA_TYPE &addData(const INDEX_TYPE &index); - DATA_TYPE &getData(const INDEX_TYPE &index); - DATA_TYPE &operator[](const INDEX_TYPE &index); - - // If index present, returns data. - // If index not present, adds <index,NULL> and returns NULL. - DATA_TYPE &getData(const INDEX_TYPE &index, BOOL &b_new_entry); - - // Returns TRUE if data present in map. - BOOL checkData(const INDEX_TYPE &index); - - // Returns TRUE if key is present in map. This is useful if you - // are potentially storing NULL pointers in the map - BOOL checkKey(const INDEX_TYPE &index); - - // If there, returns the data. - // If not, returns NULL. - // Never adds entries to the map. - DATA_TYPE getIfThere(const INDEX_TYPE &index); - - INDEX_TYPE reverseLookup(const DATA_TYPE datap); - - // returns number of items in the list - S32 getLength(); // WARNING! getLength is O(n), not O(1)! - - BOOL removeData(const INDEX_TYPE &index); - - // remove all nodes from the list but do not delete data - void removeAllData(); - - // place mCurrentp on first node - void resetList(); - - // return the data currently pointed to - DATA_TYPE getCurrentDataWithoutIncrement(); - - // return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp - DATA_TYPE getCurrentData(); - - // same as getCurrentData() but a more intuitive name for the operation - DATA_TYPE getNextData(); - - INDEX_TYPE getNextKey(); - - // return the key currently pointed to - INDEX_TYPE getCurrentKeyWithoutIncrement(); - - // The internal iterator is at the end of the list. - BOOL notDone() const; - - // remove the Node at mCurentOperatingp - // leave mCurrentp and mCurentOperatingp on the next entry - void removeCurrentData(); - - void deleteCurrentData(); - - // reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp - DATA_TYPE getFirstData(); - - INDEX_TYPE getFirstKey(); - - class LLSkipMapNode - { - public: - LLSkipMapNode() - { - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mForward[i] = NULL; - } - - U8 *zero = (U8 *)&mIndex; - - for (i = 0; i < (S32)sizeof(INDEX_TYPE); i++) - { - *(zero + i) = 0; - } - - zero = (U8 *)&mData; - - for (i = 0; i < (S32)sizeof(DATA_TYPE); i++) - { - *(zero + i) = 0; - } - } - - LLSkipMapNode(const INDEX_TYPE &index) - : mIndex(index) - { - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mForward[i] = NULL; - } - - U8 *zero = (U8 *)&mData; - - for (i = 0; i < (S32)sizeof(DATA_TYPE); i++) - { - *(zero + i) = 0; - } - } - - LLSkipMapNode(const INDEX_TYPE &index, DATA_TYPE datap) - : mIndex(index) - { - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mForward[i] = NULL; - } - - mData = datap; - } - - ~LLSkipMapNode() - { - } - - - INDEX_TYPE mIndex; - DATA_TYPE mData; - LLSkipMapNode *mForward[BINARY_DEPTH]; - - private: - // Disallow copying of LLSkipMapNodes by not implementing these methods. - LLSkipMapNode(const LLSkipMapNode &); - LLSkipMapNode &operator=(const LLSkipMapNode &rhs); - }; - - static BOOL defaultEquals(const INDEX_TYPE &first, const INDEX_TYPE &second) - { - return first == second; - } - -private: - // don't generate implicit copy constructor or copy assignment - LLSkipMap(const LLSkipMap &); - LLSkipMap &operator=(const LLSkipMap &); - -private: - LLSkipMapNode mHead; - LLSkipMapNode *mUpdate[BINARY_DEPTH]; - LLSkipMapNode *mCurrentp; - LLSkipMapNode *mCurrentOperatingp; - S32 mLevel; - BOOL (*mInsertFirst)(const INDEX_TYPE &first, const INDEX_TYPE &second); - BOOL (*mEquals)(const INDEX_TYPE &first, const INDEX_TYPE &second); - S32 mNumberOfSteps; -}; - -////////////////////////////////////////////////// -// -// LLSkipMap implementation -// - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::LLSkipMap() - : mInsertFirst(NULL), - mEquals(defaultEquals) -{ - // Skipmaps must have binary depth of at least 2 - cassert(BINARY_DEPTH >= 2); - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mUpdate[i] = NULL; - } - mLevel = 1; - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::LLSkipMap(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second), - BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second)) - : mInsertFirst(insert_first), - mEquals(equals) -{ - // Skipmaps must have binary depth of at least 2 - cassert(BINARY_DEPTH >= 2); - - mLevel = 1; - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mHead.mForward[i] = NULL; - mUpdate[i] = NULL; - } - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::~LLSkipMap() -{ - removeAllData(); -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::setInsertFirst(BOOL (*insert_first)(const INDEX_TYPE &first, const INDEX_TYPE &second)) -{ - mInsertFirst = insert_first; -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::setEquals(BOOL (*equals)(const INDEX_TYPE &first, const INDEX_TYPE &second)) -{ - mEquals = equals; -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::addData(const INDEX_TYPE &index, DATA_TYPE datap) -{ - S32 level; - LLSkipMapNode *current = &mHead; - LLSkipMapNode *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - // replace the existing data if a node is already there - if ( (current) - &&(mEquals(current->mIndex, index))) - { - current->mData = datap; - return current->mData; - } - - // now add the new node - S32 newlevel; - for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++) - { - if (rand() & 1) - { - break; - } - } - - LLSkipMapNode *snode = new LLSkipMapNode(index, datap); - - if (newlevel > mLevel) - { - mHead.mForward[mLevel] = NULL; - mUpdate[mLevel] = &mHead; - mLevel = newlevel; - } - - for (level = 0; level < newlevel; level++) - { - snode->mForward[level] = mUpdate[level]->mForward[level]; - mUpdate[level]->mForward[level] = snode; - } - return snode->mData; -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::addData(const INDEX_TYPE &index) -{ - S32 level; - LLSkipMapNode *current = &mHead; - LLSkipMapNode *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - // now add the new node - S32 newlevel; - for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++) - { - if (rand() & 1) - break; - } - - LLSkipMapNode *snode = new LLSkipMapNode(index); - - if (newlevel > mLevel) - { - mHead.mForward[mLevel] = NULL; - mUpdate[mLevel] = &mHead; - mLevel = newlevel; - } - - for (level = 0; level < newlevel; level++) - { - snode->mForward[level] = mUpdate[level]->mForward[level]; - mUpdate[level]->mForward[level] = snode; - } - return snode->mData; -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getData(const INDEX_TYPE &index) -{ - S32 level; - LLSkipMapNode *current = &mHead; - LLSkipMapNode *temp; - - mNumberOfSteps = 0; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - mNumberOfSteps++; - - if ( (current) - &&(mEquals(current->mIndex, index))) - { - - return current->mData; - } - - // now add the new node - S32 newlevel; - for (newlevel = 1; newlevel <= mLevel && newlevel < BINARY_DEPTH; newlevel++) - { - if (rand() & 1) - break; - } - - LLSkipMapNode *snode = new LLSkipMapNode(index); - - if (newlevel > mLevel) - { - mHead.mForward[mLevel] = NULL; - mUpdate[mLevel] = &mHead; - mLevel = newlevel; - } - - for (level = 0; level < newlevel; level++) - { - snode->mForward[level] = mUpdate[level]->mForward[level]; - mUpdate[level]->mForward[level] = snode; - } - - return snode->mData; -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::operator[](const INDEX_TYPE &index) -{ - - return getData(index); -} - -// If index present, returns data. -// If index not present, adds <index,NULL> and returns NULL. -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE &LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getData(const INDEX_TYPE &index, BOOL &b_new_entry) -{ - S32 level; - LLSkipMapNode *current = &mHead; - LLSkipMapNode *temp; - - mNumberOfSteps = 0; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - mNumberOfSteps++; - current = *current->mForward; - - if ( (current) - &&(mEquals(current->mIndex, index))) - { - - return current->mData; - } - b_new_entry = TRUE; - addData(index); - - return current->mData; -} - -// Returns TRUE if data present in map. -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::checkData(const INDEX_TYPE &index) -{ - S32 level; - LLSkipMapNode *current = &mHead; - LLSkipMapNode *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - if (current) - { - // Gets rid of some compiler ambiguity for the LLPointer<> templated class. - if (current->mData) - { - return mEquals(current->mIndex, index); - } - } - - return FALSE; -} - -// Returns TRUE if key is present in map. This is useful if you -// are potentially storing NULL pointers in the map -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::checkKey(const INDEX_TYPE &index) -{ - S32 level; - LLSkipMapNode *current = &mHead; - LLSkipMapNode *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - if (current) - { - return mEquals(current->mIndex, index); - } - - return FALSE; -} - -// If there, returns the data. -// If not, returns NULL. -// Never adds entries to the map. -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getIfThere(const INDEX_TYPE &index) -{ - S32 level; - LLSkipMapNode *current = &mHead; - LLSkipMapNode *temp; - - mNumberOfSteps = 0; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - mNumberOfSteps++; - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - mNumberOfSteps++; - current = *current->mForward; - - if (current) - { - if (mEquals(current->mIndex, index)) - { - return current->mData; - } - } - - // Avoid Linux compiler warning on returning NULL. - return DATA_TYPE(); -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::reverseLookup(const DATA_TYPE datap) -{ - LLSkipMapNode *current = &mHead; - - while (current) - { - if (datap == current->mData) - { - - return current->mIndex; - } - current = *current->mForward; - } - - // not found! return NULL - return INDEX_TYPE(); -} - -// returns number of items in the list -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline S32 LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getLength() -{ - U32 length = 0; - for (LLSkipMapNode* temp = *(mHead.mForward); temp != NULL; temp = temp->mForward[0]) - { - length++; - } - - return length; -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeData(const INDEX_TYPE &index) -{ - S32 level; - LLSkipMapNode *current = &mHead; - LLSkipMapNode *temp; - - // find the pointer one in front of the one we want - if (mInsertFirst) - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(mInsertFirst(temp->mIndex, index))) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - else - { - for (level = mLevel - 1; level >= 0; level--) - { - temp = *(current->mForward + level); - while ( (temp) - &&(temp->mIndex < index)) - { - current = temp; - temp = *(current->mForward + level); - } - *(mUpdate + level) = current; - } - } - - // we're now just in front of where we want to be . . . take one step forward - current = *current->mForward; - - if (!current) - { - // empty list or beyond the end! - - return FALSE; - } - - // is this the one we want? - if (!mEquals(current->mIndex, index)) - { - // nope! - - return FALSE; - } - else - { - // do we need to fix current or currentop? - if (current == mCurrentp) - { - mCurrentp = *current->mForward; - } - - if (current == mCurrentOperatingp) - { - mCurrentOperatingp = *current->mForward; - } - // yes it is! change pointers as required - for (level = 0; level < mLevel; level++) - { - if (*((*(mUpdate + level))->mForward + level) != current) - { - // cool, we've fixed all the pointers! - break; - } - *((*(mUpdate + level))->mForward + level) = *(current->mForward + level); - } - - delete current; - - // clean up mHead - while ( (mLevel > 1) - &&(!*(mHead.mForward + mLevel - 1))) - { - mLevel--; - } - } - - return TRUE; -} - - -// remove all nodes from the list but do not delete data -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeAllData() -{ - LLSkipMapNode *temp; - // reset mCurrentp - mCurrentp = *(mHead.mForward); - - while (mCurrentp) - { - temp = mCurrentp->mForward[0]; - delete mCurrentp; - mCurrentp = temp; - } - - S32 i; - for (i = 0; i < BINARY_DEPTH; i++) - { - mHead.mForward[i] = NULL; - mUpdate[i] = NULL; - } - - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - - -// place mCurrentp on first node -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::resetList() -{ - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); -} - - -// return the data currently pointed to -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentDataWithoutIncrement() -{ - if (mCurrentOperatingp) - { - return mCurrentOperatingp->mData; - } - else - { - return DATA_TYPE(); - } -} - -// return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentData() -{ - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mData; - } - else - { - // Basic types, like int, have default constructors that initialize - // them to zero. g++ 2.95 supports this. "int()" is zero. - // This also is nice for LLUUID() - return DATA_TYPE(); - } -} - -// same as getCurrentData() but a more intuitive name for the operation -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getNextData() -{ - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mData; - } - else - { - // Basic types, like int, have default constructors that initialize - // them to zero. g++ 2.95 supports this. "int()" is zero. - // This also is nice for LLUUID() - return DATA_TYPE(); - } -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getNextKey() -{ - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mIndex; - } - else - { - return mHead.mIndex; - } -} - -// return the key currently pointed to -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getCurrentKeyWithoutIncrement() -{ - if (mCurrentOperatingp) - { - return mCurrentOperatingp->mIndex; - } - else - { - // See comment for getNextData() - return INDEX_TYPE(); - } -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline BOOL LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::notDone() const -{ - if (mCurrentOperatingp) - { - return TRUE; - } - else - { - return FALSE; - } -} - - -// remove the Node at mCurentOperatingp -// leave mCurrentp and mCurentOperatingp on the next entry -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::removeCurrentData() -{ - if (mCurrentOperatingp) - { - removeData(mCurrentOperatingp->mIndex); - } -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline void LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::deleteCurrentData() -{ - if (mCurrentOperatingp) - { - deleteData(mCurrentOperatingp->mIndex); - } -} - -// reset the list and return the data currently pointed to, set mCurentOperatingp to that node and bump mCurrentp -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline DATA_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getFirstData() -{ - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mData; - } - else - { - // See comment for getNextData() - return DATA_TYPE(); - } -} - -template <class INDEX_TYPE, class DATA_TYPE, S32 BINARY_DEPTH> -inline INDEX_TYPE LLSkipMap<INDEX_TYPE, DATA_TYPE, BINARY_DEPTH>::getFirstKey() -{ - mCurrentp = *(mHead.mForward); - mCurrentOperatingp = *(mHead.mForward); - if (mCurrentp) - { - mCurrentOperatingp = mCurrentp; - mCurrentp = mCurrentp->mForward[0]; - return mCurrentOperatingp->mIndex; - } - else - { - return mHead.mIndex; - } -} - -#endif diff --git a/indra/llcommon/llsortedvector.h b/indra/llcommon/llsortedvector.h deleted file mode 100755 index 391b82ee44..0000000000 --- a/indra/llcommon/llsortedvector.h +++ /dev/null @@ -1,152 +0,0 @@ -/** - * @file llsortedvector.h - * @author Nat Goodspeed - * @date 2012-04-08 - * @brief LLSortedVector class wraps a vector that we maintain in sorted - * order so we can perform binary-search lookups. - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Copyright (c) 2012, Linden Research, Inc. - * $/LicenseInfo$ - */ - -#if ! defined(LL_LLSORTEDVECTOR_H) -#define LL_LLSORTEDVECTOR_H - -#include <vector> -#include <algorithm> - -/** - * LLSortedVector contains a std::vector<std::pair> that we keep sorted on the - * first of the pair. This makes insertion somewhat more expensive than simple - * std::vector::push_back(), but allows us to use binary search for lookups. - * It's intended for small aggregates where lookup is far more performance- - * critical than insertion; in such cases a binary search on a small, sorted - * std::vector can be more performant than a std::map lookup. - */ -template <typename KEY, typename VALUE> -class LLSortedVector -{ -public: - typedef LLSortedVector<KEY, VALUE> self; - typedef KEY key_type; - typedef VALUE mapped_type; - typedef std::pair<key_type, mapped_type> value_type; - typedef std::vector<value_type> PairVector; - typedef typename PairVector::iterator iterator; - typedef typename PairVector::const_iterator const_iterator; - - /// Empty - LLSortedVector() {} - - /// Fixed initial size - LLSortedVector(std::size_t size): - mVector(size) - {} - - /// Bulk load - template <typename ITER> - LLSortedVector(ITER begin, ITER end): - mVector(begin, end) - { - // Allow caller to dump in a bunch of (pairs convertible to) - // value_type if desired, but make sure we sort afterwards. - std::sort(mVector.begin(), mVector.end()); - } - - /// insert(key, value) - std::pair<iterator, bool> insert(const key_type& key, const mapped_type& value) - { - return insert(value_type(key, value)); - } - - /// insert(value_type) - std::pair<iterator, bool> insert(const value_type& pair) - { - typedef std::pair<iterator, bool> iterbool; - iterator found = std::lower_bound(mVector.begin(), mVector.end(), pair, - less<value_type>()); - // have to check for end() before it's even valid to dereference - if (found == mVector.end()) - { - std::size_t index(mVector.size()); - mVector.push_back(pair); - // don't forget that push_back() invalidates 'found' - return iterbool(mVector.begin() + index, true); - } - if (found->first == pair.first) - { - return iterbool(found, false); - } - // remember that insert() invalidates 'found' -- save index - std::size_t index(found - mVector.begin()); - mVector.insert(found, pair); - // okay, convert from index back to iterator - return iterbool(mVector.begin() + index, true); - } - - iterator begin() { return mVector.begin(); } - iterator end() { return mVector.end(); } - const_iterator begin() const { return mVector.begin(); } - const_iterator end() const { return mVector.end(); } - - bool empty() const { return mVector.empty(); } - std::size_t size() const { return mVector.size(); } - - /// find - iterator find(const key_type& key) - { - iterator found = std::lower_bound(mVector.begin(), mVector.end(), - value_type(key, mapped_type()), - less<value_type>()); - if (found == mVector.end() || found->first != key) - return mVector.end(); - return found; - } - - const_iterator find(const key_type& key) const - { - return const_cast<self*>(this)->find(key); - } - -private: - // Define our own 'less' comparator so we can specialize without messing - // with std::less. - template <typename T> - struct less: public std::less<T> {}; - - // Specialize 'less' for an LLSortedVector::value_type involving - // std::type_info*. This is one of LLSortedVector's foremost use cases. We - // specialize 'less' rather than just defining a specific comparator - // because LLSortedVector should be usable for other key_types as well. - template <typename T> - struct less< std::pair<std::type_info*, T> >: - public std::binary_function<std::pair<std::type_info*, T>, - std::pair<std::type_info*, T>, - bool> - { - bool operator()(const std::pair<std::type_info*, T>& lhs, - const std::pair<std::type_info*, T>& rhs) const - { - return lhs.first->before(*rhs.first); - } - }; - - // Same as above, but with const std::type_info*. - template <typename T> - struct less< std::pair<const std::type_info*, T> >: - public std::binary_function<std::pair<const std::type_info*, T>, - std::pair<const std::type_info*, T>, - bool> - { - bool operator()(const std::pair<const std::type_info*, T>& lhs, - const std::pair<const std::type_info*, T>& rhs) const - { - return lhs.first->before(*rhs.first); - } - }; - - PairVector mVector; -}; - -#endif /* ! defined(LL_LLSORTEDVECTOR_H) */ diff --git a/indra/llcommon/llstack.h b/indra/llcommon/llstack.h deleted file mode 100755 index 315de6ba2d..0000000000 --- a/indra/llcommon/llstack.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @file llstack.h - * @brief LLStack template class - * - * $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_LLSTACK_H -#define LL_LLSTACK_H - -#include "linked_lists.h" - -template <class DATA_TYPE> class LLStack -{ -private: - LLLinkedList<DATA_TYPE> mStack; - -public: - LLStack() {} - ~LLStack() {} - - void push(DATA_TYPE *data) { mStack.addData(data); } - DATA_TYPE *pop() { DATA_TYPE *tempp = mStack.getFirstData(); mStack.removeCurrentData(); return tempp; } - void deleteAllData() { mStack.deleteAllData(); } - void removeAllNodes() { mStack.removeAllNodes(); } -}; - -#endif - diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp index ccd7ef91c2..e0e9056380 100755 --- a/indra/llcommon/llstacktrace.cpp +++ b/indra/llcommon/llstacktrace.cpp @@ -32,7 +32,7 @@ #include <iostream> #include <sstream> -#include "windows.h" +#include "llwin32headerslean.h" #include "Dbghelp.h" typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp deleted file mode 100755 index 3678c8e1c1..0000000000 --- a/indra/llcommon/llstat.cpp +++ /dev/null @@ -1,404 +0,0 @@ -/** - * @file llstat.cpp - * - * $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 "linden_common.h" - -#include "llstat.h" -#include "lllivefile.h" -#include "llerrorcontrol.h" -#include "llframetimer.h" -#include "timing.h" -#include "llsd.h" -#include "llsdserialize.h" -#include "llstl.h" -#include "u64.h" - - -// statics -//------------------------------------------------------------------------ -LLTimer LLStat::sTimer; -LLFrameTimer LLStat::sFrameTimer; - -void LLStat::reset() -{ - mNumValues = 0; - mLastValue = 0.f; - delete[] mBins; - mBins = new ValueEntry[mNumBins]; - mCurBin = mNumBins-1; - mNextBin = 0; -} - -LLStat::LLStat(std::string name, S32 num_bins, BOOL use_frame_timer) -: mUseFrameTimer(use_frame_timer), - mNumBins(num_bins), - mName(name), - mBins(NULL) -{ - llassert(mNumBins > 0); - mLastTime = 0.f; - - reset(); - - if (!mName.empty()) - { - stat_map_t::iterator iter = getStatList().find(mName); - if (iter != getStatList().end()) - llwarns << "LLStat with duplicate name: " << mName << llendl; - getStatList().insert(std::make_pair(mName, this)); - } -} - -LLStat::stat_map_t& LLStat::getStatList() -{ - static LLStat::stat_map_t stat_list; - return stat_list; -} - - -LLStat::~LLStat() -{ - delete[] mBins; - - if (!mName.empty()) - { - // handle multiple entries with the same name - stat_map_t::iterator iter = getStatList().find(mName); - while (iter != getStatList().end() && iter->second != this) - ++iter; - getStatList().erase(iter); - } -} - -void LLStat::start() -{ - if (mUseFrameTimer) - { - mBins[mNextBin].mBeginTime = sFrameTimer.getElapsedSeconds(); - } - else - { - mBins[mNextBin].mBeginTime = sTimer.getElapsedTimeF64(); - } -} - -void LLStat::addValue(const F32 value) -{ - if (mNumValues < mNumBins) - { - mNumValues++; - } - - // Increment the bin counters. - mCurBin++; - if (mCurBin >= mNumBins) - { - mCurBin = 0; - } - mNextBin++; - if (mNextBin >= mNumBins) - { - mNextBin = 0; - } - - mBins[mCurBin].mValue = value; - if (mUseFrameTimer) - { - mBins[mCurBin].mTime = sFrameTimer.getElapsedSeconds(); - } - else - { - mBins[mCurBin].mTime = sTimer.getElapsedTimeF64(); - } - mBins[mCurBin].mDT = (F32)(mBins[mCurBin].mTime - mBins[mCurBin].mBeginTime); - - //this value is used to prime the min/max calls - mLastTime = mBins[mCurBin].mTime; - mLastValue = value; - - // Set the begin time for the next stat segment. - mBins[mNextBin].mBeginTime = mBins[mCurBin].mTime; - mBins[mNextBin].mTime = mBins[mCurBin].mTime; - mBins[mNextBin].mDT = 0.f; -} - - -F32 LLStat::getMax() const -{ - S32 i; - F32 current_max = mLastValue; - if (mNumBins == 0) - { - current_max = 0.f; - } - else - { - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) - { - // Skip the bin we're currently filling. - if (i == mNextBin) - { - continue; - } - if (mBins[i].mValue > current_max) - { - current_max = mBins[i].mValue; - } - } - } - return current_max; -} - -F32 LLStat::getMean() const -{ - S32 i; - F32 current_mean = 0.f; - S32 samples = 0; - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) - { - // Skip the bin we're currently filling. - if (i == mNextBin) - { - continue; - } - current_mean += mBins[i].mValue; - samples++; - } - - // There will be a wrap error at 2^32. :) - if (samples != 0) - { - current_mean /= samples; - } - else - { - current_mean = 0.f; - } - return current_mean; -} - -F32 LLStat::getMin() const -{ - S32 i; - F32 current_min = mLastValue; - - if (mNumBins == 0) - { - current_min = 0.f; - } - else - { - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) - { - // Skip the bin we're currently filling. - if (i == mNextBin) - { - continue; - } - if (mBins[i].mValue < current_min) - { - current_min = mBins[i].mValue; - } - } - } - return current_min; -} - -F32 LLStat::getPrev(S32 age) const -{ - S32 bin; - bin = mCurBin - age; - - while (bin < 0) - { - bin += mNumBins; - } - - if (bin == mNextBin) - { - // Bogus for bin we're currently working on. - return 0.f; - } - return mBins[bin].mValue; -} - -F32 LLStat::getPrevPerSec(S32 age) const -{ - S32 bin; - bin = mCurBin - age; - - while (bin < 0) - { - bin += mNumBins; - } - - if (bin == mNextBin) - { - // Bogus for bin we're currently working on. - return 0.f; - } - return mBins[bin].mValue / mBins[bin].mDT; -} - -F32 LLStat::getCurrent() const -{ - return mBins[mCurBin].mValue; -} - -F32 LLStat::getCurrentPerSec() const -{ - return mBins[mCurBin].mValue / mBins[mCurBin].mDT; -} - -F32 LLStat::getMeanPerSec() const -{ - S32 i; - F32 value = 0.f; - F32 dt = 0.f; - - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) - { - // Skip the bin we're currently filling. - if (i == mNextBin) - { - continue; - } - value += mBins[i].mValue; - dt += mBins[i].mDT; - } - - if (dt > 0.f) - { - return value/dt; - } - else - { - return 0.f; - } -} - -F32 LLStat::getMeanDuration() const -{ - F32 dur = 0.0f; - S32 count = 0; - for (S32 i=0; (i < mNumBins) && (i < mNumValues); i++) - { - if (i == mNextBin) - { - continue; - } - dur += mBins[i].mDT; - count++; - } - - if (count > 0) - { - dur /= F32(count); - return dur; - } - else - { - return 0.f; - } -} - -F32 LLStat::getMaxPerSec() const -{ - F32 value; - - if (mNextBin != 0) - { - value = mBins[0].mValue/mBins[0].mDT; - } - else if (mNumValues > 0) - { - value = mBins[1].mValue/mBins[1].mDT; - } - else - { - value = 0.f; - } - - for (S32 i = 0; (i < mNumBins) && (i < mNumValues); i++) - { - // Skip the bin we're currently filling. - if (i == mNextBin) - { - continue; - } - value = llmax(value, mBins[i].mValue/mBins[i].mDT); - } - return value; -} - -F32 LLStat::getMinPerSec() const -{ - S32 i; - F32 value; - - if (mNextBin != 0) - { - value = mBins[0].mValue/mBins[0].mDT; - } - else if (mNumValues > 0) - { - value = mBins[1].mValue/mBins[0].mDT; - } - else - { - value = 0.f; - } - - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) - { - // Skip the bin we're currently filling. - if (i == mNextBin) - { - continue; - } - value = llmin(value, mBins[i].mValue/mBins[i].mDT); - } - return value; -} - -U32 LLStat::getNumValues() const -{ - return mNumValues; -} - -S32 LLStat::getNumBins() const -{ - return mNumBins; -} - -S32 LLStat::getNextBin() const -{ - return mNextBin; -} - -F64 LLStat::getLastTime() const -{ - return mLastTime; -} diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h deleted file mode 100755 index 38377a010b..0000000000 --- a/indra/llcommon/llstat.h +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @file llstat.h - * @brief Runtime statistics accumulation. - * - * $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_LLSTAT_H -#define LL_LLSTAT_H - -#include <map> - -#include "lltimer.h" -#include "llframetimer.h" - -class LLSD; - -// ---------------------------------------------------------------------------- -class LL_COMMON_API LLStat -{ -private: - typedef std::multimap<std::string, LLStat*> stat_map_t; - - static stat_map_t& getStatList(); - -public: - LLStat(std::string name = std::string(), S32 num_bins = 32, BOOL use_frame_timer = FALSE); - ~LLStat(); - - void start(); // Start the timer for the current "frame", otherwise uses the time tracked from - // the last addValue - void reset(); - void addValue(const F32 value = 1.f); // Adds the current value being tracked, and tracks the DT. - void addValue(const S32 value) { addValue((F32)value); } - void addValue(const U32 value) { addValue((F32)value); } - - S32 getNextBin() const; - - F32 getPrev(S32 age) const; // Age is how many "addValues" previously - zero is current - F32 getPrevPerSec(S32 age) const; // Age is how many "addValues" previously - zero is current - F32 getCurrent() const; - F32 getCurrentPerSec() const; - - F32 getMin() const; - F32 getMinPerSec() const; - F32 getMean() const; - F32 getMeanPerSec() const; - F32 getMeanDuration() const; - F32 getMax() const; - F32 getMaxPerSec() const; - - U32 getNumValues() const; - S32 getNumBins() const; - - F64 getLastTime() const; -private: - BOOL mUseFrameTimer; - U32 mNumValues; - U32 mNumBins; - F32 mLastValue; - F64 mLastTime; - - struct ValueEntry - { - ValueEntry() - : mValue(0.f), - mBeginTime(0.0), - mTime(0.0), - mDT(0.f) - {} - F32 mValue; - F64 mBeginTime; - F64 mTime; - F32 mDT; - }; - ValueEntry* mBins; - S32 mCurBin; - S32 mNextBin; - - std::string mName; - - static LLTimer sTimer; - static LLFrameTimer sFrameTimer; - -public: - static LLStat* getStat(const std::string& name) - { - // return the first stat that matches 'name' - stat_map_t::iterator iter = getStatList().find(name); - if (iter != getStatList().end()) - return iter->second; - else - return NULL; - } -}; - -#endif // LL_STAT_ diff --git a/indra/llcommon/llstatenums.h b/indra/llcommon/llstatenums.h index 81c4085d16..ab9b6709e8 100755 --- a/indra/llcommon/llstatenums.h +++ b/indra/llcommon/llstatenums.h @@ -26,7 +26,7 @@ #ifndef LL_LLSTATENUMS_H #define LL_LLSTATENUMS_H -enum +enum ESimStatID { LL_SIM_STAT_TIME_DILATION = 0, LL_SIM_STAT_FPS = 1, diff --git a/indra/llcommon/llstl.h b/indra/llcommon/llstl.h index d3941e1bc9..424138dad1 100755 --- a/indra/llcommon/llstl.h +++ b/indra/llcommon/llstl.h @@ -31,6 +31,7 @@ #include <algorithm> #include <map> #include <vector> +#include <list> #include <set> #include <deque> #include <typeinfo> diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 22c8681983..66c416bfdd 100755 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -28,11 +28,10 @@ #include "llstring.h" #include "llerror.h" +#include "llfasttimer.h" #if LL_WINDOWS -#define WIN32_LEAN_AND_MEAN -#include <winsock2.h> -#include <windows.h> +#include "llwin32headerslean.h" #include <winnls.h> // for WideCharToMultiByte #endif diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index f9702868c8..17893c1910 100755 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -31,8 +31,9 @@ #include <cstdio> #include <locale> #include <iomanip> +#include <algorithm> #include "llsd.h" -#include "llfasttimer.h" +#include "llformat.h" #if LL_LINUX || LL_SOLARIS #include <wctype.h> diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 57a6de9060..95bbcbc816 100755 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -42,6 +42,7 @@ #include "llprocessor.h" #include "llerrorcontrol.h" #include "llevents.h" +#include "llformat.h" #include "lltimer.h" #include "llsdserialize.h" #include "llsdutil.h" @@ -58,9 +59,7 @@ using namespace llsd; #if LL_WINDOWS -# define WIN32_LEAN_AND_MEAN -# include <winsock2.h> -# include <windows.h> +# include "llwin32headerslean.h" # include <psapi.h> // GetPerformanceInfo() et al. #elif LL_DARWIN # include <errno.h> diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp index 1d56a52c32..118568d5ef 100755 --- a/indra/llcommon/llthread.cpp +++ b/indra/llcommon/llthread.cpp @@ -29,8 +29,11 @@ #include "apr_portable.h" #include "llthread.h" +#include "llmutex.h" #include "lltimer.h" +#include "lltrace.h" +#include "lltracethreadrecorder.h" #if LL_LINUX || LL_SOLARIS #include <sched.h> @@ -56,12 +59,17 @@ // //---------------------------------------------------------------------------- -#if !LL_DARWIN -U32 ll_thread_local sThreadID = 0; +#if LL_DARWIN +// statically allocated thread local storage not supported in Darwin executable formats +#elif LL_WINDOWS +U32 __declspec(thread) sThreadID = 0; +#elif LL_LINUX +U32 __thread sThreadID = 0; #endif U32 LLThread::sIDIter = 0; + LL_COMMON_API void assert_main_thread() { static U32 s_thread_id = LLThread::currentID(); @@ -85,6 +93,8 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap { LLThread *threadp = (LLThread *)datap; + LLTrace::ThreadRecorder* thread_recorder = new LLTrace::SlaveThreadRecorder(LLTrace::getUIThreadRecorder()); + #if !LL_DARWIN sThreadID = threadp->mID; #endif @@ -97,16 +107,18 @@ void *APR_THREAD_FUNC LLThread::staticRun(apr_thread_t *apr_threadp, void *datap // We're done with the run function, this thread is done executing now. threadp->mStatus = STOPPED; + delete thread_recorder; + return NULL; } - LLThread::LLThread(const std::string& name, apr_pool_t *poolp) : mPaused(FALSE), mName(name), mAPRThreadp(NULL), mStatus(STOPPED) { + mID = ++sIDIter; // Thread creation probably CAN be paranoid about APR being initialized, if necessary @@ -152,7 +164,7 @@ void LLThread::shutdown() //llinfos << "LLThread::~LLThread() Killing thread " << mName << " Status: " << mStatus << llendl; // Now wait a bit for the thread to exit // It's unclear whether I should even bother doing this - this destructor - // should netver get called unless we're already stopped, really... + // should never get called unless we're already stopped, really... S32 counter = 0; const S32 MAX_WAIT = 600; while (counter < MAX_WAIT) @@ -282,7 +294,13 @@ void LLThread::setQuitting() // static U32 LLThread::currentID() { +#if LL_DARWIN + // statically allocated thread local storage not supported in Darwin executable formats return (U32)apr_os_thread_current(); +#else + return sThreadID; +#endif + } // static @@ -315,155 +333,6 @@ void LLThread::wakeLocked() //============================================================================ -LLMutex::LLMutex(apr_pool_t *poolp) : - mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD) -{ - //if (poolp) - //{ - // mIsLocalPool = FALSE; - // mAPRPoolp = poolp; - //} - //else - { - mIsLocalPool = TRUE; - apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread - } - apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp); -} - - -LLMutex::~LLMutex() -{ -#if MUTEX_DEBUG - //bad assertion, the subclass LLSignal might be "locked", and that's OK - //llassert_always(!isLocked()); // better not be locked! -#endif - apr_thread_mutex_destroy(mAPRMutexp); - mAPRMutexp = NULL; - if (mIsLocalPool) - { - apr_pool_destroy(mAPRPoolp); - } -} - - -void LLMutex::lock() -{ - if(isSelfLocked()) - { //redundant lock - mCount++; - return; - } - - apr_thread_mutex_lock(mAPRMutexp); - -#if MUTEX_DEBUG - // Have to have the lock before we can access the debug info - U32 id = LLThread::currentID(); - if (mIsLocked[id] != FALSE) - llerrs << "Already locked in Thread: " << id << llendl; - mIsLocked[id] = TRUE; -#endif - -#if LL_DARWIN - mLockingThread = LLThread::currentID(); -#else - mLockingThread = sThreadID; -#endif -} - -void LLMutex::unlock() -{ - if (mCount > 0) - { //not the root unlock - mCount--; - return; - } - -#if MUTEX_DEBUG - // Access the debug info while we have the lock - U32 id = LLThread::currentID(); - if (mIsLocked[id] != TRUE) - llerrs << "Not locked in Thread: " << id << llendl; - mIsLocked[id] = FALSE; -#endif - - mLockingThread = NO_THREAD; - apr_thread_mutex_unlock(mAPRMutexp); -} - -bool LLMutex::isLocked() -{ - apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp); - if (APR_STATUS_IS_EBUSY(status)) - { - return true; - } - else - { - apr_thread_mutex_unlock(mAPRMutexp); - return false; - } -} - -bool LLMutex::isSelfLocked() -{ -#if LL_DARWIN - return mLockingThread == LLThread::currentID(); -#else - return mLockingThread == sThreadID; -#endif -} - -U32 LLMutex::lockingThread() const -{ - return mLockingThread; -} - -//============================================================================ - -LLCondition::LLCondition(apr_pool_t *poolp) : - LLMutex(poolp) -{ - // base class (LLMutex) has already ensured that mAPRPoolp is set up. - - apr_thread_cond_create(&mAPRCondp, mAPRPoolp); -} - - -LLCondition::~LLCondition() -{ - apr_thread_cond_destroy(mAPRCondp); - mAPRCondp = NULL; -} - - -void LLCondition::wait() -{ - if (!isLocked()) - { //mAPRMutexp MUST be locked before calling apr_thread_cond_wait - apr_thread_mutex_lock(mAPRMutexp); -#if MUTEX_DEBUG - // avoid asserts on destruction in non-release builds - U32 id = LLThread::currentID(); - mIsLocked[id] = TRUE; -#endif - } - apr_thread_cond_wait(mAPRCondp, mAPRMutexp); -} - -void LLCondition::signal() -{ - apr_thread_cond_signal(mAPRCondp); -} - -void LLCondition::broadcast() -{ - apr_thread_cond_broadcast(mAPRCondp); -} - -//============================================================================ - //---------------------------------------------------------------------------- //static @@ -514,7 +383,6 @@ LLThreadSafeRefCount::~LLThreadSafeRefCount() } } - //============================================================================ LLResponder::~LLResponder() diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index 0fb89c5613..4a84a14a65 100755 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -31,20 +31,14 @@ #include "llapr.h" #include "apr_thread_cond.h" #include "boost/intrusive_ptr.hpp" +#include "llmutex.h" -class LLThread; -class LLMutex; -class LLCondition; - -#if LL_WINDOWS -#define ll_thread_local __declspec(thread) -#else -#define ll_thread_local __thread -#endif +LL_COMMON_API void assert_main_thread(); class LL_COMMON_API LLThread { private: + friend class LLMutex; static U32 sIDIter; public: @@ -98,15 +92,15 @@ private: BOOL mPaused; // static function passed to APR thread creation routine - static void *APR_THREAD_FUNC staticRun(apr_thread_t *apr_threadp, void *datap); + static void *APR_THREAD_FUNC staticRun(struct apr_thread_t *apr_threadp, void *datap); protected: std::string mName; - LLCondition* mRunCondition; + class LLCondition* mRunCondition; LLMutex* mDataLock; - apr_thread_t *mAPRThreadp; - apr_pool_t *mAPRPoolp; + apr_thread_t* mAPRThreadp; + apr_pool_t* mAPRPoolp; BOOL mIsLocalPool; EThreadStatus mStatus; U32 mID; @@ -114,7 +108,7 @@ protected: //a local apr_pool for APRFile operations in this thread. If it exists, LLAPRFile::sAPRFilePoolp should not be used. //Note: this pool is used by APRFile ONLY, do NOT use it for any other purposes. // otherwise it will cause severe memory leaking!!! --bao - LLVolatileAPRPool *mLocalAPRFilePoolp ; + LLVolatileAPRPool* mLocalAPRFilePoolp ; void setQuitting(); @@ -140,75 +134,6 @@ protected: // mDataLock->unlock(); }; -//============================================================================ - -#define MUTEX_DEBUG (LL_DEBUG || LL_RELEASE_WITH_DEBUG_INFO) - -class LL_COMMON_API LLMutex -{ -public: - typedef enum - { - NO_THREAD = 0xFFFFFFFF - } e_locking_thread; - - LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex - virtual ~LLMutex(); - - void lock(); // blocks - void unlock(); - bool isLocked(); // non-blocking, but does do a lock/unlock so not free - bool isSelfLocked(); //return true if locked in a same thread - U32 lockingThread() const; //get ID of locking thread - -protected: - apr_thread_mutex_t *mAPRMutexp; - mutable U32 mCount; - mutable U32 mLockingThread; - - apr_pool_t *mAPRPoolp; - BOOL mIsLocalPool; - -#if MUTEX_DEBUG - std::map<U32, BOOL> mIsLocked; -#endif -}; - -// Actually a condition/mutex pair (since each condition needs to be associated with a mutex). -class LL_COMMON_API LLCondition : public LLMutex -{ -public: - LLCondition(apr_pool_t *apr_poolp); // Defaults to global pool, could use the thread pool as well. - ~LLCondition(); - - void wait(); // blocks - void signal(); - void broadcast(); - -protected: - apr_thread_cond_t *mAPRCondp; -}; - -class LLMutexLock -{ -public: - LLMutexLock(LLMutex* mutex) - { - mMutex = mutex; - - if(mMutex) - mMutex->lock(); - } - ~LLMutexLock() - { - if(mMutex) - mMutex->unlock(); - } -private: - LLMutex* mMutex; -}; - -//============================================================================ void LLThread::lockData() { diff --git a/indra/llcommon/llthreadlocalstorage.cpp b/indra/llcommon/llthreadlocalstorage.cpp new file mode 100644 index 0000000000..32d94331a6 --- /dev/null +++ b/indra/llcommon/llthreadlocalstorage.cpp @@ -0,0 +1,117 @@ +/** + * @file llthreadlocalstorage.cpp + * @author Richard + * @date 2013-1-11 + * @brief implementation of thread local storage utility classes + * + * $LicenseInfo:firstyear=2013&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 "linden_common.h" +#include "llthreadlocalstorage.h" +#include "llapr.h" + +// +//LLThreadLocalPointerBase +// +bool LLThreadLocalPointerBase::sInitialized = false; + +void LLThreadLocalPointerBase::set( void* value ) +{ + llassert(sInitialized && mThreadKey); + + apr_status_t result = apr_threadkey_private_set((void*)value, mThreadKey); + if (result != APR_SUCCESS) + { + ll_apr_warn_status(result); + llerrs << "Failed to set thread local data" << llendl; + } +} + +void* LLThreadLocalPointerBase::get() const +{ + // llassert(sInitialized); + void* ptr; + apr_status_t result = + apr_threadkey_private_get(&ptr, mThreadKey); + if (result != APR_SUCCESS) + { + ll_apr_warn_status(result); + llerrs << "Failed to get thread local data" << llendl; + } + return ptr; +} + + +void LLThreadLocalPointerBase::initStorage( ) +{ + apr_status_t result = apr_threadkey_private_create(&mThreadKey, NULL, gAPRPoolp); + if (result != APR_SUCCESS) + { + ll_apr_warn_status(result); + llerrs << "Failed to allocate thread local data" << llendl; + } +} + +void LLThreadLocalPointerBase::destroyStorage() +{ + if (sInitialized) + { + if (mThreadKey) + { + apr_status_t result = apr_threadkey_private_delete(mThreadKey); + if (result != APR_SUCCESS) + { + ll_apr_warn_status(result); + llerrs << "Failed to delete thread local data" << llendl; + } + } + } +} + +void LLThreadLocalPointerBase::initAllThreadLocalStorage() +{ + if (!sInitialized) + { + for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances(); + it != end_it; + ++it) + { + (*it).initStorage(); + } + sInitialized = true; + } +} + +void LLThreadLocalPointerBase::destroyAllThreadLocalStorage() +{ + if (sInitialized) + { + //for (LLInstanceTracker<LLThreadLocalPointerBase>::instance_iter it = beginInstances(), end_it = endInstances(); + // it != end_it; + // ++it) + //{ + // (*it).destroyStorage(); + //} + sInitialized = false; + } +} diff --git a/indra/llcommon/llthreadlocalstorage.h b/indra/llcommon/llthreadlocalstorage.h new file mode 100644 index 0000000000..a15f9185b1 --- /dev/null +++ b/indra/llcommon/llthreadlocalstorage.h @@ -0,0 +1,357 @@ +/** + * @file llthreadlocalstorage.h + * @author Richard + * @brief Class wrappers for thread local storage + * + * $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_LLTHREADLOCALSTORAGE_H +#define LL_LLTHREADLOCALSTORAGE_H + +#include "llinstancetracker.h" + +class LLThreadLocalPointerBase : public LLInstanceTracker<LLThreadLocalPointerBase> +{ +public: + LLThreadLocalPointerBase() + : mThreadKey(NULL) + { + if (sInitialized) + { + initStorage(); + } + } + + LLThreadLocalPointerBase( const LLThreadLocalPointerBase& other) + : mThreadKey(NULL) + { + if (sInitialized) + { + initStorage(); + } + } + + ~LLThreadLocalPointerBase() + { + destroyStorage(); + } + + static void initAllThreadLocalStorage(); + static void destroyAllThreadLocalStorage(); + +protected: + void set(void* value); + + void* get() const; + + void initStorage(); + void destroyStorage(); + +protected: + struct apr_threadkey_t* mThreadKey; + static bool sInitialized; +}; + +template <typename T> +class LLThreadLocalPointer : public LLThreadLocalPointerBase +{ +public: + + LLThreadLocalPointer() + {} + + explicit LLThreadLocalPointer(T* value) + { + set(value); + } + + + LLThreadLocalPointer(const LLThreadLocalPointer<T>& other) + : LLThreadLocalPointerBase(other) + { + set(other.get()); + } + + LL_FORCE_INLINE T* get() const + { + return (T*)LLThreadLocalPointerBase::get(); + } + + T* operator -> () const + { + return (T*)get(); + } + + T& operator*() const + { + return *(T*)get(); + } + + LLThreadLocalPointer<T>& operator = (T* value) + { + set((void*)value); + return *this; + } + + bool operator ==(const T* other) const + { + if (!sInitialized) return false; + return get() == other; + } + + bool isNull() const { return !sInitialized || get() == NULL; } + + bool notNull() const { return sInitialized && get() != NULL; } +}; + +template<typename DERIVED_TYPE> +class LLThreadLocalSingleton +{ + typedef enum e_init_state + { + UNINITIALIZED = 0, + CONSTRUCTING, + INITIALIZING, + INITIALIZED, + DELETED + } EInitState; + +public: + LLThreadLocalSingleton() + {} + + virtual ~LLThreadLocalSingleton() + { +#if LL_DARWIN + pthread_setspecific(sInstanceKey, NULL); +#else + sInstance = NULL; +#endif + setInitState(DELETED); + } + + static void deleteSingleton() + { + delete getIfExists(); + } + + static DERIVED_TYPE* getInstance() + { + EInitState init_state = getInitState(); + if (init_state == CONSTRUCTING) + { + llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl; + } + + if (init_state == DELETED) + { + llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl; + } + +#if LL_DARWIN + createTLSInstance(); +#endif + if (!getIfExists()) + { + setInitState(CONSTRUCTING); + DERIVED_TYPE* instancep = new DERIVED_TYPE(); +#if LL_DARWIN + S32 result = pthread_setspecific(sInstanceKey, (void*)instancep); + if (result != 0) + { + llerrs << "Could not set thread local storage" << llendl; + } +#else + sInstance = instancep; +#endif + setInitState(INITIALIZING); + instancep->initSingleton(); + setInitState(INITIALIZED); + } + + return getIfExists(); + } + + static DERIVED_TYPE* getIfExists() + { +#if LL_DARWIN + return (DERIVED_TYPE*)pthread_getspecific(sInstanceKey); +#else + return sInstance; +#endif + } + + // Reference version of getInstance() + // Preferred over getInstance() as it disallows checking for NULL + static DERIVED_TYPE& instance() + { + return *getInstance(); + } + + // Has this singleton been created uet? + // Use this to avoid accessing singletons before the can safely be constructed + static bool instanceExists() + { + return getInitState() == INITIALIZED; + } + + // Has this singleton already been deleted? + // Use this to avoid accessing singletons from a static object's destructor + static bool destroyed() + { + return getInitState() == DELETED; + } +private: +#if LL_DARWIN + static void createTLSInitState() + { + static S32 key_created = pthread_key_create(&sInitStateKey, NULL); + if (key_created != 0) + { + llerrs << "Could not create thread local storage" << llendl; + } + } + + static void createTLSInstance() + { + static S32 key_created = pthread_key_create(&sInstanceKey, NULL); + if (key_created != 0) + { + llerrs << "Could not create thread local storage" << llendl; + } + } +#endif + static EInitState getInitState() + { +#if LL_DARWIN + createTLSInitState(); + return (EInitState)(int)pthread_getspecific(sInitStateKey); +#else + return sInitState; +#endif + } + + static void setInitState(EInitState state) + { +#if LL_DARWIN + createTLSInitState(); + pthread_setspecific(sInitStateKey, (void*)state); +#else + sInitState = state; +#endif + } + LLThreadLocalSingleton(const LLThreadLocalSingleton& other); + virtual void initSingleton() {} + +#ifdef LL_WINDOWS + static __declspec(thread) DERIVED_TYPE* sInstance; + static __declspec(thread) EInitState sInitState; +#elif LL_LINUX + static __thread DERIVED_TYPE* sInstance; + static __thread EInitState sInitState; +#elif LL_DARWIN + static pthread_key_t sInstanceKey; + static pthread_key_t sInitStateKey; +#endif +}; + +#if LL_WINDOWS +template<typename DERIVED_TYPE> +__declspec(thread) DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL; + +template<typename DERIVED_TYPE> +__declspec(thread) typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED; +#elif LL_LINUX +template<typename DERIVED_TYPE> +__thread DERIVED_TYPE* LLThreadLocalSingleton<DERIVED_TYPE>::sInstance = NULL; + +template<typename DERIVED_TYPE> +__thread typename LLThreadLocalSingleton<DERIVED_TYPE>::EInitState LLThreadLocalSingleton<DERIVED_TYPE>::sInitState = LLThreadLocalSingleton<DERIVED_TYPE>::UNINITIALIZED; +#elif LL_DARWIN +template<typename DERIVED_TYPE> +pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInstanceKey; + +template<typename DERIVED_TYPE> +pthread_key_t LLThreadLocalSingleton<DERIVED_TYPE>::sInitStateKey; + +#endif + +template<typename DERIVED_TYPE> +class LLThreadLocalSingletonPointer +{ +public: + LL_FORCE_INLINE static DERIVED_TYPE* getInstance() + { +#if LL_DARWIN + createTLSKey(); + return (DERIVED_TYPE*)pthread_getspecific(sInstanceKey); +#else + return sInstance; +#endif + } + + static void setInstance(DERIVED_TYPE* instance) + { +#if LL_DARWIN + createTLSKey(); + pthread_setspecific(sInstanceKey, (void*)instance); +#else + sInstance = instance; +#endif + } + +private: + +#if LL_WINDOWS + static __declspec(thread) DERIVED_TYPE* sInstance; +#elif LL_LINUX + static __thread DERIVED_TYPE* sInstance; +#elif LL_DARWIN + static void TLSError() + { + llerrs << "Could not create thread local storage" << llendl; + } + static void createTLSKey() + { + static S32 key_created = pthread_key_create(&sInstanceKey, NULL); + if (key_created != 0) + { + llerrs << "Could not create thread local storage" << llendl; + } + } + static pthread_key_t sInstanceKey; +#endif +}; + +#if LL_WINDOWS +template<typename DERIVED_TYPE> +__declspec(thread) DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL; +#elif LL_LINUX +template<typename DERIVED_TYPE> +__thread DERIVED_TYPE* LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstance = NULL; +#elif LL_DARWIN +template<typename DERIVED_TYPE> +pthread_key_t LLThreadLocalSingletonPointer<DERIVED_TYPE>::sInstanceKey; +#endif + +#endif // LL_LLTHREADLOCALSTORAGE_H diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 9ebc6de7f4..838155d54d 100755 --- 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 <winsock2.h> -# include <windows.h> +# include "llwin32headerslean.h" #elif LL_LINUX || LL_SOLARIS || LL_DARWIN -# include <errno.h> +# include <errno.h> # include <sys/time.h> #else # error "architecture not supported" @@ -287,14 +285,14 @@ LLTimer::~LLTimer() } // static -U64 LLTimer::getTotalTime() +LLUnitImplicit<LLUnits::Microseconds, U64> LLTimer::getTotalTime() { // simply call into the implementation function. return totalTime(); } // static -F64 LLTimer::getTotalSeconds() +LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getTotalSeconds() { return U64_to_F64(getTotalTime()) * USEC_TO_SEC_F64; } @@ -343,23 +341,23 @@ U64 getElapsedTimeAndUpdate(U64& lastClockCount) } -F64 LLTimer::getElapsedTimeF64() const +LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeF64() const { U64 last = mLastClockCount; return (F64)getElapsedTimeAndUpdate(last) * gClockFrequencyInv; } -F32 LLTimer::getElapsedTimeF32() const +LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeF32() const { return (F32)getElapsedTimeF64(); } -F64 LLTimer::getElapsedTimeAndResetF64() +LLUnitImplicit<LLUnits::Seconds, F64> LLTimer::getElapsedTimeAndResetF64() { return (F64)getElapsedTimeAndUpdate(mLastClockCount) * gClockFrequencyInv; } -F32 LLTimer::getElapsedTimeAndResetF32() +LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getElapsedTimeAndResetF32() { return (F32)getElapsedTimeAndResetF64(); } @@ -372,7 +370,7 @@ void LLTimer::setTimerExpirySec(F32 expiration) + (U64)((F32)(expiration * gClockFrequency)); } -F32 LLTimer::getRemainingTimeF32() const +LLUnitImplicit<LLUnits::Seconds, F32> LLTimer::getRemainingTimeF32() const { U64 cur_ticks = get_clock_count(); if (cur_ticks > mExpirationTicks) diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 513de0605d..0ba87d1e15 100755 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -37,6 +37,7 @@ #include <string> #include <list> // units conversions +#include "llunit.h" #ifndef USEC_PER_SEC const U32 USEC_PER_SEC = 1000000; #endif @@ -55,7 +56,7 @@ public: protected: U64 mLastClockCount; U64 mExpirationTicks; - BOOL mStarted; + bool mStarted; public: LLTimer(); @@ -66,16 +67,16 @@ public: // Return a high precision number of seconds since the start of // this application instance. - static F64 getElapsedSeconds() + static LLUnitImplicit<LLUnits::Seconds, F64> getElapsedSeconds() { return sTimer->getElapsedTimeF64(); } // Return a high precision usec since epoch - static U64 getTotalTime(); + static LLUnitImplicit<LLUnits::Microseconds, U64> getTotalTime(); // Return a high precision seconds since epoch - static F64 getTotalSeconds(); + static LLUnitImplicit<LLUnits::Seconds, F64> getTotalSeconds(); // MANIPULATORS @@ -86,18 +87,18 @@ public: void setTimerExpirySec(F32 expiration); BOOL checkExpirationAndReset(F32 expiration); BOOL hasExpired() const; - F32 getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset - F64 getElapsedTimeAndResetF64(); + LLUnitImplicit<LLUnits::Seconds, F32> getElapsedTimeAndResetF32(); // Returns elapsed time in seconds with reset + LLUnitImplicit<LLUnits::Seconds, F64> getElapsedTimeAndResetF64(); - F32 getRemainingTimeF32() const; + LLUnitImplicit<LLUnits::Seconds, F32> getRemainingTimeF32() const; static BOOL knownBadTimer(); // ACCESSORS - F32 getElapsedTimeF32() const; // Returns elapsed time in seconds - F64 getElapsedTimeF64() const; // Returns elapsed time in seconds + LLUnitImplicit<LLUnits::Seconds, F32> getElapsedTimeF32() const; // Returns elapsed time in seconds + LLUnitImplicit<LLUnits::Seconds, F64> getElapsedTimeF64() const; // Returns elapsed time in seconds - BOOL getStarted() const { return mStarted; } + bool getStarted() const { return mStarted; } static U64 getCurrentClockCount(); // Returns the raw clockticks diff --git a/indra/llcommon/lltrace.cpp b/indra/llcommon/lltrace.cpp new file mode 100644 index 0000000000..c831a1548d --- /dev/null +++ b/indra/llcommon/lltrace.cpp @@ -0,0 +1,115 @@ +/** + * @file lltrace.cpp + * + * $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$ + */ + +#include "linden_common.h" + +#include "lltrace.h" +#include "lltracerecording.h" +#include "lltracethreadrecorder.h" +#include "llfasttimer.h" + +static S32 sInitializationCount = 0; + +namespace LLTrace +{ + +static MasterThreadRecorder* gUIThreadRecorder = NULL; + +void init() +{ + if (sInitializationCount++ == 0) + { + gUIThreadRecorder = new MasterThreadRecorder(); + } +} + +bool isInitialized() +{ + return sInitializationCount > 0; +} + +void cleanup() +{ + if (--sInitializationCount == 0) + { + delete gUIThreadRecorder; + gUIThreadRecorder = NULL; + } +} + +MasterThreadRecorder& getUIThreadRecorder() +{ + llassert(gUIThreadRecorder != NULL); + return *gUIThreadRecorder; +} + +LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder_ptr() +{ + static LLThreadLocalPointer<ThreadRecorder> s_thread_recorder; + return s_thread_recorder; +} + +const LLThreadLocalPointer<ThreadRecorder>& get_thread_recorder() +{ + return get_thread_recorder_ptr(); +} + +void set_thread_recorder(ThreadRecorder* recorder) +{ + get_thread_recorder_ptr() = recorder; +} + + +TimeBlockTreeNode::TimeBlockTreeNode() +: mBlock(NULL), + mParent(NULL), + mNeedsSorting(false) +{} + +void TimeBlockTreeNode::setParent( TimeBlock* parent ) +{ + llassert_always(parent != mBlock); + llassert_always(parent != NULL); + + TimeBlockTreeNode* parent_tree_node = get_thread_recorder()->getTimeBlockTreeNode(parent->getIndex()); + if (!parent_tree_node) return; + + if (mParent) + { + std::vector<TimeBlock*>& children = mParent->getChildren(); + std::vector<TimeBlock*>::iterator found_it = std::find(children.begin(), children.end(), mBlock); + if (found_it != children.end()) + { + children.erase(found_it); + } + } + + mParent = parent; + mBlock->getPrimaryAccumulator()->mParent = parent; + parent_tree_node->mChildren.push_back(mBlock); + parent_tree_node->mNeedsSorting = true; +} + +} diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h new file mode 100644 index 0000000000..343e1b16e8 --- /dev/null +++ b/indra/llcommon/lltrace.h @@ -0,0 +1,1083 @@ +/** + * @file lltrace.h + * @brief Runtime statistics accumulation. + * + * $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_LLTRACE_H +#define LL_LLTRACE_H + +#include "stdtypes.h" +#include "llpreprocessor.h" + +#include "llmemory.h" +#include "llrefcount.h" +#include "llunit.h" +#include "llthreadlocalstorage.h" +#include "lltimer.h" + +#include <list> + +#define LL_RECORD_BLOCK_TIME(block_timer) LLTrace::TimeBlock::Recorder LL_GLUE_TOKENS(block_time_recorder, __COUNTER__)(block_timer); + +namespace LLTrace +{ +class Recording; + +typedef LLUnit<LLUnits::Bytes, F64> Bytes; +typedef LLUnit<LLUnits::Kibibytes, F64> Kibibytes; +typedef LLUnit<LLUnits::Mibibytes, F64> Mibibytes; +typedef LLUnit<LLUnits::Gibibytes, F64> Gibibytes; +typedef LLUnit<LLUnits::Bits, F64> Bits; +typedef LLUnit<LLUnits::Kibibits, F64> Kibibits; +typedef LLUnit<LLUnits::Mibibits, F64> Mibibits; +typedef LLUnit<LLUnits::Gibibits, F64> Gibibits; + +typedef LLUnit<LLUnits::Seconds, F64> Seconds; +typedef LLUnit<LLUnits::Milliseconds, F64> Milliseconds; +typedef LLUnit<LLUnits::Minutes, F64> Minutes; +typedef LLUnit<LLUnits::Hours, F64> Hours; +typedef LLUnit<LLUnits::Milliseconds, F64> Milliseconds; +typedef LLUnit<LLUnits::Microseconds, F64> Microseconds; +typedef LLUnit<LLUnits::Nanoseconds, F64> Nanoseconds; + +typedef LLUnit<LLUnits::Meters, F64> Meters; +typedef LLUnit<LLUnits::Kilometers, F64> Kilometers; +typedef LLUnit<LLUnits::Centimeters, F64> Centimeters; +typedef LLUnit<LLUnits::Millimeters, F64> Millimeters; + +void init(); +void cleanup(); +bool isInitialized(); + +const LLThreadLocalPointer<class ThreadRecorder>& get_thread_recorder(); +void set_thread_recorder(class ThreadRecorder*); + +class MasterThreadRecorder& getUIThreadRecorder(); + +template<typename ACCUMULATOR> +class AccumulatorBuffer : public LLRefCount +{ + typedef AccumulatorBuffer<ACCUMULATOR> self_t; + static const U32 DEFAULT_ACCUMULATOR_BUFFER_SIZE = 64; +private: + struct StaticAllocationMarker { }; + + AccumulatorBuffer(StaticAllocationMarker m) + : mStorageSize(0), + mStorage(NULL) + {} + +public: + + AccumulatorBuffer(const AccumulatorBuffer& other = *getDefaultBuffer()) + : mStorageSize(0), + mStorage(NULL) + { + resize(other.mStorageSize); + for (S32 i = 0; i < sNextStorageSlot; i++) + { + mStorage[i] = other.mStorage[i]; + } + } + + ~AccumulatorBuffer() + { + if (isPrimary()) + { + LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(NULL); + } + delete[] mStorage; + } + + LL_FORCE_INLINE ACCUMULATOR& operator[](size_t index) + { + return mStorage[index]; + } + + LL_FORCE_INLINE const ACCUMULATOR& operator[](size_t index) const + { + return mStorage[index]; + } + + void addSamples(const AccumulatorBuffer<ACCUMULATOR>& other, bool append = true) + { + llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot); + for (size_t i = 0; i < sNextStorageSlot; i++) + { + mStorage[i].addSamples(other.mStorage[i], append); + } + } + + void copyFrom(const AccumulatorBuffer<ACCUMULATOR>& other) + { + llassert(mStorageSize >= sNextStorageSlot && other.mStorageSize > sNextStorageSlot); + for (size_t i = 0; i < sNextStorageSlot; i++) + { + mStorage[i] = other.mStorage[i]; + } + } + + void reset(const AccumulatorBuffer<ACCUMULATOR>* other = NULL) + { + llassert(mStorageSize >= sNextStorageSlot); + for (size_t i = 0; i < sNextStorageSlot; i++) + { + mStorage[i].reset(other ? &other->mStorage[i] : NULL); + } + } + + void flush() + { + llassert(mStorageSize >= sNextStorageSlot); + for (size_t i = 0; i < sNextStorageSlot; i++) + { + mStorage[i].flush(); + } + } + + void makePrimary() + { + LLThreadLocalSingletonPointer<ACCUMULATOR>::setInstance(mStorage); + } + + bool isPrimary() const + { + return LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance() == mStorage; + } + + LL_FORCE_INLINE static ACCUMULATOR* getPrimaryStorage() + { + ACCUMULATOR* accumulator = LLThreadLocalSingletonPointer<ACCUMULATOR>::getInstance(); + return accumulator ? accumulator : sDefaultBuffer->mStorage; + } + + // NOTE: this is not thread-safe. We assume that slots are reserved in the main thread before any child threads are spawned + size_t reserveSlot() + { +#ifndef LL_RELEASE_FOR_DOWNLOAD + if (LLTrace::isInitialized()) + { + llerrs << "Attempting to declare trace object after program initialization. Trace objects should be statically initialized." << llendl; + } +#endif + size_t next_slot = sNextStorageSlot++; + if (next_slot >= mStorageSize) + { + resize(mStorageSize + (mStorageSize >> 2)); + } + llassert(mStorage && next_slot < mStorageSize); + return next_slot; + } + + void resize(size_t new_size) + { + if (new_size <= mStorageSize) return; + + ACCUMULATOR* old_storage = mStorage; + mStorage = new ACCUMULATOR[new_size]; + if (old_storage) + { + for (S32 i = 0; i < mStorageSize; i++) + { + mStorage[i] = old_storage[i]; + } + } + mStorageSize = new_size; + delete[] old_storage; + + self_t* default_buffer = getDefaultBuffer(); + if (this != default_buffer + && new_size > default_buffer->size()) + { + //NB: this is not thread safe, but we assume that all resizing occurs during static initialization + default_buffer->resize(new_size); + } + } + + size_t size() const + { + return sNextStorageSlot; + } + + static self_t* getDefaultBuffer() + { + static bool sInitialized = false; + if (!sInitialized) + { + // this buffer is allowed to leak so that trace calls from global destructors have somewhere to put their data + // so as not to trigger an access violation + sDefaultBuffer = new AccumulatorBuffer(StaticAllocationMarker()); + sInitialized = true; + sDefaultBuffer->resize(DEFAULT_ACCUMULATOR_BUFFER_SIZE); + } + return sDefaultBuffer; + } + +private: + ACCUMULATOR* mStorage; + size_t mStorageSize; + static size_t sNextStorageSlot; + static self_t* sDefaultBuffer; +}; + +template<typename ACCUMULATOR> size_t AccumulatorBuffer<ACCUMULATOR>::sNextStorageSlot = 0; +template<typename ACCUMULATOR> AccumulatorBuffer<ACCUMULATOR>* AccumulatorBuffer<ACCUMULATOR>::sDefaultBuffer = NULL; + +template<typename ACCUMULATOR> +class TraceType +: public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string> +{ +public: + TraceType(const char* name, const char* description = NULL) + : LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name), + mName(name), + mDescription(description ? description : ""), + mAccumulatorIndex(AccumulatorBuffer<ACCUMULATOR>::getDefaultBuffer()->reserveSlot()) + {} + + LL_FORCE_INLINE ACCUMULATOR* getPrimaryAccumulator() const + { + ACCUMULATOR* accumulator_storage = AccumulatorBuffer<ACCUMULATOR>::getPrimaryStorage(); + return &accumulator_storage[mAccumulatorIndex]; + } + + size_t getIndex() const { return mAccumulatorIndex; } + + virtual const char* getUnitLabel() { return ""; } + + const std::string& getName() const { return mName; } + +protected: + const std::string mName; + const std::string mDescription; + const size_t mAccumulatorIndex; +}; + +class EventAccumulator +{ +public: + typedef F64 value_t; + typedef F64 mean_t; + + EventAccumulator() + : mSum(0), + mMin((std::numeric_limits<F64>::max)()), + mMax((std::numeric_limits<F64>::min)()), + mMean(0), + mVarianceSum(0), + mNumSamples(0), + mLastValue(0) + {} + + void record(F64 value) + { + mNumSamples++; + mSum += value; + // NOTE: both conditions will hold on first pass through + if (value < mMin) + { + mMin = value; + } + if (value > mMax) + { + mMax = value; + } + F64 old_mean = mMean; + mMean += (value - old_mean) / (F64)mNumSamples; + mVarianceSum += (value - old_mean) * (value - mMean); + mLastValue = value; + } + + void addSamples(const EventAccumulator& other, bool append) + { + if (other.mNumSamples) + { + mSum += other.mSum; + + // NOTE: both conditions will hold first time through + if (other.mMin < mMin) { mMin = other.mMin; } + if (other.mMax > mMax) { mMax = other.mMax; } + + // combine variance (and hence standard deviation) of 2 different sized sample groups using + // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm + F64 n_1 = (F64)mNumSamples, + n_2 = (F64)other.mNumSamples; + F64 m_1 = mMean, + m_2 = other.mMean; + F64 v_1 = mVarianceSum / mNumSamples, + v_2 = other.mVarianceSum / other.mNumSamples; + if (n_1 == 0) + { + mVarianceSum = other.mVarianceSum; + } + else if (n_2 == 0) + { + // don't touch variance + // mVarianceSum = mVarianceSum; + } + else + { + mVarianceSum = (F64)mNumSamples + * ((((n_1 - 1.f) * v_1) + + ((n_2 - 1.f) * v_2) + + (((n_1 * n_2) / (n_1 + n_2)) + * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2)))) + / (n_1 + n_2 - 1.f)); + } + + F64 weight = (F64)mNumSamples / (F64)(mNumSamples + other.mNumSamples); + mNumSamples += other.mNumSamples; + mMean = mMean * weight + other.mMean * (1.f - weight); + if (append) mLastValue = other.mLastValue; + } + } + + void reset(const EventAccumulator* other) + { + mNumSamples = 0; + mSum = 0; + mMin = std::numeric_limits<F64>::max(); + mMax = std::numeric_limits<F64>::min(); + mMean = 0; + mVarianceSum = 0; + mLastValue = other ? other->mLastValue : 0; + } + + void flush() {} + + F64 getSum() const { return mSum; } + F64 getMin() const { return mMin; } + F64 getMax() const { return mMax; } + F64 getLastValue() const { return mLastValue; } + F64 getMean() const { return mMean; } + F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mNumSamples); } + U32 getSampleCount() const { return mNumSamples; } + +private: + F64 mSum, + mMin, + mMax, + mLastValue; + + F64 mMean, + mVarianceSum; + + U32 mNumSamples; +}; + + +class SampleAccumulator +{ +public: + typedef F64 value_t; + typedef F64 mean_t; + + SampleAccumulator() + : mSum(0), + mMin((std::numeric_limits<F64>::max)()), + mMax((std::numeric_limits<F64>::min)()), + mMean(0), + mVarianceSum(0), + mLastSampleTimeStamp(LLTimer::getTotalSeconds()), + mTotalSamplingTime(0), + mNumSamples(0), + mLastValue(0), + mHasValue(false) + {} + + void sample(F64 value) + { + LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds(); + LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp; + mLastSampleTimeStamp = time_stamp; + + if (mHasValue) + { + mTotalSamplingTime += delta_time; + mSum += mLastValue * delta_time; + + // NOTE: both conditions will hold first time through + if (value < mMin) { mMin = value; } + if (value > mMax) { mMax = value; } + + F64 old_mean = mMean; + mMean += (delta_time / mTotalSamplingTime) * (mLastValue - old_mean); + mVarianceSum += delta_time * (mLastValue - old_mean) * (mLastValue - mMean); + } + + mLastValue = value; + mNumSamples++; + mHasValue = true; + } + + void addSamples(const SampleAccumulator& other, bool append) + { + if (other.mTotalSamplingTime) + { + mSum += other.mSum; + + // NOTE: both conditions will hold first time through + if (other.mMin < mMin) { mMin = other.mMin; } + if (other.mMax > mMax) { mMax = other.mMax; } + + // combine variance (and hence standard deviation) of 2 different sized sample groups using + // the following formula: http://www.mrc-bsu.cam.ac.uk/cochrane/handbook/chapter_7/7_7_3_8_combining_groups.htm + F64 n_1 = mTotalSamplingTime, + n_2 = other.mTotalSamplingTime; + F64 m_1 = mMean, + m_2 = other.mMean; + F64 v_1 = mVarianceSum / mTotalSamplingTime, + v_2 = other.mVarianceSum / other.mTotalSamplingTime; + if (n_1 == 0) + { + mVarianceSum = other.mVarianceSum; + } + else if (n_2 == 0) + { + // variance is unchanged + // mVarianceSum = mVarianceSum; + } + else + { + mVarianceSum = mTotalSamplingTime + * ((((n_1 - 1.f) * v_1) + + ((n_2 - 1.f) * v_2) + + (((n_1 * n_2) / (n_1 + n_2)) + * ((m_1 * m_1) + (m_2 * m_2) - (2.f * m_1 * m_2)))) + / (n_1 + n_2 - 1.f)); + } + + llassert(other.mTotalSamplingTime > 0); + F64 weight = mTotalSamplingTime / (mTotalSamplingTime + other.mTotalSamplingTime); + mNumSamples += other.mNumSamples; + mTotalSamplingTime += other.mTotalSamplingTime; + mMean = (mMean * weight) + (other.mMean * (1.0 - weight)); + if (append) + { + mLastValue = other.mLastValue; + mLastSampleTimeStamp = other.mLastSampleTimeStamp; + mHasValue |= other.mHasValue; + } + } + } + + void reset(const SampleAccumulator* other) + { + mNumSamples = 0; + mSum = 0; + mMin = std::numeric_limits<F64>::max(); + mMax = std::numeric_limits<F64>::min(); + mMean = other ? other->mLastValue : 0; + mVarianceSum = 0; + mLastSampleTimeStamp = LLTimer::getTotalSeconds(); + mTotalSamplingTime = 0; + mLastValue = other ? other->mLastValue : 0; + mHasValue = other ? other->mHasValue : false; + } + + void flush() + { + LLUnitImplicit<LLUnits::Seconds, F64> time_stamp = LLTimer::getTotalSeconds(); + LLUnitImplicit<LLUnits::Seconds, F64> delta_time = time_stamp - mLastSampleTimeStamp; + + if (mHasValue) + { + mSum += mLastValue * delta_time; + mTotalSamplingTime += delta_time; + } + mLastSampleTimeStamp = time_stamp; + } + + F64 getSum() const { return mSum; } + F64 getMin() const { return mMin; } + F64 getMax() const { return mMax; } + F64 getLastValue() const { return mLastValue; } + F64 getMean() const { return mMean; } + F64 getStandardDeviation() const { return sqrtf(mVarianceSum / mTotalSamplingTime); } + U32 getSampleCount() const { return mNumSamples; } + +private: + F64 mSum, + mMin, + mMax, + mLastValue; + + bool mHasValue; + + F64 mMean, + mVarianceSum; + + LLUnitImplicit<LLUnits::Seconds, F64> mLastSampleTimeStamp, + mTotalSamplingTime; + + U32 mNumSamples; +}; + +class CountAccumulator +{ +public: + typedef F64 value_t; + typedef F64 mean_t; + + CountAccumulator() + : mSum(0), + mNumSamples(0) + {} + + void add(F64 value) + { + mNumSamples++; + mSum += value; + } + + void addSamples(const CountAccumulator& other, bool /*append*/) + { + mSum += other.mSum; + mNumSamples += other.mNumSamples; + } + + void reset(const CountAccumulator* other) + { + mNumSamples = 0; + mSum = 0; + } + + void flush() {} + + F64 getSum() const { return mSum; } + + U32 getSampleCount() const { return mNumSamples; } + +private: + F64 mSum; + + U32 mNumSamples; +}; + +class TimeBlockAccumulator +{ +public: + typedef LLUnit<LLUnits::Seconds, F64> value_t; + typedef LLUnit<LLUnits::Seconds, F64> mean_t; + typedef TimeBlockAccumulator self_t; + + // fake classes that allows us to view different facets of underlying statistic + struct CallCountFacet + { + typedef U32 value_t; + typedef F32 mean_t; + }; + + struct SelfTimeFacet + { + typedef LLUnit<LLUnits::Seconds, F64> value_t; + typedef LLUnit<LLUnits::Seconds, F64> mean_t; + }; + + TimeBlockAccumulator(); + void addSamples(const self_t& other, bool /*append*/); + void reset(const self_t* other); + void flush() {} + + // + // members + // + U64 mStartTotalTimeCounter, + mTotalTimeCounter, + mSelfTimeCounter; + U32 mCalls; + class TimeBlock* mParent; // last acknowledged parent of this time block + class TimeBlock* mLastCaller; // used to bootstrap tree construction + U16 mActiveCount; // number of timers with this ID active on stack + bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame + +}; + +template<> +class TraceType<TimeBlockAccumulator::CallCountFacet> +: public TraceType<TimeBlockAccumulator> +{ +public: + + TraceType(const char* name, const char* description = "") + : TraceType<TimeBlockAccumulator>(name, description) + {} +}; + +template<> +class TraceType<TimeBlockAccumulator::SelfTimeFacet> + : public TraceType<TimeBlockAccumulator> +{ +public: + + TraceType(const char* name, const char* description = "") + : TraceType<TimeBlockAccumulator>(name, description) + {} +}; + +class TimeBlock; +class TimeBlockTreeNode +{ +public: + TimeBlockTreeNode(); + + void setParent(TimeBlock* parent); + TimeBlock* getParent() { return mParent; } + + TimeBlock* mBlock; + TimeBlock* mParent; + std::vector<TimeBlock*> mChildren; + bool mNeedsSorting; +}; + + +template <typename T = F64> +class EventStatHandle +: public TraceType<EventAccumulator> +{ +public: + typedef typename F64 storage_t; + typedef TraceType<EventAccumulator> trace_t; + + EventStatHandle(const char* name, const char* description = NULL) + : trace_t(name, description) + {} + + /*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); } + +}; + +template<typename T, typename VALUE_T> +void record(EventStatHandle<T>& measurement, VALUE_T value) +{ + T converted_value(value); + measurement.getPrimaryAccumulator()->record(LLUnits::rawValue(converted_value)); +} + +template <typename T = F64> +class SampleStatHandle +: public TraceType<SampleAccumulator> +{ +public: + typedef F64 storage_t; + typedef TraceType<SampleAccumulator> trace_t; + + SampleStatHandle(const char* name, const char* description = NULL) + : trace_t(name, description) + {} + + /*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); } +}; + +template<typename T, typename VALUE_T> +void sample(SampleStatHandle<T>& measurement, VALUE_T value) +{ + T converted_value(value); + measurement.getPrimaryAccumulator()->sample(LLUnits::rawValue(converted_value)); +} + +template <typename T = F64> +class CountStatHandle +: public TraceType<CountAccumulator> +{ +public: + typedef typename F64 storage_t; + typedef TraceType<CountAccumulator> trace_t; + + CountStatHandle(const char* name, const char* description = NULL) + : trace_t(name) + {} + + /*virtual*/ const char* getUnitLabel() { return LLGetUnitLabel<T>::getUnitLabel(); } +}; + +template<typename T, typename VALUE_T> +void add(CountStatHandle<T>& count, VALUE_T value) +{ + T converted_value(value); + count.getPrimaryAccumulator()->add(LLUnits::rawValue(converted_value)); +} + + +struct MemStatAccumulator +{ + typedef MemStatAccumulator self_t; + + // fake classes that allows us to view different facets of underlying statistic + struct AllocationCountFacet + { + typedef U32 value_t; + typedef F32 mean_t; + }; + + struct DeallocationCountFacet + { + typedef U32 value_t; + typedef F32 mean_t; + }; + + struct ChildMemFacet + { + typedef LLUnit<LLUnits::Bytes, F64> value_t; + typedef LLUnit<LLUnits::Bytes, F64> mean_t; + }; + + MemStatAccumulator() + : mAllocatedCount(0), + mDeallocatedCount(0) + {} + + void addSamples(const MemStatAccumulator& other, bool append) + { + mSize.addSamples(other.mSize, append); + mChildSize.addSamples(other.mChildSize, append); + mAllocatedCount += other.mAllocatedCount; + mDeallocatedCount += other.mDeallocatedCount; + } + + void reset(const MemStatAccumulator* other) + { + mSize.reset(other ? &other->mSize : NULL); + mChildSize.reset(other ? &other->mChildSize : NULL); + mAllocatedCount = 0; + mDeallocatedCount = 0; + } + + void flush() + { + mSize.flush(); + mChildSize.flush(); + } + + SampleAccumulator mSize, + mChildSize; + int mAllocatedCount, + mDeallocatedCount; +}; + + +template<> +class TraceType<MemStatAccumulator::AllocationCountFacet> +: public TraceType<MemStatAccumulator> +{ +public: + + TraceType(const char* name, const char* description = "") + : TraceType<MemStatAccumulator>(name, description) + {} +}; + +template<> +class TraceType<MemStatAccumulator::DeallocationCountFacet> +: public TraceType<MemStatAccumulator> +{ +public: + + TraceType(const char* name, const char* description = "") + : TraceType<MemStatAccumulator>(name, description) + {} +}; + +template<> +class TraceType<MemStatAccumulator::ChildMemFacet> + : public TraceType<MemStatAccumulator> +{ +public: + + TraceType(const char* name, const char* description = "") + : TraceType<MemStatAccumulator>(name, description) + {} +}; + +class MemStatHandle : public TraceType<MemStatAccumulator> +{ +public: + typedef TraceType<MemStatAccumulator> trace_t; + MemStatHandle(const char* name) + : trace_t(name) + {} + + /*virtual*/ const char* getUnitLabel() { return "B"; } + + TraceType<MemStatAccumulator::AllocationCountFacet>& allocationCount() + { + return static_cast<TraceType<MemStatAccumulator::AllocationCountFacet>&>(*(TraceType<MemStatAccumulator>*)this); + } + + TraceType<MemStatAccumulator::DeallocationCountFacet>& deallocationCount() + { + return static_cast<TraceType<MemStatAccumulator::DeallocationCountFacet>&>(*(TraceType<MemStatAccumulator>*)this); + } + + TraceType<MemStatAccumulator::ChildMemFacet>& childMem() + { + return static_cast<TraceType<MemStatAccumulator::ChildMemFacet>&>(*(TraceType<MemStatAccumulator>*)this); + } +}; + +// measures effective memory footprint of specified type +// specialize to cover different types + +template<typename T> +struct MemFootprint +{ + static size_t measure(const T& value) + { + return sizeof(T); + } + + static size_t measure() + { + return sizeof(T); + } +}; + +template<typename T> +struct MemFootprint<T*> +{ + static size_t measure(const T* value) + { + if (!value) + { + return 0; + } + return MemFootprint<T>::measure(*value); + } + + static size_t measure() + { + return MemFootprint<T>::measure(); + } +}; + +template<typename T> +struct MemFootprint<std::basic_string<T> > +{ + static size_t measure(const std::basic_string<T>& value) + { + return value.capacity() * sizeof(T); + } + + static size_t measure() + { + return sizeof(std::basic_string<T>); + } +}; + +template<typename T> +struct MemFootprint<std::vector<T> > +{ + static size_t measure(const std::vector<T>& value) + { + return value.capacity() * MemFootprint<T>::measure(); + } + + static size_t measure() + { + return sizeof(std::vector<T>); + } +}; + +template<typename T> +struct MemFootprint<std::list<T> > +{ + static size_t measure(const std::list<T>& value) + { + return value.size() * (MemFootprint<T>::measure() + sizeof(void*) * 2); + } + + static size_t measure() + { + return sizeof(std::list<T>); + } +}; + +template<typename DERIVED, size_t ALIGNMENT = LL_DEFAULT_HEAP_ALIGN> +class MemTrackable +{ + template<typename TRACKED, typename TRACKED_IS_TRACKER> + struct TrackMemImpl; + + typedef MemTrackable<DERIVED> mem_trackable_t; + +public: + typedef void mem_trackable_tag_t; + + virtual ~MemTrackable() + { + memDisclaim(mMemFootprint); + } + + void* operator new(size_t size) + { + MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); + if (accumulator) + { + accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size); + accumulator->mAllocatedCount++; + } + + return ::operator new(size); + } + + void operator delete(void* ptr, size_t size) + { + MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); + if (accumulator) + { + accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size); + accumulator->mAllocatedCount--; + accumulator->mDeallocatedCount++; + } + ::operator delete(ptr); + } + + void *operator new [](size_t size) + { + MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); + if (accumulator) + { + accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size); + accumulator->mAllocatedCount++; + } + + return ::operator new[](size); + } + + void operator delete[](void* ptr, size_t size) + { + MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); + if (accumulator) + { + accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size); + accumulator->mAllocatedCount--; + accumulator->mDeallocatedCount++; + } + ::operator delete[](ptr); + } + + // claim memory associated with other objects/data as our own, adding to our calculated footprint + template<typename CLAIM_T> + CLAIM_T& memClaim(CLAIM_T& value) + { + TrackMemImpl<CLAIM_T>::claim(*this, value); + return value; + } + + template<typename CLAIM_T> + const CLAIM_T& memClaim(const CLAIM_T& value) + { + TrackMemImpl<CLAIM_T>::claim(*this, value); + return value; + } + + + void memClaimAmount(size_t size) + { + MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); + mMemFootprint += size; + if (accumulator) + { + accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)size); + } + } + + // remove memory we had claimed from our calculated footprint + template<typename CLAIM_T> + CLAIM_T& memDisclaim(CLAIM_T& value) + { + TrackMemImpl<CLAIM_T>::disclaim(*this, value); + return value; + } + + template<typename CLAIM_T> + const CLAIM_T& memDisclaim(const CLAIM_T& value) + { + TrackMemImpl<CLAIM_T>::disclaim(*this, value); + return value; + } + + void memDisclaimAmount(size_t size) + { + MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); + if (accumulator) + { + accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)size); + } + } + +private: + size_t mMemFootprint; + + template<typename TRACKED, typename TRACKED_IS_TRACKER = void> + struct TrackMemImpl + { + static void claim(mem_trackable_t& tracker, const TRACKED& tracked) + { + MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); + if (accumulator) + { + size_t footprint = MemFootprint<TRACKED>::measure(tracked); + accumulator->mSize.sample(accumulator->mSize.getLastValue() + (F64)footprint); + tracker.mMemFootprint += footprint; + } + } + + static void disclaim(mem_trackable_t& tracker, const TRACKED& tracked) + { + MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); + if (accumulator) + { + size_t footprint = MemFootprint<TRACKED>::measure(tracked); + accumulator->mSize.sample(accumulator->mSize.getLastValue() - (F64)footprint); + tracker.mMemFootprint -= footprint; + } + } + }; + + template<typename TRACKED> + struct TrackMemImpl<TRACKED, typename TRACKED::mem_trackable_tag_t> + { + static void claim(mem_trackable_t& tracker, TRACKED& tracked) + { + MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); + if (accumulator) + { + accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() + (F64)MemFootprint<TRACKED>::measure(tracked)); + } + } + + static void disclaim(mem_trackable_t& tracker, TRACKED& tracked) + { + MemStatAccumulator* accumulator = DERIVED::sMemStat.getPrimaryAccumulator(); + if (accumulator) + { + accumulator->mChildSize.sample(accumulator->mChildSize.getLastValue() - (F64)MemFootprint<TRACKED>::measure(tracked)); + } + } + }; +}; + +} +#endif // LL_LLTRACE_H diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp new file mode 100644 index 0000000000..d32504b014 --- /dev/null +++ b/indra/llcommon/lltracerecording.cpp @@ -0,0 +1,944 @@ +/** + * @file lltracesampler.cpp + * + * $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$ + */ + +#include "linden_common.h" + +#include "lltrace.h" +#include "llfasttimer.h" +#include "lltracerecording.h" +#include "lltracethreadrecorder.h" +#include "llthread.h" + +namespace LLTrace +{ + + +/////////////////////////////////////////////////////////////////////// +// RecordingBuffers +/////////////////////////////////////////////////////////////////////// + +RecordingBuffers::RecordingBuffers() +{} + +void RecordingBuffers::handOffTo(RecordingBuffers& other) +{ + other.mCounts.reset(&mCounts); + other.mSamples.reset(&mSamples); + other.mEvents.reset(&mEvents); + other.mStackTimers.reset(&mStackTimers); + other.mMemStats.reset(&mMemStats); +} + +void RecordingBuffers::makePrimary() +{ + mCounts.makePrimary(); + mSamples.makePrimary(); + mEvents.makePrimary(); + mStackTimers.makePrimary(); + mMemStats.makePrimary(); + + ThreadRecorder* thread_recorder = get_thread_recorder().get(); + AccumulatorBuffer<TimeBlockAccumulator>& timer_accumulator_buffer = mStackTimers; + // update stacktimer parent pointers + for (S32 i = 0, end_i = mStackTimers.size(); i < end_i; i++) + { + TimeBlockTreeNode* tree_node = thread_recorder->getTimeBlockTreeNode(i); + if (tree_node) + { + timer_accumulator_buffer[i].mParent = tree_node->mParent; + } + } +} + +bool RecordingBuffers::isPrimary() const +{ + return mCounts.isPrimary(); +} + +void RecordingBuffers::append( const RecordingBuffers& other ) +{ + mCounts.addSamples(other.mCounts); + mSamples.addSamples(other.mSamples); + mEvents.addSamples(other.mEvents); + mMemStats.addSamples(other.mMemStats); + mStackTimers.addSamples(other.mStackTimers); +} + +void RecordingBuffers::merge( const RecordingBuffers& other) +{ + mCounts.addSamples(other.mCounts, false); + mSamples.addSamples(other.mSamples, false); + mEvents.addSamples(other.mEvents, false); + mMemStats.addSamples(other.mMemStats, false); + // for now, hold out timers from merge, need to be displayed per thread + //mStackTimers.addSamples(other.mStackTimers, false); +} + +void RecordingBuffers::reset(RecordingBuffers* other) +{ + mCounts.reset(other ? &other->mCounts : NULL); + mSamples.reset(other ? &other->mSamples : NULL); + mEvents.reset(other ? &other->mEvents : NULL); + mStackTimers.reset(other ? &other->mStackTimers : NULL); + mMemStats.reset(other ? &other->mMemStats : NULL); +} + +void RecordingBuffers::flush() +{ + mSamples.flush(); +} + +/////////////////////////////////////////////////////////////////////// +// Recording +/////////////////////////////////////////////////////////////////////// + +Recording::Recording() +: mElapsedSeconds(0) +{ + mBuffers = new RecordingBuffers(); +} + +Recording::Recording( const Recording& other ) +{ + // this will allow us to seamlessly start without affecting any data we've acquired from other + setPlayState(PAUSED); + + Recording& mutable_other = const_cast<Recording&>(other); + EPlayState other_play_state = other.getPlayState(); + mutable_other.pause(); + + mBuffers = other.mBuffers; + + LLStopWatchControlsMixin<Recording>::setPlayState(other_play_state); + mutable_other.setPlayState(other_play_state); + + // above call will clear mElapsedSeconds as a side effect, so copy it here + mElapsedSeconds = other.mElapsedSeconds; + mSamplingTimer = other.mSamplingTimer; +} + + +Recording::~Recording() +{ + if (isStarted() && LLTrace::get_thread_recorder().notNull()) + { + LLTrace::get_thread_recorder()->deactivate(this); + } +} + +void Recording::update() +{ + if (isStarted()) + { + mBuffers.write()->flush(); + LLTrace::get_thread_recorder()->bringUpToDate(this); + mSamplingTimer.reset(); + } +} + +void Recording::handleReset() +{ + mBuffers.write()->reset(); + + mElapsedSeconds = 0.0; + mSamplingTimer.reset(); +} + +void Recording::handleStart() +{ + mSamplingTimer.reset(); + LLTrace::get_thread_recorder()->activate(this); +} + +void Recording::handleStop() +{ + mElapsedSeconds += mSamplingTimer.getElapsedTimeF64(); + mBuffers.write()->flush(); + LLTrace::get_thread_recorder()->deactivate(this); +} + +void Recording::handleSplitTo(Recording& other) +{ + mBuffers.write()->handOffTo(*other.mBuffers.write()); +} + +void Recording::appendRecording( const Recording& other ) +{ + EPlayState play_state = getPlayState(); + { + pause(); + mBuffers.write()->append(*other.mBuffers); + mElapsedSeconds += other.mElapsedSeconds; + } + setPlayState(play_state); +} + +void Recording::mergeRecording( const Recording& other) +{ + EPlayState play_state = getPlayState(); + { + pause(); + mBuffers.write()->merge(*other.mBuffers); + } + setPlayState(play_state); +} + +LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) +{ + const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; + update(); + return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) + / (F64)LLTrace::TimeBlock::countsPerSecond(); +} + +LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat) +{ + const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; + update(); + return (F64)(accumulator.mSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond(); +} + + +U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat) +{ + update(); + return mBuffers->mStackTimers[stat.getIndex()].mCalls; +} + +LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) +{ + const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; + + update(); + return (F64)(accumulator.mTotalTimeCounter - accumulator.mStartTotalTimeCounter) + / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); +} + +LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat) +{ + const TimeBlockAccumulator& accumulator = mBuffers->mStackTimers[stat.getIndex()]; + + update(); + return (F64)(accumulator.mSelfTimeCounter) + / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); +} + +F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat) +{ + update(); + return (F32)mBuffers->mStackTimers[stat.getIndex()].mCalls / mElapsedSeconds; +} + +LLUnit<LLUnits::Bytes, F64> Recording::getMin(const TraceType<MemStatAccumulator>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mSize.getMin(); +} + +LLUnit<LLUnits::Bytes, F64> Recording::getMean(const TraceType<MemStatAccumulator>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mSize.getMean(); +} + +LLUnit<LLUnits::Bytes, F64> Recording::getMax(const TraceType<MemStatAccumulator>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mSize.getMax(); +} + +LLUnit<LLUnits::Bytes, F64> Recording::getStandardDeviation(const TraceType<MemStatAccumulator>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mSize.getStandardDeviation(); +} + +LLUnit<LLUnits::Bytes, F64> Recording::getLastValue(const TraceType<MemStatAccumulator>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mSize.getLastValue(); +} + +LLUnit<LLUnits::Bytes, F64> Recording::getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMin(); +} + +LLUnit<LLUnits::Bytes, F64> Recording::getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMean(); +} + +LLUnit<LLUnits::Bytes, F64> Recording::getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mChildSize.getMax(); +} + +LLUnit<LLUnits::Bytes, F64> Recording::getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mChildSize.getStandardDeviation(); +} + +LLUnit<LLUnits::Bytes, F64> Recording::getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mChildSize.getLastValue(); +} + +U32 Recording::getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount; +} + +U32 Recording::getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat) +{ + update(); + return mBuffers->mMemStats[stat.getIndex()].mAllocatedCount; +} + + +F64 Recording::getSum( const TraceType<CountAccumulator>& stat ) +{ + update(); + return mBuffers->mCounts[stat.getIndex()].getSum(); +} + +F64 Recording::getSum( const TraceType<EventAccumulator>& stat ) +{ + update(); + return (F64)mBuffers->mEvents[stat.getIndex()].getSum(); +} + +F64 Recording::getPerSec( const TraceType<CountAccumulator>& stat ) +{ + update(); + F64 sum = mBuffers->mCounts[stat.getIndex()].getSum(); + return (sum != 0.0) + ? (sum / mElapsedSeconds) + : 0.0; +} + +U32 Recording::getSampleCount( const TraceType<CountAccumulator>& stat ) +{ + update(); + return mBuffers->mCounts[stat.getIndex()].getSampleCount(); +} + +F64 Recording::getMin( const TraceType<SampleAccumulator>& stat ) +{ + update(); + return mBuffers->mSamples[stat.getIndex()].getMin(); +} + +F64 Recording::getMax( const TraceType<SampleAccumulator>& stat ) +{ + update(); + return mBuffers->mSamples[stat.getIndex()].getMax(); +} + +F64 Recording::getMean( const TraceType<SampleAccumulator>& stat ) +{ + update(); + return mBuffers->mSamples[stat.getIndex()].getMean(); +} + +F64 Recording::getStandardDeviation( const TraceType<SampleAccumulator>& stat ) +{ + update(); + return mBuffers->mSamples[stat.getIndex()].getStandardDeviation(); +} + +F64 Recording::getLastValue( const TraceType<SampleAccumulator>& stat ) +{ + update(); + return mBuffers->mSamples[stat.getIndex()].getLastValue(); +} + +U32 Recording::getSampleCount( const TraceType<SampleAccumulator>& stat ) +{ + update(); + return mBuffers->mSamples[stat.getIndex()].getSampleCount(); +} + +F64 Recording::getMin( const TraceType<EventAccumulator>& stat ) +{ + update(); + return mBuffers->mEvents[stat.getIndex()].getMin(); +} + +F64 Recording::getMax( const TraceType<EventAccumulator>& stat ) +{ + update(); + return mBuffers->mEvents[stat.getIndex()].getMax(); +} + +F64 Recording::getMean( const TraceType<EventAccumulator>& stat ) +{ + update(); + return mBuffers->mEvents[stat.getIndex()].getMean(); +} + +F64 Recording::getStandardDeviation( const TraceType<EventAccumulator>& stat ) +{ + update(); + return mBuffers->mEvents[stat.getIndex()].getStandardDeviation(); +} + +F64 Recording::getLastValue( const TraceType<EventAccumulator>& stat ) +{ + update(); + return mBuffers->mEvents[stat.getIndex()].getLastValue(); +} + +U32 Recording::getSampleCount( const TraceType<EventAccumulator>& stat ) +{ + update(); + return mBuffers->mEvents[stat.getIndex()].getSampleCount(); +} + +/////////////////////////////////////////////////////////////////////// +// PeriodicRecording +/////////////////////////////////////////////////////////////////////// + +PeriodicRecording::PeriodicRecording( U32 num_periods, EPlayState state) +: mAutoResize(num_periods == 0), + mCurPeriod(0), + mRecordingPeriods(num_periods ? num_periods : 1) +{ + setPlayState(state); +} + +void PeriodicRecording::nextPeriod() +{ + if (mAutoResize) + { + mRecordingPeriods.push_back(Recording()); + } + + Recording& old_recording = getCurRecording(); + + mCurPeriod = (mCurPeriod + 1) % mRecordingPeriods.size(); + old_recording.splitTo(getCurRecording()); +} + + +void PeriodicRecording::appendPeriodicRecording( PeriodicRecording& other ) +{ + if (other.mRecordingPeriods.empty()) return; + + EPlayState play_state = getPlayState(); + pause(); + + EPlayState other_play_state = other.getPlayState(); + other.pause(); + + U32 other_recording_count = other.mRecordingPeriods.size(); + + Recording& other_oldest_recording = other.mRecordingPeriods[(other.mCurPeriod + 1) % other.mRecordingPeriods.size()]; + + // if I have a recording of any length, then close it off and start a fresh one + if (getCurRecording().getDuration().value()) + { + nextPeriod(); + } + getCurRecording().appendRecording(other_oldest_recording); + + if (other_recording_count > 1) + { + if (mAutoResize) + { + for (S32 other_index = (other.mCurPeriod + 2) % other_recording_count, + end_index = (other.mCurPeriod + 1) % other_recording_count; + other_index != end_index; + other_index = (other_index + 1) % other_recording_count) + { + llassert(other.mRecordingPeriods[other_index].getDuration() != 0.f + && (mRecordingPeriods.empty() + || other.mRecordingPeriods[other_index].getDuration() != mRecordingPeriods.back().getDuration())); + mRecordingPeriods.push_back(other.mRecordingPeriods[other_index]); + } + + mCurPeriod = mRecordingPeriods.size() - 1; + } + else + { + size_t num_to_copy = llmin( mRecordingPeriods.size(), other.mRecordingPeriods.size() - 1); + std::vector<Recording>::iterator src_it = other.mRecordingPeriods.begin() + + ( (other.mCurPeriod + 1 // oldest period + + (other.mRecordingPeriods.size() - num_to_copy)) // minus room for copy + % other.mRecordingPeriods.size()); + std::vector<Recording>::iterator dest_it = mRecordingPeriods.begin() + ((mCurPeriod + 1) % mRecordingPeriods.size()); + + for(S32 i = 0; i < num_to_copy; i++) + { + *dest_it = *src_it; + + if (++src_it == other.mRecordingPeriods.end()) + { + src_it = other.mRecordingPeriods.begin(); + } + + if (++dest_it == mRecordingPeriods.end()) + { + dest_it = mRecordingPeriods.begin(); + } + } + + mCurPeriod = (mCurPeriod + num_to_copy) % mRecordingPeriods.size(); + } + } + + nextPeriod(); + + setPlayState(play_state); + other.setPlayState(other_play_state); +} + +LLUnit<LLUnits::Seconds, F64> PeriodicRecording::getDuration() const +{ + LLUnit<LLUnits::Seconds, F64> duration; + size_t num_periods = mRecordingPeriods.size(); + for (size_t i = 1; i <= num_periods; i++) + { + size_t index = (mCurPeriod + num_periods - i) % num_periods; + duration += mRecordingPeriods[index].getDuration(); + } + return duration; +} + + +LLTrace::Recording PeriodicRecording::snapshotCurRecording() const +{ + Recording recording_copy(getCurRecording()); + recording_copy.stop(); + return recording_copy; +} + + +Recording& PeriodicRecording::getLastRecording() +{ + return getPrevRecording(1); +} + +const Recording& PeriodicRecording::getLastRecording() const +{ + return getPrevRecording(1); +} + +Recording& PeriodicRecording::getCurRecording() +{ + return mRecordingPeriods[mCurPeriod]; +} + +const Recording& PeriodicRecording::getCurRecording() const +{ + return mRecordingPeriods[mCurPeriod]; +} + +Recording& PeriodicRecording::getPrevRecording( U32 offset ) +{ + U32 num_periods = mRecordingPeriods.size(); + offset = llclamp(offset, 0u, num_periods - 1); + return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods]; +} + +const Recording& PeriodicRecording::getPrevRecording( U32 offset ) const +{ + U32 num_periods = mRecordingPeriods.size(); + offset = llclamp(offset, 0u, num_periods - 1); + return mRecordingPeriods[(mCurPeriod + num_periods - offset) % num_periods]; +} + +void PeriodicRecording::handleStart() +{ + getCurRecording().start(); +} + +void PeriodicRecording::handleStop() +{ + getCurRecording().pause(); +} + +void PeriodicRecording::handleReset() +{ + if (mAutoResize) + { + mRecordingPeriods.clear(); + mRecordingPeriods.push_back(Recording()); + } + else + { + for (std::vector<Recording>::iterator it = mRecordingPeriods.begin(), end_it = mRecordingPeriods.end(); + it != end_it; + ++it) + { + it->reset(); + } + } + mCurPeriod = 0; + getCurRecording().setPlayState(getPlayState()); +} + +void PeriodicRecording::handleSplitTo(PeriodicRecording& other) +{ + getCurRecording().splitTo(other.getCurRecording()); +} + + +F64 PeriodicRecording::getPeriodMean( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) +{ + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + F64 mean = 0; + if (num_periods <= 0) { return mean; } + + S32 total_sample_count = 0; + + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + if (mRecordingPeriods[index].getDuration() > 0.f) + { + S32 period_sample_count = mRecordingPeriods[index].getSampleCount(stat); + mean += mRecordingPeriods[index].getMean(stat) * period_sample_count; + total_sample_count += period_sample_count; + } + } + + if (total_sample_count) + { + mean = mean / total_sample_count; + } + return mean; +} + +F64 PeriodicRecording::getPeriodMin( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) +{ + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + F64 min_val = std::numeric_limits<F64>::max(); + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat)); + } + return min_val; +} + +F64 PeriodicRecording::getPeriodMax( const TraceType<EventAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) +{ + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + F64 max_val = std::numeric_limits<F64>::min(); + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat)); + } + return max_val; +} + +F64 PeriodicRecording::getPeriodMin( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) +{ + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + F64 min_val = std::numeric_limits<F64>::max(); + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + min_val = llmin(min_val, mRecordingPeriods[index].getMin(stat)); + } + return min_val; +} + +F64 PeriodicRecording::getPeriodMax(const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/) +{ + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + F64 max_val = std::numeric_limits<F64>::min(); + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + max_val = llmax(max_val, mRecordingPeriods[index].getMax(stat)); + } + return max_val; +} + + +F64 PeriodicRecording::getPeriodMean( const TraceType<SampleAccumulator>& stat, size_t num_periods /*= U32_MAX*/ ) +{ + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + LLUnit<LLUnits::Seconds, F64> total_duration = 0.f; + + F64 mean = 0; + if (num_periods <= 0) { return mean; } + + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + if (mRecordingPeriods[index].getDuration() > 0.f) + { + LLUnit<LLUnits::Seconds, F64> recording_duration = mRecordingPeriods[index].getDuration(); + mean += mRecordingPeriods[index].getMean(stat) * recording_duration.value(); + total_duration += recording_duration; + } + } + + if (total_duration.value()) + { + mean = mean / total_duration; + } + return mean; +} + + + +/////////////////////////////////////////////////////////////////////// +// ExtendableRecording +/////////////////////////////////////////////////////////////////////// + +void ExtendableRecording::extend() +{ + // stop recording to get latest data + mPotentialRecording.stop(); + // push the data back to accepted recording + mAcceptedRecording.appendRecording(mPotentialRecording); + // flush data, so we can start from scratch + mPotentialRecording.reset(); + // go back to play state we were in initially + mPotentialRecording.setPlayState(getPlayState()); +} + +void ExtendableRecording::handleStart() +{ + mPotentialRecording.start(); +} + +void ExtendableRecording::handleStop() +{ + mPotentialRecording.pause(); +} + +void ExtendableRecording::handleReset() +{ + mAcceptedRecording.reset(); + mPotentialRecording.reset(); +} + +void ExtendableRecording::handleSplitTo(ExtendableRecording& other) +{ + mPotentialRecording.splitTo(other.mPotentialRecording); +} + + +/////////////////////////////////////////////////////////////////////// +// ExtendablePeriodicRecording +/////////////////////////////////////////////////////////////////////// + + +ExtendablePeriodicRecording::ExtendablePeriodicRecording() +: mAcceptedRecording(0), + mPotentialRecording(0) +{} + +void ExtendablePeriodicRecording::extend() +{ + llassert(mPotentialRecording.getPlayState() == getPlayState()); + // stop recording to get latest data + mPotentialRecording.pause(); + // push the data back to accepted recording + mAcceptedRecording.appendPeriodicRecording(mPotentialRecording); + // flush data, so we can start from scratch + mPotentialRecording.reset(); + // go back to play state we were in initially + mPotentialRecording.setPlayState(getPlayState()); +} + + +void ExtendablePeriodicRecording::handleStart() +{ + mPotentialRecording.start(); +} + +void ExtendablePeriodicRecording::handleStop() +{ + mPotentialRecording.pause(); +} + +void ExtendablePeriodicRecording::handleReset() +{ + mAcceptedRecording.reset(); + mPotentialRecording.reset(); +} + +void ExtendablePeriodicRecording::handleSplitTo(ExtendablePeriodicRecording& other) +{ + mPotentialRecording.splitTo(other.mPotentialRecording); +} + + +PeriodicRecording& get_frame_recording() +{ + static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(1000, PeriodicRecording::STARTED)); + return *sRecording; +} + +} + +void LLStopWatchControlsMixinCommon::start() +{ + switch (mPlayState) + { + case STOPPED: + handleReset(); + handleStart(); + break; + case PAUSED: + handleStart(); + break; + case STARTED: + handleReset(); + break; + default: + llassert(false); + break; + } + mPlayState = STARTED; +} + +void LLStopWatchControlsMixinCommon::stop() +{ + switch (mPlayState) + { + case STOPPED: + break; + case PAUSED: + break; + case STARTED: + handleStop(); + break; + default: + llassert(false); + break; + } + mPlayState = STOPPED; +} + +void LLStopWatchControlsMixinCommon::pause() +{ + switch (mPlayState) + { + case STOPPED: + break; + case PAUSED: + break; + case STARTED: + handleStop(); + break; + default: + llassert(false); + break; + } + mPlayState = PAUSED; +} + +void LLStopWatchControlsMixinCommon::resume() +{ + switch (mPlayState) + { + case STOPPED: + handleStart(); + break; + case PAUSED: + handleStart(); + break; + case STARTED: + break; + default: + llassert(false); + break; + } + mPlayState = STARTED; +} + +void LLStopWatchControlsMixinCommon::restart() +{ + switch (mPlayState) + { + case STOPPED: + handleReset(); + handleStart(); + break; + case PAUSED: + handleReset(); + handleStart(); + break; + case STARTED: + handleReset(); + break; + default: + llassert(false); + break; + } + mPlayState = STARTED; +} + +void LLStopWatchControlsMixinCommon::reset() +{ + handleReset(); +} + +void LLStopWatchControlsMixinCommon::setPlayState( EPlayState state ) +{ + switch(state) + { + case STOPPED: + stop(); + break; + case PAUSED: + pause(); + break; + case STARTED: + start(); + break; + default: + llassert(false); + break; + } + + mPlayState = state; +} diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h new file mode 100644 index 0000000000..4651bfcb61 --- /dev/null +++ b/indra/llcommon/lltracerecording.h @@ -0,0 +1,527 @@ +/** + * @file lltracerecording.h + * @brief Sampling object for collecting runtime statistics originating from lltrace. + * + * $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_LLTRACERECORDING_H +#define LL_LLTRACERECORDING_H + +#include "stdtypes.h" +#include "llpreprocessor.h" + +#include "llpointer.h" +#include "lltimer.h" +#include "lltrace.h" + +class LLStopWatchControlsMixinCommon +{ +public: + virtual ~LLStopWatchControlsMixinCommon() {} + + enum EPlayState + { + STOPPED, + PAUSED, + STARTED + }; + + void start(); + void stop(); + void pause(); + void resume(); + void restart(); + void reset(); + + bool isStarted() const { return mPlayState == STARTED; } + bool isPaused() const { return mPlayState == PAUSED; } + bool isStopped() const { return mPlayState == STOPPED; } + EPlayState getPlayState() const { return mPlayState; } + // force play state to specific value by calling appropriate handle* methods + void setPlayState(EPlayState state); + +protected: + LLStopWatchControlsMixinCommon() + : mPlayState(STOPPED) + {} + +private: + // trigger active behavior (without reset) + virtual void handleStart() = 0; + // stop active behavior + virtual void handleStop() = 0; + // clear accumulated state, can be called while started + virtual void handleReset() = 0; + + EPlayState mPlayState; +}; + +template<typename DERIVED> +class LLStopWatchControlsMixin +: public LLStopWatchControlsMixinCommon +{ +public: + typedef LLStopWatchControlsMixin<DERIVED> self_t; + virtual void splitTo(DERIVED& other) + { + EPlayState play_state = getPlayState(); + stop(); + other.reset(); + + handleSplitTo(other); + + other.setPlayState(play_state); + } + + virtual void splitFrom(DERIVED& other) + { + static_cast<self_t&>(other).handleSplitTo(*static_cast<DERIVED*>(this)); + } +private: + // atomically stop this object while starting the other + // no data can be missed in between stop and start + virtual void handleSplitTo(DERIVED& other) {}; + +}; + +namespace LLTrace +{ + struct RecordingBuffers : public LLRefCount + { + RecordingBuffers(); + + void handOffTo(RecordingBuffers& other); + void makePrimary(); + bool isPrimary() const; + + void append(const RecordingBuffers& other); + void merge(const RecordingBuffers& other); + void reset(RecordingBuffers* other = NULL); + void flush(); + + AccumulatorBuffer<CountAccumulator> mCounts; + AccumulatorBuffer<SampleAccumulator> mSamples; + AccumulatorBuffer<EventAccumulator> mEvents; + AccumulatorBuffer<TimeBlockAccumulator> mStackTimers; + AccumulatorBuffer<MemStatAccumulator> mMemStats; + }; + + class Recording + : public LLStopWatchControlsMixin<Recording> + { + public: + Recording(); + + Recording(const Recording& other); + ~Recording(); + + // accumulate data from subsequent, non-overlapping recording + void appendRecording(const Recording& other); + + // gather data from recording, ignoring time relationship (for example, pulling data from slave threads) + void mergeRecording(const Recording& other); + + // grab latest recorded data + void update(); + + // ensure that buffers are exclusively owned by this recording + void makeUnique() { mBuffers.makeUnique(); } + + // Timer accessors + LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator>& stat); + LLUnit<LLUnits::Seconds, F64> getSum(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat); + U32 getSum(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat); + + LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator>& stat); + LLUnit<LLUnits::Seconds, F64> getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeFacet>& stat); + F32 getPerSec(const TraceType<TimeBlockAccumulator::CallCountFacet>& stat); + + // Memory accessors + LLUnit<LLUnits::Bytes, F64> getMin(const TraceType<MemStatAccumulator>& stat); + LLUnit<LLUnits::Bytes, F64> getMean(const TraceType<MemStatAccumulator>& stat); + LLUnit<LLUnits::Bytes, F64> getMax(const TraceType<MemStatAccumulator>& stat); + LLUnit<LLUnits::Bytes, F64> getStandardDeviation(const TraceType<MemStatAccumulator>& stat); + LLUnit<LLUnits::Bytes, F64> getLastValue(const TraceType<MemStatAccumulator>& stat); + + LLUnit<LLUnits::Bytes, F64> getMin(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<LLUnits::Bytes, F64> getMean(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<LLUnits::Bytes, F64> getMax(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<LLUnits::Bytes, F64> getStandardDeviation(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + LLUnit<LLUnits::Bytes, F64> getLastValue(const TraceType<MemStatAccumulator::ChildMemFacet>& stat); + + U32 getSum(const TraceType<MemStatAccumulator::AllocationCountFacet>& stat); + U32 getSum(const TraceType<MemStatAccumulator::DeallocationCountFacet>& stat); + + // CountStatHandle accessors + F64 getSum(const TraceType<CountAccumulator>& stat); + template <typename T> + T getSum(const CountStatHandle<T>& stat) + { + return (T)getSum(static_cast<const TraceType<CountAccumulator>&> (stat)); + } + + F64 getPerSec(const TraceType<CountAccumulator>& stat); + template <typename T> + T getPerSec(const CountStatHandle<T>& stat) + { + return (T)getPerSec(static_cast<const TraceType<CountAccumulator>&> (stat)); + } + + U32 getSampleCount(const TraceType<CountAccumulator>& stat); + + + // SampleStatHandle accessors + F64 getMin(const TraceType<SampleAccumulator>& stat); + template <typename T> + T getMin(const SampleStatHandle<T>& stat) + { + return (T)getMin(static_cast<const TraceType<SampleAccumulator>&> (stat)); + } + + F64 getMean(const TraceType<SampleAccumulator>& stat); + template <typename T> + T getMean(SampleStatHandle<T>& stat) + { + return (T)getMean(static_cast<const TraceType<SampleAccumulator>&> (stat)); + } + + F64 getMax(const TraceType<SampleAccumulator>& stat); + template <typename T> + T getMax(const SampleStatHandle<T>& stat) + { + return (T)getMax(static_cast<const TraceType<SampleAccumulator>&> (stat)); + } + + F64 getStandardDeviation(const TraceType<SampleAccumulator>& stat); + template <typename T> + T getStandardDeviation(const SampleStatHandle<T>& stat) + { + return (T)getStandardDeviation(static_cast<const TraceType<SampleAccumulator>&> (stat)); + } + + F64 getLastValue(const TraceType<SampleAccumulator>& stat); + template <typename T> + T getLastValue(const SampleStatHandle<T>& stat) + { + return (T)getLastValue(static_cast<const TraceType<SampleAccumulator>&> (stat)); + } + + U32 getSampleCount(const TraceType<SampleAccumulator>& stat); + + // EventStatHandle accessors + F64 getSum(const TraceType<EventAccumulator>& stat); + template <typename T> + T getSum(const EventStatHandle<T>& stat) + { + return (T)getSum(static_cast<const TraceType<EventAccumulator>&> (stat)); + } + + F64 getMin(const TraceType<EventAccumulator>& stat); + template <typename T> + T getMin(const EventStatHandle<T>& stat) + { + return (T)getMin(static_cast<const TraceType<EventAccumulator>&> (stat)); + } + + F64 getMax(const TraceType<EventAccumulator>& stat); + template <typename T> + T getMax(const EventStatHandle<T>& stat) + { + return (T)getMax(static_cast<const TraceType<EventAccumulator>&> (stat)); + } + + F64 getMean(const TraceType<EventAccumulator>& stat); + template <typename T> + T getMean(EventStatHandle<T>& stat) + { + return (T)getMean(static_cast<const TraceType<EventAccumulator>&> (stat)); + } + + F64 getStandardDeviation(const TraceType<EventAccumulator>& stat); + template <typename T> + T getStandardDeviation(const EventStatHandle<T>& stat) + { + return (T)getStandardDeviation(static_cast<const TraceType<EventAccumulator>&> (stat)); + } + + F64 getLastValue(const TraceType<EventAccumulator>& stat); + template <typename T> + T getLastValue(const EventStatHandle<T>& stat) + { + return (T)getLastValue(static_cast<const TraceType<EventAccumulator>&> (stat)); + } + + U32 getSampleCount(const TraceType<EventAccumulator>& stat); + + LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); } + + protected: + friend class ThreadRecorder; + + // implementation for LLStopWatchControlsMixin + /*virtual*/ void handleStart(); + /*virtual*/ void handleStop(); + /*virtual*/ void handleReset(); + /*virtual*/ void handleSplitTo(Recording& other); + + // returns data for current thread + class ThreadRecorder* getThreadRecorder(); + + LLTimer mSamplingTimer; + F64 mElapsedSeconds; + LLCopyOnWritePointer<RecordingBuffers> mBuffers; + }; + + class LL_COMMON_API PeriodicRecording + : public LLStopWatchControlsMixin<PeriodicRecording> + { + public: + PeriodicRecording(U32 num_periods, EPlayState state = STOPPED); + + void nextPeriod(); + U32 getNumPeriods() { return mRecordingPeriods.size(); } + + LLUnit<LLUnits::Seconds, F64> getDuration() const; + + void appendPeriodicRecording(PeriodicRecording& other); + Recording& getLastRecording(); + const Recording& getLastRecording() const; + Recording& getCurRecording(); + const Recording& getCurRecording() const; + Recording& getPrevRecording(U32 offset); + const Recording& getPrevRecording(U32 offset) const; + Recording snapshotCurRecording() const; + + // catch all for stats that have a defined sum + template <typename T> + typename T::value_t getPeriodMin(const TraceType<T>& stat, size_t num_periods = U32_MAX) + { + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + typename T::value_t min_val = std::numeric_limits<typename T::value_t>::max(); + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + min_val = llmin(min_val, mRecordingPeriods[index].getSum(stat)); + } + return min_val; + } + + F64 getPeriodMin(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX); + template<typename T> + T getPeriodMin(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX) + { + return T(getPeriodMin(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodMin(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX); + template<typename T> + T getPeriodMin(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX) + { + return T(getPeriodMin(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods)); + } + + template <typename T> + F64 getPeriodMinPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) + { + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + F64 min_val = std::numeric_limits<F64>::max(); + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + min_val = llmin(min_val, mRecordingPeriods[index].getPerSec(stat)); + } + return min_val; + } + + // catch all for stats that have a defined sum + template <typename T> + typename T::value_t getPeriodMax(const TraceType<T>& stat, size_t num_periods = U32_MAX) + { + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + typename T::value_t max_val = std::numeric_limits<typename T::value_t>::min(); + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + max_val = llmax(max_val, mRecordingPeriods[index].getSum(stat)); + } + return max_val; + } + + F64 getPeriodMax(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX); + template<typename T> + T getPeriodMax(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX) + { + return T(getPeriodMax(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodMax(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX); + template<typename T> + T getPeriodMax(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX) + { + return T(getPeriodMax(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods)); + } + + template <typename T> + F64 getPeriodMaxPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) + { + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + F64 max_val = std::numeric_limits<F64>::min(); + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + max_val = llmax(max_val, mRecordingPeriods[index].getPerSec(stat)); + } + return max_val; + } + + // catch all for stats that have a defined sum + template <typename T> + typename T::mean_t getPeriodMean(const TraceType<T >& stat, size_t num_periods = U32_MAX) + { + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + typename T::mean_t mean = 0; + if (num_periods <= 0) { return mean; } + + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + if (mRecordingPeriods[index].getDuration() > 0.f) + { + mean += mRecordingPeriods[index].getSum(stat); + } + } + mean = mean / num_periods; + return mean; + } + + F64 getPeriodMean(const TraceType<SampleAccumulator>& stat, size_t num_periods = U32_MAX); + template<typename T> + T getPeriodMean(const SampleStatHandle<T>& stat, size_t num_periods = U32_MAX) + { + return T(getPeriodMean(static_cast<const TraceType<SampleAccumulator>&>(stat), num_periods)); + } + + F64 getPeriodMean(const TraceType<EventAccumulator>& stat, size_t num_periods = U32_MAX); + template<typename T> + T getPeriodMean(const EventStatHandle<T>& stat, size_t num_periods = U32_MAX) + { + return T(getPeriodMean(static_cast<const TraceType<EventAccumulator>&>(stat), num_periods)); + } + + template <typename T> + typename T::mean_t getPeriodMeanPerSec(const TraceType<T>& stat, size_t num_periods = U32_MAX) + { + size_t total_periods = mRecordingPeriods.size(); + num_periods = llmin(num_periods, total_periods); + + typename T::mean_t mean = 0; + if (num_periods <= 0) { return mean; } + + for (S32 i = 1; i <= num_periods; i++) + { + S32 index = (mCurPeriod + total_periods - i) % total_periods; + if (mRecordingPeriods[index].getDuration() > 0.f) + { + mean += mRecordingPeriods[index].getPerSec(stat); + } + } + mean = mean / num_periods; + return mean; + } + + private: + // implementation for LLStopWatchControlsMixin + /*virtual*/ void handleStart(); + /*virtual*/ void handleStop(); + /*virtual*/ void handleReset(); + /*virtual*/ void handleSplitTo(PeriodicRecording& other); + + private: + std::vector<Recording> mRecordingPeriods; + const bool mAutoResize; + S32 mCurPeriod; + }; + + PeriodicRecording& get_frame_recording(); + + class ExtendableRecording + : public LLStopWatchControlsMixin<ExtendableRecording> + { + public: + void extend(); + + Recording& getAcceptedRecording() { return mAcceptedRecording; } + const Recording& getAcceptedRecording() const {return mAcceptedRecording;} + + Recording& getPotentialRecording() { return mPotentialRecording; } + const Recording& getPotentialRecording() const { return mPotentialRecording;} + + private: + // implementation for LLStopWatchControlsMixin + /*virtual*/ void handleStart(); + /*virtual*/ void handleStop(); + /*virtual*/ void handleReset(); + /*virtual*/ void handleSplitTo(ExtendableRecording& other); + + private: + Recording mAcceptedRecording; + Recording mPotentialRecording; + }; + + class ExtendablePeriodicRecording + : public LLStopWatchControlsMixin<ExtendablePeriodicRecording> + { + public: + ExtendablePeriodicRecording(); + void extend(); + + PeriodicRecording& getAcceptedRecording() { return mAcceptedRecording; } + const PeriodicRecording& getAcceptedRecording() const {return mAcceptedRecording;} + + PeriodicRecording& getPotentialRecording() { return mPotentialRecording; } + const PeriodicRecording& getPotentialRecording() const {return mPotentialRecording;} + + private: + // implementation for LLStopWatchControlsMixin + /*virtual*/ void handleStart(); + /*virtual*/ void handleStop(); + /*virtual*/ void handleReset(); + /*virtual*/ void handleSplitTo(ExtendablePeriodicRecording& other); + + private: + PeriodicRecording mAcceptedRecording; + PeriodicRecording mPotentialRecording; + }; +} + +#endif // LL_LLTRACERECORDING_H diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp new file mode 100644 index 0000000000..c1a0700eff --- /dev/null +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -0,0 +1,291 @@ +/** + * @file lltracethreadrecorder.cpp + * + * $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$ + */ + +#include "linden_common.h" + +#include "lltracethreadrecorder.h" +#include "llfasttimer.h" + +namespace LLTrace +{ + + +/////////////////////////////////////////////////////////////////////// +// ThreadRecorder +/////////////////////////////////////////////////////////////////////// + +ThreadRecorder::ThreadRecorder() +{ + //NB: the ordering of initialization in this function is very fragile due to a large number of implicit dependencies + set_thread_recorder(this); + TimeBlock& root_time_block = TimeBlock::getRootTimeBlock(); + + ThreadTimerStack* timer_stack = ThreadTimerStack::getInstance(); + timer_stack->mTimeBlock = &root_time_block; + timer_stack->mActiveTimer = NULL; + + mNumTimeBlockTreeNodes = AccumulatorBuffer<TimeBlockAccumulator>::getDefaultBuffer()->size(); + mTimeBlockTreeNodes = new TimeBlockTreeNode[mNumTimeBlockTreeNodes]; + + mThreadRecording.start(); + + // initialize time block parent pointers + for (LLInstanceTracker<TimeBlock>::instance_iter it = LLInstanceTracker<TimeBlock>::beginInstances(), end_it = LLInstanceTracker<TimeBlock>::endInstances(); + it != end_it; + ++it) + { + TimeBlock& time_block = *it; + TimeBlockTreeNode& tree_node = mTimeBlockTreeNodes[it->getIndex()]; + tree_node.mBlock = &time_block; + tree_node.mParent = &root_time_block; + + it->getPrimaryAccumulator()->mParent = &root_time_block; + } + + mRootTimer = new BlockTimer(root_time_block); + timer_stack->mActiveTimer = mRootTimer; + + TimeBlock::getRootTimeBlock().getPrimaryAccumulator()->mActiveCount = 1; +} + +ThreadRecorder::~ThreadRecorder() +{ + delete mRootTimer; + + if (!mActiveRecordings.empty()) + { + std::for_each(mActiveRecordings.begin(), mActiveRecordings.end(), DeletePointer()); + mActiveRecordings.clear(); + } + + set_thread_recorder(NULL); + delete[] mTimeBlockTreeNodes; +} + +TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode(S32 index) +{ + if (0 <= index && index < mNumTimeBlockTreeNodes) + { + return &mTimeBlockTreeNodes[index]; + } + return NULL; +} + + +void ThreadRecorder::activate( Recording* recording ) +{ + ActiveRecording* active_recording = new ActiveRecording(recording); + if (!mActiveRecordings.empty()) + { + mActiveRecordings.back()->mPartialRecording.handOffTo(active_recording->mPartialRecording); + } + mActiveRecordings.push_back(active_recording); + + mActiveRecordings.back()->mPartialRecording.makePrimary(); +} + +ThreadRecorder::active_recording_list_t::reverse_iterator ThreadRecorder::bringUpToDate( Recording* recording ) +{ + if (mActiveRecordings.empty()) return mActiveRecordings.rend(); + + mActiveRecordings.back()->mPartialRecording.flush(); + + active_recording_list_t::reverse_iterator it, end_it; + for (it = mActiveRecordings.rbegin(), end_it = mActiveRecordings.rend(); + it != end_it; + ++it) + { + ActiveRecording* cur_recording = *it; + + active_recording_list_t::reverse_iterator next_it = it; + ++next_it; + + // if we have another recording further down in the stack... + if (next_it != mActiveRecordings.rend()) + { + // ...push our gathered data down to it + (*next_it)->mPartialRecording.append(cur_recording->mPartialRecording); + } + + // copy accumulated measurements into result buffer and clear accumulator (mPartialRecording) + cur_recording->movePartialToTarget(); + + if (cur_recording->mTargetRecording == recording) + { + // found the recording, so return it + break; + } + } + + if (it == end_it) + { + llwarns << "Recording not active on this thread" << llendl; + } + + return it; +} + +void ThreadRecorder::deactivate( Recording* recording ) +{ + active_recording_list_t::reverse_iterator it = bringUpToDate(recording); + if (it != mActiveRecordings.rend()) + { + // and if we've found the recording we wanted to update + active_recording_list_t::reverse_iterator next_it = it; + ++next_it; + if (next_it != mActiveRecordings.rend()) + { + (*next_it)->mPartialRecording.makePrimary(); + } + + active_recording_list_t::iterator recording_to_remove = (++it).base(); + llassert((*recording_to_remove)->mTargetRecording == recording); + delete *recording_to_remove; + mActiveRecordings.erase(recording_to_remove); + } +} + +ThreadRecorder::ActiveRecording::ActiveRecording( Recording* target ) +: mTargetRecording(target) +{ +} + +void ThreadRecorder::ActiveRecording::movePartialToTarget() +{ + mTargetRecording->mBuffers.write()->append(mPartialRecording); + // reset based on self to keep history + mPartialRecording.reset(&mPartialRecording); +} + + +/////////////////////////////////////////////////////////////////////// +// SlaveThreadRecorder +/////////////////////////////////////////////////////////////////////// + +SlaveThreadRecorder::SlaveThreadRecorder(MasterThreadRecorder& master) +: mMasterRecorder(master) +{ + mMasterRecorder.addSlaveThread(this); +} + +SlaveThreadRecorder::~SlaveThreadRecorder() +{ + mMasterRecorder.removeSlaveThread(this); +} + +void SlaveThreadRecorder::pushToMaster() +{ + mThreadRecording.stop(); + { + LLMutexLock(mMasterRecorder.getSlaveListMutex()); + mSharedData.appendFrom(mThreadRecording); + } + mThreadRecording.start(); +} + +void SlaveThreadRecorder::SharedData::appendFrom( const Recording& source ) +{ + LLMutexLock lock(&mRecordingMutex); + appendRecording(source); +} + +void SlaveThreadRecorder::SharedData::appendTo( Recording& sink ) +{ + LLMutexLock lock(&mRecordingMutex); + sink.appendRecording(*this); +} + +void SlaveThreadRecorder::SharedData::mergeFrom( const RecordingBuffers& source ) +{ + LLMutexLock lock(&mRecordingMutex); + mBuffers.write()->merge(source); +} + +void SlaveThreadRecorder::SharedData::mergeTo( RecordingBuffers& sink ) +{ + LLMutexLock lock(&mRecordingMutex); + sink.merge(*mBuffers); +} + +void SlaveThreadRecorder::SharedData::reset() +{ + LLMutexLock lock(&mRecordingMutex); + Recording::reset(); +} + + +/////////////////////////////////////////////////////////////////////// +// MasterThreadRecorder +/////////////////////////////////////////////////////////////////////// + +static LLFastTimer::DeclareTimer FTM_PULL_TRACE_DATA_FROM_SLAVES("Pull slave trace data"); +void MasterThreadRecorder::pullFromSlaveThreads() +{ + LLFastTimer _(FTM_PULL_TRACE_DATA_FROM_SLAVES); + if (mActiveRecordings.empty()) return; + + LLMutexLock lock(&mSlaveListMutex); + + RecordingBuffers& target_recording_buffers = mActiveRecordings.back()->mPartialRecording; + for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end(); + it != end_it; + ++it) + { + // ignore block timing info for now + (*it)->mSharedData.mergeTo(target_recording_buffers); + (*it)->mSharedData.reset(); + } +} + +void MasterThreadRecorder::addSlaveThread( class SlaveThreadRecorder* child ) +{ + LLMutexLock lock(&mSlaveListMutex); + + mSlaveThreadRecorders.push_back(child); +} + +void MasterThreadRecorder::removeSlaveThread( class SlaveThreadRecorder* child ) +{ + LLMutexLock lock(&mSlaveListMutex); + + for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end(); + it != end_it; + ++it) + { + if ((*it) == child) + { + mSlaveThreadRecorders.erase(it); + break; + } + } +} + +void MasterThreadRecorder::pushToMaster() +{} + +MasterThreadRecorder::MasterThreadRecorder() +{} + +} diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h new file mode 100644 index 0000000000..bf3701304f --- /dev/null +++ b/indra/llcommon/lltracethreadrecorder.h @@ -0,0 +1,126 @@ +/** + * @file lltrace.h + * @brief Runtime statistics accumulation. + * + * $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_LLTRACETHREADRECORDER_H +#define LL_LLTRACETHREADRECORDER_H + +#include "stdtypes.h" +#include "llpreprocessor.h" + +#include "llmutex.h" +#include "lltracerecording.h" + +namespace LLTrace +{ + class LL_COMMON_API ThreadRecorder + { + protected: + struct ActiveRecording; + typedef std::vector<ActiveRecording*> active_recording_list_t; + public: + ThreadRecorder(); + + virtual ~ThreadRecorder(); + + void activate(Recording* recording); + void deactivate(Recording* recording); + active_recording_list_t::reverse_iterator bringUpToDate(Recording* recording); + + virtual void pushToMaster() = 0; + + TimeBlockTreeNode* getTimeBlockTreeNode(S32 index); + + protected: + struct ActiveRecording + { + ActiveRecording(Recording* target); + + Recording* mTargetRecording; + RecordingBuffers mPartialRecording; + + void movePartialToTarget(); + }; + Recording mThreadRecording; + + active_recording_list_t mActiveRecordings; + + class BlockTimer* mRootTimer; + TimeBlockTreeNode* mTimeBlockTreeNodes; + size_t mNumTimeBlockTreeNodes; + }; + + class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder + { + public: + MasterThreadRecorder(); + + void addSlaveThread(class SlaveThreadRecorder* child); + void removeSlaveThread(class SlaveThreadRecorder* child); + + /*virtual */ void pushToMaster(); + + // call this periodically to gather stats data from slave threads + void pullFromSlaveThreads(); + + LLMutex* getSlaveListMutex() { return &mSlaveListMutex; } + + + private: + + typedef std::list<class SlaveThreadRecorder*> slave_thread_recorder_list_t; + + slave_thread_recorder_list_t mSlaveThreadRecorders; // list of slave thread recorders associated with this master + LLMutex mSlaveListMutex; // protects access to slave list + }; + + class LL_COMMON_API SlaveThreadRecorder : public ThreadRecorder + { + public: + SlaveThreadRecorder(MasterThreadRecorder& master); + ~SlaveThreadRecorder(); + + // call this periodically to gather stats data for master thread to consume + /*virtual*/ void pushToMaster(); + + MasterThreadRecorder* mMaster; + + class SharedData : public Recording + { + public: + void appendFrom(const Recording& source); + void appendTo(Recording& sink); + void mergeFrom(const RecordingBuffers& source); + void mergeTo(RecordingBuffers& sink); + void reset(); + private: + LLMutex mRecordingMutex; + }; + SharedData mSharedData; + MasterThreadRecorder& mMasterRecorder; + }; +} + +#endif // LL_LLTRACETHREADRECORDER_H diff --git a/indra/llcommon/lltypeinfolookup.h b/indra/llcommon/lltypeinfolookup.h deleted file mode 100755 index 0b6862444e..0000000000 --- a/indra/llcommon/lltypeinfolookup.h +++ /dev/null @@ -1,117 +0,0 @@ -/** - * @file lltypeinfolookup.h - * @author Nat Goodspeed - * @date 2012-04-08 - * @brief Template data structure like std::map<std::type_info*, T> - * - * $LicenseInfo:firstyear=2012&license=viewerlgpl$ - * Copyright (c) 2012, Linden Research, Inc. - * $/LicenseInfo$ - */ - -#if ! defined(LL_LLTYPEINFOLOOKUP_H) -#define LL_LLTYPEINFOLOOKUP_H - -#include <boost/unordered_map.hpp> -#include <boost/functional/hash.hpp> -#include <boost/optional.hpp> -#include <functional> // std::binary_function -#include <typeinfo> - -/** - * The following helper classes are based on the Boost.Unordered documentation: - * http://www.boost.org/doc/libs/1_45_0/doc/html/unordered/hash_equality.html - */ - -/** - * Compute hash for a string passed as const char* - */ -struct const_char_star_hash: public std::unary_function<const char*, std::size_t> -{ - std::size_t operator()(const char* str) const - { - std::size_t seed = 0; - for ( ; *str; ++str) - { - boost::hash_combine(seed, *str); - } - return seed; - } -}; - -/** - * Compute equality for strings passed as const char* - * - * I (nat) suspect that this is where the default behavior breaks for the - * const char* values returned from std::type_info::name(). If you compare the - * two const char* pointer values, as a naive, unspecialized implementation - * will surely do, they'll compare unequal. - */ -struct const_char_star_equal: public std::binary_function<const char*, const char*, bool> -{ - bool operator()(const char* lhs, const char* rhs) const - { - return strcmp(lhs, rhs) == 0; - } -}; - -/** - * LLTypeInfoLookup is specifically designed for use cases for which you might - * consider std::map<std::type_info*, VALUE>. We have several such data - * structures in the viewer. The trouble with them is that at least on Linux, - * you can't rely on always getting the same std::type_info* for a given type: - * different load modules will produce different std::type_info*. - * LLTypeInfoLookup contains a workaround to address this issue. - * - * The API deliberately diverges from std::map in several respects: - * * It avoids iterators, not only begin()/end() but also as return values - * from insert() and find(). This bypasses transform_iterator overhead. - * * Since we literally use compile-time types as keys, the essential insert() - * and find() methods accept the key type as a @em template parameter, - * accepting and returning value_type as a normal runtime value. This is to - * permit future optimization (e.g. compile-time type hashing) without - * changing the API. - */ -template <typename VALUE> -class LLTypeInfoLookup -{ - // Use this for our underlying implementation: lookup by - // std::type_info::name() string. This is one of the rare cases in which I - // dare use const char* directly, rather than std::string, because I'm - // sure that every value returned by std::type_info::name() is static. - // HOWEVER, specify our own hash + equality functors: naively comparing - // distinct const char* values won't work. - typedef boost::unordered_map<const char*, VALUE, - const_char_star_hash, const_char_star_equal> impl_map_type; - -public: - typedef VALUE value_type; - - LLTypeInfoLookup() {} - - bool empty() const { return mMap.empty(); } - std::size_t size() const { return mMap.size(); } - - template <typename KEY> - bool insert(const value_type& value) - { - // Obtain and store the std::type_info::name() string as the key. - // Return just the bool from std::map::insert()'s return pair. - return mMap.insert(typename impl_map_type::value_type(typeid(KEY).name(), value)).second; - } - - template <typename KEY> - boost::optional<value_type> find() const - { - // Use the std::type_info::name() string as the key. - typename impl_map_type::const_iterator found = mMap.find(typeid(KEY).name()); - if (found == mMap.end()) - return boost::optional<value_type>(); - return found->second; - } - -private: - impl_map_type mMap; -}; - -#endif /* ! defined(LL_LLTYPEINFOLOOKUP_H) */ diff --git a/indra/llcommon/llunit.h b/indra/llcommon/llunit.h new file mode 100644 index 0000000000..a5406fb3f0 --- /dev/null +++ b/indra/llcommon/llunit.h @@ -0,0 +1,481 @@ +/** + * @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_LLUNIT_H +#define LL_LLUNIT_H + +#include "stdtypes.h" +#include "llpreprocessor.h" +#include "llerrorlegacy.h" + +namespace LLUnits +{ + +template<typename DERIVED_UNITS_TAG, typename BASE_UNITS_TAG, typename VALUE_TYPE> +struct ConversionFactor +{ + static F64 get() + { + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + llstatic_assert_template(DERIVED_UNITS_TAG, false, "Cannot convert between types."); + } +}; + +template<typename BASE_UNITS_TAG, typename VALUE_TYPE> +struct ConversionFactor<BASE_UNITS_TAG, BASE_UNITS_TAG, VALUE_TYPE> +{ + static F64 get() + { + return 1; + } +}; + +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE> +struct LLUnit +{ + typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> self_t; + typedef STORAGE_TYPE storage_t; + + // value initialization + LLUnit(storage_t value = storage_t()) + : mValue(value) + {} + + // unit initialization and conversion + template<typename OTHER_UNIT, typename OTHER_STORAGE> + LLUnit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + : mValue(convert(other)) + {} + + // value assignment + self_t& operator = (storage_t value) + { + mValue = value; + return *this; + } + + // unit assignment + template<typename OTHER_UNIT, typename OTHER_STORAGE> + self_t& operator = (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + { + mValue = convert(other); + return *this; + } + + storage_t value() const + { + return mValue; + } + + template<typename NEW_UNIT_TYPE> LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE> as() + { + return LLUnit<NEW_UNIT_TYPE, STORAGE_TYPE>(*this); + } + + + void operator += (storage_t value) + { + mValue += value; + } + + template<typename OTHER_UNIT, typename OTHER_STORAGE> + void operator += (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + { + mValue += convert(other); + } + + void operator -= (storage_t value) + { + mValue -= value; + } + + template<typename OTHER_UNIT, typename OTHER_STORAGE> + void operator -= (LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + { + mValue -= convert(other); + } + + void operator *= (storage_t multiplicand) + { + mValue *= multiplicand; + } + + template<typename OTHER_UNIT, typename OTHER_STORAGE> + void operator *= (LLUnit<OTHER_UNIT, OTHER_STORAGE> multiplicand) + { + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + llstatic_assert_template(OTHER_UNIT, false, "Multiplication of unit types not supported."); + } + + void operator /= (storage_t divisor) + { + mValue /= divisor; + } + + template<typename OTHER_UNIT, typename OTHER_STORAGE> + void operator /= (LLUnit<OTHER_UNIT, OTHER_STORAGE> divisor) + { + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + llstatic_assert_template(OTHER_UNIT, false, "Illegal in-place division of unit types."); + } + + template<typename SOURCE_UNITS, typename SOURCE_STORAGE> + static storage_t convert(LLUnit<SOURCE_UNITS, SOURCE_STORAGE> v) + { + return (storage_t)(v.value() + * LLUnits::ConversionFactor<SOURCE_UNITS, typename UNIT_TYPE::base_unit_t, SOURCE_STORAGE>::get() + * LLUnits::ConversionFactor<typename UNIT_TYPE::base_unit_t, UNIT_TYPE, STORAGE_TYPE>::get()); + } + +protected: + storage_t mValue; +}; + +template<typename UNIT_TYPE, typename STORAGE_TYPE> +struct LLUnitImplicit : public LLUnit<UNIT_TYPE, STORAGE_TYPE> +{ + typedef LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> self_t; + typedef typename LLUnit<UNIT_TYPE, STORAGE_TYPE>::storage_t storage_t; + typedef LLUnit<UNIT_TYPE, STORAGE_TYPE> base_t; + + LLUnitImplicit(storage_t value = storage_t()) + : base_t(value) + {} + + template<typename OTHER_UNIT, typename OTHER_STORAGE> + LLUnitImplicit(LLUnit<OTHER_UNIT, OTHER_STORAGE> other) + : base_t(convert(other)) + {} + + // unlike LLUnit, LLUnitImplicit is *implicitly* convertable to a POD scalar (F32, S32, etc) + // this allows for interoperability with legacy code + operator storage_t() const + { + return base_t::value(); + } +}; + +// +// operator + +// +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> +LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +{ + LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + result += second; + return result; +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnit<UNIT_TYPE, STORAGE_TYPE> operator + (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +{ + LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + result += second; + return result; +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnit<UNIT_TYPE, STORAGE_TYPE> operator + (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +{ + LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + result += second; + return result; +} + +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> +LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +{ + LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + result += second; + return result; +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator + (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +{ + LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + result += second; + return result; +} + +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> +LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator + (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +{ + LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + result += second; + return result; +} + +// +// operator - +// +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> +LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator - (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +{ + LLUnit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + result -= second; + return result; +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnit<UNIT_TYPE, STORAGE_TYPE> operator - (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +{ + LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + result -= second; + return result; +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +{ + LLUnit<UNIT_TYPE, STORAGE_TYPE> result(first); + result -= second; + return result; +} + +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> +LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator - (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +{ + LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> result(first); + result -= second; + return result; +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +{ + LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + result -= second; + return result; +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator - (SCALAR_TYPE first, LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> second) +{ + LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> result(first); + result -= second; + return result; +} + +// +// operator * +// +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +{ + return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first * second.value())); +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnit<UNIT_TYPE, STORAGE_TYPE> operator * (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +{ + return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() * second)); +} + +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> +LLUnit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnit<UNIT_TYPE2, STORAGE_TYPE2>) +{ + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + llstatic_assert_template(STORAGE_TYPE1, false, "Multiplication of unit types results in new unit type - not supported."); + return LLUnit<UNIT_TYPE1, STORAGE_TYPE1>(); +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator * (SCALAR_TYPE first, LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> second) +{ + return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>(first * second.value()); +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator * (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +{ + return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>(first.value() * second); +} + +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> +LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> operator * (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2>) +{ + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + llstatic_assert_template(STORAGE_TYPE1, false, "Multiplication of unit types results in new unit type - not supported."); + return LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1>(); +} + +// +// operator / +// +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +SCALAR_TYPE operator / (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) +{ + return SCALAR_TYPE(first / second.value()); +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +{ + return LLUnit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second)); +} + +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> +STORAGE_TYPE1 operator / (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) +{ + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + return STORAGE_TYPE1(first.value() / second.value()); +} + +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> +LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> operator / (LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) +{ + return LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE>((STORAGE_TYPE)(first.value() / second)); +} + +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> +STORAGE_TYPE1 operator / (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) +{ + // spurious use of dependent type to stop gcc from triggering the static assertion before instantiating the template + return STORAGE_TYPE1(first.value() / second.value()); +} + +#define COMPARISON_OPERATORS(op) \ +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> \ +bool operator op (SCALAR_TYPE first, LLUnit<UNIT_TYPE, STORAGE_TYPE> second) \ +{ \ + return first op second.value(); \ +} \ + \ +template<typename UNIT_TYPE, typename STORAGE_TYPE, typename SCALAR_TYPE> \ +bool operator op (LLUnit<UNIT_TYPE, STORAGE_TYPE> first, SCALAR_TYPE second) \ +{ \ + return first.value() op second; \ +} \ + \ +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> \ +bool operator op (LLUnitImplicit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnitImplicit<UNIT_TYPE2, STORAGE_TYPE2> second) \ +{ \ + return first.value() op first.convert(second); \ +} \ + \ +template<typename UNIT_TYPE1, typename STORAGE_TYPE1, typename UNIT_TYPE2, typename STORAGE_TYPE2> \ + bool operator op (LLUnit<UNIT_TYPE1, STORAGE_TYPE1> first, LLUnit<UNIT_TYPE2, STORAGE_TYPE2> second) \ +{ \ + return first.value() op first.convert(second); \ +} + +COMPARISON_OPERATORS(<) +COMPARISON_OPERATORS(<=) +COMPARISON_OPERATORS(>) +COMPARISON_OPERATORS(>=) +COMPARISON_OPERATORS(==) +COMPARISON_OPERATORS(!=) + + +template<typename T> +struct LLGetUnitLabel +{ + static const char* getUnitLabel() { return ""; } +}; + +template<typename T, typename STORAGE_T> +struct LLGetUnitLabel<LLUnit<T, STORAGE_T> > +{ + static const char* getUnitLabel() { return T::getUnitLabel(); } +}; + +// +// Unit declarations +// +namespace LLUnits +{ +template<typename T> +T rawValue(T val) { return val; } + +template<typename UNIT_TYPE, typename STORAGE_TYPE> +STORAGE_TYPE rawValue(LLUnit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); } + +template<typename UNIT_TYPE, typename STORAGE_TYPE> +STORAGE_TYPE rawValue(LLUnitImplicit<UNIT_TYPE, STORAGE_TYPE> val) { return val.value(); } + +#define LL_DECLARE_DERIVED_UNIT(conversion_factor, base_unit_name, unit_name, unit_label) \ +struct unit_name \ +{ \ + typedef base_unit_name base_unit_t; \ + static const char* getUnitLabel() { return unit_label; } \ +}; \ +template<typename STORAGE_TYPE> \ +struct ConversionFactor<unit_name, base_unit_name, STORAGE_TYPE> \ +{ \ + static F64 get() \ + { \ + return (F64)conversion_factor; \ + } \ +}; \ + \ +template<typename STORAGE_TYPE> \ +struct ConversionFactor<base_unit_name, unit_name, STORAGE_TYPE> \ +{ \ + static F64 get() \ + { \ + return (F64)(1.0 / (conversion_factor)); \ + } \ +} + +#define LL_DECLARE_BASE_UNIT(base_unit_name, unit_label) \ +struct base_unit_name { typedef base_unit_name base_unit_t; static const char* getUnitLabel() { return unit_label; }} + +LL_DECLARE_BASE_UNIT(Bytes, "B"); +LL_DECLARE_DERIVED_UNIT(1024, Bytes, Kibibytes, "KiB"); +LL_DECLARE_DERIVED_UNIT(1024 * 1024, Bytes, Mibibytes, "MiB"); +LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024, Bytes, Gibibytes, "GiB"); +LL_DECLARE_DERIVED_UNIT(1.0 / 8.0, Bytes, Bits, "b"); +LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Kibibits, "Kib"); +LL_DECLARE_DERIVED_UNIT(1024 / 8, Bytes, Mibibits, "Mib"); +LL_DECLARE_DERIVED_UNIT(1024 * 1024 * 1024 / 8, Bytes, Gibibits, "Gib"); + +LL_DECLARE_BASE_UNIT(Seconds, "s"); +LL_DECLARE_DERIVED_UNIT(60, Seconds, Minutes, "min"); +LL_DECLARE_DERIVED_UNIT(60 * 60, Seconds, Hours, "h"); +LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Seconds, Milliseconds, "ms"); +LL_DECLARE_DERIVED_UNIT(1.0 / 1000000.0, Seconds, Microseconds, "\x09\x3cs"); +LL_DECLARE_DERIVED_UNIT(1.0 / 1000000000.0, Seconds, Nanoseconds, "ns"); + +LL_DECLARE_BASE_UNIT(Meters, "m"); +LL_DECLARE_DERIVED_UNIT(1000, Meters, Kilometers, "km"); +LL_DECLARE_DERIVED_UNIT(1.0 / 100.0, Meters, Centimeters, "cm"); +LL_DECLARE_DERIVED_UNIT(1.0 / 1000.0, Meters, Millimeters, "mm"); + +LL_DECLARE_BASE_UNIT(Hertz, "Hz"); +LL_DECLARE_DERIVED_UNIT(1000, Hertz, Kilohertz, "KHz"); +LL_DECLARE_DERIVED_UNIT(1000 * 1000, Hertz, Megahertz, "MHz"); +LL_DECLARE_DERIVED_UNIT(1000 * 1000 * 1000, Hertz, Gigahertz, "GHz"); + +LL_DECLARE_BASE_UNIT(Radians, "rad"); +LL_DECLARE_DERIVED_UNIT(DEG_TO_RAD, Radians, Degrees, "deg"); + + +} // namespace LLUnits + +#endif // LL_LLUNIT_H diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index 0aaa50d231..ba4b670b9a 100755 --- 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 <winsock2.h> -#include <windows.h> +#include "llwin32headers.h" // ugh, this is ugly. We need to straighten out our linking for this library #pragma comment(lib, "IPHLPAPI.lib") #include <iphlpapi.h> diff --git a/indra/llcommon/lluuidhashmap.h b/indra/llcommon/lluuidhashmap.h deleted file mode 100755 index e294670030..0000000000 --- a/indra/llcommon/lluuidhashmap.h +++ /dev/null @@ -1,583 +0,0 @@ -/** - * @file lluuidhashmap.h - * @brief A uuid based hash map. - * - * $LicenseInfo:firstyear=2003&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_LLUUIDHASHMAP_H -#define LL_LLUUIDHASHMAP_H - -#include "stdtypes.h" -#include "llerror.h" -#include "lluuid.h" - -// UUID hash map - - /* - LLUUIDHashMap<uuid_pair, 32> foo(test_equals); - LLUUIDHashMapIter<uuid_pair, 32> bar(&foo); - - LLDynamicArray<LLUUID> source_ids; - const S32 COUNT = 100000; - S32 q; - for (q = 0; q < COUNT; q++) - { - llinfos << "Creating" << llendl; - LLUUID id; - id.generate(); - //llinfos << q << ":" << id << llendl; - uuid_pair pair; - pair.mUUID = id; - pair.mValue = q; - foo.set(id, pair); - source_ids.put(id); - //ms_sleep(1); - } - - uuid_pair cur; - llinfos << "Iterating" << llendl; - for (cur = bar.first(); !bar.done(); cur = bar.next()) - { - if (source_ids[cur.mValue] != cur.mUUID) - { - llerrs << "Incorrect value iterated!" << llendl; - } - //llinfos << cur.mValue << ":" << cur.mUUID << llendl; - //ms_sleep(1); - } - - llinfos << "Finding" << llendl; - for (q = 0; q < COUNT; q++) - { - cur = foo.get(source_ids[q]); - if (source_ids[cur.mValue] != cur.mUUID) - { - llerrs << "Incorrect value found!" << llendl; - } - //llinfos << res.mValue << ":" << res.mUUID << llendl; - //ms_sleep(1); - } - - llinfos << "Removing" << llendl; - for (q = 0; q < COUNT/2; q++) - { - if (!foo.remove(source_ids[q])) - { - llerrs << "Remove failed!" << llendl; - } - //ms_sleep(1); - } - - llinfos << "Iterating" << llendl; - for (cur = bar.first(); !bar.done(); cur = bar.next()) - { - if (source_ids[cur.mValue] != cur.mUUID) - { - llerrs << "Incorrect value found!" << llendl; - } - //llinfos << cur.mValue << ":" << cur.mUUID << llendl; - //ms_sleep(1); - } - llinfos << "Done with UUID map test" << llendl; - - return 0; - */ - - -// -// LLUUIDHashNode -// - -template <class DATA, int SIZE> -class LLUUIDHashNode -{ -public: - LLUUIDHashNode(); - -public: - S32 mCount; - U8 mKey[SIZE]; - DATA mData[SIZE]; - LLUUIDHashNode<DATA, SIZE> *mNextNodep; -}; - - -// -// LLUUIDHashNode implementation -// -template <class DATA, int SIZE> -LLUUIDHashNode<DATA, SIZE>::LLUUIDHashNode() -{ - mCount = 0; - mNextNodep = NULL; -} - - -template <class DATA_TYPE, int SIZE> -class LLUUIDHashMap -{ -public: - // basic constructor including sorter - LLUUIDHashMap(BOOL (*equals)(const LLUUID &uuid, const DATA_TYPE &data), - const DATA_TYPE &null_data); - ~LLUUIDHashMap(); - - inline DATA_TYPE &get(const LLUUID &uuid); - inline BOOL check(const LLUUID &uuid) const; - inline DATA_TYPE &set(const LLUUID &uuid, const DATA_TYPE &type); - inline BOOL remove(const LLUUID &uuid); - void removeAll(); - - inline S32 getLength() const; // Warning, NOT O(1!) -public: - BOOL (*mEquals)(const LLUUID &uuid, const DATA_TYPE &data); - LLUUIDHashNode<DATA_TYPE, SIZE> mNodes[256]; - - S32 mIterCount; -protected: - DATA_TYPE mNull; -}; - - -// -// LLUUIDHashMap implementation -// - -template <class DATA_TYPE, int SIZE> -LLUUIDHashMap<DATA_TYPE, SIZE>::LLUUIDHashMap(BOOL (*equals)(const LLUUID &uuid, const DATA_TYPE &data), - const DATA_TYPE &null_data) -: mEquals(equals), - mIterCount(0), - mNull(null_data) -{ } - -template <class DATA_TYPE, int SIZE> -LLUUIDHashMap<DATA_TYPE, SIZE>::~LLUUIDHashMap() -{ - removeAll(); -} - -template <class DATA_TYPE, int SIZE> -void LLUUIDHashMap<DATA_TYPE, SIZE>::removeAll() -{ - S32 bin; - for (bin = 0; bin < 256; bin++) - { - LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[bin]; - - BOOL first = TRUE; - while (nodep) - { - S32 i; - const S32 count = nodep->mCount; - - // Iterate through all members of this node - for (i = 0; i < count; i++) - { - nodep->mData[i] = mNull; - } - - nodep->mCount = 0; - // Done with all objects in this node, go to the next. - - LLUUIDHashNode<DATA_TYPE, SIZE>* curp = nodep; - nodep = nodep->mNextNodep; - - // Delete the node if it's not the first node - if (first) - { - first = FALSE; - curp->mNextNodep = NULL; - } - else - { - delete curp; - } - } - } -} - -template <class DATA_TYPE, int SIZE> -inline S32 LLUUIDHashMap<DATA_TYPE, SIZE>::getLength() const -{ - S32 count = 0; - S32 bin; - for (bin = 0; bin < 256; bin++) - { - LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = (LLUUIDHashNode<DATA_TYPE, SIZE>*) &mNodes[bin]; - while (nodep) - { - count += nodep->mCount; - nodep = nodep->mNextNodep; - } - } - return count; -} - -template <class DATA_TYPE, int SIZE> -inline DATA_TYPE &LLUUIDHashMap<DATA_TYPE, SIZE>::get(const LLUUID &uuid) -{ - LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]]; - - // Grab the second byte of the UUID, which is the key for the node data - const S32 second_byte = uuid.mData[1]; - while (nodep) - { - S32 i; - const S32 count = nodep->mCount; - - // Iterate through all members of this node - for (i = 0; i < count; i++) - { - if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i])) - { - // The second byte matched, and our equality test passed. - // We found it. - return nodep->mData[i]; - } - } - - // Done with all objects in this node, go to the next. - nodep = nodep->mNextNodep; - } - return mNull; -} - - -template <class DATA_TYPE, int SIZE> -inline BOOL LLUUIDHashMap<DATA_TYPE, SIZE>::check(const LLUUID &uuid) const -{ - const LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]]; - - // Grab the second byte of the UUID, which is the key for the node data - const S32 second_byte = uuid.mData[1]; - while (nodep) - { - S32 i; - const S32 count = nodep->mCount; - - // Iterate through all members of this node - for (i = 0; i < count; i++) - { - if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i])) - { - // The second byte matched, and our equality test passed. - // We found it. - return TRUE; - } - } - - // Done with all objects in this node, go to the next. - nodep = nodep->mNextNodep; - } - - // Didn't find anything - return FALSE; -} - - -template <class DATA_TYPE, int SIZE> -inline DATA_TYPE &LLUUIDHashMap<DATA_TYPE, SIZE>::set(const LLUUID &uuid, const DATA_TYPE &data) -{ - // Set is just like a normal find, except that if we find a match - // we replace it with the input value. - // If we don't find a match, we append to the end of the list. - - LLUUIDHashNode<DATA_TYPE, SIZE>* nodep = &mNodes[uuid.mData[0]]; - - const S32 second_byte = uuid.mData[1]; - while (1) - { - const S32 count = nodep->mCount; - - S32 i; - for (i = 0; i < count; i++) - { - if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i])) - { - // We found a match for this key, replace the data with - // the incoming data. - nodep->mData[i] = data; - return nodep->mData[i]; - } - } - if (!nodep->mNextNodep) - { - // We've iterated through all of the keys without finding a match - if (i < SIZE) - { - // There's still some space on this node, append - // the key and data to it. - nodep->mKey[i] = second_byte; - nodep->mData[i] = data; - nodep->mCount++; - - return nodep->mData[i]; - } - else - { - // This node is full, append a new node to the end. - nodep->mNextNodep = new LLUUIDHashNode<DATA_TYPE, SIZE>; - nodep->mNextNodep->mKey[0] = second_byte; - nodep->mNextNodep->mData[0] = data; - nodep->mNextNodep->mCount = 1; - - return nodep->mNextNodep->mData[0]; - } - } - - // No match on this node, go to the next - nodep = nodep->mNextNodep; - } -} - - -template <class DATA_TYPE, int SIZE> -inline BOOL LLUUIDHashMap<DATA_TYPE, SIZE>::remove(const LLUUID &uuid) -{ - if (mIterCount) - { - // We don't allow remove when we're iterating, it's bad karma! - llerrs << "Attempted remove while an outstanding iterator in LLUUIDHashMap!" << llendl; - } - // Remove is the trickiest operation. - // What we want to do is swap the last element of the last - // node if we find the one that we want to remove, but we have - // to deal with deleting the node from the tail if it's empty, but - // NOT if it's the only node left. - - LLUUIDHashNode<DATA_TYPE, SIZE> *nodep = &mNodes[uuid.mData[0]]; - - // Not empty, we need to search through the nodes - const S32 second_byte = uuid.mData[1]; - - // A modification of the standard search algorithm. - while (nodep) - { - const S32 count = nodep->mCount; - - S32 i; - for (i = 0; i < count; i++) - { - if ((nodep->mKey[i] == second_byte) && mEquals(uuid, nodep->mData[i])) - { - // We found the node that we want to remove. - // Find the last (and next-to-last) node, and the index of the last - // element. We could conceviably start from the node we're on, - // but that makes it more complicated, this is easier. - - LLUUIDHashNode<DATA_TYPE, SIZE> *prevp = &mNodes[uuid.mData[0]]; - LLUUIDHashNode<DATA_TYPE, SIZE> *lastp = prevp; - - // Find the last and next-to-last - while (lastp->mNextNodep) - { - prevp = lastp; - lastp = lastp->mNextNodep; - } - - // First, swap in the last to the current location. - nodep->mKey[i] = lastp->mKey[lastp->mCount - 1]; - nodep->mData[i] = lastp->mData[lastp->mCount - 1]; - - // Now, we delete the entry - lastp->mCount--; - lastp->mData[lastp->mCount] = mNull; - - if (!lastp->mCount) - { - // We deleted the last element! - if (lastp != &mNodes[uuid.mData[0]]) - { - // Only blitz the node if it's not the head - // Set the previous node to point to NULL, then - // blitz the empty last node - prevp->mNextNodep = NULL; - delete lastp; - } - } - return TRUE; - } - } - - // Iterate to the next node, we've scanned all the entries in this one. - nodep = nodep->mNextNodep; - } - return FALSE; -} - - -// -// LLUUIDHashMapIter -// - -template <class DATA_TYPE, int SIZE> -class LLUUIDHashMapIter -{ -public: - LLUUIDHashMapIter(LLUUIDHashMap<DATA_TYPE, SIZE> *hash_mapp); - ~LLUUIDHashMapIter(); - - - inline void reset(); - inline void first(); - inline void next(); - inline BOOL done() const; - - DATA_TYPE& operator*() const - { - return mCurHashNodep->mData[mCurHashNodeKey]; - } - DATA_TYPE* operator->() const - { - return &(operator*()); - } - -protected: - LLUUIDHashMap<DATA_TYPE, SIZE> *mHashMapp; - LLUUIDHashNode<DATA_TYPE, SIZE> *mCurHashNodep; - - S32 mCurHashMapNodeNum; - S32 mCurHashNodeKey; - - DATA_TYPE mNull; -}; - - -// -// LLUUIDHashMapIter Implementation -// -template <class DATA_TYPE, int SIZE> -LLUUIDHashMapIter<DATA_TYPE, SIZE>::LLUUIDHashMapIter(LLUUIDHashMap<DATA_TYPE, SIZE> *hash_mapp) -{ - mHashMapp = hash_mapp; - mCurHashNodep = NULL; - mCurHashMapNodeNum = 0; - mCurHashNodeKey = 0; -} - -template <class DATA_TYPE, int SIZE> -LLUUIDHashMapIter<DATA_TYPE, SIZE>::~LLUUIDHashMapIter() -{ - reset(); -} - -template <class DATA_TYPE, int SIZE> -inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::reset() -{ - if (mCurHashNodep) - { - // We're partway through an iteration, we can clean up now - mHashMapp->mIterCount--; - mCurHashNodep = NULL; - } -} - -template <class DATA_TYPE, int SIZE> -inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::first() -{ - // Iterate through until we find the first non-empty node; - S32 i; - for (i = 0; i < 256; i++) - { - if (mHashMapp->mNodes[i].mCount) - { - if (!mCurHashNodep) - { - // Increment, since it's no longer safe for us to do a remove - mHashMapp->mIterCount++; - } - - mCurHashNodep = &mHashMapp->mNodes[i]; - mCurHashMapNodeNum = i; - mCurHashNodeKey = 0; - //return mCurHashNodep->mData[0]; - return; - } - } - - // Completely empty! - mCurHashNodep = NULL; - //return mNull; - return; -} - -template <class DATA_TYPE, int SIZE> -inline BOOL LLUUIDHashMapIter<DATA_TYPE, SIZE>::done() const -{ - return mCurHashNodep ? FALSE : TRUE; -} - -template <class DATA_TYPE, int SIZE> -inline void LLUUIDHashMapIter<DATA_TYPE, SIZE>::next() -{ - // No current entry, this iterator is done - if (!mCurHashNodep) - { - //return mNull; - return; - } - - // Go to the next element - mCurHashNodeKey++; - if (mCurHashNodeKey < mCurHashNodep->mCount) - { - // We're not done with this node, return the current element - //return mCurHashNodep->mData[mCurHashNodeKey]; - return; - } - - // Done with this node, move to the next - mCurHashNodep = mCurHashNodep->mNextNodep; - if (mCurHashNodep) - { - // Return the first element - mCurHashNodeKey = 0; - //return mCurHashNodep->mData[0]; - return; - } - - // Find the next non-empty node (keyed on the first byte) - mCurHashMapNodeNum++; - - S32 i; - for (i = mCurHashMapNodeNum; i < 256; i++) - { - if (mHashMapp->mNodes[i].mCount) - { - // We found one that wasn't empty - mCurHashNodep = &mHashMapp->mNodes[i]; - mCurHashMapNodeNum = i; - mCurHashNodeKey = 0; - //return mCurHashNodep->mData[0]; - return; - } - } - - // OK, we're done, nothing else to iterate - mCurHashNodep = NULL; - mHashMapp->mIterCount--; // Decrement since we're safe to do removes now - //return mNull; -} - -#endif // LL_LLUUIDHASHMAP_H diff --git a/indra/llcommon/reflective.h b/indra/llcommon/llwin32headers.h index da5c5a2630..cf85067d95 100755..100644 --- a/indra/llcommon/reflective.h +++ b/indra/llcommon/llwin32headers.h @@ -1,10 +1,8 @@ /** - * @file reflective.h - * @author Babbage - * @date 2006-05-15 - * @brief Interface that must be implemented by all reflective classes. + * @file llwindows.h + * @brief sanitized include of windows header files * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code * Copyright (C) 2010, Linden Research, Inc. * @@ -26,17 +24,19 @@ * $/LicenseInfo$ */ -#ifndef LL_REFLECTIVE_H -#define LL_REFLECTIVE_H +#ifndef LL_LLWINDOWS_H +#define LL_LLWINDOWS_H -class LLMetaClass; -class LL_COMMON_API LLReflective -{ -public: - LLReflective(); - virtual ~LLReflective(); - - virtual const LLMetaClass& getMetaClass() const = 0; -}; +#ifdef LL_WINDOWS +#ifndef NOMINMAX +#define NOMINMAX +#endif +#undef WIN32_LEAN_AND_MEAN +#include <winsock2.h> +#include <windows.h> +// reset to default, which is lean +#define WIN32_LEAN_AND_MEAN +#undef NOMINMAX +#endif -#endif // LL_REFLECTIVE_H +#endif diff --git a/indra/llcommon/lldarrayptr.h b/indra/llcommon/llwin32headerslean.h index c9a0b204d1..f7e71301a8 100755..100644 --- a/indra/llcommon/lldarrayptr.h +++ b/indra/llcommon/llwin32headerslean.h @@ -1,6 +1,6 @@ /** - * @file lldarrayptr.h - * @brief Wrapped std::vector for backward compatibility. + * @file llwindows.h + * @brief sanitized include of windows header files * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code @@ -23,14 +23,18 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -#ifndef LL_LLDARRAYPTR_H -#define LL_LLDARRAYPTR_H -#include "lldarray.h" +#ifndef LL_LLWINDOWS_H +#define LL_LLWINDOWS_H -template <class Type, int BlockSize = 32> -class LLDynamicArrayPtr : public LLDynamicArray<Type, BlockSize> -{ -}; +#ifdef LL_WINDOWS +#ifndef NOMINMAX +#define NOMINMAX +#endif +#define WIN32_LEAN_AND_MEAN +#include <winsock2.h> +#include <windows.h> +#undef NOMINMAX +#endif -#endif // LL_LLDARRAYPTR_H +#endif diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index be46394d6e..09776816a8 100755 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -26,10 +26,11 @@ #ifndef LL_LLWORKERTHREAD_H #define LL_LLWORKERTHREAD_H -#include <queue> -#include <string> +#include <list> #include <map> +#include <queue> #include <set> +#include <string> #include "llqueuedthread.h" #include "llapr.h" diff --git a/indra/llcommon/metaclass.cpp b/indra/llcommon/metaclass.cpp deleted file mode 100755 index 5e403511cf..0000000000 --- a/indra/llcommon/metaclass.cpp +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @file metaclass.cpp - * @author Babbage - * @date 2006-05-15 - * @brief Implementation of LLMetaClass - * - * $LicenseInfo:firstyear=2006&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 "linden_common.h" - -#include "metaclass.h" - -#include "metaproperty.h" -#include "reflective.h" - -LLMetaClass::LLMetaClass() -{ -} - -//virtual -LLMetaClass::~LLMetaClass() -{ -} - -const LLMetaProperty* LLMetaClass::findProperty(const std::string& name) const -{ - PropertyIterator iter = mProperties.find(name); - if(iter == mProperties.end()) - { - return NULL; - } - return (*iter).second; -} - -void LLMetaClass::addProperty(const LLMetaProperty* property) -{ - mProperties.insert(std::make_pair(property->getName(), property)); -} - -U32 LLMetaClass::getPropertyCount() const -{ - return mProperties.size(); -} - -LLMetaClass::PropertyIterator LLMetaClass::beginProperties() const -{ - return mProperties.begin(); -} - -LLMetaClass::PropertyIterator LLMetaClass::endProperties() const -{ - return mProperties.end(); -} - -bool LLMetaClass::isInstance(const LLReflective* object) const -{ - // TODO: Babbage: Search through super classes of objects MetaClass. - const LLMetaClass* object_meta_class = &(object->getMetaClass()); - return (object_meta_class == this); -} - diff --git a/indra/llcommon/metaclass.h b/indra/llcommon/metaclass.h deleted file mode 100755 index 626757d58d..0000000000 --- a/indra/llcommon/metaclass.h +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @file metaclass.h - * @author Babbage - * @date 2006-05-15 - * @brief Reflective meta information describing a class. - * - * $LicenseInfo:firstyear=2006&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_METACLASS_H -#define LL_METACLASS_H - -#include <string> -#include <map> - -#include "stdtypes.h" - -class LLReflective; -class LLMetaProperty; -class LLMetaMethod; -class LL_COMMON_API LLMetaClass -{ -public: - - LLMetaClass(); - virtual ~LLMetaClass(); - - // Create instance of this MetaClass. NULL if class is abstract. - // Gives ownership of returned object. - // virtual LLReflective* create() const = 0; - - // Returns named property or NULL. - const LLMetaProperty* findProperty(const std::string& name) const; - - // Add property to metaclass. Takes ownership of given property. - void addProperty(const LLMetaProperty* property); - - typedef std::map<std::string, const LLMetaProperty*>::const_iterator PropertyIterator; - - U32 getPropertyCount() const; - - PropertyIterator beginProperties() const; - PropertyIterator endProperties() const; - - // Returns named property or NULL. - // const LLMetaMethod* findMethod(const std::string& name) const; - - // Add method to metaclass. Takes ownership of given method. - // void addMethod(const LLMetaMethod* method); - - // Find MetaClass by name. NULL if name is unknown. - // static LLMetaClass* findClass(const std::string& name); - - // True if object is instance of this meta class. - bool isInstance(const LLReflective* object) const; - -private: - - typedef std::map<std::string, const LLMetaProperty*> PropertyMap; - PropertyMap mProperties; -}; - -#endif // LL_METACLASS_H diff --git a/indra/llcommon/metaclasst.h b/indra/llcommon/metaclasst.h deleted file mode 100755 index b9a7ae219d..0000000000 --- a/indra/llcommon/metaclasst.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file metaclasst.h - * - * $LicenseInfo:firstyear=2006&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_METACLASST_H -#define LL_METACLASST_H - -#include "metaclass.h" - -template<class TObject> -class LLMetaClassT : public LLMetaClass -{ - public: - - virtual ~LLMetaClassT() {;} - - static const LLMetaClassT& instance() - { - static const LLMetaClassT& instance = buildMetaClass(); - return instance; - } - - private: - - static const LLMetaClassT& buildMetaClass() - { - LLMetaClassT& meta_class = *(new LLMetaClassT()); - reflectProperties(meta_class); - return meta_class; - } - - LLMetaClassT() {;} - - static void reflectProperties(LLMetaClass&) - { - } -}; - -#endif // LL_METACLASST_H diff --git a/indra/llcommon/metaproperty.h b/indra/llcommon/metaproperty.h deleted file mode 100755 index bd5bb1a30f..0000000000 --- a/indra/llcommon/metaproperty.h +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @file metaproperty.h - * @author Babbage - * @date 2006-05-15 - * @brief Reflective meta information describing a property of a class. - * - * $LicenseInfo:firstyear=2006&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_METAPROPERTY_H -#define LL_METAPROPERTY_H - -#include "stdtypes.h" -#include "llsd.h" -#include "reflective.h" - -class LLMetaClass; -class LLReflective; -class LL_COMMON_API LLMetaProperty -{ -public: - LLMetaProperty(const std::string& name, const LLMetaClass& object_class); - virtual ~LLMetaProperty(); - - // Get property name. - const std::string& getName() const {return mName;} - - // Get value of this property. - virtual const LLReflective* get(const LLReflective* object) const = 0; - - // Set value of this property. - // virtual void set(LLReflective* object, const LLReflective* value) = 0; - - // Get value of this property as LLSD. Default returns undefined LLSD. - virtual LLSD getLLSD(const LLReflective* object) const = 0; - - // Get the MetaClass of legal values of this property. - // const LLMetaClass& getValueMetaClass(); - - // Get the meta class that this property is a member of. - const LLMetaClass& getObjectMetaClass() const; - -protected: - - // Check object is instance of object class, throw exception if not. - void checkObjectClass(const LLReflective* object) const; - -private: - - std::string mName; - const LLMetaClass& mObjectClass; -}; - -#endif // LL_METAPROPERTY_H diff --git a/indra/llcommon/metapropertyt.h b/indra/llcommon/metapropertyt.h deleted file mode 100755 index 7a36c161da..0000000000 --- a/indra/llcommon/metapropertyt.h +++ /dev/null @@ -1,183 +0,0 @@ -/** - * @file metapropertyt.h - * - * $LicenseInfo:firstyear=2006&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_METAPROPERTYT_H -#define LL_METAPROPERTYT_H - -#include "llsd.h" -#include "llstring.h" -#include "metaclasst.h" -#include "metaproperty.h" -#include "reflectivet.h" - -template<class TProperty> -class LLMetaPropertyT : public LLMetaProperty -{ -public: - - virtual ~LLMetaPropertyT() {;} - - // Get value of this property. Gives ownership of returned value. - virtual const LLReflective* get(const LLReflective* object) const - { - checkObjectClass(object); - return getProperty(object); - } - - // Set value of this property. - /*virtual void set(LLReflective* object, const LLReflective* value) - { - // TODO: Babbage: Check types. - ref(object) = static_cast<const LLReflectiveT<TProperty>* >(value)->getValue(); - }*/ - - // Get value of this property as LLSD. - virtual LLSD getLLSD(const LLReflective* object) const - { - return LLSD(); - } - -protected: - - LLMetaPropertyT(const std::string& name, const LLMetaClass& object_class) : LLMetaProperty(name, object_class) {;} - - virtual const TProperty* getProperty(const LLReflective* object) const = 0; -}; - -template <> -inline const LLReflective* LLMetaPropertyT<S32>::get(const LLReflective* object) const -{ - checkObjectClass(object); - return NULL; -} - -template <> -inline const LLReflective* LLMetaPropertyT<std::string>::get(const LLReflective* object) const -{ - checkObjectClass(object); - return NULL; -} - -template <> -inline const LLReflective* LLMetaPropertyT<LLUUID>::get(const LLReflective* object) const -{ - checkObjectClass(object); - return NULL; -} - -template <> -inline const LLReflective* LLMetaPropertyT<bool>::get(const LLReflective* object) const -{ - checkObjectClass(object); - return NULL; -} - -template <> -inline LLSD LLMetaPropertyT<S32>::getLLSD(const LLReflective* object) const -{ - return *(getProperty(object)); -} - -template <> -inline LLSD LLMetaPropertyT<std::string>::getLLSD(const LLReflective* object) const -{ - return *(getProperty(object)); -} - -template <> -inline LLSD LLMetaPropertyT<LLUUID>::getLLSD(const LLReflective* object) const -{ - return *(getProperty(object)); -} - -template <> -inline LLSD LLMetaPropertyT<bool>::getLLSD(const LLReflective* object) const -{ - return *(getProperty(object)); -} - -template<class TObject, class TProperty> -class LLMetaPropertyTT : public LLMetaPropertyT<TProperty> -{ -public: - - LLMetaPropertyTT(const std::string& name, const LLMetaClass& object_class, TProperty (TObject::*property)) : - LLMetaPropertyT<TProperty>(name, object_class), mProperty(property) {;} - -protected: - - // Get void* to property. - virtual const TProperty* getProperty(const LLReflective* object) const - { - const TObject* typed_object = static_cast<const TObject*>(object); - return &(typed_object->*mProperty); - }; - -private: - - TProperty (TObject::*mProperty); -}; - -template<class TObject, class TProperty> -class LLMetaPropertyPtrTT : public LLMetaPropertyT<TProperty> -{ -public: - - LLMetaPropertyPtrTT(const std::string& name, const LLMetaClass& object_class, TProperty* (TObject::*property)) : - LLMetaPropertyT<TProperty>(name, object_class), mProperty(property) {;} - -protected: - - // Get void* to property. - virtual const TProperty* getProperty(const LLReflective* object) const - { - const TObject* typed_object = static_cast<const TObject*>(object); - return typed_object->*mProperty; - }; - -private: - - TProperty* (TObject::*mProperty); -}; - -// Utility function to simplify the registration of members. -template<class TObject, class TProperty> -void reflectProperty(LLMetaClass& meta_class, const std::string& name, TProperty (TObject::*property)) -{ - typedef LLMetaPropertyTT<TObject, TProperty> PropertyType; - const LLMetaProperty* meta_property = new PropertyType(name, meta_class, property); - meta_class.addProperty(meta_property); -} - -// Utility function to simplify the registration of ptr properties. -template<class TObject, class TProperty> -void reflectPtrProperty(LLMetaClass& meta_class, const std::string& name, TProperty* (TObject::*property)) -{ - typedef LLMetaPropertyPtrTT<TObject, TProperty> PropertyType; - const LLMetaProperty* meta_property = new PropertyType(name, meta_class, property); - meta_class.addProperty(meta_property); -} - -#endif // LL_METAPROPERTYT_H diff --git a/indra/llcommon/reflectivet.h b/indra/llcommon/reflectivet.h deleted file mode 100755 index 958921f23e..0000000000 --- a/indra/llcommon/reflectivet.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @file reflectivet.h - * - * $LicenseInfo:firstyear=2006&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_REFLECTIVET_H -#define LL_REFLECTIVET_H - -#include "reflective.h" - -template <class T> -class LLReflectiveT : public LLReflective -{ -public: - - LLReflectiveT(const T& value) : mValue(value) {;} - virtual ~LLReflectiveT() {;} - - virtual const LLMetaClass& getMetaClass() const {return LLMetaClassT<LLReflectiveT<T> >::instance();} - - const T& getValue() const {return mValue;} - -private: - - T mValue; -}; - -#endif diff --git a/indra/llcommon/tests/llunits_test.cpp b/indra/llcommon/tests/llunits_test.cpp new file mode 100644 index 0000000000..2a941e8229 --- /dev/null +++ b/indra/llcommon/tests/llunits_test.cpp @@ -0,0 +1,208 @@ +/** + * @file llsingleton_test.cpp + * @date 2011-08-11 + * @brief Unit test for the LLSingleton class + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, 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 "linden_common.h" + +#include "llunit.h" +#include "../test/lltut.h" + +namespace LLUnits +{ + // using powers of 2 to allow strict floating point equality + struct Quatloos { typedef Quatloos base_unit_t; }; + LL_DECLARE_DERIVED_UNIT(4, Quatloos, Latinum); + LL_DECLARE_DERIVED_UNIT((1.0 / 4.0), Quatloos, Solari); +} + +namespace tut +{ + using namespace LLUnits; + struct units + { + }; + + typedef test_group<units> units_t; + typedef units_t::object units_object_t; + tut::units_t tut_singleton("LLUnit"); + + // storage type conversions + template<> template<> + void units_object_t::test<1>() + { + LLUnit<Quatloos, F32> float_quatloos; + ensure(float_quatloos.value() == 0.f); + + LLUnit<Quatloos, S32> int_quatloos; + ensure(int_quatloos.value() == 0); + + int_quatloos = 42; + ensure(int_quatloos.value() == 42); + float_quatloos = int_quatloos; + ensure(float_quatloos.value() == 42.f); + + int_quatloos = float_quatloos; + ensure(int_quatloos.value() == 42); + + float_quatloos = 42.1f; + ensure(float_quatloos.value() == 42.1f); + int_quatloos = float_quatloos; + ensure(int_quatloos.value() == 42); + LLUnit<Quatloos, U32> unsigned_int_quatloos(float_quatloos); + ensure(unsigned_int_quatloos.value() == 42); + } + + // conversions to/from base unit + template<> template<> + void units_object_t::test<2>() + { + LLUnit<Quatloos, F32> quatloos(1.f); + ensure(quatloos.value() == 1.f); + LLUnit<Latinum, F32> latinum_bars(quatloos); + ensure(latinum_bars.value() == 1.f / 4.f); + + latinum_bars = 256; + quatloos = latinum_bars; + ensure(quatloos.value() == 1024); + + LLUnit<Solari, F32> solari(quatloos); + ensure(solari.value() == 4096); + } + + // conversions across non-base units + template<> template<> + void units_object_t::test<3>() + { + LLUnit<Solari, F32> solari = 4.f; + LLUnit<Latinum, F32> latinum_bars = solari; + ensure(latinum_bars.value() == 0.25f); + } + + // math operations + template<> template<> + void units_object_t::test<4>() + { + LLUnit<Quatloos, F32> quatloos = 1.f; + quatloos *= 4.f; + ensure(quatloos.value() == 4); + quatloos = quatloos * 2; + ensure(quatloos.value() == 8); + quatloos = 2.f * quatloos; + ensure(quatloos.value() == 16); + + quatloos += 4.f; + ensure(quatloos.value() == 20); + quatloos += 4; + ensure(quatloos.value() == 24); + quatloos = quatloos + 4; + ensure(quatloos.value() == 28); + quatloos = 4 + quatloos; + ensure(quatloos.value() == 32); + quatloos += quatloos * 3; + ensure(quatloos.value() == 128); + + quatloos -= quatloos / 4 * 3; + ensure(quatloos.value() == 32); + quatloos = quatloos - 8; + ensure(quatloos.value() == 24); + quatloos -= 4; + ensure(quatloos.value() == 20); + quatloos -= 4.f; + ensure(quatloos.value() == 16); + + quatloos *= 2.f; + ensure(quatloos.value() == 32); + quatloos = quatloos * 2.f; + ensure(quatloos.value() == 64); + quatloos = 0.5f * quatloos; + ensure(quatloos.value() == 32); + + quatloos /= 2.f; + ensure(quatloos.value() == 16); + quatloos = quatloos / 4; + ensure(quatloos.value() == 4); + + F32 ratio = quatloos / LLUnit<Quatloos, F32>(4.f); + ensure(ratio == 1); + + quatloos += LLUnit<Solari, F32>(4.f); + ensure(quatloos.value() == 5); + quatloos -= LLUnit<Latinum, F32>(1.f); + ensure(quatloos.value() == 1); + } + + // implicit units + template<> template<> + void units_object_t::test<5>() + { + // 0-initialized + LLUnit<Quatloos, F32> quatloos(0); + // initialize implicit unit from explicit + LLUnitImplicit<Quatloos, F32> quatloos_implicit = quatloos + 1; + ensure(quatloos_implicit.value() == 1); + + // assign implicit to explicit, or perform math operations + quatloos = quatloos_implicit; + ensure(quatloos.value() == 1); + quatloos += quatloos_implicit; + ensure(quatloos.value() == 2); + + // math operations on implicits + quatloos_implicit = 1; + ensure(quatloos_implicit == 1); + + quatloos_implicit += 2; + ensure(quatloos_implicit == 3); + + quatloos_implicit *= 2; + ensure(quatloos_implicit == 6); + + quatloos_implicit -= 1; + ensure(quatloos_implicit == 5); + + quatloos_implicit /= 5; + ensure(quatloos_implicit == 1); + + quatloos_implicit = quatloos_implicit + 3 + quatloos_implicit; + ensure(quatloos_implicit == 5); + + quatloos_implicit = 10 - quatloos_implicit - 1; + ensure(quatloos_implicit == 4); + + quatloos_implicit = 2 * quatloos_implicit * 2; + ensure(quatloos_implicit == 16); + + F32 one_half = quatloos_implicit / (quatloos_implicit * 2); + ensure(one_half == 0.5f); + + // implicit conversion to POD + F32 float_val = quatloos_implicit; + ensure(float_val == 16); + + S32 int_val = quatloos_implicit; + ensure(int_val == 16); + } +} diff --git a/indra/llcommon/tests/reflection_test.cpp b/indra/llcommon/tests/reflection_test.cpp deleted file mode 100755 index 8980ebb1f1..0000000000 --- a/indra/llcommon/tests/reflection_test.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/** - * @file reflection_test.cpp - * @date May 2006 - * @brief Reflection unit tests. - * - * $LicenseInfo:firstyear=2006&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 "../linden_common.h" -#include "../reflective.h" -#include "../metaclasst.h" -#include "../metapropertyt.h" -#include "../stdtypes.h" - -#include "../test/lltut.h" - -namespace tut -{ - class TestAggregatedData : public LLReflective - { - public: - TestAggregatedData() {;} - virtual const LLMetaClass& getMetaClass() const; - - private: - }; - - class TestReflectionData : public LLReflective - { - public: - TestReflectionData() : mInt(42), mString("foo"), mNullPtr(NULL), mPtr(new TestAggregatedData()), mRef(*(new TestAggregatedData)) {;} - virtual ~TestReflectionData() {delete mPtr;} - virtual const LLMetaClass& getMetaClass() const; - - static U32 getPropertyCount() {return 5;} - - private: - - friend class LLMetaClassT<TestReflectionData>; - S32 mInt; - std::string mString; - TestAggregatedData* mNullPtr; - TestAggregatedData* mPtr; - TestAggregatedData mObj; - TestAggregatedData& mRef; - }; -} - -template <> -void LLMetaClassT<tut::TestReflectionData>::reflectProperties(LLMetaClass& meta_class) -{ - reflectProperty(meta_class, "mInt", &tut::TestReflectionData::mInt); - reflectProperty(meta_class, "mString", &tut::TestReflectionData::mString); - reflectPtrProperty(meta_class, "mNullPtr", &tut::TestReflectionData::mNullPtr); - reflectPtrProperty(meta_class, "mPtr", &tut::TestReflectionData::mPtr); - reflectProperty(meta_class, "mObj", &tut::TestReflectionData::mObj); - //reflectProperty(meta_class, "mRef", &tut::TestReflectionData::mRef); // AARGH! -} - -namespace tut -{ - // virtual - const LLMetaClass& TestReflectionData::getMetaClass() const - { - return LLMetaClassT<TestReflectionData>::instance(); - } - - const LLMetaClass& TestAggregatedData::getMetaClass() const - { - return LLMetaClassT<TestAggregatedData>::instance(); - } -} - -namespace tut -{ - typedef tut::test_group<TestReflectionData> TestReflectionGroup; - typedef TestReflectionGroup::object TestReflectionObject; - TestReflectionGroup gTestReflectionGroup("reflection"); - - template<> template<> - void TestReflectionObject::test<1>() - { - // Check properties can be found. - const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); - const LLMetaProperty* null = NULL; - ensure_not_equals(meta_class.findProperty("mInt"), null); - ensure_not_equals(meta_class.findProperty("mString"), null); - } - - template<> template<> - void TestReflectionObject::test<2>() - { - // Check non-existent property cannot be found. - const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); - const LLMetaProperty* null = NULL; - ensure_equals(meta_class.findProperty("foo"), null); - } - - template<> template<> - void TestReflectionObject::test<3>() - { - // Check integer property has correct value. - const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); - ensure_equals(meta_class.findProperty("mInt")->getLLSD(this).asInteger(), 42); - } - - template<> template<> - void TestReflectionObject::test<4>() - { - // Check string property has correct value. - const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); - ensure_equals(meta_class.findProperty("mString")->getLLSD(this).asString(), std::string("foo")); - } - - template<> template<> - void TestReflectionObject::test<5>() - { - // Check NULL reference property has correct value. - const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); - const LLReflective* null = NULL; - ensure_equals(meta_class.findProperty("mNullPtr")->get(this), null); - } - - template<> template<> - void TestReflectionObject::test<6>() - { - // Check reference property has correct value. - const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); - const LLReflective* null = NULL; - const LLReflective* ref = meta_class.findProperty("mPtr")->get(this); - ensure_not_equals(ref, null); - } - - template<> template<> - void TestReflectionObject::test<7>() - { - // Check reflective property has correct value. - const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); - const LLReflective* null = NULL; - const LLReflective* ref = meta_class.findProperty("mObj")->get(this); - ensure_not_equals(ref, null); - } - - template<> template<> - void TestReflectionObject::test<8>() - { - // Check property count. - const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); - ensure_equals(meta_class.getPropertyCount(), TestReflectionData::getPropertyCount()); - } - - template<> template<> - void TestReflectionObject::test<9>() - { - // Check property iteration. - const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); - U32 count = 0; - LLMetaClass::PropertyIterator iter; - for(iter = meta_class.beginProperties(); iter != meta_class.endProperties(); ++iter) - { - ++count; - } - ensure_equals(count, TestReflectionData::getPropertyCount()); - } - - template<> template<> - void TestReflectionObject::test<10>() - { - // Check meta classes of different types do not compare equal. - const LLMetaClass* reflection_data_meta_class = &(LLMetaClassT<TestReflectionData>::instance()); - const LLMetaClass* aggregated_data_meta_class = &(LLMetaClassT<TestAggregatedData>::instance()); - ensure_not_equals(reflection_data_meta_class, aggregated_data_meta_class); - } - - template<> template<> - void TestReflectionObject::test<11>() - { - // Check class cast checks. - const LLMetaClass& meta_class = LLMetaClassT<TestReflectionData>::instance(); - TestAggregatedData* aggregated_data = new TestAggregatedData(); - LLMetaClass::PropertyIterator iter; - U32 exception_count = 0; - for(iter = meta_class.beginProperties(); iter != meta_class.endProperties(); ++iter) - { - try - { - const LLMetaProperty* property = (*iter).second; - const LLReflective* reflective = property->get(aggregated_data); // Wrong reflective type, should throw exception. - - // useless op to get rid of compiler warning. - reflective = reflective; - } - catch(...) - { - ++exception_count; - } - } - ensure_equals(exception_count, getPropertyCount()); - - } -} diff --git a/indra/llcorehttp/_refcounted.h b/indra/llcorehttp/_refcounted.h index 21a916b13b..402e725152 100755 --- a/indra/llcorehttp/_refcounted.h +++ b/indra/llcorehttp/_refcounted.h @@ -72,7 +72,7 @@ private: inline void RefCounted::addRef() const { - S32 count(mRefCount++); + S32 count(++mRefCount); llassert_always(count >= 0); } @@ -82,7 +82,7 @@ inline void RefCounted::release() const S32 count(mRefCount); llassert_always(count != NOT_REF_COUNTED); llassert_always(count > 0); - count = mRefCount--; + count = --mRefCount; // clean ourselves up if that was the last reference if (0 == count) diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 1c25256e95..50df2ebe55 100755 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -50,6 +50,7 @@ LLMutex* LLImage::sMutex = NULL; bool LLImage::sUseNewByteRange = false; S32 LLImage::sMinimalReverseByteRangePercent = 75; LLPrivateMemoryPool* LLImageBase::sPrivatePoolp = NULL ; +LLTrace::MemStatHandle LLImageBase::sMemStat("LLImage"); //static void LLImage::initClass(bool use_new_byte_range, S32 minimal_reverse_byte_range_percent) @@ -158,6 +159,7 @@ void LLImageBase::sanityCheck() void LLImageBase::deleteData() { FREE_MEM(sPrivatePoolp, mData) ; + memDisclaimAmount(mDataSize); mData = NULL; mDataSize = 0; } @@ -201,6 +203,7 @@ U8* LLImageBase::allocateData(S32 size) mBadBufferAllocation = true ; } mDataSize = size; + memClaimAmount(mDataSize); } return mData; @@ -222,7 +225,9 @@ U8* LLImageBase::reallocateData(S32 size) FREE_MEM(sPrivatePoolp, mData) ; } mData = new_datap; + memDisclaimAmount(mDataSize); mDataSize = size; + memClaimAmount(mDataSize); return mData; } @@ -288,7 +293,6 @@ LLImageRaw::LLImageRaw(U16 width, U16 height, S8 components) LLImageRaw::LLImageRaw(U8 *data, U16 width, U16 height, S8 components, bool no_copy) : LLImageBase() { - if(no_copy) { setDataAndSize(data, width, height, components); @@ -1608,7 +1612,9 @@ static void avg4_colors2(const U8* a, const U8* b, const U8* c, const U8* d, U8* void LLImageBase::setDataAndSize(U8 *data, S32 size) { ll_assert_aligned(data, 16); + memDisclaimAmount(mDataSize); mData = data; mDataSize = size; + memClaimAmount(mDataSize); } //static diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index 4fc40ecff7..504b7e4795 100755 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -30,6 +30,7 @@ #include "lluuid.h" #include "llstring.h" #include "llthread.h" +#include "lltrace.h" const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 const S32 MAX_IMAGE_MIP = 11; // 2048x2048 @@ -110,7 +111,9 @@ protected: //============================================================================ // Image base class -class LLImageBase : public LLThreadSafeRefCount +class LLImageBase +: public LLThreadSafeRefCount, + public LLTrace::MemTrackable<LLImageBase> { protected: virtual ~LLImageBase(); @@ -162,6 +165,8 @@ public: static void destroyPrivatePool() ; static LLPrivateMemoryPool* getPrivatePool() {return sPrivatePoolp;} + static LLTrace::MemStatHandle sMemStat; + private: U8 *mData; S32 mDataSize; diff --git a/indra/llimage/tests/llimageworker_test.cpp b/indra/llimage/tests/llimageworker_test.cpp index e255d65b43..b6f2694742 100755 --- a/indra/llimage/tests/llimageworker_test.cpp +++ b/indra/llimage/tests/llimageworker_test.cpp @@ -31,6 +31,8 @@ #include "../llimageworker.h" // For timer class #include "../llcommon/lltimer.h" +// for lltrace class +#include "../llcommon/lltrace.h" // Tut header #include "../test/lltut.h" @@ -42,6 +44,9 @@ // * Do not make any assumption as to how those classes or methods work (i.e. don't copy/paste code) // * A simulator for a class can be implemented here. Please comment and document thoroughly. +LLTrace::MemStatHandle LLImageBase::sMemStat("LLImage"); + + LLImageBase::LLImageBase() : mData(NULL), mDataSize(0), @@ -114,11 +119,13 @@ namespace tut // Constructor and destructor of the test wrapper imagedecodethread_test() { + LLTrace::init(); mThread = NULL; } ~imagedecodethread_test() { delete mThread; + LLTrace::cleanup(); } }; @@ -136,6 +143,8 @@ namespace tut imagerequest_test() { done = false; + LLTrace::init(); + mRequest = new LLImageDecodeThread::ImageRequest(0, 0, LLQueuedThread::PRIORITY_NORMAL, 0, FALSE, new responder_test(&done)); @@ -145,6 +154,7 @@ namespace tut // We should delete the object *but*, because its destructor is protected, that cannot be // done from outside an LLImageDecodeThread instance... So we leak memory here... It's fine... //delete mRequest; + LLTrace::cleanup(); } }; diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h index eb2ecf71ba..47fcf688a2 100755 --- a/indra/llinventory/lleconomy.h +++ b/indra/llinventory/lleconomy.h @@ -27,6 +27,7 @@ #define LL_LLECONOMY_H #include "llsingleton.h" +#include <list> class LLMessageSystem; class LLVector3; diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 41d58c6deb..2a319c635f 100755 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -28,6 +28,7 @@ #include "llinventory.h" #include "lldbstrings.h" +#include "llfasttimer.h" #include "llinventorydefines.h" #include "llxorcipher.h" #include "llsd.h" diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index 7e013de11a..55067cde73 100755 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -31,7 +31,6 @@ // library includes #include "message.h" -#include "metapropertyt.h" #include "llsd.h" ///---------------------------------------------------------------------------- @@ -895,21 +894,6 @@ std::ostream& operator<<(std::ostream &s, const LLPermissions &perm) return s; } -template <> -void LLMetaClassT<LLPermissions>::reflectProperties(LLMetaClass& meta_class) -{ - reflectProperty(meta_class, "mCreator", &LLPermissions::mCreator); - reflectProperty(meta_class, "mOwner", &LLPermissions::mOwner); - reflectProperty(meta_class, "mGroup", &LLPermissions::mGroup); - reflectProperty(meta_class, "mIsGroupOwned", &LLPermissions::mIsGroupOwned); -} - -// virtual -const LLMetaClass& LLPermissions::getMetaClass() const -{ - return LLMetaClassT<LLPermissions>::instance(); -} - ///---------------------------------------------------------------------------- /// Class LLAggregatePermissions ///---------------------------------------------------------------------------- diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h index 3ecc922370..89c66f6ebd 100755 --- a/indra/llinventory/llpermissions.h +++ b/indra/llinventory/llpermissions.h @@ -31,7 +31,6 @@ #include "llsd.h" #include "lluuid.h" #include "llxmlnode.h" -#include "reflective.h" #include "llinventorytype.h" // prototypes @@ -83,7 +82,7 @@ template<class T> class LLMetaClassT; // logical consistency. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -class LLPermissions : public LLReflective +class LLPermissions { private: LLUUID mCreator; // null if object created by system @@ -324,9 +323,6 @@ public: friend std::ostream& operator<<(std::ostream &s, const LLPermissions &perm); - // Reflection. - friend class LLMetaClassT<LLPermissions>; - virtual const LLMetaClass& getMetaClass() const; }; // Inlines diff --git a/indra/llkdu/tests/llimagej2ckdu_test.cpp b/indra/llkdu/tests/llimagej2ckdu_test.cpp index 62c245f125..14fbf344ab 100755 --- a/indra/llkdu/tests/llimagej2ckdu_test.cpp +++ b/indra/llkdu/tests/llimagej2ckdu_test.cpp @@ -43,7 +43,9 @@ // End Stubbing // ------------------------------------------------------------------------------------------- -// Stubb the LL Image Classes +// Stub the LL Image Classes +LLTrace::MemStatHandle LLImageBase::sMemStat("LLImage"); + LLImageRaw::LLImageRaw() { } LLImageRaw::~LLImageRaw() { } U8* LLImageRaw::allocateData(S32 ) { return NULL; } diff --git a/indra/llmath/llcamera.cpp b/indra/llmath/llcamera.cpp index 22ba26f99b..6551b52462 100755 --- a/indra/llmath/llcamera.cpp +++ b/indra/llmath/llcamera.cpp @@ -161,7 +161,7 @@ size_t LLCamera::readFrustumFromBuffer(const char *buffer) // ---------------- test methods ---------------- -S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius) +S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius, const LLPlane* planes) { static const LLVector4a scaler[] = { LLVector4a(-1,-1,-1), @@ -174,6 +174,12 @@ S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius) LLVector4a( 1, 1, 1) }; + if(!planes) + { + //use agent space + planes = mAgentPlanes; + } + U8 mask = 0; bool result = false; LLVector4a rscale, maxp, minp; @@ -183,7 +189,7 @@ S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius) mask = mPlaneMask[i]; if (mask != 0xff) { - const LLPlane& p(mAgentPlanes[i]); + const LLPlane& p(planes[i]); p.getAt<3>(d); rscale.setMul(radius, scaler[mask]); minp.setSub(center, rscale); @@ -204,8 +210,14 @@ S32 LLCamera::AABBInFrustum(const LLVector4a ¢er, const LLVector4a& radius) return result?1:2; } +//exactly same as the function AABBInFrustum(...) +//except uses mRegionPlanes instead of mAgentPlanes. +S32 LLCamera::AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius) +{ + return AABBInFrustum(center, radius, mRegionPlanes); +} -S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius) +S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes) { static const LLVector4a scaler[] = { LLVector4a(-1,-1,-1), @@ -218,6 +230,12 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& LLVector4a( 1, 1, 1) }; + if(!planes) + { + //use agent space + planes = mAgentPlanes; + } + U8 mask = 0; bool result = false; LLVector4a rscale, maxp, minp; @@ -227,7 +245,7 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& mask = mPlaneMask[i]; if ((i != 5) && (mask != 0xff)) { - const LLPlane& p(mAgentPlanes[i]); + const LLPlane& p(planes[i]); p.getAt<3>(d); rscale.setMul(radius, scaler[mask]); minp.setSub(center, rscale); @@ -248,6 +266,13 @@ S32 LLCamera::AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& return result?1:2; } +//exactly same as the function AABBInFrustumNoFarClip(...) +//except uses mRegionPlanes instead of mAgentPlanes. +S32 LLCamera::AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius) +{ + return AABBInFrustumNoFarClip(center, radius, mRegionPlanes); +} + int LLCamera::sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius) { LLVector3 dist = sphere_center-mFrustCenter; @@ -584,6 +609,23 @@ void LLCamera::calcAgentFrustumPlanes(LLVector3* frust) } } +//calculate regional planes from mAgentPlanes. +//vector "shift" is the vector of the region origin in the agent space. +void LLCamera::calcRegionFrustumPlanes(const LLVector3& shift) +{ + F32 d; + LLVector3 n; + for(S32 i = 0 ; i < 7; i++) + { + if (mPlaneMask[i] != 0xff) + { + n.setVec(mAgentPlanes[i][0], mAgentPlanes[i][1], mAgentPlanes[i][2]); + d = mAgentPlanes[i][3] - n * shift; + mRegionPlanes[i].setVec(n, d); + } + } +} + void LLCamera::calculateFrustumPlanes(F32 left, F32 right, F32 top, F32 bottom) { LLVector3 a, b, c; diff --git a/indra/llmath/llcamera.h b/indra/llmath/llcamera.h index 0b591be622..898d73ed7e 100755 --- a/indra/llmath/llcamera.h +++ b/indra/llmath/llcamera.h @@ -109,6 +109,7 @@ public: private: LL_ALIGN_16(LLPlane mAgentPlanes[7]); //frustum planes in agent space a la gluUnproject (I'm a bastard, I know) - DaveP + LL_ALIGN_16(LLPlane mRegionPlanes[7]); //frustum planes in a local region space, derived from mAgentPlanes U8 mPlaneMask[8]; // 8 for alignment F32 mView; // angle between top and bottom frustum planes in radians. @@ -178,6 +179,7 @@ public: // Return number of bytes copied. size_t readFrustumFromBuffer(const char *buffer); void calcAgentFrustumPlanes(LLVector3* frust); + void calcRegionFrustumPlanes(const LLVector3& shift); //calculate regional planes from mAgentPlanes. void ignoreAgentFrustumPlane(S32 idx); // Returns 1 if partly in, 2 if fully in. @@ -186,8 +188,10 @@ public: S32 sphereInFrustum(const LLVector3 ¢er, const F32 radius) const; S32 pointInFrustum(const LLVector3 &point) const { return sphereInFrustum(point, 0.0f); } S32 sphereInFrustumFull(const LLVector3 ¢er, const F32 radius) const { return sphereInFrustum(center, radius); } - S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius); - S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius); + S32 AABBInFrustum(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL); + S32 AABBInRegionFrustum(const LLVector4a& center, const LLVector4a& radius); + S32 AABBInFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius, const LLPlane* planes = NULL); + S32 AABBInRegionFrustumNoFarClip(const LLVector4a& center, const LLVector4a& radius); //does a quick 'n dirty sphere-sphere check S32 sphereInFrustumQuick(const LLVector3 &sphere_center, const F32 radius); diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index b047f86e6e..0d632f59be 100755 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -49,10 +49,10 @@ class LLColor4 LLColor4(); // Initializes LLColor4 to (0, 0, 0, 1) LLColor4(F32 r, F32 g, F32 b); // Initializes LLColor4 to (r, g, b, 1) LLColor4(F32 r, F32 g, F32 b, F32 a); // Initializes LLColor4 to (r. g, b, a) - LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc)) - LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1) LLColor4(const LLColor3 &vec, F32 a = 1.f); // Initializes LLColor4 to (vec, a) explicit LLColor4(const LLSD& sd); + explicit LLColor4(const F32 *vec); // Initializes LLColor4 to (vec[0]. vec[1], vec[2], 1) + explicit LLColor4(U32 clr); // Initializes LLColor4 to (r=clr>>24, etc)) explicit LLColor4(const LLColor4U& color4u); // "explicit" to avoid automatic conversion explicit LLColor4(const LLVector4& vector4); // "explicit" to avoid automatic conversion diff --git a/indra/llmessage/llassetstorage.cpp b/indra/llmessage/llassetstorage.cpp index 9b86daebe5..430c9503ac 100755 --- a/indra/llmessage/llassetstorage.cpp +++ b/indra/llmessage/llassetstorage.cpp @@ -50,10 +50,14 @@ #include "lltransfertargetvfile.h" // For debugging #include "llmetrics.h" +#include "lltrace.h" LLAssetStorage *gAssetStorage = NULL; LLMetrics *LLAssetStorage::metric_recipient = NULL; +static LLTrace::CountStatHandle<> sFailedDownloadCount("faileddownloads", "Number of times LLAssetStorage::getAssetData() has failed"); + + const LLUUID CATEGORIZE_LOST_AND_FOUND_ID(std::string("00000000-0000-0000-0000-000000000010")); const U64 TOXIC_ASSET_LIFETIME = (120 * 1000000); // microseconds @@ -450,6 +454,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LL if (callback) { + add(sFailedDownloadCount, 1); callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_FAILED, LL_EXSTAT_NONE); } return; @@ -460,6 +465,7 @@ void LLAssetStorage::getAssetData(const LLUUID uuid, LLAssetType::EType type, LL // Special case early out for NULL uuid and for shutting down if (callback) { + add(sFailedDownloadCount, 1); callback(mVFS, uuid, type, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID); } return; @@ -572,6 +578,7 @@ void LLAssetStorage::_queueDataRequest(const LLUUID& uuid, LLAssetType::EType at llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl; if (callback) { + add(sFailedDownloadCount, 1); callback(mVFS, uuid, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM); } } @@ -649,6 +656,10 @@ void LLAssetStorage::downloadCompleteCallback( LLAssetRequest* tmp = *curiter; if (tmp->mDownCallback) { + if (result != LL_ERR_NOERR) + { + add(sFailedDownloadCount, 1); + } tmp->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), tmp->mUserData, result, ext_status); } delete tmp; @@ -669,6 +680,7 @@ void LLAssetStorage::getEstateAsset(const LLHost &object_sim, const LLUUID &agen // Special case early out for NULL uuid if (callback) { + add(sFailedDownloadCount, 1); callback(mVFS, asset_id, atype, user_data, LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE, LL_EXSTAT_NULL_UUID); } return; @@ -741,6 +753,7 @@ void LLAssetStorage::getEstateAsset(const LLHost &object_sim, const LLUUID &agen llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl; if (callback) { + add(sFailedDownloadCount, 1); callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM); } } @@ -783,6 +796,10 @@ void LLAssetStorage::downloadEstateAssetCompleteCallback( } } + if (result != LL_ERR_NOERR) + { + add(sFailedDownloadCount, 1); + } req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getAType(), req->mUserData, result, ext_status); } @@ -883,6 +900,7 @@ void LLAssetStorage::getInvItemAsset(const LLHost &object_sim, const LLUUID &age llwarns << "Attempt to move asset data request upstream w/o valid upstream provider" << llendl; if (callback) { + add(sFailedDownloadCount, 1); callback(mVFS, asset_id, atype, user_data, LL_ERR_CIRCUIT_GONE, LL_EXSTAT_NO_UPSTREAM); } } @@ -925,6 +943,10 @@ void LLAssetStorage::downloadInvItemCompleteCallback( } } + if (result != LL_ERR_NOERR) + { + add(sFailedDownloadCount, 1); + } req->mDownCallback(gAssetStorage->mVFS, req->getUUID(), req->getType(), req->mUserData, result, ext_status); } @@ -1237,6 +1259,7 @@ bool LLAssetStorage::deletePendingRequestImpl(LLAssetStorage::request_list_t* re } if (req->mDownCallback) { + add(sFailedDownloadCount, 1); req->mDownCallback(mVFS, req->getUUID(), req->getType(), req->mUserData, error, LL_EXSTAT_REQUEST_DROPPED); } if (req->mInfoCallback) @@ -1363,6 +1386,10 @@ void LLAssetStorage::legacyGetDataCallback(LLVFS *vfs, const LLUUID &uuid, LLAss } } + if (status != LL_ERR_NOERR) + { + add(sFailedDownloadCount, 1); + } legacy->mDownCallback(filename.c_str(), uuid, legacy->mUserData, status, ext_status); delete legacy; } diff --git a/indra/llmessage/llbuffer.cpp b/indra/llmessage/llbuffer.cpp index 01da20f060..1722b48f44 100755 --- a/indra/llmessage/llbuffer.cpp +++ b/indra/llmessage/llbuffer.cpp @@ -32,6 +32,7 @@ #include "llmath.h" #include "llstl.h" #include "llthread.h" +#include <iterator> #define ASSERT_LLBUFFERARRAY_MUTEX_LOCKED llassert(!mMutexp || mMutexp->isSelfLocked()); diff --git a/indra/llmessage/lldatapacker.h b/indra/llmessage/lldatapacker.h index b0a638c16e..226752d52e 100755 --- a/indra/llmessage/lldatapacker.h +++ b/indra/llmessage/lldatapacker.h @@ -170,6 +170,7 @@ public: S32 getBufferSize() const { return mBufferSize; } const U8* getBuffer() const { return mBufferp; } void reset() { mCurBufferp = mBufferp; mWriteEnabled = (mCurBufferp != NULL); } + void shift(S32 offset) { reset(); mCurBufferp += offset;} void freeBuffer() { delete [] mBufferp; mBufferp = mCurBufferp = NULL; mBufferSize = 0; mWriteEnabled = FALSE; } void assignBuffer(U8 *bufferp, S32 size) { diff --git a/indra/llmessage/lldispatcher.cpp b/indra/llmessage/lldispatcher.cpp index b2dc414a68..7ac3651a76 100755 --- a/indra/llmessage/lldispatcher.cpp +++ b/indra/llmessage/lldispatcher.cpp @@ -29,6 +29,7 @@ #include "lldispatcher.h" #include <algorithm> +#include <iterator> #include "llstl.h" #include "message.h" diff --git a/indra/llmessage/llfiltersd2xmlrpc.cpp b/indra/llmessage/llfiltersd2xmlrpc.cpp index e0ca056a5f..dbb8c4e28d 100755 --- a/indra/llmessage/llfiltersd2xmlrpc.cpp +++ b/indra/llmessage/llfiltersd2xmlrpc.cpp @@ -80,6 +80,7 @@ #include "llbuffer.h" #include "llbufferstream.h" +#include "llfasttimer.h" #include "llmemorystream.h" #include "llsd.h" #include "llsdserialize.h" diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 1236fc8b71..f9d37b2e39 100755 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -33,6 +33,7 @@ #include "llapr.h" #include "llbuffer.h" #include "llbufferstream.h" +#include "llfasttimer.h" #include "llhttpnode.h" #include "lliopipe.h" #include "lliosocket.h" diff --git a/indra/llmessage/lliopipe.h b/indra/llmessage/lliopipe.h index cbd17b5a3d..9a0a427efd 100755 --- a/indra/llmessage/lliopipe.h +++ b/indra/llmessage/lliopipe.h @@ -31,6 +31,7 @@ #include <boost/intrusive_ptr.hpp> #include <boost/shared_ptr.hpp> +#include "llwin32headerslean.h" #include "apr_poll.h" #include "llsd.h" diff --git a/indra/llmessage/lliosocket.cpp b/indra/llmessage/lliosocket.cpp index 2043bae5e7..27e3cc7898 100755 --- a/indra/llmessage/lliosocket.cpp +++ b/indra/llmessage/lliosocket.cpp @@ -32,6 +32,7 @@ #include "llapr.h" #include "llbuffer.h" +#include "llfasttimer.h" #include "llhost.h" #include "llpumpio.h" diff --git a/indra/llmessage/lliosocket.h b/indra/llmessage/lliosocket.h index be0f7dfcc6..ec998552d0 100755 --- a/indra/llmessage/lliosocket.h +++ b/indra/llmessage/lliosocket.h @@ -38,6 +38,7 @@ */ #include "lliopipe.h" +#include "llwin32headerslean.h" #include "apr_pools.h" #include "apr_network_io.h" #include "llchainio.h" diff --git a/indra/llmessage/llioutil.cpp b/indra/llmessage/llioutil.cpp index 8c50fd5069..9fd49d23d4 100755 --- a/indra/llmessage/llioutil.cpp +++ b/indra/llmessage/llioutil.cpp @@ -28,6 +28,7 @@ #include "linden_common.h" #include "llioutil.h" +#include "llfasttimer.h" /** * LLIOFlush diff --git a/indra/llmessage/llmail.cpp b/indra/llmessage/llmail.cpp index 08b31e9c7a..dc27f2ca4a 100755 --- a/indra/llmessage/llmail.cpp +++ b/indra/llmessage/llmail.cpp @@ -29,12 +29,7 @@ #include "llmail.h" // APR on Windows needs full windows headers -#ifdef LL_WINDOWS -# undef WIN32_LEAN_AND_MEAN -# include <winsock2.h> -# include <windows.h> -#endif - +#include "llwin32headers.h" #include <string> #include <sstream> diff --git a/indra/llmessage/llproxy.cpp b/indra/llmessage/llproxy.cpp index 9988fcd9c0..9b8d19cc3e 100755 --- a/indra/llmessage/llproxy.cpp +++ b/indra/llmessage/llproxy.cpp @@ -57,13 +57,15 @@ LLProxy::LLProxy(): mAuthMethodSelected(METHOD_NOAUTH), mSocksUsername(), mSocksPassword() -{ -} +{} LLProxy::~LLProxy() { - stopSOCKSProxy(); - disableHTTPProxy(); + if (ll_apr_is_initialized()) + { + stopSOCKSProxy(); + disableHTTPProxy(); + } } /** diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index 0623e99f0a..e3f09f34ee 100755 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -34,6 +34,7 @@ #include "apr_poll.h" #include "llapr.h" +#include "llfasttimer.h" #include "llstl.h" // These should not be enabled in production, but they can be diff --git a/indra/llmessage/llsdrpcclient.cpp b/indra/llmessage/llsdrpcclient.cpp index fcda0e81a3..05b27f582c 100755 --- a/indra/llmessage/llsdrpcclient.cpp +++ b/indra/llmessage/llsdrpcclient.cpp @@ -30,6 +30,7 @@ #include "llsdrpcclient.h" #include "llbufferstream.h" +#include "llfasttimer.h" #include "llfiltersd2xmlrpc.h" #include "llpumpio.h" #include "llsd.h" diff --git a/indra/llmessage/llsdrpcserver.cpp b/indra/llmessage/llsdrpcserver.cpp index f26ee52f71..2c233c1c0d 100755 --- a/indra/llmessage/llsdrpcserver.cpp +++ b/indra/llmessage/llsdrpcserver.cpp @@ -31,6 +31,7 @@ #include "llbuffer.h" #include "llbufferstream.h" +#include "llfasttimer.h" #include "llpumpio.h" #include "llsdserialize.h" #include "llstl.h" diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp index 627d591839..7281ac35af 100755 --- a/indra/llmessage/llurlrequest.cpp +++ b/indra/llmessage/llurlrequest.cpp @@ -33,6 +33,7 @@ #include <openssl/x509_vfy.h> #include <openssl/ssl.h> #include "llcurl.h" +#include "llfasttimer.h" #include "llioutil.h" #include "llproxy.h" #include "llpumpio.h" @@ -284,6 +285,8 @@ LLIOPipe::EStatus LLURLRequest::handleError( static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST("URL Request"); static LLFastTimer::DeclareTimer FTM_PROCESS_URL_REQUEST_GET_RESULT("Get Result"); static LLFastTimer::DeclareTimer FTM_URL_PERFORM("Perform"); +static LLFastTimer::DeclareTimer FTM_PROCESS_URL_PUMP_RESPOND("Pump Respond"); +static LLFastTimer::DeclareTimer FTM_URL_ADJUST_TIMEOUT("Adjust Timeout"); // virtual LLIOPipe::EStatus LLURLRequest::process_impl( @@ -303,7 +306,6 @@ LLIOPipe::EStatus LLURLRequest::process_impl( const S32 MIN_ACCUMULATION = 100000; if(pump && (mDetail->mByteAccumulator > MIN_ACCUMULATION)) { - static LLFastTimer::DeclareTimer FTM_URL_ADJUST_TIMEOUT("Adjust Timeout"); LLFastTimer t(FTM_URL_ADJUST_TIMEOUT); // This is a pretty sloppy calculation, but this // tries to make the gross assumption that if data @@ -402,7 +404,6 @@ LLIOPipe::EStatus LLURLRequest::process_impl( link.mChannels = LLBufferArray::makeChannelConsumer( channels); chain.push_back(link); - static LLFastTimer::DeclareTimer FTM_PROCESS_URL_PUMP_RESPOND("Pump Respond"); { LLFastTimer t(FTM_PROCESS_URL_PUMP_RESPOND); pump->respond(chain, buffer, context); diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index 1589ea29c1..e94e2282a0 100755 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -50,9 +50,9 @@ #include "lltimer.h" #include "llpacketring.h" #include "llhost.h" -#include "llhttpclient.h" +#include "llcurl.h" #include "llhttpnode.h" -#include "llpacketack.h" +//#include "llpacketack.h" #include "llsingleton.h" #include "message_prehash.h" #include "llstl.h" @@ -158,7 +158,6 @@ const F32 LL_MAX_LOST_TIMEOUT = 5.f; // Maximum amount of time before cons const S32 MAX_MESSAGE_COUNT_NUM = 1024; // Forward declarations -class LLCircuit; class LLVector3; class LLVector4; class LLVector3d; @@ -214,19 +213,19 @@ class LLMessageSystem : public LLMessageSenderInterface public: LLPacketRing mPacketRing; - LLReliablePacketParams mReliablePacketParams; + LLReliablePacketParams mReliablePacketParams; // Set this flag to TRUE when you want *very* verbose logs. - BOOL mVerboseLog; + BOOL mVerboseLog; - F32 mMessageFileVersionNumber; + F32 mMessageFileVersionNumber; typedef std::map<const char *, LLMessageTemplate*> message_template_name_map_t; typedef std::map<U32, LLMessageTemplate*> message_template_number_map_t; private: message_template_name_map_t mMessageTemplates; - message_template_number_map_t mMessageNumbers; + message_template_number_map_t mMessageNumbers; public: S32 mSystemVersionMajor; @@ -235,7 +234,7 @@ public: S32 mSystemVersionServer; U32 mVersionFlags; - BOOL mbProtected; + BOOL mbProtected; U32 mNumberHighFreqMessages; U32 mNumberMediumFreqMessages; @@ -255,11 +254,11 @@ public: U32 mReliablePacketsIn; // total reliable packets in U32 mReliablePacketsOut; // total reliable packets out - U32 mDroppedPackets; // total dropped packets in - U32 mResentPackets; // total resent packets out - U32 mFailedResendPackets; // total resend failure packets out - U32 mOffCircuitPackets; // total # of off-circuit packets rejected - U32 mInvalidOnCircuitPackets; // total # of on-circuit but invalid packets rejected + U32 mDroppedPackets; // total dropped packets in + U32 mResentPackets; // total resent packets out + U32 mFailedResendPackets; // total resend failure packets out + U32 mOffCircuitPackets; // total # of off-circuit packets rejected + U32 mInvalidOnCircuitPackets; // total # of on-circuit but invalid packets rejected S64 mUncompressedBytesIn; // total uncompressed size of compressed packets in S64 mUncompressedBytesOut; // total uncompressed size of compressed packets out @@ -268,14 +267,14 @@ public: S64 mTotalBytesIn; // total size of all uncompressed packets in S64 mTotalBytesOut; // total size of all uncompressed packets out - BOOL mSendReliable; // does the outgoing message require a pos ack? + BOOL mSendReliable; // does the outgoing message require a pos ack? - LLCircuit mCircuitInfo; + LLCircuit mCircuitInfo; F64 mCircuitPrintTime; // used to print circuit debug info every couple minutes F32 mCircuitPrintFreq; // seconds - std::map<U64, U32> mIPPortToCircuitCode; - std::map<U32, U64> mCircuitCodeToIPPort; + std::map<U64, U32> mIPPortToCircuitCode; + std::map<U32, U64> mCircuitCodeToIPPort; U32 mOurCircuitCode; S32 mSendPacketFailureCount; S32 mUnackedListDepth; @@ -494,7 +493,7 @@ public: void (*callback)(void **,S32), void ** callback_data); - LLHTTPClient::ResponderPtr createResponder(const std::string& name); + LLCurl::ResponderPtr createResponder(const std::string& name); S32 sendMessage(const LLHost &host); S32 sendMessage(const U32 circuit); private: diff --git a/indra/llmessage/net.cpp b/indra/llmessage/net.cpp index 85aef5da00..1c9508214c 100755 --- a/indra/llmessage/net.cpp +++ b/indra/llmessage/net.cpp @@ -26,15 +26,13 @@ #include "linden_common.h" -#include "net.h" +//#include "net.h" // system library includes #include <stdexcept> #if LL_WINDOWS - #define WIN32_LEAN_AND_MEAN - #include <winsock2.h> - #include <windows.h> +#include "llwin32headerslean.h" #else #include <sys/types.h> #include <sys/socket.h> diff --git a/indra/llplugin/llpluginprocesschild.h b/indra/llplugin/llpluginprocesschild.h index a9d6794e40..531422e792 100755 --- a/indra/llplugin/llpluginprocesschild.h +++ b/indra/llplugin/llpluginprocesschild.h @@ -29,6 +29,7 @@ #ifndef LL_LLPLUGINPROCESSCHILD_H #define LL_LLPLUGINPROCESSCHILD_H +#include <queue> #include "llpluginmessage.h" #include "llpluginmessagepipe.h" #include "llplugininstance.h" diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h index 990fc5cbae..24be7eb148 100755 --- a/indra/llplugin/llpluginprocessparent.h +++ b/indra/llplugin/llpluginprocessparent.h @@ -29,6 +29,8 @@ #ifndef LL_LLPLUGINPROCESSPARENT_H #define LL_LLPLUGINPROCESSPARENT_H +#include <queue> + #include "llapr.h" #include "llprocess.h" #include "llpluginmessage.h" diff --git a/indra/llplugin/tests/llplugincookiestore_test.cpp b/indra/llplugin/tests/llplugincookiestore_test.cpp index aefa1ca144..c2cb236cba 100755 --- a/indra/llplugin/tests/llplugincookiestore_test.cpp +++ b/indra/llplugin/tests/llplugincookiestore_test.cpp @@ -27,6 +27,7 @@ */ #include "linden_common.h" +#include <list> #include "../test/lltut.h" #include "../llplugincookiestore.h" diff --git a/indra/llprimitive/CMakeLists.txt b/indra/llprimitive/CMakeLists.txt index 1768a06a27..d15ed1ca1f 100755 --- a/indra/llprimitive/CMakeLists.txt +++ b/indra/llprimitive/CMakeLists.txt @@ -33,7 +33,6 @@ set(llprimitive_SOURCE_FILES lltextureentry.cpp lltreeparams.cpp llvolumemessage.cpp - llvolumexml.cpp material_codes.cpp ) @@ -51,7 +50,6 @@ set(llprimitive_HEADER_FILES lltreeparams.h lltree_common.h llvolumemessage.h - llvolumexml.h material_codes.h object_flags.h ) diff --git a/indra/llprimitive/llvolumexml.cpp b/indra/llprimitive/llvolumexml.cpp deleted file mode 100755 index bf2297a029..0000000000 --- a/indra/llprimitive/llvolumexml.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @file llvolumexml.cpp - * @brief LLVolumeXml base class - * - * $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 "linden_common.h" - -#include "llvolumexml.h" - -//============================================================================ - -// LLVolumeXml is just a wrapper class; all members are static - -//============================================================================ - -LLPointer<LLXMLNode> LLVolumeXml::exportProfileParams(const LLProfileParams* params) -{ - LLPointer<LLXMLNode> ret = new LLXMLNode("profile", FALSE); - - ret->createChild("curve_type", TRUE)->setByteValue(1, ¶ms->getCurveType()); - ret->createChild("interval", FALSE)->setFloatValue(2, ¶ms->getBegin()); - ret->createChild("hollow", FALSE)->setFloatValue(1, ¶ms->getHollow()); - - return ret; -} - - -LLPointer<LLXMLNode> LLVolumeXml::exportPathParams(const LLPathParams* params) -{ - LLPointer<LLXMLNode> ret = new LLXMLNode("path", FALSE); - ret->createChild("curve_type", TRUE)->setByteValue(1, ¶ms->getCurveType()); - ret->createChild("interval", FALSE)->setFloatValue(2, ¶ms->getBegin()); - ret->createChild("scale", FALSE)->setFloatValue(2, params->getScale().mV); - ret->createChild("shear", FALSE)->setFloatValue(2, params->getShear().mV); - ret->createChild("twist_interval", FALSE)->setFloatValue(2, ¶ms->getTwistBegin()); - ret->createChild("radius_offset", FALSE)->setFloatValue(1, ¶ms->getRadiusOffset()); - ret->createChild("taper", FALSE)->setFloatValue(2, params->getTaper().mV); - ret->createChild("revolutions", FALSE)->setFloatValue(1, ¶ms->getRevolutions()); - ret->createChild("skew", FALSE)->setFloatValue(1, ¶ms->getSkew()); - - return ret; -} - - -LLPointer<LLXMLNode> LLVolumeXml::exportVolumeParams(const LLVolumeParams* params) -{ - LLPointer<LLXMLNode> ret = new LLXMLNode("shape", FALSE); - - LLPointer<LLXMLNode> node ; - node = exportPathParams(¶ms->getPathParams()) ; - node->setParent(ret); - node = exportProfileParams(¶ms->getProfileParams()) ; - node->setParent(ret); - - return ret; -} - diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index c4f36cabd0..a646a0d35a 100755 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -29,6 +29,7 @@ #include "llfontgl.h" // Linden library includes +#include "llfasttimer.h" #include "llfontfreetype.h" #include "llfontbitmapcache.h" #include "llfontregistry.h" diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index f5ca8d5b04..77aa3fcd2c 100755 --- 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) @@ -207,7 +209,7 @@ 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; } } @@ -230,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")) { @@ -263,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; @@ -281,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 @@ -306,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; } } } @@ -318,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 059248fbbd..177eb6c8a5 100755 --- 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,6 +65,7 @@ private: class LLFontRegistry { public: + friend bool init_from_xml(LLFontRegistry*, LLPointer<class LLXMLNode>); // create_gl_textures - set to false for test apps with no OpenGL window, // such as llui_libtest LLFontRegistry(bool create_gl_textures); @@ -72,7 +73,6 @@ public: // 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(); @@ -94,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<LLFontDescriptor,LLFontGL*> font_reg_map_t; typedef std::map<std::string,F32> font_size_map_t; diff --git a/indra/llrender/llglheaders.h b/indra/llrender/llglheaders.h index 509de51f4d..c9ce0d5588 100755 --- a/indra/llrender/llglheaders.h +++ b/indra/llrender/llglheaders.h @@ -540,9 +540,7 @@ extern PFNGLBINDBUFFERRANGEPROC glBindBufferRange; // LL_WINDOWS // windows gl headers depend on things like APIENTRY, so include windows. -#define WIN32_LEAN_AND_MEAN -#include <winsock2.h> -#include <windows.h> +#include "llwin32headerslean.h" //---------------------------------------------------------------------------- #include <GL/gl.h> diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index 5c171d372c..2c3fcfcec1 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -32,6 +32,7 @@ #include "llimagegl.h" #include "llerror.h" +#include "llfasttimer.h" #include "llimage.h" #include "llmath.h" @@ -50,9 +51,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; +LLUnit<LLUnits::Bytes, S32> LLImageGL::sGlobalTextureMemory = 0; +LLUnit<LLUnits::Bytes, S32> LLImageGL::sBoundTextureMemory = 0; +LLUnit<LLUnits::Bytes, S32> LLImageGL::sCurBoundTextureMemory = 0; S32 LLImageGL::sCount = 0; LLImageGL::dead_texturelist_t LLImageGL::sDeadTextureList[LLTexUnit::TT_NONE]; U32 LLImageGL::sCurTexName = 1; @@ -247,7 +248,7 @@ void LLImageGL::updateStats(F32 current_time) { LLFastTimer t(FTM_IMAGE_UPDATE_STATS); sLastFrameTime = current_time; - sBoundTextureMemoryInBytes = sCurBoundTextureMemory; + sBoundTextureMemory = sCurBoundTextureMemory; sCurBoundTextureMemory = 0; } @@ -255,7 +256,7 @@ void LLImageGL::updateStats(F32 current_time) S32 LLImageGL::updateBoundTexMem(const S32 mem, const S32 ncomponents, S32 category) { LLImageGL::sCurBoundTextureMemory += mem ; - return LLImageGL::sCurBoundTextureMemory; + return LLImageGL::sCurBoundTextureMemory.value(); } //---------------------------------------------------------------------------- @@ -624,7 +625,7 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) { is_compressed = true; } - + if (mUseMipMaps) @@ -1142,7 +1143,7 @@ void LLImageGL::deleteTextures(LLTexUnit::eTextureType type, U32 format, S32 mip sDeadTextureList[type][format].push_back(textures[i]); } } - } + } break; } } @@ -1440,7 +1441,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ if (old_name != 0) { - sGlobalTextureMemoryInBytes -= mTextureMemory; + sGlobalTextureMemory -= mTextureMemory; LLImageGL::deleteTextures(mBindTarget, mFormatInternal, mMipLevels, 1, &old_name); @@ -1448,7 +1449,7 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ } mTextureMemory = getMipBytes(discard_level); - sGlobalTextureMemoryInBytes += mTextureMemory; + sGlobalTextureMemory += mTextureMemory; mTexelsInGLTexture = getWidth() * getHeight() ; // mark this as bound at this point, so we don't throw it out immediately @@ -1607,7 +1608,7 @@ void LLImageGL::destroyGLTexture() { if(mTextureMemory) { - sGlobalTextureMemoryInBytes -= mTextureMemory; + sGlobalTextureMemory -= mTextureMemory; mTextureMemory = 0; } diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 57a052b258..2b568e5e0f 100755 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -34,6 +34,7 @@ #include "llpointer.h" #include "llrefcount.h" #include "v2math.h" +#include "llunit.h" #include "llrender.h" class LLTextureAtlas ; @@ -245,9 +246,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 LLUnit<LLUnits::Bytes, S32> sGlobalTextureMemory; // Tracks main memory texmem + static LLUnit<LLUnits::Bytes, S32> sBoundTextureMemory; // Tracks bound texmem for last completed frame + static LLUnit<LLUnits::Bytes, S32> 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; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index c60eb8d9d9..918f5585a8 100755 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -245,6 +245,11 @@ bool LLTexUnit::bind(LLTexture* texture, bool for_rendering, bool forceBind) return texture->bindDefaultImage(mIndex); } + if(texture->isActiveFetching()) //in debug + { + return texture->bindDebugImage(mIndex); + } + //in audit, replace the selected texture by the default one. if ((mCurrTexture != gl_tex->getTexName()) || forceBind) { diff --git a/indra/llrender/llrender2dutils.cpp b/indra/llrender/llrender2dutils.cpp index d3cfbaf03a..9d23a64e4c 100644 --- a/indra/llrender/llrender2dutils.cpp +++ b/indra/llrender/llrender2dutils.cpp @@ -35,6 +35,7 @@ #include "llrect.h" #include "llgl.h" #include "lltexture.h" +#include "llfasttimer.h" // Project includes #include "llrender2dutils.h" @@ -353,6 +354,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) @@ -639,99 +645,111 @@ 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) -{ - if (NULL == image) - { - llwarns << "image == NULL; aborting function" << llendl; - return; - } - - LLGLSUIDefault gls_ui; - - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - if (degrees == 0.f) - { - const S32 NUM_VERTICES = 4; // 9 quads - LLVector2 uv[NUM_VERTICES]; - LLVector3 pos[NUM_VERTICES]; - - gGL.begin(LLRender::QUADS); - { - LLVector3 ui_scale = gGL.getUIScale(); - LLVector3 ui_translation = gGL.getUITranslation(); - ui_translation.mV[VX] += x; - ui_translation.mV[VY] += y; - ui_translation.scaleVec(ui_scale); - S32 index = 0; - S32 scaled_width = llround(width * ui_scale.mV[VX]); - S32 scaled_height = llround(height * ui_scale.mV[VY]); - - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f); - index++; - - uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom); - pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f); - index++; - - gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES); - } - gGL.end(); - } - else - { - gGL.pushUIMatrix(); - gGL.translateUI((F32)x, (F32)y, 0.f); - - F32 offset_x = F32(width/2); - F32 offset_y = F32(height/2); - - gGL.translateUI(offset_x, offset_y, 0.f); - - LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD); - - gGL.getTexUnit(0)->bind(image, true); - - gGL.color4fv(color.mV); - - gGL.begin(LLRender::QUADS); - { - LLVector3 v; - - v = LLVector3(offset_x, offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(-offset_x, offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(-offset_x, -offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom); - gGL.vertex2f(v.mV[0], v.mV[1] ); - - v = LLVector3(offset_x, -offset_y, 0.f) * quat; - gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom); - gGL.vertex2f(v.mV[0], v.mV[1] ); - } - gGL.end(); - gGL.popUIMatrix(); - } -} - +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 (!image && !target)
+ {
+ llwarns << "image == NULL; aborting function" << llendl;
+ return;
+ }
+
+ LLGLSUIDefault gls_ui;
+
+ if(image != NULL)
+ {
+ gGL.getTexUnit(0)->bind(image, true);
+ }
+ else
+ {
+ gGL.getTexUnit(0)->bind(target);
+ }
+
+ gGL.color4fv(color.mV);
+
+ if (degrees == 0.f)
+ {
+ const S32 NUM_VERTICES = 4; // 9 quads
+ LLVector2 uv[NUM_VERTICES];
+ LLVector3 pos[NUM_VERTICES];
+
+ gGL.begin(LLRender::QUADS);
+ {
+ LLVector3 ui_scale = gGL.getUIScale();
+ LLVector3 ui_translation = gGL.getUITranslation();
+ ui_translation.mV[VX] += x;
+ ui_translation.mV[VY] += y;
+ ui_translation.scaleVec(ui_scale);
+ S32 index = 0;
+ S32 scaled_width = llround(width * ui_scale.mV[VX]);
+ S32 scaled_height = llround(height * ui_scale.mV[VY]);
+
+ uv[index] = LLVector2(uv_rect.mRight, uv_rect.mTop);
+ pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY] + scaled_height, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mTop);
+ pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY] + scaled_height, 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mLeft, uv_rect.mBottom);
+ pos[index] = LLVector3(ui_translation.mV[VX], ui_translation.mV[VY], 0.f);
+ index++;
+
+ uv[index] = LLVector2(uv_rect.mRight, uv_rect.mBottom);
+ pos[index] = LLVector3(ui_translation.mV[VX] + scaled_width, ui_translation.mV[VY], 0.f);
+ index++;
+
+ gGL.vertexBatchPreTransformed(pos, uv, NUM_VERTICES);
+ }
+ gGL.end();
+ }
+ else
+ {
+ gGL.pushUIMatrix();
+ gGL.translateUI((F32)x, (F32)y, 0.f);
+
+ F32 offset_x = F32(width/2);
+ F32 offset_y = F32(height/2);
+
+ gGL.translateUI(offset_x, offset_y, 0.f);
+
+ LLMatrix3 quat(0.f, 0.f, degrees*DEG_TO_RAD);
+
+ 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;
+
+ v = LLVector3(offset_x, offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mRight, uv_rect.mTop);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+
+ v = LLVector3(-offset_x, offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mLeft, uv_rect.mTop);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+
+ v = LLVector3(-offset_x, -offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mLeft, uv_rect.mBottom);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+
+ v = LLVector3(offset_x, -offset_y, 0.f) * quat;
+ gGL.texCoord2f(uv_rect.mRight, uv_rect.mBottom);
+ gGL.vertex2f(v.mV[0], v.mV[1] );
+ }
+ gGL.end();
+ gGL.popUIMatrix();
+ }
+}
void gl_stippled_line_3d( const LLVector3& start, const LLVector3& end, const LLColor4& color, F32 phase ) { @@ -1044,6 +1062,8 @@ void gl_rect_2d_simple( S32 width, S32 height ) gGL.end(); } +static LLFastTimer::DeclareTimer FTM_RENDER_SEGMENTED_RECT ("Render segmented rectangle"); + void gl_segmented_rect_2d_tex(const S32 left, const S32 top, const S32 right, @@ -1053,6 +1073,8 @@ void gl_segmented_rect_2d_tex(const S32 left, const S32 border_size, const U32 edges) { + LLFastTimer _(FTM_RENDER_SEGMENTED_RECT); + S32 width = llabs(right - left); S32 height = llabs(top - bottom); @@ -1202,18 +1224,19 @@ 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) { + LLFastTimer _(FTM_RENDER_SEGMENTED_RECT); + 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); @@ -1251,9 +1274,9 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, { if (start_fragment < middle_start) { - u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX]; + u_min = (start_fragment / middle_start) * border_uv_scale.mV[VX]; u_max = llmin(end_fragment / middle_start, 1.f) * border_uv_scale.mV[VX]; - x_min = (start_fragment / middle_start) * border_width_left; + x_min = (start_fragment / middle_start) * border_width_left; x_max = llmin(end_fragment / middle_start, 1.f) * border_width_left; // draw bottom left @@ -1281,7 +1304,7 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); - + // draw top left gGL.texCoord2f(u_min, 1.f - border_uv_scale.mV[VY]); gGL.vertex2fv((x_min + height_vec - border_height_top).mV); @@ -1343,10 +1366,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); @@ -1396,6 +1419,8 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, 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) { + LLFastTimer _(FTM_RENDER_SEGMENTED_RECT); + gGL.begin(LLRender::QUADS); { // draw bottom left diff --git a/indra/llrender/llrender2dutils.h b/indra/llrender/llrender2dutils.h index 4884422c58..2b8964742b 100644 --- a/indra/llrender/llrender2dutils.h +++ b/indra/llrender/llrender2dutils.h @@ -71,9 +71,10 @@ 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_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_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)); 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)); @@ -105,7 +106,7 @@ 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_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/lltexture.h b/indra/llrender/lltexture.h index 093bac20d1..ff711b8004 100755 --- a/indra/llrender/lltexture.h +++ b/indra/llrender/lltexture.h @@ -57,10 +57,12 @@ public: virtual S8 getType() const = 0 ; virtual void setKnownDrawSize(S32 width, S32 height) = 0 ; virtual bool bindDefaultImage(const S32 stage = 0) = 0 ; + virtual bool bindDebugImage(const S32 stage = 0) = 0; virtual void forceImmediateUpdate() = 0 ; virtual void setActive() = 0 ; virtual S32 getWidth(S32 discard_level = -1) const = 0 ; virtual S32 getHeight(S32 discard_level = -1) const = 0 ; + virtual bool isActiveFetching() = 0; private: //note: do not make this function public. diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 4909b43e8a..55a616ef34 100755 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -26,7 +26,7 @@ #include "linden_common.h" -#include <boost/static_assert.hpp> +#include "llfasttimer.h" #include "llsys.h" #include "llvertexbuffer.h" // #include "llrender.h" diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 34a08603fa..c4270a62bd 100755 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -61,7 +61,6 @@ set(llui_SOURCE_FILES llfolderview.cpp llfolderviewitem.cpp llfolderviewmodel.cpp - llfunctorregistry.cpp lliconctrl.cpp llkeywords.cpp lllayoutstack.cpp diff --git a/indra/llui/llaccordionctrltab.cpp b/indra/llui/llaccordionctrltab.cpp index 43462bd244..53720a6044 100755 --- a/indra/llui/llaccordionctrltab.cpp +++ b/indra/llui/llaccordionctrltab.cpp @@ -444,9 +444,9 @@ void LLAccordionCtrlTab::changeOpenClose(bool is_open) } } -void LLAccordionCtrlTab::handleVisibilityChange(BOOL new_visibility) +void LLAccordionCtrlTab::onVisibilityChange(BOOL new_visibility) { - LLUICtrl::handleVisibilityChange(new_visibility); + LLUICtrl::onVisibilityChange(new_visibility); notifyParent(LLSD().with("child_visibility_change", new_visibility)); } diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index dddaa581e6..7a78700e0f 100755 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -158,7 +158,7 @@ public: /** * Raises notifyParent event with "child_visibility_change" = new_visibility */ - void handleVisibilityChange(BOOL new_visibility); + void onVisibilityChange(BOOL new_visibility); // Changes expand/collapse state and triggers expand/collapse callbacks virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index a8149a9a1d..ce4d137478 100755 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -779,11 +779,11 @@ void LLButton::draw() { mCurGlowStrength = lerp(mCurGlowStrength, mFlashing ? (mFlashingTimer->isCurrentlyHighlighted() || !mFlashingTimer->isFlashingInProgress() || mNeedsHighlight? 1.0 : 0.0) : mHoverGlowStrength, - LLCriticalDamp::getInterpolant(0.05f)); + LLSmoothInterpolation::getInterpolant(0.05f)); } else { - mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLCriticalDamp::getInterpolant(0.05f)); + mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLSmoothInterpolation::getInterpolant(0.05f)); } // Draw button image, if available. diff --git a/indra/llui/llcontainerview.cpp b/indra/llui/llcontainerview.cpp index e08ccb0b78..06f8e72c9c 100755 --- a/indra/llui/llcontainerview.cpp +++ b/indra/llui/llcontainerview.cpp @@ -49,7 +49,6 @@ LLContainerView::LLContainerView(const LLContainerView::Params& p) mLabel(p.label), mDisplayChildren(p.display_children) { - mCollapsible = TRUE; mScrollContainer = NULL; } @@ -75,6 +74,11 @@ bool LLContainerView::addChild(LLView* child, S32 tab_group) return res; } +BOOL LLContainerView::handleDoubleClick(S32 x, S32 y, MASK mask) +{ + return handleMouseDown(x, y, mask); +} + BOOL LLContainerView::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; @@ -84,7 +88,7 @@ BOOL LLContainerView::handleMouseDown(S32 x, S32 y, MASK mask) } if (!handled) { - if( mCollapsible && mShowLabel && (y >= getRect().getHeight() - 10) ) + if( mShowLabel && (y >= getRect().getHeight() - 10) ) { setDisplayChildren(!mDisplayChildren); reshape(getRect().getWidth(), getRect().getHeight(), FALSE); diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h index e81600fd6c..ac92b19977 100755 --- a/indra/llui/llcontainerview.h +++ b/indra/llui/llcontainerview.h @@ -66,6 +66,7 @@ public: /*virtual*/ BOOL postBuild(); /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); + /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); @@ -87,8 +88,5 @@ public: protected: BOOL mDisplayChildren; std::string mLabel; -public: - BOOL mCollapsible; - }; #endif // LL_CONTAINERVIEW_ diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 09e27a264a..d06e2c9334 100755 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -598,7 +598,7 @@ LLControlGroup* LLFloater::getControlGroup() void LLFloater::setVisible( BOOL visible ) { - LLPanel::setVisible(visible); // calls handleVisibilityChange() + LLPanel::setVisible(visible); // calls onVisibilityChange() if( visible && mFirstLook ) { mFirstLook = FALSE; @@ -641,21 +641,21 @@ void LLFloater::setIsSingleInstance(BOOL is_single_instance) // virtual -void LLFloater::handleVisibilityChange ( BOOL new_visibility ) +void LLFloater::onVisibilityChange ( BOOL new_visibility ) { if (new_visibility) { if (getHost()) getHost()->setFloaterFlashing(this, FALSE); } - LLPanel::handleVisibilityChange ( new_visibility ); + LLPanel::onVisibilityChange ( new_visibility ); } void LLFloater::openFloater(const LLSD& key) { llinfos << "Opening floater " << getName() << llendl; mKey = key; // in case we need to open ourselves again - + if (getSoundFlags() != SILENT // don't play open sound for hosted (tabbed) windows && !getHost() @@ -803,7 +803,7 @@ void LLFloater::closeFloater(bool app_quitting) } else { - setVisible(FALSE); // hide before destroying (so handleVisibilityChange() gets called) + setVisible(FALSE); // hide before destroying (so onVisibilityChange() gets called) if (!mReuseInstance) { destroy(); @@ -1157,11 +1157,11 @@ void LLFloater::handleReshape(const LLRect& new_rect, bool by_user) { setDocked( false, false); } - storeRectControl(); - mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; - LLRect screen_rect = calcScreenRect(); - mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); - } + storeRectControl(); + mPositioning = LLFloaterEnums::POSITIONING_RELATIVE; + LLRect screen_rect = calcScreenRect(); + mPosition = LLCoordGL(screen_rect.getCenterX(), screen_rect.getCenterY()).convert(); + } // gather all snapped dependents for(handle_set_iter_t dependent_it = mDependents.begin(); @@ -3149,7 +3149,7 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str parser.readXUI(node, output_params, LLUICtrlFactory::getInstance()->getCurFileName()); setupParamsForExport(output_params, parent); output_node->setName(node->getName()->mString); - parser.writeXUI(output_node, output_params, &default_params); + parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params); return TRUE; } @@ -3179,9 +3179,8 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, const std::str { Params output_params(params); setupParamsForExport(output_params, parent); - Params default_params(LLUICtrlFactory::getDefaultParams<LLFloater>()); output_node->setName(node->getName()->mString); - parser.writeXUI(output_node, output_params, &default_params); + parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params); } // Default floater position to top-left corner of screen diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 4dba1e645f..ad0b800f1c 100755 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -302,7 +302,7 @@ public: virtual BOOL canClose() { return TRUE; } /*virtual*/ void setVisible(BOOL visible); // do not override - /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); // do not override + /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // do not override void setFrontmost(BOOL take_focus = TRUE); virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE, const LLSD& key = LLSD()); diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h index a1e1f8a988..e3b17dcb4f 100755 --- a/indra/llui/llfloaterreg.h +++ b/indra/llui/llfloaterreg.h @@ -30,6 +30,7 @@ #include "llrect.h" #include "llsd.h" +#include <list> #include <boost/function.hpp> //******************************************************* diff --git a/indra/llui/llfolderviewitem.cpp b/indra/llui/llfolderviewitem.cpp index fdb4108afb..c7910cb883 100755..100644 --- a/indra/llui/llfolderviewitem.cpp +++ b/indra/llui/llfolderviewitem.cpp @@ -489,7 +489,7 @@ BOOL LLFolderViewItem::handleMouseDown( S32 x, S32 y, MASK mask ) // No handler needed for focus lost since this class has no // state that depends on it. gFocusMgr.setMouseCapture( this ); - + if (!mIsSelected) { if(mask & MASK_CONTROL) @@ -706,7 +706,7 @@ void LLFolderViewItem::drawHighlight(const BOOL showContent, const BOOL hasKeybo bg_color.mV[VALPHA] = clamp_rescale(fade_time, 0.f, 0.4f, 0.f, bg_color.mV[VALPHA]); } gl_rect_2d(FOCUS_LEFT, - focus_top, + focus_top, getRect().getWidth() - 2, focus_bottom, bg_color, hasKeyboardFocus); @@ -860,7 +860,7 @@ void LLFolderViewItem::draw() LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, &right_x, FALSE ); } - + //--------------------------------------------------------------------------------// // Highlight string match // @@ -882,7 +882,7 @@ const LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) c { return getRoot()->getFolderViewModel(); } - + LLFolderViewModelInterface* LLFolderViewItem::getFolderViewModel( void ) { return getRoot()->getFolderViewModel(); @@ -919,11 +919,11 @@ void LLFolderViewFolder::updateLabelRotation() } else if (isOpen()) { - mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLCriticalDamp::getInterpolant(0.04f)); + mControlLabelRotation = lerp(mControlLabelRotation, -90.f, LLSmoothInterpolation::getInterpolant(0.04f)); } else { - mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLCriticalDamp::getInterpolant(0.025f)); + mControlLabelRotation = lerp(mControlLabelRotation, 0.f, LLSmoothInterpolation::getInterpolant(0.025f)); } } @@ -1056,7 +1056,7 @@ S32 LLFolderViewFolder::arrange( S32* width, S32* height ) // animate current height towards target height if (llabs(mCurHeight - mTargetHeight) > 1.f) { - mCurHeight = lerp(mCurHeight, mTargetHeight, LLCriticalDamp::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); + mCurHeight = lerp(mCurHeight, mTargetHeight, LLSmoothInterpolation::getInterpolant(isOpen() ? FOLDER_OPEN_TIME_CONSTANT : FOLDER_CLOSE_TIME_CONSTANT)); requestArrange(); @@ -1577,7 +1577,7 @@ void LLFolderViewFolder::addItem(LLFolderViewItem* item) item->setVisible(FALSE); addChild(item); - + // When the model is already hooked into a hierarchy (i.e. has a parent), do not reparent it // Note: this happens when models are created before views or shared between views if (!item->getViewModelItem()->hasParent()) diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp index e33ac1d5c2..edb32954c6 100755 --- a/indra/llui/lllayoutstack.cpp +++ b/indra/llui/lllayoutstack.cpp @@ -41,12 +41,6 @@ static const F32 MAX_FRACTIONAL_SIZE = 1.f; static LLDefaultChildRegistry::Register<LLLayoutStack> register_layout_stack("layout_stack"); static LLLayoutStack::LayoutStackRegistry::Register<LLLayoutPanel> register_layout_panel("layout_panel"); -void LLLayoutStack::OrientationNames::declareValues() -{ - declare("horizontal", HORIZONTAL); - declare("vertical", VERTICAL); -} - // // LLLayoutPanel // @@ -140,7 +134,7 @@ S32 LLLayoutPanel::getVisibleDim() const + (((F32)mTargetDim - min_dim) * (1.f - mCollapseAmt)))); } -void LLLayoutPanel::setOrientation( LLLayoutStack::ELayoutOrientation orientation ) +void LLLayoutPanel::setOrientation( LLView::EOrientation orientation ) { mOrientation = orientation; S32 layout_dim = llround((F32)((mOrientation == LLLayoutStack::HORIZONTAL) @@ -590,7 +584,7 @@ bool LLLayoutStack::animatePanels() { if (!mAnimatedThisFrame) { - panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 1.f, LLCriticalDamp::getInterpolant(mOpenTimeConstant)); + panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 1.f, LLSmoothInterpolation::getInterpolant(mOpenTimeConstant)); if (panelp->mVisibleAmt > 0.99f) { panelp->mVisibleAmt = 1.f; @@ -615,7 +609,7 @@ bool LLLayoutStack::animatePanels() { if (!mAnimatedThisFrame) { - panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 0.f, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); + panelp->mVisibleAmt = lerp(panelp->mVisibleAmt, 0.f, LLSmoothInterpolation::getInterpolant(mCloseTimeConstant)); if (panelp->mVisibleAmt < 0.001f) { panelp->mVisibleAmt = 0.f; @@ -642,7 +636,7 @@ bool LLLayoutStack::animatePanels() { if (!mAnimatedThisFrame) { - panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLCriticalDamp::getInterpolant(mCloseTimeConstant)); + panelp->mCollapseAmt = lerp(panelp->mCollapseAmt, collapse_state, LLSmoothInterpolation::getInterpolant(mCloseTimeConstant)); } if (llabs(panelp->mCollapseAmt - collapse_state) < 0.001f) diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h index 02c664f1a0..5930741d5c 100755 --- a/indra/llui/lllayoutstack.h +++ b/indra/llui/lllayoutstack.h @@ -38,24 +38,13 @@ class LLLayoutPanel; class LLLayoutStack : public LLView, public LLInstanceTracker<LLLayoutStack> { public: - typedef enum e_layout_orientation - { - HORIZONTAL, - VERTICAL - } ELayoutOrientation; - - struct OrientationNames - : public LLInitParam::TypeValuesHelper<ELayoutOrientation, OrientationNames> - { - static void declareValues(); - }; struct LayoutStackRegistry : public LLChildRegistry<LayoutStackRegistry> {}; struct Params : public LLInitParam::Block<Params, LLView::Params> { - Mandatory<ELayoutOrientation, OrientationNames> orientation; + Mandatory<EOrientation> orientation; Optional<S32> border_size; Optional<bool> animate, clip; @@ -105,7 +94,7 @@ private: bool animatePanels(); void createResizeBar(LLLayoutPanel* panel); - const ELayoutOrientation mOrientation; + const EOrientation mOrientation; typedef std::vector<LLLayoutPanel*> e_panel_list_t; e_panel_list_t mPanels; @@ -183,7 +172,7 @@ public: bool isCollapsed() const { return mCollapsed;} - void setOrientation(LLLayoutStack::ELayoutOrientation orientation); + void setOrientation(LLView::EOrientation orientation); void storeOriginalDim(); void setIgnoreReshape(bool ignore) { mIgnoreReshape = ignore; } @@ -202,7 +191,7 @@ protected: F32 mFractionalSize; S32 mTargetDim; bool mIgnoreReshape; - LLLayoutStack::ELayoutOrientation mOrientation; + LLView::EOrientation mOrientation; class LLResizeBar* mResizeBar; }; diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp index f7bf39c897..385dbc6e19 100755 --- a/indra/llui/llmenugl.cpp +++ b/indra/llui/llmenugl.cpp @@ -549,13 +549,13 @@ BOOL LLMenuItemGL::setLabelArg( const std::string& key, const LLStringExplicit& return TRUE; } -void LLMenuItemGL::handleVisibilityChange(BOOL new_visibility) +void LLMenuItemGL::onVisibilityChange(BOOL new_visibility) { if (getMenu()) { getMenu()->needsArrange(); } - LLView::handleVisibilityChange(new_visibility); + LLView::onVisibilityChange(new_visibility); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1146,13 +1146,13 @@ void LLMenuItemBranchGL::updateBranchParent(LLView* parentp) } } -void LLMenuItemBranchGL::handleVisibilityChange( BOOL new_visibility ) +void LLMenuItemBranchGL::onVisibilityChange( BOOL new_visibility ) { if (new_visibility == FALSE && getBranch() && !getBranch()->getTornOff()) { getBranch()->setVisible(FALSE); } - LLMenuItemGL::handleVisibilityChange(new_visibility); + LLMenuItemGL::onVisibilityChange(new_visibility); } BOOL LLMenuItemBranchGL::handleKeyHere( KEY key, MASK mask ) @@ -1794,7 +1794,7 @@ bool LLMenuGL::addContextChild(LLView* view, S32 tab_group) { return appendMenu(menup); } - + return false; } @@ -3749,7 +3749,7 @@ void LLTearOffMenu::draw() if (getRect().getHeight() != mTargetHeight) { // animate towards target height - reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLCriticalDamp::getInterpolant(0.05f)))); + reshape(getRect().getWidth(), llceil(lerp((F32)getRect().getHeight(), mTargetHeight, LLSmoothInterpolation::getInterpolant(0.05f)))); } LLFloater::draw(); } diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h index 51df5df1f8..feafaab199 100755 --- a/indra/llui/llmenugl.h +++ b/indra/llui/llmenugl.h @@ -82,7 +82,7 @@ protected: friend class LLUICtrlFactory; public: // LLView overrides - /*virtual*/ void handleVisibilityChange(BOOL new_visibility); + /*virtual*/ void onVisibilityChange(BOOL new_visibility); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); @@ -637,7 +637,7 @@ public: virtual void updateBranchParent( LLView* parentp ); // LLView Functionality - virtual void handleVisibilityChange( BOOL curVisibilityIn ); + virtual void onVisibilityChange( BOOL curVisibilityIn ); virtual void draw(); diff --git a/indra/llui/llmultifloater.h b/indra/llui/llmultifloater.h index d992212650..c1b1a357ed 100755 --- a/indra/llui/llmultifloater.h +++ b/indra/llui/llmultifloater.h @@ -100,6 +100,3 @@ private: }; #endif // LL_MULTI_FLOATER_H - - - diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp index 1789f003b9..37b0a52036 100755 --- a/indra/llui/llnotifications.cpp +++ b/indra/llui/llnotifications.cpp @@ -516,7 +516,7 @@ LLNotification::LLNotification(const LLSDParamAdapter<Params>& p) : LLSD LLNotification::asLLSD(bool excludeTemplateElements) -{ +{ LLParamSDParser parser; Params p; @@ -544,12 +544,12 @@ LLSD LLNotification::asLLSD(bool excludeTemplateElements) mForm->getElements(dynamicElements, templateForm->getNumElements()); p.form_elements = dynamicElements; } - + if(mResponder) { p.functor.responder_sd = mResponder->asLLSD(); } - + if(!mResponseFunctorName.empty()) { p.functor.name = mResponseFunctorName; diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h index 87573c2a56..2948f88755 100755 --- a/indra/llui/llnotifications.h +++ b/indra/llui/llnotifications.h @@ -92,6 +92,7 @@ #include "llevents.h" #include "llfunctorregistry.h" #include "llinitparam.h" +#include "llinstancetracker.h" #include "llmortician.h" #include "llnotificationptr.h" #include "llpointer.h" @@ -845,7 +846,7 @@ public: Iterator begin(); Iterator end(); size_t size(); - + std::string summarize(); private: diff --git a/indra/llui/llnotificationtemplate.h b/indra/llui/llnotificationtemplate.h index 18a82190b5..0315ddbea8 100755 --- a/indra/llui/llnotificationtemplate.h +++ b/indra/llui/llnotificationtemplate.h @@ -28,32 +28,9 @@ #ifndef LL_LLNOTIFICATION_TEMPLATE_H #define LL_LLNOTIFICATION_TEMPLATE_H -//#include <string> -//#include <list> -//#include <vector> -//#include <map> -//#include <set> -//#include <iomanip> -//#include <sstream> -// -//#include <boost/utility.hpp> -//#include <boost/shared_ptr.hpp> -//#include <boost/enable_shared_from_this.hpp> -//#include <boost/type_traits.hpp> -// -//// we want to minimize external dependencies, but this one is important -//#include "llsd.h" -// -//// and we need this to manage the notification callbacks -//#include "llevents.h" -//#include "llfunctorregistry.h" -//#include "llpointer.h" #include "llinitparam.h" -//#include "llnotificationptr.h" -//#include "llcachename.h" #include "llnotifications.h" - typedef boost::shared_ptr<LLNotificationForm> LLNotificationFormPtr; // This is the class of object read from the XML file (notifications.xml, diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp index 67472ad166..f157d6a923 100755 --- a/indra/llui/llpanel.cpp +++ b/indra/llui/llpanel.cpp @@ -342,9 +342,9 @@ BOOL LLPanel::handleKeyHere( KEY key, MASK mask ) return handled; } -void LLPanel::handleVisibilityChange ( BOOL new_visibility ) +void LLPanel::onVisibilityChange ( BOOL new_visibility ) { - LLUICtrl::handleVisibilityChange ( new_visibility ); + LLUICtrl::onVisibilityChange ( new_visibility ); if (mVisibleSignal) (*mVisibleSignal)(this, LLSD(new_visibility) ); // Pass BOOL as LLSD } @@ -520,7 +520,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu Params output_params(params); setupParamsForExport(output_params, parent); output_node->setName(node->getName()->mString); - parser.writeXUI(output_node, output_params, &default_params); + parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params); return TRUE; } @@ -551,7 +551,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu Params output_params(params); setupParamsForExport(output_params, parent); output_node->setName(node->getName()->mString); - parser.writeXUI(output_node, output_params, &default_params); + parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &default_params); } params.from_xui = true; diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h index e63b41f97c..ac8583ece9 100755 --- a/indra/llui/llpanel.h +++ b/indra/llui/llpanel.h @@ -115,7 +115,7 @@ public: /*virtual*/ BOOL isPanel() const; /*virtual*/ void draw(); /*virtual*/ BOOL handleKeyHere( KEY key, MASK mask ); - /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); + /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); // From LLFocusableElement /*virtual*/ void setFocus( BOOL b ); diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp index 13887cbe73..bef1854748 100755 --- a/indra/llui/llscrollbar.cpp +++ b/indra/llui/llscrollbar.cpp @@ -493,11 +493,11 @@ void LLScrollbar::draw() BOOL hovered = getEnabled() && !other_captor && (hasMouseCapture() || mThumbRect.pointInRect(local_mouse_x, local_mouse_y)); if (hovered) { - mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLCriticalDamp::getInterpolant(0.05f)); + mCurGlowStrength = lerp(mCurGlowStrength, mHoverGlowStrength, LLSmoothInterpolation::getInterpolant(0.05f)); } else { - mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLCriticalDamp::getInterpolant(0.05f)); + mCurGlowStrength = lerp(mCurGlowStrength, 0.f, LLSmoothInterpolation::getInterpolant(0.05f)); } // Draw background and thumb. diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h index 21fd2d631e..e2bf52c14b 100755 --- a/indra/llui/llscrollbar.h +++ b/indra/llui/llscrollbar.h @@ -40,13 +40,11 @@ class LLScrollbar { public: - enum ORIENTATION { HORIZONTAL, VERTICAL }; - typedef boost::function<void (S32, LLScrollbar*)> callback_t; struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { - Mandatory<ORIENTATION> orientation; + Mandatory<EOrientation> orientation; Mandatory<S32> doc_size; Mandatory<S32> doc_pos; Mandatory<S32> page_size; @@ -124,7 +122,7 @@ public: void onLineUpBtnPressed(const LLSD& data); void onLineDownBtnPressed(const LLSD& data); - + S32 getThickness() const { return mThickness; } void setThickness(S32 thickness); @@ -134,7 +132,7 @@ private: callback_t mChangeCallback; - const ORIENTATION mOrientation; + const EOrientation mOrientation; S32 mDocSize; // Size of the document that the scrollbar is modeling. Units depend on the user. 0 <= mDocSize. S32 mDocPos; // Position within the doc that the scrollbar is modeling, in "lines" (user size) S32 mPageSize; // Maximum number of lines that can be seen at one time. diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp index cbcce0ece5..3b5fb2adfb 100755 --- a/indra/llui/llscrollcontainer.cpp +++ b/indra/llui/llscrollcontainer.cpp @@ -144,7 +144,7 @@ LLScrollContainer::~LLScrollContainer( void ) { // mScrolledView and mScrollbar are child views, so the LLView // destructor takes care of memory deallocation. - for( S32 i = 0; i < SCROLLBAR_COUNT; i++ ) + for( S32 i = 0; i < ORIENTATION_COUNT; i++ ) { mScrollbar[i] = NULL; } @@ -215,7 +215,7 @@ BOOL LLScrollContainer::handleKeyHere(KEY key, MASK mask) { return TRUE; } - for( S32 i = 0; i < SCROLLBAR_COUNT; i++ ) + for( S32 i = 0; i < ORIENTATION_COUNT; i++ ) { if( mScrollbar[i]->handleKeyHere(key, mask) ) { diff --git a/indra/llui/llscrollcontainer.h b/indra/llui/llscrollcontainer.h index 4eb43539b8..b67236c939 100755 --- a/indra/llui/llscrollcontainer.h +++ b/indra/llui/llscrollcontainer.h @@ -56,7 +56,6 @@ class LLScrollContainer : public LLUICtrl public: // Note: vertical comes before horizontal because vertical // scrollbars have priority for mouse and keyboard events. - enum SCROLL_ORIENTATION { VERTICAL, HORIZONTAL, SCROLLBAR_COUNT }; struct Params : public LLInitParam::Block<Params, LLUICtrl::Params> { @@ -130,7 +129,7 @@ private: void updateScroll(); void calcVisibleSize( S32 *visible_width, S32 *visible_height, BOOL* show_h_scrollbar, BOOL* show_v_scrollbar ) const; - LLScrollbar* mScrollbar[SCROLLBAR_COUNT]; + LLScrollbar* mScrollbar[ORIENTATION_COUNT]; S32 mSize; BOOL mIsOpaque; LLUIColor mBackgroundColor; diff --git a/indra/llui/llslider.h b/indra/llui/llslider.h index 700c17ea3e..3b492d8182 100755 --- a/indra/llui/llslider.h +++ b/indra/llui/llslider.h @@ -34,8 +34,6 @@ class LLSlider : public LLF32UICtrl { public: - enum ORIENTATION { HORIZONTAL, VERTICAL }; - struct Params : public LLInitParam::Block<Params, LLF32UICtrl::Params> { Optional<std::string> orientation; @@ -98,7 +96,7 @@ private: LLPointer<LLUIImage> mTrackHighlightHorizontalImage; LLPointer<LLUIImage> mTrackHighlightVerticalImage; - const ORIENTATION mOrientation; + const EOrientation mOrientation; LLRect mThumbRect; LLUIColor mTrackColor; diff --git a/indra/llui/llstatbar.cpp b/indra/llui/llstatbar.cpp index 04cce7878e..6966df8213 100755 --- a/indra/llui/llstatbar.cpp +++ b/indra/llui/llstatbar.cpp @@ -34,8 +34,9 @@ #include "llgl.h" #include "llfontgl.h" -#include "llstat.h" #include "lluictrlfactory.h" +#include "lltracerecording.h" +#include "llcriticaldamp.h" /////////////////////////////////////////////////////////////////////////////////// @@ -45,68 +46,105 @@ LLStatBar::LLStatBar(const Params& p) mUnitLabel(p.unit_label), mMinBar(p.bar_min), mMaxBar(p.bar_max), - mStatp(LLStat::getStat(p.stat)), + mCurMaxBar(p.bar_max), mTickSpacing(p.tick_spacing), - mLabelSpacing(p.label_spacing), mPrecision(p.precision), mUpdatesPerSec(p.update_rate), + mUnitScale(p.unit_scale), + mNumFrames(p.num_frames), + mMaxHeight(p.max_height), mPerSec(p.show_per_sec), mDisplayBar(p.show_bar), mDisplayHistory(p.show_history), - mDisplayMean(p.show_mean) + mDisplayMean(p.show_mean), + mOrientation(p.orientation), + mScaleRange(p.scale_range) { + setStat(p.stat); } BOOL LLStatBar::handleMouseDown(S32 x, S32 y, MASK mask) { - if (mDisplayBar) + BOOL handled = LLView::handleMouseDown(x, y, mask); + if (!handled) { - if (mDisplayHistory) + if (mDisplayBar) { - mDisplayBar = FALSE; - mDisplayHistory = FALSE; + if (mDisplayHistory || mOrientation == HORIZONTAL) + { + mDisplayBar = FALSE; + mDisplayHistory = FALSE; + } + else + { + mDisplayHistory = TRUE; + } } else { - mDisplayHistory = TRUE; + mDisplayBar = TRUE; + if (mOrientation == HORIZONTAL) + { + mDisplayHistory = TRUE; + } } + LLView* parent = getParent(); + parent->reshape(parent->getRect().getWidth(), parent->getRect().getHeight(), FALSE); } - else - { - mDisplayBar = TRUE; - } - - LLView* parent = getParent(); - parent->reshape(parent->getRect().getWidth(), parent->getRect().getHeight(), FALSE); - - return FALSE; + return TRUE; } void LLStatBar::draw() { - if (!mStatp) + F32 current = 0.f, + min = 0.f, + max = 0.f, + mean = 0.f; + + LLTrace::PeriodicRecording& frame_recording = LLTrace::get_frame_recording(); + + if (mCountFloatp) { -// llinfos << "No stats for statistics bar!" << llendl; - return; - } + LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording(); - // Get the values. - F32 current, min, max, mean; - if (mPerSec) + if (mPerSec) + { + current = last_frame_recording.getPerSec(*mCountFloatp); + min = frame_recording.getPeriodMinPerSec(*mCountFloatp, mNumFrames); + max = frame_recording.getPeriodMaxPerSec(*mCountFloatp, mNumFrames); + mean = frame_recording.getPeriodMeanPerSec(*mCountFloatp, mNumFrames); + } + else + { + current = last_frame_recording.getSum(*mCountFloatp); + min = frame_recording.getPeriodMin(*mCountFloatp, mNumFrames); + max = frame_recording.getPeriodMax(*mCountFloatp, mNumFrames); + mean = frame_recording.getPeriodMean(*mCountFloatp, mNumFrames); + } + } + else if (mEventFloatp) { - current = mStatp->getCurrentPerSec(); - min = mStatp->getMinPerSec(); - max = mStatp->getMaxPerSec(); - mean = mStatp->getMeanPerSec(); + LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording(); + + current = last_frame_recording.getMean(*mEventFloatp); + min = frame_recording.getPeriodMin(*mEventFloatp, mNumFrames); + max = frame_recording.getPeriodMax(*mEventFloatp, mNumFrames); + mean = frame_recording.getPeriodMean(*mEventFloatp, mNumFrames); } - else + else if (mSampleFloatp) { - current = mStatp->getCurrent(); - min = mStatp->getMin(); - max = mStatp->getMax(); - mean = mStatp->getMean(); + LLTrace::Recording& last_frame_recording = frame_recording.getLastRecording(); + + current = last_frame_recording.getLastValue(*mSampleFloatp); + min = frame_recording.getPeriodMin(*mSampleFloatp, mNumFrames); + max = frame_recording.getPeriodMax(*mSampleFloatp, mNumFrames); + mean = frame_recording.getPeriodMean(*mSampleFloatp, mNumFrames); } + current *= mUnitScale; + min *= mUnitScale; + max *= mUnitScale; + mean *= mUnitScale; if ((mUpdatesPerSec == 0.f) || (mUpdateTimer.getElapsedTimeF32() > 1.f/mUpdatesPerSec) || (mValue == 0.f)) { @@ -121,15 +159,41 @@ void LLStatBar::draw() mUpdateTimer.reset(); } - S32 width = getRect().getWidth() - 40; - S32 max_width = width; - S32 bar_top = getRect().getHeight() - 15; // 16 pixels from top. - S32 bar_height = bar_top - 20; - S32 tick_height = 4; - S32 tick_width = 1; - S32 left, top, right, bottom; + S32 bar_top, bar_left, bar_right, bar_bottom; + if (mOrientation == HORIZONTAL) + { + bar_top = llmax(5, getRect().getHeight() - 15); + bar_left = 0; + bar_right = getRect().getWidth() - 40; + bar_bottom = llmin(bar_top - 5, 0); + } + else // VERTICAL + { + bar_top = llmax(5, getRect().getHeight() - 15); + bar_left = 0; + bar_right = getRect().getWidth(); + bar_bottom = llmin(bar_top - 5, 20); + } + const S32 tick_length = 4; + const S32 tick_width = 1; - F32 value_scale = max_width/(mMaxBar - mMinBar); + if (mScaleRange && min < max) + { + F32 cur_max = mTickSpacing; + while(max > cur_max && mMaxBar > cur_max) + { + cur_max += mTickSpacing; + } + mCurMaxBar = LLSmoothInterpolation::lerp(mCurMaxBar, cur_max, 0.05f); + } + else + { + mCurMaxBar = mMaxBar; + } + + F32 value_scale = (mOrientation == HORIZONTAL) + ? (bar_top - bar_bottom)/(mCurMaxBar - mMinBar) + : (bar_right - bar_left)/(mCurMaxBar - mMinBar); LLFontGL::getFontMonospace()->renderUTF8(mLabel, 0, 0, getRect().getHeight(), LLColor4(1.f, 1.f, 1.f, 1.f), LLFontGL::LEFT, LLFontGL::TOP); @@ -148,120 +212,231 @@ void LLStatBar::draw() } // Draw the value. - LLFontGL::getFontMonospace()->renderUTF8(value_str, 0, width, getRect().getHeight(), - LLColor4(1.f, 1.f, 1.f, 0.5f), - LLFontGL::RIGHT, LLFontGL::TOP); + if (mOrientation == HORIZONTAL) + { + LLFontGL::getFontMonospace()->renderUTF8(value_str, 0, bar_right, getRect().getHeight(), + LLColor4(1.f, 1.f, 1.f, 0.5f), + LLFontGL::RIGHT, LLFontGL::TOP); + } + else + { + LLFontGL::getFontMonospace()->renderUTF8(value_str, 0, bar_right, getRect().getHeight(), + LLColor4(1.f, 1.f, 1.f, 0.5f), + LLFontGL::RIGHT, LLFontGL::TOP); + } value_format = llformat( "%%.%df", mPrecision); - if (mDisplayBar) + if (mDisplayBar && (mCountFloatp || mEventFloatp || mSampleFloatp)) { std::string tick_label; // Draw the tick marks. - F32 tick_value; - top = bar_top; - bottom = bar_top - bar_height - tick_height/2; - LLGLSUIDefault gls_ui; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - - for (tick_value = mMinBar; tick_value <= mMaxBar; tick_value += mTickSpacing) - { - left = llfloor((tick_value - mMinBar)*value_scale); - right = left + tick_width; - gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.1f)); - } - - // Draw the tick labels (and big ticks). - bottom = bar_top - bar_height - tick_height; - for (tick_value = mMinBar; tick_value <= mMaxBar; tick_value += mLabelSpacing) + S32 last_tick = 0; + S32 last_label = 0; + const S32 MIN_TICK_SPACING = mOrientation == HORIZONTAL ? 20 : 30; + const S32 MIN_LABEL_SPACING = mOrientation == HORIZONTAL ? 40 : 60; + for (F32 tick_value = mMinBar + mTickSpacing; tick_value <= mCurMaxBar; tick_value += mTickSpacing) { - left = llfloor((tick_value - mMinBar)*value_scale); - right = left + tick_width; - gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.25f)); + const S32 begin = llfloor((tick_value - mMinBar)*value_scale); + const S32 end = begin + tick_width; + if (begin - last_tick < MIN_TICK_SPACING) + { + continue; + } + last_tick = begin; tick_label = llformat( value_format.c_str(), tick_value); - // draw labels for the tick marks - LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, left - 1, bar_top - bar_height - tick_height, - LLColor4(1.f, 1.f, 1.f, 0.5f), - LLFontGL::LEFT, LLFontGL::TOP); - } - // Now, draw the bars - top = bar_top; - bottom = bar_top - bar_height; + if (mOrientation == HORIZONTAL) + { + if (begin - last_label > MIN_LABEL_SPACING) + { + gl_rect_2d(bar_left, end, bar_right - tick_length, begin, LLColor4(1.f, 1.f, 1.f, 0.25f)); + LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, bar_right, begin, + LLColor4(1.f, 1.f, 1.f, 0.5f), + LLFontGL::LEFT, LLFontGL::VCENTER); + last_label = begin; + } + else + { + gl_rect_2d(bar_left, end, bar_right - tick_length/2, begin, LLColor4(1.f, 1.f, 1.f, 0.1f)); + } + } + else + { + if (begin - last_label > MIN_LABEL_SPACING) + { + gl_rect_2d(begin, bar_top, end, bar_bottom - tick_length, LLColor4(1.f, 1.f, 1.f, 0.25f)); + LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, begin - 1, bar_bottom - tick_length, + LLColor4(1.f, 1.f, 1.f, 0.5f), + LLFontGL::RIGHT, LLFontGL::TOP); + last_label = begin; + } + else + { + gl_rect_2d(begin, bar_top, end, bar_bottom - tick_length/2, LLColor4(1.f, 1.f, 1.f, 0.1f)); + } + } + } // draw background bar. - left = 0; - right = width; - gl_rect_2d(left, top, right, bottom, LLColor4(0.f, 0.f, 0.f, 0.25f)); + gl_rect_2d(bar_left, bar_top, bar_right, bar_bottom, LLColor4(0.f, 0.f, 0.f, 0.25f)); - if (mStatp->getNumValues() == 0) + if (frame_recording.getNumPeriods() == 0) { // No data, don't draw anything... return; } + // draw min and max - left = (S32) ((min - mMinBar) * value_scale); + S32 begin = (S32) ((min - mMinBar) * value_scale); - if (left < 0) + if (begin < 0) { - left = 0; + begin = 0; llwarns << "Min:" << min << llendl; } - right = (S32) ((max - mMinBar) * value_scale); - gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 0.f, 0.f, 0.25f)); + S32 end = (S32) ((max - mMinBar) * value_scale); + if (mOrientation == HORIZONTAL) + { + gl_rect_2d(bar_left, end, bar_right, begin, LLColor4(1.f, 0.f, 0.f, 0.25f)); + } + else // VERTICAL + { + gl_rect_2d(begin, bar_top, end, bar_bottom, LLColor4(1.f, 0.f, 0.f, 0.25f)); + } + + F32 span = (mOrientation == HORIZONTAL) + ? (bar_right - bar_left) + : (bar_top - bar_bottom); - S32 num_values = mStatp->getNumValues() - 1; - if (mDisplayHistory) + if (mDisplayHistory && (mCountFloatp || mEventFloatp || mSampleFloatp)) { + const S32 num_values = frame_recording.getNumPeriods() - 1; + F32 begin = 0; + F32 end = 0; S32 i; - for (i = 0; i < num_values; i++) + gGL.color4f( 1.f, 0.f, 0.f, 1.f ); + gGL.begin( LLRender::QUADS ); + const S32 max_frame = llmin(mNumFrames, num_values); + U32 num_samples = 0; + for (i = 1; i <= max_frame; i++) { - if (i == mStatp->getNextBin()) + F32 offset = ((F32)i / (F32)mNumFrames) * span; + LLTrace::Recording& recording = frame_recording.getPrevRecording(i); + if (mPerSec) { - continue; + if (mCountFloatp) + { + begin = ((recording.getPerSec(*mCountFloatp) - mMinBar) * value_scale); + end = ((recording.getPerSec(*mCountFloatp) - mMinBar) * value_scale) + 1; + num_samples = recording.getSampleCount(*mCountFloatp); + } + else if (mEventFloatp) + { + //rate isn't defined for measurement stats, so use mean + begin = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale); + end = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale) + 1; + num_samples = recording.getSampleCount(*mEventFloatp); + } + else if (mSampleFloatp) + { + //rate isn't defined for sample stats, so use mean + begin = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale); + end = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale) + 1; + num_samples = recording.getSampleCount(*mEventFloatp); + } } - if (mPerSec) + else + { + if (mCountFloatp) + { + begin = ((recording.getSum(*mCountFloatp) - mMinBar) * value_scale); + end = ((recording.getSum(*mCountFloatp) - mMinBar) * value_scale) + 1; + num_samples = recording.getSampleCount(*mCountFloatp); + } + else if (mEventFloatp) + { + begin = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale); + end = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale) + 1; + num_samples = recording.getSampleCount(*mEventFloatp); + } + else if (mSampleFloatp) + { + begin = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale); + end = ((recording.getMean(*mEventFloatp) - mMinBar) * value_scale) + 1; + num_samples = recording.getSampleCount(*mEventFloatp); + } + } + + if (!num_samples) continue; + + if (mOrientation == HORIZONTAL) { - left = (S32)((mStatp->getPrevPerSec(i) - mMinBar) * value_scale); - right = (S32)((mStatp->getPrevPerSec(i) - mMinBar) * value_scale) + 1; - gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f)); + gGL.vertex2f((F32)bar_right - offset, end); + gGL.vertex2f((F32)bar_right - offset, begin); + gGL.vertex2f((F32)bar_right - offset - 1.f, begin); + gGL.vertex2f((F32)bar_right - offset - 1.f, end); } else { - left = (S32)((mStatp->getPrev(i) - mMinBar) * value_scale); - right = (S32)((mStatp->getPrev(i) - mMinBar) * value_scale) + 1; - gl_rect_2d(left, bottom+i+1, right, bottom+i, LLColor4(1.f, 0.f, 0.f, 1.f)); + gGL.vertex2f(begin, (F32)bar_bottom+offset+1.f); + gGL.vertex2f(begin, (F32)bar_bottom+offset); + gGL.vertex2f(end, (F32)bar_bottom+offset); + gGL.vertex2f(end, (F32)bar_bottom+offset+1.f); } } + gGL.end(); } else { + S32 begin = (S32) ((current - mMinBar) * value_scale) - 1; + S32 end = (S32) ((current - mMinBar) * value_scale) + 1; // draw current - left = (S32) ((current - mMinBar) * value_scale) - 1; - right = (S32) ((current - mMinBar) * value_scale) + 1; - gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 0.f, 0.f, 1.f)); + if (mOrientation == HORIZONTAL) + { + gl_rect_2d(bar_left, end, bar_right, begin, LLColor4(1.f, 0.f, 0.f, 1.f)); + } + else + { + gl_rect_2d(begin, bar_top, end, bar_bottom, LLColor4(1.f, 0.f, 0.f, 1.f)); + } } // draw mean bar - top = bar_top + 2; - bottom = bar_top - bar_height - 2; - left = (S32) ((mean - mMinBar) * value_scale) - 1; - right = (S32) ((mean - mMinBar) * value_scale) + 1; - gl_rect_2d(left, top, right, bottom, LLColor4(0.f, 1.f, 0.f, 1.f)); + { + const S32 begin = (S32) ((mean - mMinBar) * value_scale) - 1; + const S32 end = (S32) ((mean - mMinBar) * value_scale) + 1; + if (mOrientation == HORIZONTAL) + { + gl_rect_2d(bar_left - 2, begin, bar_right + 2, end, LLColor4(0.f, 1.f, 0.f, 1.f)); + } + else + { + gl_rect_2d(begin, bar_top + 2, end, bar_bottom - 2, LLColor4(0.f, 1.f, 0.f, 1.f)); + } + } } LLView::draw(); } -void LLStatBar::setRange(F32 bar_min, F32 bar_max, F32 tick_spacing, F32 label_spacing) +void LLStatBar::setStat(const std::string& stat_name) { - mMinBar = bar_min; - mMaxBar = bar_max; - mTickSpacing = tick_spacing; - mLabelSpacing = label_spacing; + mCountFloatp = LLTrace::TraceType<LLTrace::CountAccumulator>::getInstance(stat_name); + mEventFloatp = LLTrace::TraceType<LLTrace::EventAccumulator>::getInstance(stat_name); + mSampleFloatp = LLTrace::TraceType<LLTrace::SampleAccumulator>::getInstance(stat_name); +} + + +void LLStatBar::setRange(F32 bar_min, F32 bar_max, F32 tick_spacing) +{ + mMinBar = bar_min; + mMaxBar = bar_max; + mTickSpacing = tick_spacing; } LLRect LLStatBar::getRequiredRect() @@ -272,7 +447,7 @@ LLRect LLStatBar::getRequiredRect() { if (mDisplayHistory) { - rect.mTop = 35 + mStatp->getNumBins(); + rect.mTop = mMaxHeight; } else { @@ -285,3 +460,4 @@ LLRect LLStatBar::getRequiredRect() } return rect; } + diff --git a/indra/llui/llstatbar.h b/indra/llui/llstatbar.h index 513fff3234..3daec297bb 100755 --- a/indra/llui/llstatbar.h +++ b/indra/llui/llstatbar.h @@ -29,41 +29,54 @@ #include "llview.h" #include "llframetimer.h" - -class LLStat; +#include "lltracerecording.h" class LLStatBar : public LLView { public: + struct Params : public LLInitParam::Block<Params, LLView::Params> { - Optional<std::string> label; - Optional<std::string> unit_label; - Optional<F32> bar_min; - Optional<F32> bar_max; - Optional<F32> tick_spacing; - Optional<F32> label_spacing; - Optional<U32> precision; - Optional<F32> update_rate; - Optional<bool> show_per_sec; - Optional<bool> show_bar; - Optional<bool> show_history; - Optional<bool> show_mean; - Optional<std::string> stat; + Optional<std::string> label, + unit_label; + + Optional<F32> bar_min, + bar_max, + tick_spacing, + update_rate, + unit_scale; + + Optional<U32> precision; + + Optional<bool> show_per_sec, + show_bar, + show_history, + show_mean, + scale_range; + + Optional<S32> num_frames, + max_height; + Optional<std::string> stat; + Optional<EOrientation> orientation; + Params() : label("label"), unit_label("unit_label"), bar_min("bar_min", 0.0f), bar_max("bar_max", 50.0f), tick_spacing("tick_spacing", 10.0f), - label_spacing("label_spacing", 10.0f), precision("precision", 0), update_rate("update_rate", 5.0f), - show_per_sec("show_per_sec", TRUE), - show_bar("show_bar", TRUE), - show_history("show_history", FALSE), - show_mean("show_mean", TRUE), - stat("stat") + unit_scale("unit_scale", 1.f), + show_per_sec("show_per_sec", true), + show_bar("show_bar", true), + show_history("show_history", false), + show_mean("show_mean", true), + scale_range("scale_range", true), + num_frames("num_frames", 300), + max_height("max_height", 200), + stat("stat"), + orientation("orientation", VERTICAL) { changeDefault(follows.flags, FOLLOWS_TOP | FOLLOWS_LEFT); } @@ -73,30 +86,39 @@ public: virtual void draw(); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - void setStat(LLStat* stat) { mStatp = stat; } - void setRange(F32 bar_min, F32 bar_max, F32 tick_spacing, F32 label_spacing); + void setStat(const std::string& stat_name); + + void setRange(F32 bar_min, F32 bar_max, F32 tick_spacing); void getRange(F32& bar_min, F32& bar_max) { bar_min = mMinBar; bar_max = mMaxBar; } /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. private: - F32 mMinBar; - F32 mMaxBar; - F32 mTickSpacing; - F32 mLabelSpacing; - U32 mPrecision; - F32 mUpdatesPerSec; - BOOL mPerSec; // Use the per sec stats. - BOOL mDisplayBar; // Display the bar graph. - BOOL mDisplayHistory; - BOOL mDisplayMean; // If true, display mean, if false, display current value - - LLStat* mStatp; + F32 mMinBar; + F32 mMaxBar; + F32 mCurMaxBar; + F32 mTickSpacing; + F32 mLabelSpacing; + U32 mPrecision; + F32 mUpdatesPerSec; + F32 mUnitScale; + S32 mNumFrames; + S32 mMaxHeight; + bool mPerSec; // Use the per sec stats. + bool mDisplayBar; // Display the bar graph. + bool mDisplayHistory; + bool mDisplayMean; // If true, display mean, if false, display current value + bool mScaleRange; + EOrientation mOrientation; + + LLTrace::TraceType<LLTrace::CountAccumulator>* mCountFloatp; + LLTrace::TraceType<LLTrace::EventAccumulator>* mEventFloatp; + LLTrace::TraceType<LLTrace::SampleAccumulator>* mSampleFloatp; LLFrameTimer mUpdateTimer; - LLUIString mLabel; - std::string mUnitLabel; - F32 mValue; + LLUIString mLabel; + std::string mUnitLabel; + F32 mValue; }; #endif diff --git a/indra/llui/llstatgraph.cpp b/indra/llui/llstatgraph.cpp index e44887ebf0..a44bc18733 100755 --- a/indra/llui/llstatgraph.cpp +++ b/indra/llui/llstatgraph.cpp @@ -32,48 +32,51 @@ #include "llmath.h" #include "llui.h" -#include "llstat.h" #include "llgl.h" #include "llglheaders.h" +#include "lltracerecording.h" +#include "lltracethreadrecorder.h" //#include "llviewercontrol.h" /////////////////////////////////////////////////////////////////////////////////// -LLStatGraph::LLStatGraph(const LLView::Params& p) -: LLView(p) +LLStatGraph::LLStatGraph(const Params& p) +: LLView(p), + mMin(p.min), + mMax(p.max), + mPerSec(true), + mPrecision(p.precision), + mValue(p.value), + mNewStatFloatp(p.stat.count_stat_float) { - mStatp = NULL; setToolTip(p.name()); - mNumThresholds = 3; - mThresholdColors[0] = LLColor4(0.f, 1.f, 0.f, 1.f); - mThresholdColors[1] = LLColor4(1.f, 1.f, 0.f, 1.f); - mThresholdColors[2] = LLColor4(1.f, 0.f, 0.f, 1.f); - mThresholdColors[3] = LLColor4(1.f, 0.f, 0.f, 1.f); - mThresholds[0] = 50.f; - mThresholds[1] = 75.f; - mThresholds[2] = 100.f; - mMin = 0.f; - mMax = 125.f; - mPerSec = TRUE; - mValue = 0.f; - mPrecision = 0; + + for(LLInitParam::ParamIterator<ThresholdParams>::const_iterator it = p.thresholds.threshold.begin(), end_it = p.thresholds.threshold.end(); + it != end_it; + ++it) + { + mThresholds.push_back(Threshold(it->value(), it->color)); + } } void LLStatGraph::draw() { F32 range, frac; range = mMax - mMin; - if (mStatp) + if (mNewStatFloatp) { + LLTrace::Recording& recording = LLTrace::get_frame_recording().getLastRecording(); + if (mPerSec) { - mValue = mStatp->getMeanPerSec(); + mValue = recording.getPerSec(*mNewStatFloatp); } else { - mValue = mStatp->getMean(); + mValue = recording.getSum(*mNewStatFloatp); } } + frac = (mValue - mMin) / range; frac = llmax(0.f, frac); frac = llmin(1.f, frac); @@ -91,19 +94,13 @@ void LLStatGraph::draw() LLColor4 color; - S32 i; - for (i = 0; i < mNumThresholds - 1; i++) + threshold_vec_t::iterator it = std::lower_bound(mThresholds.begin(), mThresholds.end(), Threshold(mValue / mMax, LLUIColor())); + + if (it != mThresholds.begin()) { - if (mThresholds[i] > mValue) - { - break; - } + it--; } - //gl_drop_shadow(0, getRect().getHeight(), getRect().getWidth(), 0, - // LLUIColorTable::instance().getColor("ColorDropShadow"), - // (S32) gSavedSettings.getF32("DropShadowFloater") ); - color = LLUIColorTable::instance().getColor( "MenuDefaultBgColor" ); gGL.color4fv(color.mV); gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, TRUE); @@ -111,16 +108,11 @@ void LLStatGraph::draw() gGL.color4fv(LLColor4::black.mV); gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, FALSE); - color = mThresholdColors[i]; + color = it->mColor; gGL.color4fv(color.mV); gl_rect_2d(1, llround(frac*getRect().getHeight()), getRect().getWidth() - 1, 0, TRUE); } -void LLStatGraph::setValue(const LLSD& value) -{ - mValue = (F32)value.asReal(); -} - void LLStatGraph::setMin(const F32 min) { mMin = min; @@ -131,27 +123,3 @@ void LLStatGraph::setMax(const F32 max) mMax = max; } -void LLStatGraph::setStat(LLStat *statp) -{ - mStatp = statp; -} - -void LLStatGraph::setLabel(const std::string& label) -{ - mLabel = label; -} - -void LLStatGraph::setUnits(const std::string& units) -{ - mUnits = units; -} - -void LLStatGraph::setPrecision(const S32 precision) -{ - mPrecision = precision; -} - -void LLStatGraph::setThreshold(const S32 i, F32 value) -{ - mThresholds[i] = value; -} diff --git a/indra/llui/llstatgraph.h b/indra/llui/llstatgraph.h index 757525e232..38fe12d18b 100755 --- a/indra/llui/llstatgraph.h +++ b/indra/llui/llstatgraph.h @@ -30,29 +30,84 @@ #include "llview.h" #include "llframetimer.h" #include "v4color.h" - -class LLStat; +#include "lltrace.h" class LLStatGraph : public LLView { public: - LLStatGraph(const LLView::Params&); + struct ThresholdParams : public LLInitParam::Block<ThresholdParams> + { + Mandatory<F32> value; + Optional<LLUIColor> color; - virtual void draw(); + ThresholdParams() + : value("value"), + color("color", LLColor4::white) + {} + }; + + struct Thresholds : public LLInitParam::Block<Thresholds> + { + Multiple<ThresholdParams> threshold; + + Thresholds() + : threshold("threshold") + {} + }; + + struct StatParams : public LLInitParam::ChoiceBlock<StatParams> + { + Alternative<LLTrace::TraceType<LLTrace::CountAccumulator>* > count_stat_float; + Alternative<LLTrace::TraceType<LLTrace::EventAccumulator>* > event_stat_float; + Alternative<LLTrace::TraceType<LLTrace::SampleAccumulator>* > sample_stat_float; + }; + + struct Params : public LLInitParam::Block<Params, LLView::Params> + { + Mandatory<StatParams> stat; + Optional<std::string> label, + units; + Optional<S32> precision; + Optional<F32> min, + max; + Optional<bool> per_sec; + Optional<F32> value; + + Optional<Thresholds> thresholds; + + Params() + : stat("stat"), + label("label"), + units("units"), + precision("precision", 0), + min("min", 0.f), + max("max", 125.f), + per_sec("per_sec", true), + value("value", 0.f), + thresholds("thresholds") + { + Thresholds _thresholds; + _thresholds.threshold.add(ThresholdParams().value(0.f).color(LLColor4::green)) + .add(ThresholdParams().value(0.33f).color(LLColor4::yellow)) + .add(ThresholdParams().value(0.5f).color(LLColor4::red)) + .add(ThresholdParams().value(0.75f).color(LLColor4::red)); + thresholds = _thresholds; + } + }; + LLStatGraph(const Params&); - void setLabel(const std::string& label); - void setUnits(const std::string& units); - void setPrecision(const S32 precision); - void setStat(LLStat *statp); - void setThreshold(const S32 i, F32 value); void setMin(const F32 min); void setMax(const F32 max); + virtual void draw(); + /*virtual*/ void setValue(const LLSD& value); - LLStat *mStatp; - BOOL mPerSec; private: + LLTrace::TraceType<LLTrace::CountAccumulator>* mNewStatFloatp; + + BOOL mPerSec; + F32 mValue; F32 mMin; @@ -62,9 +117,25 @@ private: std::string mUnits; S32 mPrecision; // Num of digits of precision after dot - S32 mNumThresholds; - F32 mThresholds[4]; - LLColor4 mThresholdColors[4]; + struct Threshold + { + Threshold(F32 value, const LLUIColor& color) + : mValue(value), + mColor(color) + {} + + F32 mValue; + LLUIColor mColor; + bool operator <(const Threshold& other) + { + return mValue < other.mValue; + } + }; + typedef std::vector<Threshold> threshold_vec_t; + threshold_vec_t mThresholds; + //S32 mNumThresholds; + //F32 mThresholds[4]; + //LLColor4 mThresholdColors[4]; }; #endif // LL_LLSTATGRAPH_H diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp index fd98155704..415da0b3d6 100755 --- a/indra/llui/lltabcontainer.cpp +++ b/indra/llui/lltabcontainer.cpp @@ -406,7 +406,7 @@ void LLTabContainer::draw() } } - setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLCriticalDamp::getInterpolant(0.08f))); + setScrollPosPixels((S32)lerp((F32)getScrollPosPixels(), (F32)target_pixel_scroll, LLSmoothInterpolation::getInterpolant(0.08f))); BOOL has_scroll_arrows = !getTabsHidden() && ((mMaxScrollPos > 0) || (mScrollPosPixels > 0)); if (!mIsVertical) diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index a45c4ced2e..7243931dbb 100755 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -48,6 +48,8 @@ const F32 CURSOR_FLASH_DELAY = 1.0f; // in seconds const S32 CURSOR_THICKNESS = 2; const F32 TRIPLE_CLICK_INTERVAL = 0.3f; // delay between double and triple click. +LLTrace::MemStatHandle LLTextSegment::sMemStat("LLTextSegment"); + LLTextBase::line_info::line_info(S32 index_start, S32 index_end, LLRect rect, S32 line_num) : mDocIndexStart(index_start), mDocIndexEnd(index_end), @@ -575,7 +577,7 @@ void LLTextBase::drawText() if ( (mSpellCheckStart != start) || (mSpellCheckEnd != end) ) { const LLWString& wstrText = getWText(); - mMisspellRanges.clear(); + memDisclaim(mMisspellRanges).clear(); segment_set_t::const_iterator seg_it = getSegIterContaining(start); while (mSegments.end() != seg_it) @@ -651,6 +653,7 @@ void LLTextBase::drawText() mSpellCheckStart = start; mSpellCheckEnd = end; + memClaim(mMisspellRanges); } } @@ -916,9 +919,11 @@ void LLTextBase::createDefaultSegment() if (mSegments.empty()) { LLStyleConstSP sp(new LLStyle(getStyleParams())); + memDisclaim(mSegments); LLTextSegmentPtr default_segment = new LLNormalTextSegment( sp, 0, getLength() + 1, *this); mSegments.insert(default_segment); default_segment->linkToDocument(this); + memClaim(mSegments); } } @@ -929,6 +934,8 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert) return; } + memDisclaim(mSegments); + segment_set_t::iterator cur_seg_iter = getSegIterContaining(segment_to_insert->getStart()); S32 reflow_start_index = 0; @@ -1001,6 +1008,7 @@ void LLTextBase::insertSegment(LLTextSegmentPtr segment_to_insert) // layout potentially changed needsReflow(reflow_start_index); + memClaim(mSegments); } BOOL LLTextBase::handleMouseDown(S32 x, S32 y, MASK mask) @@ -1254,13 +1262,13 @@ void LLTextBase::setReadOnlyColor(const LLColor4 &c) } //virtual -void LLTextBase::handleVisibilityChange( BOOL new_visibility ) +void LLTextBase::onVisibilityChange( BOOL new_visibility ) { if(!new_visibility && mPopupMenu) { mPopupMenu->hide(); } - LLUICtrl::handleVisibilityChange(new_visibility); + LLUICtrl::onVisibilityChange(new_visibility); } //virtual @@ -1311,8 +1319,11 @@ void LLTextBase::replaceWithSuggestion(U32 index) removeStringNoUndo(it->first, it->second - it->first); // Insert the suggestion in its place + memDisclaim(mSuggestionList); LLWString suggestion = utf8str_to_wstring(mSuggestionList[index]); insertStringNoUndo(it->first, utf8str_to_wstring(mSuggestionList[index])); + memClaim(mSuggestionList); + setCursorPos(it->first + (S32)suggestion.length()); break; @@ -1374,7 +1385,7 @@ bool LLTextBase::isMisspelledWord(U32 pos) const void LLTextBase::onSpellCheckSettingsChange() { // Recheck the spelling on every change - mMisspellRanges.clear(); + memDisclaim(mMisspellRanges).clear(); mSpellCheckStart = mSpellCheckEnd = -1; } @@ -1652,7 +1663,7 @@ LLRect LLTextBase::getTextBoundingRect() void LLTextBase::clearSegments() { - mSegments.clear(); + memDisclaim(mSegments).clear(); createDefaultSegment(); } @@ -3154,7 +3165,9 @@ void LLNormalTextSegment::setToolTip(const std::string& tooltip) llwarns << "LLTextSegment::setToolTip: cannot replace keyword tooltip." << llendl; return; } + memDisclaim(mTooltip); mTooltip = tooltip; + memClaim(mTooltip); } bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 20a73387b5..74dc7f9693 100755 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -51,7 +51,10 @@ class LLUrlMatch; /// includes a start/end offset from the start of the string, a /// style to render with, an optional tooltip, etc. /// -class LLTextSegment : public LLRefCount, public LLMouseHandler +class LLTextSegment +: public LLRefCount, + public LLMouseHandler, + public LLTrace::MemTrackable<LLTextSegment> { public: LLTextSegment(S32 start, S32 end) : mStart(start), mEnd(end){}; @@ -92,10 +95,12 @@ public: /*virtual*/ void localPointToScreen(S32 local_x, S32 local_y, S32* screen_x, S32* screen_y) const; /*virtual*/ BOOL hasMouseCapture(); - S32 getStart() const { return mStart; } - void setStart(S32 start) { mStart = start; } - S32 getEnd() const { return mEnd; } - void setEnd( S32 end ) { mEnd = end; } + S32 getStart() const { return mStart; } + void setStart(S32 start) { mStart = start; } + S32 getEnd() const { return mEnd; } + void setEnd( S32 end ) { mEnd = end; } + + static LLTrace::MemStatHandle sMemStat; protected: S32 mStart; @@ -325,7 +330,7 @@ public: /*virtual*/ BOOL acceptsTextInput() const { return !mReadOnly; } /*virtual*/ void setColor( const LLColor4& c ); virtual void setReadOnlyColor(const LLColor4 &c); - virtual void handleVisibilityChange( BOOL new_visibility ); + virtual void onVisibilityChange( BOOL new_visibility ); /*virtual*/ void setValue(const LLSD& value ); /*virtual*/ LLTextViewModel* getViewModel() const; @@ -603,7 +608,7 @@ protected: S32 mSelectionStart; S32 mSelectionEnd; LLTimer mTripleClickTimer; - + BOOL mIsSelecting; // Are we in the middle of a drag-select? // spell checking diff --git a/indra/llui/lltoggleablemenu.cpp b/indra/llui/lltoggleablemenu.cpp index 00d52fe10d..ccb92ffbb2 100755 --- a/indra/llui/lltoggleablemenu.cpp +++ b/indra/llui/lltoggleablemenu.cpp @@ -52,7 +52,7 @@ boost::signals2::connection LLToggleableMenu::setVisibilityChangeCallback(const } // virtual -void LLToggleableMenu::handleVisibilityChange (BOOL curVisibilityIn) +void LLToggleableMenu::onVisibilityChange (BOOL curVisibilityIn) { S32 x,y; LLUI::getMousePositionLocal(LLUI::getRootView(), &x, &y); diff --git a/indra/llui/lltoggleablemenu.h b/indra/llui/lltoggleablemenu.h index dfe70cbf54..55a6483021 100755 --- a/indra/llui/lltoggleablemenu.h +++ b/indra/llui/lltoggleablemenu.h @@ -45,7 +45,7 @@ public: boost::signals2::connection setVisibilityChangeCallback( const commit_signal_t::slot_type& cb ); - virtual void handleVisibilityChange (BOOL curVisibilityIn); + virtual void onVisibilityChange (BOOL curVisibilityIn); virtual bool addChild (LLView* view, S32 tab_group = 0); diff --git a/indra/llui/lltoolbar.cpp b/indra/llui/lltoolbar.cpp index 3d9f5cbbc2..f683758962 100755 --- a/indra/llui/lltoolbar.cpp +++ b/indra/llui/lltoolbar.cpp @@ -42,9 +42,9 @@ namespace LLToolBarEnums { - LLLayoutStack::ELayoutOrientation getOrientation(SideType sideType) + LLView::EOrientation getOrientation(SideType sideType) { - LLLayoutStack::ELayoutOrientation orientation = LLLayoutStack::HORIZONTAL; + LLView::EOrientation orientation = LLLayoutStack::HORIZONTAL; if ((sideType == SIDE_LEFT) || (sideType == SIDE_RIGHT)) { @@ -173,7 +173,7 @@ void LLToolBar::initFromParams(const LLToolBar::Params& p) // Initialize the base object LLUICtrl::initFromParams(p); - LLLayoutStack::ELayoutOrientation orientation = getOrientation(p.side); + LLView::EOrientation orientation = getOrientation(p.side); LLLayoutStack::Params centering_stack_p; centering_stack_p.name = "centering_stack"; @@ -525,7 +525,7 @@ int LLToolBar::getRankFromPosition(S32 x, S32 y) int rank = 0; // Convert the toolbar coord into button panel coords - LLLayoutStack::ELayoutOrientation orientation = getOrientation(mSideType); + LLView::EOrientation orientation = getOrientation(mSideType); S32 button_panel_x = 0; S32 button_panel_y = 0; localPointToOtherView(x, y, &button_panel_x, &button_panel_y, mButtonPanel); @@ -644,7 +644,7 @@ void LLToolBar::updateLayoutAsNeeded() { if (!mNeedsLayout) return; - LLLayoutStack::ELayoutOrientation orientation = getOrientation(mSideType); + LLView::EOrientation orientation = getOrientation(mSideType); // our terminology for orientation-agnostic layout is such that // length refers to a distance in the direction we stack the buttons diff --git a/indra/llui/lltoolbar.h b/indra/llui/lltoolbar.h index 31424a36d4..6936cb37f7 100755 --- a/indra/llui/lltoolbar.h +++ b/indra/llui/lltoolbar.h @@ -125,7 +125,7 @@ namespace LLToolBarEnums SIDE_TOP, }; - LLLayoutStack::ELayoutOrientation getOrientation(SideType sideType); + LLView::EOrientation getOrientation(SideType sideType); } // NOTE: This needs to occur before Param block declaration for proper compilation. diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 0a0e0e164e..4ebfd0fd6e 100755 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -29,9 +29,11 @@ #define LL_LLUI_H #include "llrect.h" +#include "llcoord.h" #include "llcontrol.h" #include "llcoord.h" -#include "v2math.h" +#include "llcontrol.h" +#include "llglslshader.h" #include "llinitparam.h" #include "llregistry.h" #include "llrender2dutils.h" @@ -40,8 +42,8 @@ #include "lluicolortable.h" #include "lluiimage.h" #include <boost/signals2.hpp> -#include "lllazyvalue.h" #include "llframetimer.h" +#include "v2math.h" #include <limits> // for initparam specialization diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp index b9c843e931..08358484ef 100755 --- a/indra/llui/lluictrl.cpp +++ b/indra/llui/lluictrl.cpp @@ -118,6 +118,7 @@ LLUICtrl::LLUICtrl(const LLUICtrl::Params& p, const LLViewModelPtr& viewmodel) mDoubleClickSignal(NULL), mTransparencyType(TT_DEFAULT) { + memClaim(viewmodel.get()); } void LLUICtrl::initFromParams(const Params& p) @@ -940,7 +941,7 @@ boost::signals2::connection LLUICtrl::setCommitCallback( boost::function<void (L } boost::signals2::connection LLUICtrl::setValidateBeforeCommit( boost::function<bool (const LLSD& data)> cb ) { - if (!mValidateSignal) mValidateSignal = new enable_signal_t(); + if (!mValidateSignal) mValidateSignal = memClaim(new enable_signal_t()); return mValidateSignal->connect(boost::bind(cb, _2)); } @@ -1003,55 +1004,55 @@ boost::signals2::connection LLUICtrl::setValidateCallback(const EnableCallbackPa boost::signals2::connection LLUICtrl::setCommitCallback( const commit_signal_t::slot_type& cb ) { - if (!mCommitSignal) mCommitSignal = new commit_signal_t(); + if (!mCommitSignal) mCommitSignal = memClaim(new commit_signal_t()); return mCommitSignal->connect(cb); } boost::signals2::connection LLUICtrl::setValidateCallback( const enable_signal_t::slot_type& cb ) { - if (!mValidateSignal) mValidateSignal = new enable_signal_t(); + if (!mValidateSignal) mValidateSignal = memClaim(new enable_signal_t()); return mValidateSignal->connect(cb); } boost::signals2::connection LLUICtrl::setMouseEnterCallback( const commit_signal_t::slot_type& cb ) { - if (!mMouseEnterSignal) mMouseEnterSignal = new commit_signal_t(); + if (!mMouseEnterSignal) mMouseEnterSignal = memClaim(new commit_signal_t()); return mMouseEnterSignal->connect(cb); } boost::signals2::connection LLUICtrl::setMouseLeaveCallback( const commit_signal_t::slot_type& cb ) { - if (!mMouseLeaveSignal) mMouseLeaveSignal = new commit_signal_t(); + if (!mMouseLeaveSignal) mMouseLeaveSignal = memClaim(new commit_signal_t()); return mMouseLeaveSignal->connect(cb); } boost::signals2::connection LLUICtrl::setMouseDownCallback( const mouse_signal_t::slot_type& cb ) { - if (!mMouseDownSignal) mMouseDownSignal = new mouse_signal_t(); + if (!mMouseDownSignal) mMouseDownSignal = memClaim(new mouse_signal_t()); return mMouseDownSignal->connect(cb); } boost::signals2::connection LLUICtrl::setMouseUpCallback( const mouse_signal_t::slot_type& cb ) { - if (!mMouseUpSignal) mMouseUpSignal = new mouse_signal_t(); + if (!mMouseUpSignal) mMouseUpSignal = memClaim(new mouse_signal_t()); return mMouseUpSignal->connect(cb); } boost::signals2::connection LLUICtrl::setRightMouseDownCallback( const mouse_signal_t::slot_type& cb ) { - if (!mRightMouseDownSignal) mRightMouseDownSignal = new mouse_signal_t(); + if (!mRightMouseDownSignal) mRightMouseDownSignal = memClaim(new mouse_signal_t()); return mRightMouseDownSignal->connect(cb); } boost::signals2::connection LLUICtrl::setRightMouseUpCallback( const mouse_signal_t::slot_type& cb ) { - if (!mRightMouseUpSignal) mRightMouseUpSignal = new mouse_signal_t(); + if (!mRightMouseUpSignal) mRightMouseUpSignal = memClaim(new mouse_signal_t()); return mRightMouseUpSignal->connect(cb); } boost::signals2::connection LLUICtrl::setDoubleClickCallback( const mouse_signal_t::slot_type& cb ) { - if (!mDoubleClickSignal) mDoubleClickSignal = new mouse_signal_t(); + if (!mDoubleClickSignal) mDoubleClickSignal = memClaim(new mouse_signal_t()); return mDoubleClickSignal->connect(cb); } diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 876bb5ef46..f2fe4334ee 100755 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -170,7 +170,7 @@ public: LLXMLNodePtr root_node; if (!LLUICtrlFactory::getLayeredXMLNode(filename, root_node)) - { + { llwarns << "Couldn't parse XUI file: " << instance().getCurFileName() << llendl; goto fail; } @@ -259,10 +259,8 @@ private: // We always want to output top-left coordinates typename T::Params output_params(params); T::setupParamsForExport(output_params, parent); - // Export only the differences between this any default params - typename T::Params default_params(getDefaultParams<T>()); copyName(node, output_node); - parser.writeXUI(output_node, output_params, &default_params); + parser.writeXUI(output_node, output_params, LLInitParam::default_parse_rules(), &getDefaultParams<T>()); } // Apply layout transformations, usually munging rect diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp index c4e073ccdb..23fc53ea88 100755 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -26,6 +26,8 @@ #include "linden_common.h" #include "lluistring.h" + +#include "llfasttimer.h" #include "llsd.h" #include "lltrans.h" diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 3613a40e2c..daeb4d7939 100755 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -30,7 +30,6 @@ #define LLVIEW_CPP #include "llview.h" -#include <cassert> #include <sstream> #include <boost/tokenizer.hpp> #include <boost/foreach.hpp> @@ -70,6 +69,7 @@ LLView* LLView::sPreviewClickedElement = NULL; BOOL LLView::sDrawPreviewHighlights = FALSE; S32 LLView::sLastLeftXML = S32_MIN; S32 LLView::sLastBottomXML = S32_MIN; +LLTrace::MemStatHandle LLView::sMemStat("LLView"); std::vector<LLViewDrawContext*> LLViewDrawContext::sDrawContextStack; LLView::DrilldownFunc LLView::sDrilldown = @@ -85,6 +85,16 @@ template class LLView* LLView::getChild<class LLView>( static LLDefaultChildRegistry::Register<LLView> r("view"); +namespace LLInitParam +{ + void TypeValues<LLView::EOrientation>::declareValues() + { + declare("horizontal", LLView::HORIZONTAL); + declare("vertical", LLView::VERTICAL); + } +} + + LLView::Follows::Follows() : string(""), flags("flags", FOLLOWS_LEFT | FOLLOWS_TOP) @@ -633,21 +643,21 @@ void LLView::setVisible(BOOL visible) { // tell all children of this view that the visibility may have changed dirtyRect(); - handleVisibilityChange( visible ); + onVisibilityChange( visible ); } updateBoundingRect(); } } // virtual -void LLView::handleVisibilityChange ( BOOL new_visibility ) +void LLView::onVisibilityChange ( BOOL new_visibility ) { BOOST_FOREACH(LLView* viewp, mChildList) { // only views that are themselves visible will have their overall visibility affected by their ancestors if (viewp->getVisible()) { - viewp->handleVisibilityChange ( new_visibility ); + viewp->onVisibilityChange ( new_visibility ); } } } diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 15b85a6418..0568fa889a 100755 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -100,9 +100,13 @@ class LLView : public LLMouseHandler, // handles mouse events public LLFocusableElement, // handles keyboard events public LLMortician, // lazy deletion - public LLHandleProvider<LLView> // passes out weak references to self + public LLHandleProvider<LLView>, // passes out weak references to self + public LLTrace::MemTrackable<LLView> // track memory usage { public: + + enum EOrientation { HORIZONTAL, VERTICAL, ORIENTATION_COUNT }; + struct Follows : public LLInitParam::ChoiceBlock<Follows> { Alternative<std::string> string; @@ -303,7 +307,7 @@ public: virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); - virtual void handleVisibilityChange ( BOOL new_visibility ); + virtual void onVisibilityChange ( BOOL new_visibility ); void pushVisible(BOOL visible) { mLastVisible = mVisible; setVisible(visible); } void popVisible() { setVisible(mLastVisible); } @@ -671,7 +675,18 @@ public: static S32 sLastLeftXML; static S32 sLastBottomXML; static BOOL sForceReshape; + static LLTrace::MemStatHandle sMemStat; +}; + +namespace LLInitParam +{ +template<> +struct TypeValues<LLView::EOrientation> : public LLInitParam::TypeValuesHelper<LLView::EOrientation> +{ + static void declareValues(); }; +} + class LLCompareByTabOrder { diff --git a/indra/llui/llviewmodel.cpp b/indra/llui/llviewmodel.cpp index a9f8acc440..901260bec8 100755 --- a/indra/llui/llviewmodel.cpp +++ b/indra/llui/llviewmodel.cpp @@ -35,6 +35,8 @@ // external library headers // other Linden headers +LLTrace::MemStatHandle LLViewModel::sMemStat("LLViewModel"); + /// LLViewModel::LLViewModel() : mDirty(false) @@ -80,7 +82,10 @@ LLTextViewModel::LLTextViewModel(const LLSD& value) void LLTextViewModel::setValue(const LLSD& value) { LLViewModel::setValue(value); + memDisclaim(mDisplay); mDisplay = utf8str_to_wstring(value.asString()); + memClaim(mDisplay); + // mDisplay and mValue agree mUpdateFromDisplay = false; } @@ -91,7 +96,9 @@ void LLTextViewModel::setDisplay(const LLWString& value) // and do the utf8str_to_wstring() to get the corresponding mDisplay // value. But a text editor might want to edit the display string // directly, then convert back to UTF8 on commit. + memDisclaim(mDisplay); mDisplay = value; + memClaim(mDisplay); mDirty = true; // Don't immediately convert to UTF8 -- do it lazily -- we expect many // more setDisplay() calls than getValue() calls. Just flag that it needs diff --git a/indra/llui/llviewmodel.h b/indra/llui/llviewmodel.h index ef2e314799..2c016d2560 100755 --- a/indra/llui/llviewmodel.h +++ b/indra/llui/llviewmodel.h @@ -39,6 +39,7 @@ #include "llrefcount.h" #include "stdenums.h" #include "llstring.h" +#include "lltrace.h" #include <string> class LLScrollListItem; @@ -60,7 +61,9 @@ typedef LLPointer<LLListViewModel> LLListViewModelPtr; * LLViewModel data. This way, the LLViewModel is quietly deleted when the * last referencing widget is destroyed. */ -class LLViewModel: public LLRefCount +class LLViewModel +: public LLRefCount, + public LLTrace::MemTrackable<LLViewModel> { public: LLViewModel(); @@ -80,6 +83,8 @@ public: // void setDirty() { mDirty = true; } + static LLTrace::MemStatHandle sMemStat; + protected: LLSD mValue; bool mDirty; diff --git a/indra/llui/llxuiparser.cpp b/indra/llui/llxuiparser.cpp index 3ad5ad7d42..dc273ec990 100755 --- a/indra/llui/llxuiparser.cpp +++ b/indra/llui/llxuiparser.cpp @@ -29,7 +29,7 @@ #include "llxuiparser.h" #include "llxmlnode.h" - +#include "llfasttimer.h" #ifdef LL_STANDALONE #include <expat.h> #else @@ -334,6 +334,8 @@ LLXSDWriter::LLXSDWriter() registerInspectFunc<LLSD>(boost::bind(&LLXSDWriter::writeAttribute, this, "xs:string", _1, _2, _3, _4)); } +LLXSDWriter::~LLXSDWriter() {} + void LLXSDWriter::writeXSD(const std::string& type_name, LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const std::string& xml_namespace) { Schema schema(xml_namespace); @@ -858,11 +860,11 @@ bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& blo return any_parsed; } -void LLXUIParser::writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::BaseBlock* diff_block) +void LLXUIParser::writeXUIImpl(LLXMLNodePtr node, const LLInitParam::BaseBlock &block, const LLInitParam::predicate_rule_t rules, const LLInitParam::BaseBlock* diff_block) { mWriteRootNode = node; name_stack_t name_stack = Parser::name_stack_t(); - block.serializeBlock(*this, name_stack, diff_block); + block.serializeBlock(*this, name_stack, rules, diff_block); mOutNodes.clear(); } diff --git a/indra/llui/llxuiparser.h b/indra/llui/llxuiparser.h index e48663e5cc..ad2a39cab7 100755 --- a/indra/llui/llxuiparser.h +++ b/indra/llui/llxuiparser.h @@ -29,21 +29,15 @@ #include "llinitparam.h" #include "llregistry.h" -#include "llpointer.h" +#include "llxmlnode.h" #include <boost/function.hpp> #include <iosfwd> #include <stack> #include <set> - - class LLView; - -typedef LLPointer<class LLXMLNode> LLXMLNodePtr; - - // lookup widget type by name class LLWidgetTypeRegistry : public LLRegistrySingleton<std::string, const std::type_info*, LLWidgetTypeRegistry> @@ -59,8 +53,6 @@ class LLChildRegistryRegistry : public LLRegistrySingleton<const std::type_info*, widget_registry_t, LLChildRegistryRegistry> {}; - - class LLXSDWriter : public LLInitParam::Parser { LOG_CLASS(LLXSDWriter); @@ -70,6 +62,7 @@ public: /*virtual*/ std::string getCurrentElementName() { return LLStringUtil::null; } LLXSDWriter(); + ~LLXSDWriter(); protected: void writeAttribute(const std::string& type, const Parser::name_stack_t&, S32 min_count, S32 max_count, const std::vector<std::string>* possible_values); @@ -109,9 +102,26 @@ public: /*virtual*/ void parserError(const std::string& message); void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, const std::string& filename = LLStringUtil::null, bool silent=false); - void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL); + template<typename BLOCK> + void writeXUI(LLXMLNodePtr node, + const BLOCK& block, + const LLInitParam::predicate_rule_t rules = LLInitParam::default_parse_rules(), + const LLInitParam::BaseBlock* diff_block = NULL) + { + if (!diff_block + && !rules.isAmbivalent(LLInitParam::HAS_DEFAULT_VALUE)) + { + diff_block = &LLInitParam::defaultValue<BLOCK>(); + } + writeXUIImpl(node, block, rules, diff_block); + } private: + LLXUIParser(const LLXUIParser& other); // no-copy + void writeXUIImpl(LLXMLNodePtr node, + const LLInitParam::BaseBlock& block, + const LLInitParam::predicate_rule_t rules, + const LLInitParam::BaseBlock* diff_block); bool readXUIImpl(LLXMLNodePtr node, LLInitParam::BaseBlock& block); bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block); diff --git a/indra/llvfs/llpidlock.cpp b/indra/llvfs/llpidlock.cpp index 0424f2379e..3b83d1b9e3 100755 --- a/indra/llvfs/llpidlock.cpp +++ b/indra/llvfs/llpidlock.cpp @@ -36,7 +36,7 @@ #if LL_WINDOWS //For windows platform. -#include <windows.h> +#include "llwin32headerslean.h" namespace { inline DWORD getpid() { diff --git a/indra/llvfs/llvfile.cpp b/indra/llvfs/llvfile.cpp index 03d2cc25e3..ed74488af4 100755 --- a/indra/llvfs/llvfile.cpp +++ b/indra/llvfs/llvfile.cpp @@ -30,9 +30,10 @@ #include "llerror.h" #include "llthread.h" -#include "llstat.h" -#include "llvfs.h" +#include "lltimer.h" +#include "llfasttimer.h" #include "llmemory.h" +#include "llvfs.h" const S32 LLVFile::READ = 0x00000001; const S32 LLVFile::WRITE = 0x00000002; @@ -135,7 +136,7 @@ U8* LLVFile::readFile(LLVFS *vfs, const LLUUID &uuid, LLAssetType::EType type, S data = NULL; } else - { + { data = (U8*) ll_aligned_malloc_16(file_size); file.read(data, file_size); /* Flawfinder: ignore */ diff --git a/indra/llwindow/lldragdropwin32.h b/indra/llwindow/lldragdropwin32.h index 929e7f9e37..ba7fac0bd1 100755 --- a/indra/llwindow/lldragdropwin32.h +++ b/indra/llwindow/lldragdropwin32.h @@ -31,7 +31,7 @@ #ifndef LL_LLDRAGDROP32_H #define LL_LLDRAGDROP32_H -#include <windows.h> +#include "llwin32headerslean.h" #include <ole2.h> class LLDragDropWin32 @@ -54,7 +54,7 @@ class LLDragDropWin32 #ifndef LL_LLDRAGDROP32_H #define LL_LLDRAGDROP32_H -#include <windows.h> +#include "llwin32headerslean.h" #include <ole2.h> // imposter class that does nothing diff --git a/indra/llwindow/llkeyboard.h b/indra/llwindow/llkeyboard.h index c155c1b362..276074d4ca 100755 --- a/indra/llwindow/llkeyboard.h +++ b/indra/llwindow/llkeyboard.h @@ -28,6 +28,7 @@ #define LL_LLKEYBOARD_H #include <map> +#include <boost/function.hpp> #include "string_table.h" #include "lltimer.h" diff --git a/indra/llwindow/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp index be3fe5deb0..b76d526c5a 100755 --- a/indra/llwindow/llkeyboardwin32.cpp +++ b/indra/llwindow/llkeyboardwin32.cpp @@ -28,10 +28,7 @@ #include "linden_common.h" -#define WIN32_LEAN_AND_MEAN -#include <winsock2.h> -#include <windows.h> - +#include "llwin32headerslean.h" #include "llkeyboardwin32.h" #include "llwindowcallbacks.h" diff --git a/indra/llwindow/llwindow.h b/indra/llwindow/llwindow.h index e9147d552e..c235d77656 100755 --- a/indra/llwindow/llwindow.h +++ b/indra/llwindow/llwindow.h @@ -31,6 +31,7 @@ #include "llcoord.h" #include "llstring.h" #include "llcursortypes.h" +#include "llinstancetracker.h" #include "llsd.h" class LLSplashScreen; diff --git a/indra/llwindow/llwindowwin32.cpp b/indra/llwindow/llwindowwin32.cpp index 43c0090993..6d887926fa 100755 --- a/indra/llwindow/llwindowwin32.cpp +++ b/indra/llwindow/llwindowwin32.cpp @@ -38,6 +38,7 @@ // Linden library includes #include "llerror.h" +#include "llfasttimer.h" #include "llgl.h" #include "llstring.h" #include "lldir.h" diff --git a/indra/llwindow/llwindowwin32.h b/indra/llwindow/llwindowwin32.h index 54c9ac4d4d..169d264808 100755 --- a/indra/llwindow/llwindowwin32.h +++ b/indra/llwindow/llwindowwin32.h @@ -28,9 +28,7 @@ #define LL_LLWINDOWWIN32_H // Limit Windows API to small and manageable set. -#define WIN32_LEAN_AND_MEAN -#include <winsock2.h> -#include <windows.h> +#include "llwin32headerslean.h" #include "llwindow.h" #include "llwindowcallbacks.h" diff --git a/indra/lscript/lscript_execute/lscript_execute.cpp b/indra/lscript/lscript_execute/lscript_execute.cpp index b12d2e4a16..e9b4d1fcbb 100755 --- a/indra/lscript/lscript_execute/lscript_execute.cpp +++ b/indra/lscript/lscript_execute/lscript_execute.cpp @@ -35,7 +35,6 @@ #include "lscript_library.h" #include "lscript_heapruntime.h" #include "lscript_alloc.h" -#include "llstat.h" // Static diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp index 24328202cb..eb18a3776f 100755 --- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp +++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp @@ -28,18 +28,10 @@ #include "linden_common.h" -#include "llgl.h" - -#include "llplugininstance.h" -#include "llpluginmessage.h" -#include "llpluginmessageclasses.h" -#include "media_plugin_base.h" - -#if LL_QUICKTIME_ENABLED - #if defined(LL_DARWIN) #include <QuickTime/QuickTime.h> #elif defined(LL_WINDOWS) + #include "llwin32headers.h" #include "MacTypes.h" #include "QTML.h" #include "Movies.h" @@ -48,6 +40,17 @@ #include "QTLoadLibraryUtils.h" #endif +#include "llgl.h" + +#include "llplugininstance.h" +#include "llpluginmessage.h" +#include "llpluginmessageclasses.h" +#include "media_plugin_base.h" + +#if LL_QUICKTIME_ENABLED + + + // TODO: Make sure that the only symbol exported from this library is LLPluginInitEntryPoint //////////////////////////////////////////////////////////////////////////////// // diff --git a/indra/media_plugins/webkit/mac_volume_catcher.cpp b/indra/media_plugins/webkit/mac_volume_catcher.cpp index 8a06bb8487..c20bcd374d 100755 --- a/indra/media_plugins/webkit/mac_volume_catcher.cpp +++ b/indra/media_plugins/webkit/mac_volume_catcher.cpp @@ -38,6 +38,7 @@ #include <Carbon/Carbon.h> #include <QuickTime/QuickTime.h> #include <AudioUnit/AudioUnit.h> +#include <list> struct VolumeCatcherStorage; diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt index 227644f14f..639982a305 100755 --- a/indra/newview/CMakeLists.txt +++ b/indra/newview/CMakeLists.txt @@ -237,7 +237,6 @@ set(viewer_SOURCE_FILES llfloaterinspect.cpp llfloaterinventory.cpp llfloaterjoystick.cpp - llfloaterlagmeter.cpp llfloaterland.cpp llfloaterlandholdings.cpp llfloatermap.cpp @@ -262,6 +261,7 @@ set(viewer_SOURCE_FILES llfloaterregiondebugconsole.cpp llfloaterregioninfo.cpp llfloaterreporter.cpp + llfloatersceneloadstats.cpp llfloaterscriptdebug.cpp llfloaterscriptlimits.cpp llfloatersearch.cpp @@ -484,6 +484,7 @@ set(viewer_SOURCE_FILES llremoteparcelrequest.cpp llsavedsettingsglue.cpp llsaveoutfitcombobtn.cpp + llscenemonitor.cpp llsceneview.cpp llscreenchannel.cpp llscriptfloater.cpp @@ -605,6 +606,7 @@ set(viewer_SOURCE_FILES llviewernetwork.cpp llviewerobject.cpp llviewerobjectlist.cpp + llvieweroctree.cpp llviewerparcelmedia.cpp llviewerparcelmediaautoplay.cpp llviewerparcelmgr.cpp @@ -818,7 +820,6 @@ set(viewer_HEADER_FILES llfloaterinspect.h llfloaterinventory.h llfloaterjoystick.h - llfloaterlagmeter.h llfloaterland.h llfloaterlandholdings.h llfloatermap.h @@ -843,6 +844,7 @@ set(viewer_HEADER_FILES llfloaterregiondebugconsole.h llfloaterregioninfo.h llfloaterreporter.h + llfloatersceneloadstats.h llfloaterscriptdebug.h llfloaterscriptlimits.h llfloatersearch.h @@ -1055,6 +1057,7 @@ set(viewer_HEADER_FILES llrootview.h llsavedsettingsglue.h llsaveoutfitcombobtn.h + llscenemonitor.h llsceneview.h llscreenchannel.h llscriptfloater.h @@ -1176,6 +1179,7 @@ set(viewer_HEADER_FILES llviewernetwork.h llviewerobject.h llviewerobjectlist.h + llvieweroctree.h llviewerparcelmedia.h llviewerparcelmediaautoplay.h llviewerparcelmgr.h @@ -1563,7 +1567,7 @@ endif (WINDOWS) if (OPENAL) set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_OPENAL") -endif (OPENAL) +endif (OPENAL) if (FMODEX) set(LLSTARTUP_COMPILE_FLAGS "${LLSTARTUP_COMPILE_FLAGS} -DLL_FMODEX") diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index f356cff9d8..4d5b0c62e4 100755 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -41,7 +41,7 @@ <string> Time before automatically setting AFK (away from keyboard) mode (seconds, 0=never). Valid values are: 0, 120, 300, 600, 1800 -</string> + </string> <key>Persist</key> <integer>1</integer> <key>Type</key> @@ -6642,6 +6642,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>ObjectCacheViewCullingEnabled</key> + <map> + <key>Comment</key> + <string>Enable the object cache view culling. Needs to restart viewer.</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>OpenDebugStatAdvanced</key> <map> <key>Comment</key> @@ -7134,6 +7145,17 @@ <key>Value</key> <real>6.0</real> </map> + <key>ClothingLoadingDelay</key> + <map> + <key>Comment</key> + <string>Time to wait for avatar appearance to resolve before showing world (seconds)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>10.0</real> + </map> <key>PreferredMaturity</key> <map> <key>Comment</key> @@ -7689,7 +7711,6 @@ <key>Value</key> <integer>1</integer> </map> - <key>OctreeMaxNodeCapacity</key> <map> <key>Comment</key> @@ -9766,6 +9787,39 @@ <key>Value</key> <integer>0</integer> </map> + <key>SceneLoadingMonitorEnabled</key> + <map> + <key>Comment</key> + <string>Enabled scene loading monitor if set</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>0</integer> + </map> + <key>SceneLoadingMonitorSampleTime</key> + <map> + <key>Comment</key> + <string>Time between screen samples when monitor scene load (seconds)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.25</real> + </map> + <key>SceneLoadingPixelDiffThreshold</key> + <map> + <key>Comment</key> + <string>Amount of pixels changed required to consider the scene as still loading (fraction of pixels on screen)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>0.0003</real> + </map> <key>ScriptHelpFollowsCursor</key> <map> <key>Comment</key> @@ -12714,6 +12768,17 @@ <key>Value</key> <integer>1</integer> </map> + <key>UseObjectCacheOcclusion</key> + <map> + <key>Comment</key> + <string>Enable object cache level object culling based on occlusion (coverage) by other objects</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>Boolean</string> + <key>Value</key> + <integer>1</integer> + </map> <key>RenderSynchronousOcclusion</key> <map> <key>Comment</key> @@ -14480,6 +14545,28 @@ <key>Value</key> <integer>0</integer> </map> + <key>TeleportArrivalDelay</key> + <map> + <key>Comment</key> + <string>Time to wait before displaying world during teleport (seconds)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>2</real> + </map> + <key>TeleportLocalDelay</key> + <map> + <key>Comment</key> + <string>Delay to prevent teleports after starting an in-sim teleport. (seconds)</string> + <key>Persist</key> + <integer>1</integer> + <key>Type</key> + <string>F32</string> + <key>Value</key> + <real>1</real> + </map> <key>DisablePrecacheDelayAfterTeleporting</key> <map> <key>Comment</key> diff --git a/indra/newview/app_settings/shaders/class1/interface/onetexturefilterF.glsl b/indra/newview/app_settings/shaders/class1/interface/onetexturefilterF.glsl new file mode 100644 index 0000000000..f1400c9b44 --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/onetexturefilterF.glsl @@ -0,0 +1,49 @@ +/** + * @file onetexturefilterF.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, 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$ + */ + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform sampler2D tex0; +uniform float tolerance; + +VARYING vec2 vary_texcoord0; + +void main() +{ + frag_color = texture2D(tex0, vary_texcoord0.xy); + + if(frag_color[0] + frag_color[1] + frag_color[2] < tolerance) + { + discard; + } + else + { + frag_color[3] = 0.95f; + } +} diff --git a/indra/llcommon/reflective.cpp b/indra/newview/app_settings/shaders/class1/interface/onetexturefilterV.glsl index 2cc0e7e1f2..a33ef7e92c 100755..100644 --- a/indra/llcommon/reflective.cpp +++ b/indra/newview/app_settings/shaders/class1/interface/onetexturefilterV.glsl @@ -1,12 +1,9 @@ /** - * @file reflective.cpp - * @author Babbage - * @date 2006-05-15 - * @brief Implementation of LLReflective. + * @file onetexturefilterV.glsl * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2007, 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 @@ -25,16 +22,17 @@ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ - -#include "linden_common.h" -#include "reflective.h" +uniform mat4 modelview_projection_matrix; -LLReflective::LLReflective() -{ -} +ATTRIBUTE vec3 position; +ATTRIBUTE vec2 texcoord0; -//virtual -LLReflective::~LLReflective() +VARYING vec2 vary_texcoord0; + +void main() { + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_texcoord0 = texcoord0; } + diff --git a/indra/llcommon/metaproperty.cpp b/indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl index 98d850bf1e..6eeb2596b2 100755..100644 --- a/indra/llcommon/metaproperty.cpp +++ b/indra/newview/app_settings/shaders/class1/interface/twotexturecompareF.glsl @@ -1,12 +1,9 @@ /** - * @file metaproperty.cpp - * @author Babbage - * @date 2006-05-15 - * @brief Implementation of LLMetaProperty. + * @file twotexturecompareF.glsl * - * $LicenseInfo:firstyear=2006&license=viewerlgpl$ + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * Copyright (C) 2007, 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 @@ -26,31 +23,36 @@ * $/LicenseInfo$ */ -#include "linden_common.h" +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif -#include "metaproperty.h" +uniform sampler2D tex0; +uniform sampler2D tex1; +uniform sampler2D dither_tex; +uniform float dither_scale; +uniform float dither_scale_s; +uniform float dither_scale_t; -#include "metaclass.h" +VARYING vec2 vary_texcoord0; +VARYING vec2 vary_texcoord1; -LLMetaProperty::LLMetaProperty(const std::string& name, const LLMetaClass& object_class) : - mName(name), mObjectClass(object_class) +void main() { -} + frag_color = abs(texture2D(tex0, vary_texcoord0.xy) - texture2D(tex1, vary_texcoord0.xy)); -//virtual -LLMetaProperty::~LLMetaProperty() -{ -} + vec2 dither_coord; + dither_coord[0] = vary_texcoord0[0] * dither_scale_s; + dither_coord[1] = vary_texcoord0[1] * dither_scale_t; + vec4 dither_vec = texture(dither_tex, dither_coord.xy); -const LLMetaClass& LLMetaProperty::getObjectMetaClass() const -{ - return mObjectClass; -} - -void LLMetaProperty::checkObjectClass(const LLReflective* object) const -{ - if(! mObjectClass.isInstance(object)) + for(int i = 0; i < 3; i++) { - throw "class cast exception"; + if(frag_color[i] < dither_vec[i] * dither_scale) + { + frag_color[i] = 0.f; + } } } diff --git a/indra/newview/app_settings/shaders/class1/interface/twotexturecompareV.glsl b/indra/newview/app_settings/shaders/class1/interface/twotexturecompareV.glsl new file mode 100644 index 0000000000..67c6674f0c --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/interface/twotexturecompareV.glsl @@ -0,0 +1,41 @@ +/** + * @file twotexturecompareV.glsl + * + * $LicenseInfo:firstyear=2007&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2007, 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$ + */ + +uniform mat4 modelview_projection_matrix; + +ATTRIBUTE vec3 position; +ATTRIBUTE vec2 texcoord0; +ATTRIBUTE vec2 texcoord1; + +VARYING vec2 vary_texcoord0; +VARYING vec2 vary_texcoord1; + +void main() +{ + gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); + vary_texcoord0 = texcoord0; + vary_texcoord1 = texcoord1; +} + diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 8c42defa73..8ec74bb268 100755 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -754,7 +754,7 @@ void LLAgent::setFlying(BOOL fly) } if( !was_flying ) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_FLY_COUNT); + add(LLStatViewer::FLY, 1); } setControlFlags(AGENT_CONTROL_FLY); } @@ -2830,10 +2830,10 @@ BOOL LLAgent::isInGroup(const LLUUID& group_id, BOOL ignore_god_mode /* FALSE */ if (!ignore_god_mode && isGodlike()) return true; - S32 count = mGroups.count(); - for(S32 i = 0; i < count; ++i) + U32 count = mGroups.size(); + for(U32 i = 0; i < count; ++i) { - if(mGroups.get(i).mID == group_id) + if(mGroups[i].mID == group_id) { return TRUE; } @@ -2850,12 +2850,12 @@ BOOL LLAgent::hasPowerInGroup(const LLUUID& group_id, U64 power) const // GP_NO_POWERS can also mean no power is enough to grant an ability. if (GP_NO_POWERS == power) return FALSE; - S32 count = mGroups.count(); - for(S32 i = 0; i < count; ++i) + U32 count = mGroups.size(); + for(U32 i = 0; i < count; ++i) { - if(mGroups.get(i).mID == group_id) + if(mGroups[i].mID == group_id) { - return (BOOL)((mGroups.get(i).mPowers & power) > 0); + return (BOOL)((mGroups[i].mPowers & power) > 0); } } return FALSE; @@ -2871,12 +2871,12 @@ U64 LLAgent::getPowerInGroup(const LLUUID& group_id) const if (isGodlike()) return GP_ALL_POWERS; - S32 count = mGroups.count(); - for(S32 i = 0; i < count; ++i) + U32 count = mGroups.size(); + for(U32 i = 0; i < count; ++i) { - if(mGroups.get(i).mID == group_id) + if(mGroups[i].mID == group_id) { - return (mGroups.get(i).mPowers); + return (mGroups[i].mPowers); } } @@ -2885,12 +2885,12 @@ U64 LLAgent::getPowerInGroup(const LLUUID& group_id) const BOOL LLAgent::getGroupData(const LLUUID& group_id, LLGroupData& data) const { - S32 count = mGroups.count(); + S32 count = mGroups.size(); for(S32 i = 0; i < count; ++i) { - if(mGroups.get(i).mID == group_id) + if(mGroups[i].mID == group_id) { - data = mGroups.get(i); + data = mGroups[i]; return TRUE; } } @@ -2899,12 +2899,12 @@ BOOL LLAgent::getGroupData(const LLUUID& group_id, LLGroupData& data) const S32 LLAgent::getGroupContribution(const LLUUID& group_id) const { - S32 count = mGroups.count(); + S32 count = mGroups.size(); for(S32 i = 0; i < count; ++i) { - if(mGroups.get(i).mID == group_id) + if(mGroups[i].mID == group_id) { - S32 contribution = mGroups.get(i).mContribution; + S32 contribution = mGroups[i].mContribution; return contribution; } } @@ -2913,12 +2913,12 @@ S32 LLAgent::getGroupContribution(const LLUUID& group_id) const BOOL LLAgent::setGroupContribution(const LLUUID& group_id, S32 contribution) { - S32 count = mGroups.count(); + S32 count = mGroups.size(); for(S32 i = 0; i < count; ++i) { - if(mGroups.get(i).mID == group_id) + if(mGroups[i].mID == group_id) { - mGroups.get(i).mContribution = contribution; + mGroups[i].mContribution = contribution; LLMessageSystem* msg = gMessageSystem; msg->newMessage("SetGroupContribution"); msg->nextBlock("AgentData"); @@ -2936,13 +2936,13 @@ BOOL LLAgent::setGroupContribution(const LLUUID& group_id, S32 contribution) BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOOL list_in_profile) { - S32 count = mGroups.count(); + S32 count = mGroups.size(); for(S32 i = 0; i < count; ++i) { - if(mGroups.get(i).mID == group_id) + if(mGroups[i].mID == group_id) { - mGroups.get(i).mAcceptNotices = accept_notices; - mGroups.get(i).mListInProfile = list_in_profile; + mGroups[i].mAcceptNotices = accept_notices; + mGroups[i].mListInProfile = list_in_profile; LLMessageSystem* msg = gMessageSystem; msg->newMessage("SetGroupAcceptNotices"); msg->nextBlock("AgentData"); @@ -2962,7 +2962,7 @@ BOOL LLAgent::setUserGroupFlags(const LLUUID& group_id, BOOL accept_notices, BOO BOOL LLAgent::canJoinGroups() const { - return mGroups.count() < gMaxAgentGroups; + return (S32)mGroups.size() < gMaxAgentGroups; } LLQuaternion LLAgent::getHeadRotation() @@ -3792,7 +3792,7 @@ bool LLAgent::teleportCore(bool is_local) gAgentCamera.resetView(FALSE); // local logic - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TELEPORT_COUNT); + add(LLStatViewer::TELEPORT, 1); if (is_local) { gAgent.setTeleportState( LLAgent::TELEPORT_LOCAL ); @@ -4109,7 +4109,7 @@ void LLAgent::setTeleportState(ETeleportState state) case TELEPORT_ARRIVING: // First two position updates after a teleport tend to be weird - LLViewerStats::getInstance()->mAgentPositionSnaps.mCountOfNextUpdatesToIgnore = 2; + //LLViewerStats::getInstance()->mAgentPositionSnaps.mCountOfNextUpdatesToIgnore = 2; // Let the interested parties know we've teleported. LLViewerParcelMgr::getInstance()->onTeleportFinished(false, getPositionGlobal()); diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h index f5f26f69d8..4153fbbfff 100755 --- a/indra/newview/llagent.h +++ b/indra/newview/llagent.h @@ -35,6 +35,7 @@ #include "llcoordframe.h" // for mFrameAgent #include "llavatarappearancedefines.h" #include "llpermissionsflags.h" +#include "lldarray.h" #include <boost/function.hpp> #include <boost/shared_ptr.hpp> @@ -251,6 +252,7 @@ public: const LLVector3d &getLastPositionGlobal() const { return mLastPositionGlobal; } void setLastPositionGlobal(const LLVector3d &pos) { mLastPositionGlobal = pos; } + private: std::set<U64> mRegionsVisited; // Stat - what distinct regions has the avatar been to? F64 mDistanceTraveled; // Stat - how far has the avatar moved? diff --git a/indra/newview/llagentcamera.cpp b/indra/newview/llagentcamera.cpp index 0896aa5972..d02817df7b 100755 --- a/indra/newview/llagentcamera.cpp +++ b/indra/newview/llagentcamera.cpp @@ -337,7 +337,7 @@ void LLAgentCamera::resetView(BOOL reset_camera, BOOL change_camera) LLVector3 agent_at_axis = gAgent.getAtAxis(); agent_at_axis -= projected_vec(agent_at_axis, gAgent.getReferenceUpVector()); agent_at_axis.normalize(); - gAgent.resetAxes(lerp(gAgent.getAtAxis(), agent_at_axis, LLCriticalDamp::getInterpolant(0.3f))); + gAgent.resetAxes(lerp(gAgent.getAtAxis(), agent_at_axis, LLSmoothInterpolation::getInterpolant(0.3f))); } setFocusOnAvatar(TRUE, ANIMATE); @@ -1070,8 +1070,8 @@ void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y) LLQuaternion av_inv_rot = ~gAgentAvatarp->mRoot->getWorldRotation(); LLVector3 root_at = LLVector3::x_axis * gAgentAvatarp->mRoot->getWorldRotation(); - if ((gViewerWindow->getMouseVelocityStat()->getCurrent() < 0.01f) && - (root_at * last_at_axis > 0.95f)) + if (LLTrace::get_frame_recording().getLastRecording().getLastValue(*gViewerWindow->getMouseVelocityStat()) < 0.01f + && (root_at * last_at_axis > 0.95f)) { LLVector3 vel = gAgentAvatarp->getVelocity(); if (vel.magVecSquared() > 4.f) @@ -1126,13 +1126,14 @@ void LLAgentCamera::updateLookAt(const S32 mouse_x, const S32 mouse_y) } } +static LLFastTimer::DeclareTimer FTM_UPDATE_CAMERA("Camera"); + //----------------------------------------------------------------------------- // updateCamera() //----------------------------------------------------------------------------- void LLAgentCamera::updateCamera() { - static LLFastTimer::DeclareTimer ftm("Camera"); - LLFastTimer t(ftm); + LLFastTimer t(FTM_UPDATE_CAMERA); // - changed camera_skyward to the new global "mCameraUpVector" mCameraUpVector = LLVector3::z_axis; @@ -1234,7 +1235,7 @@ void LLAgentCamera::updateCamera() gAgentCamera.clearPanKeys(); // lerp camera focus offset - mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLCriticalDamp::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); + mCameraFocusOffset = lerp(mCameraFocusOffset, mCameraFocusOffsetTarget, LLSmoothInterpolation::getInterpolant(CAMERA_FOCUS_HALF_LIFE)); if ( mCameraMode == CAMERA_MODE_FOLLOW ) { @@ -1352,7 +1353,7 @@ void LLAgentCamera::updateCamera() { const F32 SMOOTHING_HALF_LIFE = 0.02f; - F32 smoothing = LLCriticalDamp::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, FALSE); + F32 smoothing = LLSmoothInterpolation::getInterpolant(gSavedSettings.getF32("CameraPositionSmoothing") * SMOOTHING_HALF_LIFE, FALSE); if (!mFocusObject) // we differentiate on avatar mode { @@ -1382,7 +1383,7 @@ void LLAgentCamera::updateCamera() } - mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLCriticalDamp::getInterpolant(FOV_ZOOM_HALF_LIFE)); + mCameraCurrentFOVZoomFactor = lerp(mCameraCurrentFOVZoomFactor, mCameraFOVZoomFactor, LLSmoothInterpolation::getInterpolant(FOV_ZOOM_HALF_LIFE)); // llinfos << "Current FOV Zoom: " << mCameraCurrentFOVZoomFactor << " Target FOV Zoom: " << mCameraFOVZoomFactor << " Object penetration: " << mFocusObjectDist << llendl; @@ -1796,7 +1797,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) if (mTargetCameraDistance != mCurrentCameraDistance) { - F32 camera_lerp_amt = LLCriticalDamp::getInterpolant(CAMERA_ZOOM_HALF_LIFE); + F32 camera_lerp_amt = LLSmoothInterpolation::getInterpolant(CAMERA_ZOOM_HALF_LIFE); mCurrentCameraDistance = lerp(mCurrentCameraDistance, mTargetCameraDistance, camera_lerp_amt); } @@ -1813,7 +1814,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) if (isAgentAvatarValid()) { LLVector3d camera_lag_d; - F32 lag_interp = LLCriticalDamp::getInterpolant(CAMERA_LAG_HALF_LIFE); + F32 lag_interp = LLSmoothInterpolation::getInterpolant(CAMERA_LAG_HALF_LIFE); LLVector3 target_lag; LLVector3 vel = gAgent.getVelocity(); @@ -1858,7 +1859,7 @@ LLVector3d LLAgentCamera::calcCameraPositionTargetGlobal(BOOL *hit_limit) } else { - mCameraLag = lerp(mCameraLag, LLVector3::zero, LLCriticalDamp::getInterpolant(0.15f)); + mCameraLag = lerp(mCameraLag, LLVector3::zero, LLSmoothInterpolation::getInterpolant(0.15f)); } camera_lag_d.setVec(mCameraLag); diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index c88694ef76..861991f3c2 100755 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -39,6 +39,7 @@ #include "llinventoryfunctions.h" #include "llinventoryobserver.h" #include "llinventorypanel.h" +#include "lllocaltextureobject.h" #include "llmd5.h" #include "llnotificationsutil.h" #include "lloutfitobserver.h" @@ -64,10 +65,10 @@ using namespace LLAvatarAppearanceDefines; void wear_and_edit_cb(const LLUUID& inv_item) { if (inv_item.isNull()) return; - + // Request editing the item after it gets worn. gAgentWearables.requestEditingWearable(inv_item); - + // Wear it. LLAppearanceMgr::instance().wearItemOnAvatar(inv_item); } @@ -180,7 +181,7 @@ void LLAgentWearables::initClass() } void LLAgentWearables::setAvatarObject(LLVOAvatarSelf *avatar) -{ +{ llassert(avatar); avatar->outputRezTiming("Sending wearables request"); sendAgentWearablesRequest(); diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h index 46252afbde..862b428e48 100755 --- a/indra/newview/llappearancemgr.h +++ b/indra/newview/llappearancemgr.h @@ -34,6 +34,7 @@ #include "llinventorymodel.h" #include "llinventoryobserver.h" #include "llviewerinventory.h" +#include "llhttpclient.h" class LLWearableHoldingPattern; class LLInventoryCallback; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index fdc2cdb78d..42bf9b657b 100755 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -61,7 +61,8 @@ #include "llcalc.h" #include "llconversationlog.h" #include "lltexturestats.h" -#include "lltexturestats.h" +#include "lltrace.h" +#include "lltracethreadrecorder.h" #include "llviewerwindow.h" #include "llviewerdisplay.h" #include "llviewermedia.h" @@ -96,6 +97,7 @@ #include "llupdaterservice.h" #include "llfloatertexturefetchdebugger.h" #include "llspellcheck.h" +#include "llscenemonitor.h" // Linden library includes #include "llavatarnamecache.h" @@ -294,7 +296,7 @@ LLPumpIO* gServicePump = NULL; U64 gFrameTime = 0; F32 gFrameTimeSeconds = 0.f; -F32 gFrameIntervalSeconds = 0.f; +LLUnit<LLUnits::Seconds, F32> gFrameIntervalSeconds = 0.f; F32 gFPSClamped = 10.f; // Pretend we start at target rate. F32 gFrameDTClamped = 0.f; // Time between adjacent checks to network for packets U64 gStartTime = 0; // gStartTime is "private", used only to calculate gFrameTimeSeconds @@ -624,7 +626,7 @@ public: while (!LLAppViewer::instance()->isQuitting()) { - LLFastTimer::writeLog(os); + LLTrace::TimeBlock::writeLog(os); os.flush(); ms_sleep(32); } @@ -722,7 +724,6 @@ bool LLAppViewer::init() // into the log files during normal startup until AFTER // we run the "program crashed last time" error handler below. // - LLFastTimer::reset(); // initialize LLWearableType translation bridge. // Memory will be cleaned up in ::cleanupClass() @@ -1082,9 +1083,9 @@ bool LLAppViewer::init() if (gGLManager.mGLVersion < LLFeatureManager::getInstance()->getExpectedGLVersion()) { if (gGLManager.mIsIntel) - { - LLNotificationsUtil::add("IntelOldDriver"); - } + { + LLNotificationsUtil::add("IntelOldDriver"); + } else if (gGLManager.mIsNVIDIA) { LLNotificationsUtil::add("NVIDIAOldDriver"); @@ -1251,6 +1252,8 @@ LLFastTimer::DeclareTimer FTM_FRAME("Frame", true); bool LLAppViewer::mainLoop() { + llinfos << "***********************Entering main_loop***********************" << llendflush; + mMainloopTimeout = new LLWatchdogTimeout(); //------------------------------------------- @@ -1287,7 +1290,11 @@ bool LLAppViewer::mainLoop() while (!LLApp::isExiting()) { LLFastTimer _(FTM_FRAME); - LLFastTimer::nextFrame(); + LLTrace::TimeBlock::processTimes(); + LLTrace::get_frame_recording().nextPeriod(); + LLTrace::TimeBlock::logStats(); + + LLTrace::getUIThreadRecorder().pullFromSlaveThreads(); //clear call stack records llclearcallstacks; @@ -1404,7 +1411,6 @@ bool LLAppViewer::mainLoop() LLFloaterSnapshot::update(); // take snapshots gGLActive = FALSE; } - } pingMainloopTimeout("Main:Sleep"); @@ -1459,20 +1465,9 @@ bool LLAppViewer::mainLoop() { S32 work_pending = 0; S32 io_pending = 0; - F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f); + F32 max_time = llmin(gFrameIntervalSeconds.value() *10.f, 1.f); - { - LLFastTimer ftm(FTM_TEXTURE_CACHE); - work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread - } - { - LLFastTimer ftm(FTM_DECODE); - work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread - } - { - LLFastTimer ftm(FTM_DECODE); - work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread - } + work_pending += updateTextureThreads(max_time); { LLFastTimer ftm(FTM_VFS); @@ -1585,11 +1580,29 @@ bool LLAppViewer::mainLoop() destroyMainloopTimeout(); - llinfos << "Exiting main_loop" << llendflush; + llinfos << "***********************Exiting main_loop***********************" << llendflush; return true; } +S32 LLAppViewer::updateTextureThreads(F32 max_time) +{ + S32 work_pending = 0; + { + LLFastTimer ftm(FTM_TEXTURE_CACHE); + work_pending += LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread + } + { + LLFastTimer ftm(FTM_DECODE); + work_pending += LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread + } + { + LLFastTimer ftm(FTM_DECODE); + work_pending += LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread + } + return work_pending; +} + void LLAppViewer::flushVFSIO() { while (1) @@ -1613,12 +1626,15 @@ bool LLAppViewer::cleanup() // workaround for DEV-35406 crash on shutdown LLEventPumps::instance().reset(); + //dump scene loading monitor results + LLSceneMonitor::instance().dumpToFile(gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "scene_monitor_results.csv")); + if (LLFastTimerView::sAnalyzePerformance) { llinfos << "Analyzing performance" << llendl; - std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp"; - std::string current_name = LLFastTimer::sLogName + ".slp"; - std::string report_name = LLFastTimer::sLogName + "_report.csv"; + std::string baseline_name = LLTrace::TimeBlock::sLogName + "_baseline.slp"; + std::string current_name = LLTrace::TimeBlock::sLogName + ".slp"; + std::string report_name = LLTrace::TimeBlock::sLogName + "_report.csv"; LLFastTimerView::doAnalysis( gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name), @@ -1799,7 +1815,7 @@ bool LLAppViewer::cleanup() llinfos << "Cleaning up Objects" << llendflush; LLViewerObject::cleanupVOClasses(); - + LLAvatarAppearance::cleanupClass(); LLPostProcess::cleanupClass(); @@ -1970,9 +1986,9 @@ bool LLAppViewer::cleanup() { llinfos << "Analyzing performance" << llendl; - std::string baseline_name = LLFastTimer::sLogName + "_baseline.slp"; - std::string current_name = LLFastTimer::sLogName + ".slp"; - std::string report_name = LLFastTimer::sLogName + "_report.csv"; + std::string baseline_name = LLTrace::TimeBlock::sLogName + "_baseline.slp"; + std::string current_name = LLTrace::TimeBlock::sLogName + ".slp"; + std::string report_name = LLTrace::TimeBlock::sLogName + "_report.csv"; LLFastTimerView::doAnalysis( gDirUtilp->getExpandedFilename(LL_PATH_LOGS, baseline_name), @@ -2097,10 +2113,10 @@ bool LLAppViewer::initThreads() enable_threads && true, app_metrics_qa_mode); - if (LLFastTimer::sLog || LLFastTimer::sMetricLog) + if (LLTrace::TimeBlock::sLog || LLTrace::TimeBlock::sMetricLog) { - LLFastTimer::sLogLock = new LLMutex(NULL); - mFastTimerLogThread = new LLFastTimerLogThread(LLFastTimer::sLogName); + LLTrace::TimeBlock::setLogLock(new LLMutex(NULL)); + mFastTimerLogThread = new LLFastTimerLogThread(LLTrace::TimeBlock::sLogName); mFastTimerLogThread->start(); } @@ -2538,13 +2554,13 @@ bool LLAppViewer::initConfiguration() if (clp.hasOption("logperformance")) { - LLFastTimer::sLog = TRUE; - LLFastTimer::sLogName = std::string("performance"); + LLTrace::TimeBlock::sLog = true; + LLTrace::TimeBlock::sLogName = std::string("performance"); } if (clp.hasOption("logmetrics")) { - LLFastTimer::sMetricLog = TRUE ; + LLTrace::TimeBlock::sMetricLog = true ; // '--logmetrics' can be specified with a named test metric argument so the data gathering is done only on that test // In the absence of argument, every metric is gathered (makes for a rather slow run and hard to decipher report...) std::string test_name = clp.getOption("logmetrics")[0]; @@ -2552,11 +2568,11 @@ bool LLAppViewer::initConfiguration() if (test_name == "") { llwarns << "No '--logmetrics' argument given, will output all metrics to " << DEFAULT_METRIC_NAME << llendl; - LLFastTimer::sLogName = DEFAULT_METRIC_NAME; + LLTrace::TimeBlock::sLogName = DEFAULT_METRIC_NAME; } else { - LLFastTimer::sLogName = test_name; + LLTrace::TimeBlock::sLogName = test_name; } } @@ -2769,7 +2785,7 @@ bool LLAppViewer::initConfiguration() } initMarkerFile(); - + if (mSecondInstance) { // This is the second instance of SL. Turn off voice support, @@ -2989,7 +3005,7 @@ namespace { relnotes_url.setArg("[RELEASE_NOTES_BASE_URL]", LLTrans::getString("RELEASE_NOTES_BASE_URL")); substitutions["INFO_URL"] = relnotes_url.getString(); } - + LLNotificationsUtil::add(notification_name, substitutions, LLSD(), apply_callback); } @@ -3771,7 +3787,7 @@ void LLAppViewer::requestQuit() // Try to send metrics back to the grid metricsSend(!gDisconnected); - + // Try to send last batch of avatar rez metrics. if (!gDisconnected && isAgentAvatarValid()) { @@ -3972,7 +3988,7 @@ U32 LLAppViewer::getObjectCacheVersion() { // Viewer object cache version, change if object update // format changes. JC - const U32 INDRA_OBJECT_CACHE_VERSION = 14; + const U32 INDRA_OBJECT_CACHE_VERSION = 15; return INDRA_OBJECT_CACHE_VERSION; } @@ -4229,6 +4245,14 @@ void LLAppViewer::purgeCache() gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""), "*.*"); } +//purge cache immediately, do not wait until the next login. +void LLAppViewer::purgeCacheImmediate() +{ + LL_INFOS("AppCache") << "Purging Object Cache and Texture Cache immediately..." << LL_ENDL; + LLAppViewer::getTextureCache()->purgeCache(LL_PATH_CACHE, false); + LLVOCache::getInstance()->removeCache(LL_PATH_CACHE, true); +} + std::string LLAppViewer::getSecondLifeTitle() const { return LLTrans::getString("APP_NAME"); @@ -4413,6 +4437,8 @@ static LLFastTimer::DeclareTimer FTM_WORLD_UPDATE("Update World"); static LLFastTimer::DeclareTimer FTM_NETWORK("Network"); static LLFastTimer::DeclareTimer FTM_AGENT_NETWORK("Agent Network"); static LLFastTimer::DeclareTimer FTM_VLMANAGER("VL Manager"); +static LLFastTimer::DeclareTimer FTM_AGENT_POSITION("Agent Position"); +static LLFastTimer::DeclareTimer FTM_HUD_EFFECTS("HUD Effects"); /////////////////////////////////////////////////////// // idle() @@ -4431,7 +4457,7 @@ void LLAppViewer::idle() LLFrameTimer::updateFrameCount(); LLEventTimer::updateClass(); LLNotificationsUI::LLToast::updateClass(); - LLCriticalDamp::updateInterpolants(); + LLSmoothInterpolation::updateInterpolants(); LLMortician::updateClass(); LLFilePickerThread::clearDead(); //calls LLFilePickerThread::notify() @@ -4456,6 +4482,7 @@ void LLAppViewer::idle() { if (gRenderStartTime.getElapsedTimeF32() > qas) { + llinfos << "Quitting after " << qas << " seconds. See setting \"QuitAfterSeconds\"." << llendl; LLAppViewer::instance()->forceQuit(); } } @@ -4554,21 +4581,12 @@ void LLAppViewer::idle() llinfos << "Dead object updates: " << gObjectList.mNumDeadObjectUpdates << llendl; gObjectList.mNumDeadObjectUpdates = 0; } - if (gObjectList.mNumUnknownKills) - { - llinfos << "Kills on unknown objects: " << gObjectList.mNumUnknownKills << llendl; - gObjectList.mNumUnknownKills = 0; - } if (gObjectList.mNumUnknownUpdates) { llinfos << "Unknown object updates: " << gObjectList.mNumUnknownUpdates << llendl; gObjectList.mNumUnknownUpdates = 0; } - // ViewerMetrics FPS piggy-backing on the debug timer. - // The 5-second interval is nice for this purpose. If the object debug - // bit moves or is disabled, please give this a suitable home. - LLViewerAssetStatsFF::record_fps_main(gFPSClamped); } } @@ -4649,8 +4667,7 @@ void LLAppViewer::idle() { // Handle pending gesture processing - static LLFastTimer::DeclareTimer ftm("Agent Position"); - LLFastTimer t(ftm); + LLFastTimer t(FTM_AGENT_POSITION); LLGestureMgr::instance().update(); gAgent.updateAgentPosition(gFrameDTClamped, yaw, current_mouse.mX, current_mouse.mY); @@ -4697,8 +4714,7 @@ void LLAppViewer::idle() // { - static LLFastTimer::DeclareTimer ftm("HUD Effects"); - LLFastTimer t(ftm); + LLFastTimer t(FTM_HUD_EFFECTS); LLSelectMgr::getInstance()->updateEffects(); LLHUDManager::getInstance()->cleanupEffects(); LLHUDManager::getInstance()->sendEffects(); @@ -5102,7 +5118,7 @@ void LLAppViewer::idleNetwork() gPrintMessagesThisFrame = FALSE; } } - LLViewerStats::getInstance()->mNumNewObjectsStat.addValue(gObjectList.mNumNewObjects); + add(LLStatViewer::NUM_NEW_OBJECTS, gObjectList.mNumNewObjects); // Retransmit unacknowledged packets. gXferManager->retransmitUnackedPackets(); @@ -5181,6 +5197,7 @@ void LLAppViewer::disconnectViewer() { LLWorld::getInstance()->destroyClass(); } + LLVOCache::deleteSingleton(); // call all self-registered classes LLDestroyClassList::instance().fireCallbacks(); @@ -5504,17 +5521,7 @@ void LLAppViewer::metricsUpdateRegion(U64 region_handle) { if (0 != region_handle) { - LLViewerAssetStatsFF::set_region_main(region_handle); - if (LLAppViewer::sTextureFetch) - { - // Send a region update message into 'thread1' to get the new region. - LLAppViewer::sTextureFetch->commandSetRegion(region_handle); - } - else - { - // No 'thread1', a.k.a. TextureFetch, so update directly - LLViewerAssetStatsFF::set_region_thread1(region_handle); - } + LLViewerAssetStatsFF::set_region(region_handle); } } @@ -5525,7 +5532,7 @@ void LLAppViewer::metricsUpdateRegion(U64 region_handle) */ void LLAppViewer::metricsSend(bool enable_reporting) { - if (! gViewerAssetStatsMain) + if (! gViewerAssetStats) return; if (LLAppViewer::sTextureFetch) @@ -5538,7 +5545,10 @@ void LLAppViewer::metricsSend(bool enable_reporting) // Make a copy of the main stats to send into another thread. // Receiving thread takes ownership. - LLViewerAssetStats * main_stats(new LLViewerAssetStats(*gViewerAssetStatsMain)); + LLViewerAssetStats * main_stats(new LLViewerAssetStats(*gViewerAssetStats)); + main_stats->stop(); + + main_stats->updateStats(); // Send a report request into 'thread1' to get the rest of the data // and provide some additional parameters while here. @@ -5557,6 +5567,6 @@ void LLAppViewer::metricsSend(bool enable_reporting) // Reset even if we can't report. Rather than gather up a huge chunk of // data, we'll keep to our sampling interval and retain the data // resolution in time. - gViewerAssetStatsMain->reset(); + gViewerAssetStats->reset(); } diff --git a/indra/newview/llappviewer.h b/indra/newview/llappviewer.h index d3a8cf24d9..2e75de445f 100755 --- a/indra/newview/llappviewer.h +++ b/indra/newview/llappviewer.h @@ -32,6 +32,7 @@ #include "llsys.h" // for LLOSInfo #include "lltimer.h" #include "llappcorehttp.h" +#include "llunit.h" class LLCommandLineParser; class LLFrameTimer; @@ -169,6 +170,8 @@ public: void addOnIdleCallback(const boost::function<void()>& cb); // add a callback to fire (once) when idle void purgeCache(); // Clear the local cache. + void purgeCacheImmediate(); //clear local cache immediately. + S32 updateTextureThreads(F32 max_time); // mute/unmute the system's master audio virtual void setMasterSystemAudioMute(bool mute); @@ -219,7 +222,7 @@ private: void initMarkerFile(); static void recordMarkerVersion(LLAPRFile& marker_file); bool markerIsSameVersion(const std::string& marker_name) const; - + void idle(); void idleShutdown(); // update avatar SLID and display name caches @@ -334,7 +337,7 @@ extern LLPumpIO* gServicePump; extern U64 gFrameTime; // The timestamp of the most-recently-processed frame extern F32 gFrameTimeSeconds; // Loses msec precision after ~4.5 hours... -extern F32 gFrameIntervalSeconds; // Elapsed time between current and previous gFrameTimeSeconds +extern LLUnit<LLUnits::Seconds, F32> gFrameIntervalSeconds; // Elapsed time between current and previous gFrameTimeSeconds extern F32 gFPSClamped; // Frames per second, smoothed, weighted toward last frame extern F32 gFrameDTClamped; extern U64 gStartTime; diff --git a/indra/newview/llappviewerwin32.cpp b/indra/newview/llappviewerwin32.cpp index 0ba3669487..a113ab2508 100755 --- a/indra/newview/llappviewerwin32.cpp +++ b/indra/newview/llappviewerwin32.cpp @@ -29,11 +29,12 @@ #ifdef INCLUDE_VLD #include "vld.h" #endif +#include "llwin32headers.h" -#include "llappviewerwin32.h" +#include "llwindowwin32.h" // *FIX: for setting gIconResource. +#include "llappviewerwin32.h" -#include "llwindowwin32.h" // *FIX: for setting gIconResource. #include "llgl.h" #include "res/resource.h" // *FIX: for setting gIconResource. diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp index 14583e402d..3da77857c6 100755 --- a/indra/newview/llcallingcard.cpp +++ b/indra/newview/llcallingcard.cpp @@ -32,13 +32,10 @@ #include "llcallingcard.h" -#include <vector> #include <algorithm> -//#include <iterator> #include "indra_constants.h" -#include "llavatarnamecache.h" -#include "llcachename.h" +//#include "llcachename.h" #include "llstl.h" #include "lltimer.h" #include "lluuid.h" @@ -46,19 +43,14 @@ #include "llagent.h" #include "llavatarnamecache.h" -#include "llbutton.h" #include "llinventoryobserver.h" #include "llinventorymodel.h" #include "llnotifications.h" -#include "llnotificationsutil.h" -#include "llresmgr.h" #include "llslurl.h" #include "llimview.h" #include "lltrans.h" #include "llviewercontrol.h" -#include "llviewernetwork.h" #include "llviewerobjectlist.h" -#include "llviewerwindow.h" #include "llvoavatar.h" #include "llavataractions.h" @@ -105,8 +97,6 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, LLAvatarTracker::LLAvatarTracker() : mTrackingData(NULL), mTrackedAgentValid(false), - //mInventory(NULL), - //mInventoryObserver(NULL), mModifyMask(0x0) { } @@ -641,11 +631,11 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg) payload["from_id"] = agent_id; if(LLRelationship::GRANT_MODIFY_OBJECTS & new_rights) { - LLNotificationsUtil::add("GrantedModifyRights",args, payload); + LLNotifications::instance().add("GrantedModifyRights",args, payload); } else { - LLNotificationsUtil::add("RevokedModifyRights",args, payload); + LLNotifications::instance().add("RevokedModifyRights",args, payload); } } (mBuddyInfo[agent_id])->setRightsFrom(new_rights); @@ -729,7 +719,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, if (online) { notification = - LLNotificationsUtil::add("FriendOnlineOffline", + LLNotifications::instance().add("FriendOnlineOffline", args, payload.with("respond_on_mousedown", TRUE), boost::bind(&LLAvatarActions::startIM, agent_id)); @@ -737,7 +727,7 @@ static void on_avatar_name_cache_notify(const LLUUID& agent_id, else { notification = - LLNotificationsUtil::add("FriendOnlineOffline", args, payload); + LLNotifications::instance().add("FriendOnlineOffline", args, payload); } // If there's an open IM session with this agent, send a notification there too. diff --git a/indra/newview/llchatbar.cpp b/indra/newview/llchatbar.cpp index 7d0331757b..b883941963 100755 --- a/indra/newview/llchatbar.cpp +++ b/indra/newview/llchatbar.cpp @@ -618,24 +618,6 @@ void LLChatBar::sendChatFromViewer(const LLWString &wtext, EChatType type, BOOL send_chat_from_viewer(utf8_out_text, type, channel); } -/* -void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel) -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ChatFromViewer); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ChatData); - msg->addStringFast(_PREHASH_Message, utf8_out_text); - msg->addU8Fast(_PREHASH_Type, type); - msg->addS32("Channel", channel); - - gAgent.sendReliableMessage(); - - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); -} -*/ void LLChatBar::onCommitGesture(LLUICtrl* ctrl) { diff --git a/indra/newview/llcompilequeue.cpp b/indra/newview/llcompilequeue.cpp index 4588424474..d70d575eab 100755 --- a/indra/newview/llcompilequeue.cpp +++ b/indra/newview/llcompilequeue.cpp @@ -424,8 +424,6 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ) { LLSD args; diff --git a/indra/newview/lldebugview.cpp b/indra/newview/lldebugview.cpp index aeecf054b8..1264f05d77 100755 --- a/indra/newview/lldebugview.cpp +++ b/indra/newview/lldebugview.cpp @@ -40,7 +40,7 @@ #include "llsceneview.h" #include "llviewertexture.h" #include "llfloaterreg.h" - +#include "llscenemonitor.h" // // Globals // @@ -66,6 +66,7 @@ LLDebugView::~LLDebugView() gDebugView = NULL; gTextureView = NULL; gSceneView = NULL; + gSceneMonitorView = NULL; } void LLDebugView::init() @@ -99,6 +100,13 @@ void LLDebugView::init() addChild(gSceneView); gSceneView->setRect(rect); + gSceneMonitorView = new LLSceneMonitorView(r); + gSceneMonitorView->setFollowsTop(); + gSceneMonitorView->setFollowsLeft(); + gSceneMonitorView->setVisible(FALSE); + addChild(gSceneMonitorView); + gSceneMonitorView->setRect(rect); + r.setLeftTopAndSize(25, rect.getHeight() - 50, (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.75f), (S32) (gViewerWindow->getWindowRectScaled().getHeight() * 0.75f)); diff --git a/indra/newview/lldirpicker.cpp b/indra/newview/lldirpicker.cpp index d7d9f82910..6fd0897919 100755 --- a/indra/newview/lldirpicker.cpp +++ b/indra/newview/lldirpicker.cpp @@ -27,7 +27,6 @@ #include "llviewerprecompiledheaders.h" #include "lldirpicker.h" -//#include "llviewermessage.h" #include "llworld.h" #include "llviewerwindow.h" #include "llkeyboard.h" @@ -36,6 +35,7 @@ #include "lltrans.h" #include "llwindow.h" // beforeDialog() #include "llviewercontrol.h" +#include "llwin32headerslean.h" #if LL_LINUX || LL_SOLARIS # include "llfilepicker.h" diff --git a/indra/newview/lldirpicker.h b/indra/newview/lldirpicker.h index 682f9d6476..2299341aba 100755 --- a/indra/newview/lldirpicker.h +++ b/indra/newview/lldirpicker.h @@ -46,11 +46,6 @@ #endif -// Need commdlg.h for OPENDIRNAMEA -#ifdef LL_WINDOWS -#include <commdlg.h> -#endif - class LLFilePicker; class LLDirPicker diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 47306d3a6a..93fb484f06 100755 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -49,6 +49,7 @@ #include "llspatialpartition.h" #include "llviewerobjectlist.h" #include "llviewerwindow.h" +#include "llvocache.h" const F32 MIN_INTERPOLATE_DISTANCE_SQUARED = 0.001f * 0.001f; const F32 MAX_INTERPOLATE_DISTANCE_SQUARED = 10.f * 10.f; @@ -58,6 +59,7 @@ const F32 MIN_SHADOW_CASTER_RADIUS = 2.0f; static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound"); extern bool gShiftFrame; +LLTrace::MemStatHandle LLDrawable::sMemStat("LLDrawable"); //////////////////////// @@ -75,43 +77,68 @@ extern bool gShiftFrame; // // static -U32 LLDrawable::sCurVisible = 0; U32 LLDrawable::sNumZombieDrawables = 0; F32 LLDrawable::sCurPixelAngle = 0; -LLDynamicArrayPtr<LLPointer<LLDrawable> > LLDrawable::sDeadList; +LLDynamicArray<LLPointer<LLDrawable>, 32 > LLDrawable::sDeadList; #define FORCE_INVISIBLE_AREA 16.f // static void LLDrawable::incrementVisible() { - sCurVisible++; + LLViewerOctreeEntryData::incrementVisible(); sCurPixelAngle = (F32) gViewerWindow->getWindowHeightRaw()/LLViewerCamera::getInstance()->getView(); } -void LLDrawable::init() +LLDrawable::LLDrawable(LLViewerObject *vobj, bool new_entry) + : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLDRAWABLE), + mVObjp(vobj) +{ + init(new_entry); +} + +void LLDrawable::init(bool new_entry) { // mXform mParent = NULL; mRenderType = 0; mCurrentScale = LLVector3(1,1,1); mDistanceWRTCamera = 0.0f; - mPositionGroup.clear(); - mExtents[0].clear(); - mExtents[1].clear(); - mState = 0; - mVObjp = NULL; + // mFaces - mSpatialGroupp = NULL; - mVisible = sCurVisible - 2;//invisible for the current frame and the last frame. mRadius = 0.f; + mGeneration = -1; + mSpatialBridge = NULL; + + LLViewerOctreeEntry* entry = NULL; + LLVOCacheEntry* vo_entry = NULL; + if(!new_entry && mVObjp && getRegion() != NULL) + { + vo_entry = getRegion()->getCacheEntryForOctree(mVObjp->getLocalID()); + if(vo_entry) + { + entry = vo_entry->getEntry(); + } + } + setOctreeEntry(entry); + if(vo_entry) + { + if(!entry) + { + vo_entry->setOctreeEntry(mEntry); + } + else if(vo_entry->getNumOfChildren() > 0) + { + getRegion()->addVisibleCacheEntry(vo_entry); //to load all children. + } - mGeneration = -1; - mBinRadius = 1.f; - mBinIndex = -1; + getRegion()->addActiveCacheEntry(vo_entry); + } + + llassert(!vo_entry || vo_entry->getEntry() == mEntry); - mSpatialBridge = NULL; + initVisible(sCurVisible - 2);//invisible for the current frame and the last frame. } // static @@ -155,6 +182,7 @@ void LLDrawable::markDead() llwarns << "Warning! Marking dead multiple times!" << llendl; return; } + setState(DEAD); if (mSpatialBridge) { @@ -165,7 +193,6 @@ void LLDrawable::markDead() sNumZombieDrawables++; // We're dead. Free up all of our references to other objects - setState(DEAD); cleanupReferences(); // sDeadList.put(this); } @@ -219,6 +246,8 @@ void LLDrawable::cleanupReferences() gPipeline.unlinkDrawable(this); + removeFromOctree(); + { LLFastTimer t(FTM_DEREF_DRAWABLE); // Cleanup references to other objects @@ -227,6 +256,21 @@ void LLDrawable::cleanupReferences() } } +void LLDrawable::removeFromOctree() +{ + if(!mEntry) + { + return; + } + + mEntry->removeData(this); + if(mEntry->hasVOCacheEntry()) + { + getRegion()->removeActiveCacheEntry((LLVOCacheEntry*)mEntry->getVOCacheEntry(), this); + } + mEntry = NULL; +} + void LLDrawable::cleanupDeadDrawables() { /* @@ -290,7 +334,7 @@ LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerTexture *texturep) { LLFastTimer t(FTM_ALLOCATE_FACE); - face = new LLFace(this, mVObjp); + face = new LLFace(this, mVObjp); } face->setTEOffset(mFaces.size()); @@ -439,6 +483,12 @@ void LLDrawable::makeActive() } updatePartition(); } + else if (!isRoot() && !mParent->isActive()) //this should not happen, but occasionally it does... + { + mParent->makeActive(); + //NOTE: linked set will now NEVER become static + mParent->setState(LLDrawable::ACTIVE_CHILD); + } llassert(isAvatar() || isRoot() || mParent->isActive()); } @@ -455,7 +505,7 @@ void LLDrawable::makeStatic(BOOL warning_enabled) //drawable became static with active parent, not acceptable llassert(mParent.isNull() || !mParent->isActive() || !warning_enabled); - + LLViewerObject::const_child_list_t& child_list = mVObjp->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) @@ -518,7 +568,7 @@ F32 LLDrawable::updateXform(BOOL undamped) if (damped && isVisible()) { - F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f); + F32 lerp_amt = llclamp(LLSmoothInterpolation::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f); LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt); dist_squared = dist_vec_squared(new_pos, target_pos); @@ -647,7 +697,7 @@ BOOL LLDrawable::updateMove() { return FALSE; } - + makeActive(); return isState(MOVE_UNDAMPED) ? updateMoveUndamped() : updateMoveDamped(); @@ -733,7 +783,7 @@ void LLDrawable::updateDistance(LLCamera& camera, bool force_update) LLVOVolume* volume = getVOVolume(); if (volume) { - if (getSpatialGroup()) + if (getGroup()) { pos.set(getPositionGroup().getF32ptr()); } @@ -851,9 +901,7 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) } } - mExtents[0].add(shift_vector); - mExtents[1].add(shift_vector); - mPositionGroup.add(shift_vector); + shift(shift_vector); } else if (mSpatialBridge) { @@ -861,9 +909,7 @@ void LLDrawable::shiftPos(const LLVector4a &shift_vector) } else if (isAvatar()) { - mExtents[0].add(shift_vector); - mExtents[1].add(shift_vector); - mPositionGroup.add(shift_vector); + shift(shift_vector); } mVObjp->onShift(shift_vector); @@ -875,40 +921,24 @@ const LLVector3& LLDrawable::getBounds(LLVector3& min, LLVector3& max) const return mXform.getPositionW(); } -const LLVector4a* LLDrawable::getSpatialExtents() const -{ - return mExtents; -} - -void LLDrawable::setSpatialExtents(const LLVector3& min, const LLVector3& max) -{ - mExtents[0].load3(min.mV); - mExtents[1].load3(max.mV); -} - -void LLDrawable::setSpatialExtents(const LLVector4a& min, const LLVector4a& max) -{ - mExtents[0] = min; - mExtents[1] = max; -} - -void LLDrawable::setPositionGroup(const LLVector4a& pos) -{ - mPositionGroup = pos; -} - void LLDrawable::updateSpatialExtents() { if (mVObjp) { - mVObjp->updateSpatialExtents(mExtents[0], mExtents[1]); + const LLVector4a* exts = getSpatialExtents(); + LLVector4a extents[2]; + extents[0] = exts[0]; + extents[1] = exts[1]; + + mVObjp->updateSpatialExtents(extents[0], extents[1]); + setSpatialExtents(extents[0], extents[1]); } updateBinRadius(); if (mSpatialBridge.notNull()) { - mPositionGroup.splat(0.f); + getGroupPosition().splat(0.f); } } @@ -917,11 +947,11 @@ void LLDrawable::updateBinRadius() { if (mVObjp.notNull()) { - mBinRadius = llmin(mVObjp->getBinRadius(), 256.f); + setBinRadius(llmin(mVObjp->getBinRadius(), 256.f)); } else { - mBinRadius = llmin(getRadius()*4.f, 256.f); + setBinRadius(llmin(getRadius()*4.f, 256.f)); } } @@ -955,26 +985,56 @@ void LLDrawable::updateUVMinMax() { } -LLSpatialGroup* LLDrawable::getSpatialGroup() const +//virtual +bool LLDrawable::isVisible() const +{ + if (LLViewerOctreeEntryData::isVisible()) { - llassert((mSpatialGroupp == NULL) ? getBinIndex() == -1 : getBinIndex() != -1); - return mSpatialGroupp; + return true; } -void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) { - //precondition: mSpatialGroupp MUST be null or DEAD or mSpatialGroupp MUST NOT contain this - llassert(!mSpatialGroupp || mSpatialGroupp->isDead() || !mSpatialGroupp->hasElement(this)); + LLviewerOctreeGroup* group = mEntry->getGroup(); + if (group && group->isVisible()) + { + LLViewerOctreeEntryData::setVisible(); + return true; + } + } - //precondition: groupp MUST be null or groupp MUST contain this - llassert(!groupp || groupp->hasElement(this)); + return false; +} + +//virtual +bool LLDrawable::isRecentlyVisible() const +{ + //currently visible or visible in the previous frame. + bool vis = LLViewerOctreeEntryData::isRecentlyVisible(); -/*if (mSpatialGroupp && (groupp != mSpatialGroupp)) + if(!vis) { - mSpatialGroupp->setState(LLSpatialGroup::GEOM_DIRTY); - }*/ + LLviewerOctreeGroup* group = getGroup(); + if (group && group->isRecentlyVisible()) + { + LLViewerOctreeEntryData::setVisible(); + vis = TRUE ; + } + } + + return vis ; +} + +void LLDrawable::setGroup(LLviewerOctreeGroup *groupp) + { + LLSpatialGroup* cur_groupp = (LLSpatialGroup*)getGroup(); + + //precondition: mGroupp MUST be null or DEAD or mGroupp MUST NOT contain this + //llassert(!cur_groupp || cur_groupp->isDead() || !cur_groupp->hasElement(this)); + + //precondition: groupp MUST be null or groupp MUST contain this + llassert(!groupp || (LLSpatialGroup*)groupp->hasElement(this)); - if (mSpatialGroupp != groupp && getVOVolume()) + if (cur_groupp != groupp && getVOVolume()) { //NULL out vertex buffer references for volumes on spatial group change to maintain //requirement that every face vertex buffer is either NULL or points to a vertex buffer //contained by its drawable's spatial group @@ -990,10 +1050,10 @@ void LLDrawable::setSpatialGroup(LLSpatialGroup *groupp) //postcondition: if next group is NULL, previous group must be dead OR NULL OR binIndex must be -1 //postcondition: if next group is NOT NULL, binIndex must not be -1 - llassert(groupp == NULL ? (mSpatialGroupp == NULL || mSpatialGroupp->isDead()) || getBinIndex() == -1 : - getBinIndex() != -1); + //llassert(groupp == NULL ? (cur_groupp == NULL || cur_groupp->isDead()) || (!getEntry() || getEntry()->getBinIndex() == -1) : + // (getEntry() && getEntry()->getBinIndex() != -1)); - mSpatialGroupp = groupp; + LLViewerOctreeEntryData::setGroup(groupp); } LLSpatialPartition* LLDrawable::getSpatialPartition() @@ -1012,11 +1072,11 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() { if (mVObjp->isHUDAttachment()) { - setSpatialBridge(new LLHUDBridge(this)); + setSpatialBridge(new LLHUDBridge(this, getRegion())); } else { - setSpatialBridge(new LLVolumeBridge(this)); + setSpatialBridge(new LLVolumeBridge(this, getRegion())); } } return mSpatialBridge->asPartition(); @@ -1035,89 +1095,26 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() return retval; } -const S32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one. -//static -S32 LLDrawable::getMinVisFrameRange() -{ - return MIN_VIS_FRAME_RANGE ; -} - -BOOL LLDrawable::isRecentlyVisible() const +//virtual +S32 LLDrawable::getMinFrameRange() const { - //currently visible or visible in the previous frame. - BOOL vis = isVisible() || (sCurVisible - mVisible < MIN_VIS_FRAME_RANGE) ; - - if(!vis) - { - LLSpatialGroup* group = getSpatialGroup(); - if (group && group->isRecentlyVisible()) - { - mVisible = sCurVisible; - vis = TRUE ; - } - } - - return vis ; -} - -BOOL LLDrawable::isVisible() const -{ - if (mVisible == sCurVisible) - { - return TRUE; - } - -#if 0 - //disabling this code fixes DEV-20105. Leaving in place in case some other bug pops up as a a result. - //should be safe to just always ask the spatial group for visibility. - if (isActive()) - { - if (isRoot()) - { - LLSpatialGroup* group = mSpatialBridge.notNull() ? mSpatialBridge->getSpatialGroup() : - getSpatialGroup(); - if (group && group->isVisible()) - { - mVisible = sCurVisible; - return TRUE; - } - } - else - { - if (getParent()->isVisible()) - { - mVisible = sCurVisible; - return TRUE; - } - } - } - else -#endif - { - LLSpatialGroup* group = getSpatialGroup(); - if (group && group->isVisible()) - { - mVisible = sCurVisible; - return TRUE; - } - } +const S32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one. - return FALSE; + return MIN_VIS_FRAME_RANGE ; } //======================================= // Spatial Partition Bridging Drawable //======================================= -LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask) -: LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB) +LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 data_mask, LLViewerRegion* regionp) : + LLDrawable(root->getVObj(), true), + LLSpatialPartition(data_mask, render_by_group, GL_STREAM_DRAW_ARB, regionp) { mBridge = this; mDrawable = root; root->setSpatialBridge(this); - mBinIndex = -1; - mRenderType = mDrawable->mRenderType; mDrawableType = mDrawable->mRenderType; @@ -1138,10 +1135,13 @@ LLSpatialBridge::LLSpatialBridge(LLDrawable* root, BOOL render_by_group, U32 dat LLSpatialBridge::~LLSpatialBridge() { + if(mEntry) + { LLSpatialGroup* group = getSpatialGroup(); if (group) { - group->mSpatialPartition->remove(this, group); + group->getSpatialPartition()->remove(this, group); + } } //delete octree here so listeners will still be able to access bridge specific state @@ -1163,8 +1163,9 @@ void LLSpatialBridge::updateSpatialExtents() root->rebound(); } + const LLVector4a* root_bounds = root->getBounds(); LLVector4a offset; - LLVector4a size = root->mBounds[1]; + LLVector4a size = root_bounds[1]; //VECTORIZE THIS LLMatrix4a mat; @@ -1176,7 +1177,7 @@ void LLSpatialBridge::updateSpatialExtents() LLVector4a center; mat.affineTransform(t, center); - mat.rotate(root->mBounds[0], offset); + mat.rotate(root_bounds[0], offset); center.add(offset); LLVector4a v[4]; @@ -1198,12 +1199,9 @@ void LLSpatialBridge::updateSpatialExtents() scale.mul(size); mat.rotate(scale, v[3]); - - LLVector4a& newMin = mExtents[0]; - LLVector4a& newMax = mExtents[1]; - + LLVector4a newMin; + LLVector4a newMax; newMin = newMax = center; - for (U32 i = 0; i < 4; i++) { LLVector4a delta; @@ -1216,19 +1214,21 @@ void LLSpatialBridge::updateSpatialExtents() newMin.setMin(newMin, min); newMax.setMax(newMax, max); } + setSpatialExtents(newMin, newMax); LLVector4a diagonal; diagonal.setSub(newMax, newMin); mRadius = diagonal.getLength3().getF32() * 0.5f; - mPositionGroup.setAdd(newMin,newMax); - mPositionGroup.mul(0.5f); + LLVector4a& pos = getGroupPosition(); + pos.setAdd(newMin,newMax); + pos.mul(0.5f); updateBinRadius(); } void LLSpatialBridge::updateBinRadius() { - mBinRadius = llmin( mOctree->getSize()[0]*0.5f, 256.f); + setBinRadius(llmin( mOctree->getSize()[0]*0.5f, 256.f)); } LLCamera LLSpatialBridge::transformCamera(LLCamera& camera) @@ -1262,7 +1262,7 @@ LLCamera LLSpatialBridge::transformCamera(LLCamera& camera) void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results, BOOL for_select) { - mVisible = sCurVisible; + LLViewerOctreeEntryData::setVisible(); #if 0 && !LL_RELEASE_FOR_DOWNLOAD //crazy paranoid rules checking @@ -1297,21 +1297,21 @@ void LLDrawable::setVisible(LLCamera& camera, std::vector<LLDrawable*>* results, #endif } -class LLOctreeMarkNotCulled: public LLOctreeTraveler<LLDrawable> +class LLOctreeMarkNotCulled: public OctreeTraveler { public: LLCamera* mCamera; LLOctreeMarkNotCulled(LLCamera* camera_in) : mCamera(camera_in) { } - virtual void traverse(const LLOctreeNode<LLDrawable>* node) + virtual void traverse(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); group->setVisible(); - LLOctreeTraveler<LLDrawable>::traverse(node); + OctreeTraveler::traverse(node); } - void visit(const LLOctreeNode<LLDrawable>* branch) + void visit(const OctreeNode* branch) { gPipeline.markNotCulled((LLSpatialGroup*) branch->getListener(0), *mCamera); } @@ -1355,7 +1355,7 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* } if (!group || - LLDrawable::getCurrentFrame() - av->mVisible > 1 || + LLDrawable::getCurrentFrame() - av->getVisible() > 1 || impostor || !loaded) { @@ -1369,16 +1369,17 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* group->rebound(); LLVector4a center; - center.setAdd(mExtents[0], mExtents[1]); + const LLVector4a* exts = getSpatialExtents(); + center.setAdd(exts[0], exts[1]); center.mul(0.5f); LLVector4a size; - size.setSub(mExtents[1], mExtents[0]); + size.setSub(exts[1], exts[0]); size.mul(0.5f); if ((LLPipeline::sShadowRender && camera_in.AABBInFrustum(center, size)) || LLPipeline::sImpostorRender || (camera_in.AABBInFrustumNoFarClip(center, size) && - AABBSphereIntersect(mExtents[0], mExtents[1], camera_in.getOrigin(), camera_in.mFrustumCornerDist))) + AABBSphereIntersect(exts[0], exts[1], camera_in.getOrigin(), camera_in.mFrustumCornerDist))) { if (!LLPipeline::sImpostorRender && !LLPipeline::sShadowRender && @@ -1493,9 +1494,7 @@ BOOL LLSpatialBridge::updateMove() void LLSpatialBridge::shiftPos(const LLVector4a& vec) { - mExtents[0].add(vec); - mExtents[1].add(vec); - mPositionGroup.add(vec); + LLDrawable::shift(vec); } void LLSpatialBridge::cleanupReferences() @@ -1503,11 +1502,8 @@ void LLSpatialBridge::cleanupReferences() LLDrawable::cleanupReferences(); if (mDrawable) { - /* - - DON'T DO THIS -- this should happen through octree destruction + mDrawable->setGroup(NULL); - mDrawable->setSpatialGroup(NULL); if (mDrawable->getVObj()) { LLViewerObject::const_child_list_t& child_list = mDrawable->getVObj()->getChildren(); @@ -1518,10 +1514,10 @@ void LLSpatialBridge::cleanupReferences() LLDrawable* drawable = child->mDrawable; if (drawable) { - drawable->setSpatialGroup(NULL); + drawable->setGroup(NULL); + } } } - }*/ LLDrawable* drawablep = mDrawable; mDrawable = NULL; @@ -1590,8 +1586,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_AVATAR; mPartitionType = LLViewerRegion::PARTITION_BRIDGE; @@ -1599,8 +1595,8 @@ LLBridgePartition::LLBridgePartition() mSlopRatio = 0.25f; } -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/lldrawable.h b/indra/newview/lldrawable.h index 4420a34fae..98f0b51a97 100755 --- a/indra/newview/lldrawable.h +++ b/indra/newview/lldrawable.h @@ -42,6 +42,7 @@ #include "llviewerobject.h" #include "llrect.h" #include "llappviewer.h" // for gFrameTimeSeconds +#include "llvieweroctree.h" class LLCamera; class LLDrawPool; @@ -59,10 +60,12 @@ const U32 SILHOUETTE_HIGHLIGHT = 0; // All data for new renderer goes into this class. LL_ALIGN_PREFIX(16) -class LLDrawable : public LLRefCount +class LLDrawable +: public LLViewerOctreeEntryData, + public LLTrace::MemTrackable<LLDrawable> { public: - LLDrawable(const LLDrawable& rhs) + LLDrawable(const LLDrawable& rhs) : LLViewerOctreeEntryData(rhs) { *this = rhs; } @@ -75,17 +78,7 @@ public: static void initClass(); - void* operator new(size_t size) - { - return ll_aligned_malloc_16(size); - } - - void operator delete(void* ptr) - { - ll_aligned_free_16(ptr); - } - - LLDrawable() { init(); } + LLDrawable(LLViewerObject *vobj, bool new_entry = false); void markDead(); // Mark this drawable as dead BOOL isDead() const { return isState(DEAD); } @@ -93,11 +86,9 @@ public: BOOL isLight() const; - BOOL isVisible() const; - BOOL isRecentlyVisible() const; virtual void setVisible(LLCamera& camera_in, std::vector<LLDrawable*>* results = NULL, BOOL for_select = FALSE); - + LLSpatialGroup* getSpatialGroup()const {return (LLSpatialGroup*)getGroup();} LLViewerRegion* getRegion() const { return mVObjp->getRegion(); } const LLTextureEntry* getTextureEntry(U8 which) const { return mVObjp->getTE(which); } LLPointer<LLViewerObject>& getVObj() { return mVObjp; } @@ -110,16 +101,12 @@ public: const LLVector3& getPosition() const { return mXform.getPosition(); } const LLVector3& getWorldPosition() const { return mXform.getPositionW(); } const LLVector3 getPositionAgent() const; - const LLVector4a& getPositionGroup() const { return mPositionGroup; } const LLVector3& getScale() const { return mCurrentScale; } void setScale(const LLVector3& scale) { mCurrentScale = scale; } const LLQuaternion& getWorldRotation() const { return mXform.getWorldRotation(); } const LLQuaternion& getRotation() const { return mXform.getRotation(); } F32 getIntensity() const { return llmin(mXform.getScale().mV[0], 4.f); } S32 getLOD() const { return mVObjp ? mVObjp->getLOD() : 1; } - F32 getBinRadius() const { return mBinRadius; } - S32 getBinIndex() const { return mBinIndex; } - void setBinIndex(S32 index) const { mBinIndex = index; } void getMinMax(LLVector3& min,LLVector3& max) const { mXform.getMinMax(min,max); } LLXformMatrix* getXform() { return &mXform; } @@ -150,7 +137,7 @@ public: void setNumFacesFast(const S32 numFaces, LLFacePool *poolp, LLViewerTexture *texturep); void mergeFaces(LLDrawable* src); - void init(); + void init(bool new_entry); void destroy(); void update(); @@ -181,8 +168,12 @@ public: BOOL getLit() const { return isState(UNLIT) ? FALSE : TRUE; } void setLit(BOOL lit) { lit ? clearState(UNLIT) : setState(UNLIT); } + bool isVisible() const; + bool isRecentlyVisible() const; + virtual void cleanupReferences(); + void setGroup(LLviewerOctreeGroup* group); void setRadius(const F32 radius); F32 getRadius() const { return mRadius; } F32 getVisibilityRadius() const; @@ -192,11 +183,6 @@ public: const LLVector3& getBounds(LLVector3& min, LLVector3& max) const; virtual void updateSpatialExtents(); virtual void updateBinRadius(); - const LLVector4a* getSpatialExtents() const; - void setSpatialExtents(const LLVector3& min, const LLVector3& max); - void setSpatialExtents(const LLVector4a& min, const LLVector4a& max); - - void setPositionGroup(const LLVector4a& pos); void setRenderType(S32 type) { mRenderType = type; } BOOL isRenderType(S32 type) { return mRenderType == type; } @@ -205,10 +191,14 @@ public: // Debugging methods S32 findReferences(LLDrawable *drawablep); // Not const because of @#$! iterators... - void setSpatialGroup(LLSpatialGroup *groupp); - LLSpatialGroup *getSpatialGroup() const; LLSpatialPartition* getSpatialPartition(); + virtual S32 getMinFrameRange()const; + void removeFromOctree(); + + void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; } + LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; } + // Statics static void incrementVisible(); static void cleanupDeadDrawables(); @@ -292,10 +282,6 @@ public: ACTIVE_CHILD = 0x40000000, } EDrawableFlags; -private: //aligned members - LL_ALIGN_16(LLVector4a mExtents[2]); - LL_ALIGN_16(LLVector4a mPositionGroup); - public: LLXformMatrix mXform; @@ -304,13 +290,8 @@ public: F32 mDistanceWRTCamera; - static S32 getCurrentFrame() { return sCurVisible; } - static S32 getMinVisFrameRange(); - - void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; } - LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; } - static F32 sCurPixelAngle; //current pixels per radian + static LLTrace::MemStatHandle sMemStat; private: typedef std::vector<LLFace*> face_list_t; @@ -319,21 +300,15 @@ private: S32 mRenderType; LLPointer<LLViewerObject> mVObjp; face_list_t mFaces; - LLSpatialGroup* mSpatialGroupp; LLPointer<LLDrawable> mSpatialBridge; - mutable U32 mVisible; F32 mRadius; - F32 mBinRadius; - mutable S32 mBinIndex; S32 mGeneration; LLVector3 mCurrentScale; - static U32 sCurVisible; // Counter for what value of mVisible means currently visible - static U32 sNumZombieDrawables; - static LLDynamicArrayPtr<LLPointer<LLDrawable> > sDeadList; + static LLDynamicArray<LLPointer<LLDrawable>, 32> sDeadList; } LL_ALIGN_POSTFIX(16); diff --git a/indra/newview/lldrawpoolalpha.cpp b/indra/newview/lldrawpoolalpha.cpp index 313b310e1e..7020db917b 100755 --- a/indra/newview/lldrawpoolalpha.cpp +++ b/indra/newview/lldrawpoolalpha.cpp @@ -351,7 +351,7 @@ void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask) for (LLCullResult::sg_iterator i = gPipeline.beginAlphaGroups(); i != gPipeline.endAlphaGroups(); ++i) { LLSpatialGroup* group = *i; - if (group->mSpatialPartition->mRenderByGroup && + if (group->getSpatialPartition()->mRenderByGroup && !group->isDead()) { LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; @@ -389,15 +389,15 @@ void LLDrawPoolAlpha::renderAlpha(U32 mask) { LLSpatialGroup* group = *i; llassert(group); - llassert(group->mSpatialPartition); + llassert(group->getSpatialPartition()); - if (group->mSpatialPartition->mRenderByGroup && + if (group->getSpatialPartition()->mRenderByGroup && !group->isDead()) { bool draw_glow_for_this_partition = mVertexShaderLevel > 0 && // no shaders = no glow. // All particle systems seem to come off the wire with texture entries which claim that they glow. This is probably a bug in the data. Suppress. - group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_PARTICLE && - group->mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE; + group->getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_PARTICLE && + group->getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_HUD_PARTICLE; LLSpatialGroup::drawmap_elem_t& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; diff --git a/indra/newview/lldrawpoolavatar.cpp b/indra/newview/lldrawpoolavatar.cpp index 294cecc703..67dbe6de8b 100755 --- a/indra/newview/lldrawpoolavatar.cpp +++ b/indra/newview/lldrawpoolavatar.cpp @@ -421,7 +421,7 @@ void LLDrawPoolAvatar::renderShadow(S32 pass) if (pass == 0) { - avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); + avatarp->renderSkinned(); } else { @@ -1246,7 +1246,7 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) if( !single_avatar || (avatarp == single_avatar) ) { - avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); + avatarp->renderSkinned(); } } diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp index 5ddc15df42..9a5743919d 100755 --- a/indra/newview/lldrawpoolwater.cpp +++ b/indra/newview/lldrawpoolwater.cpp @@ -463,7 +463,7 @@ void LLDrawPoolWater::renderReflection(LLFace* face) gGL.getTexUnit(0)->bind(mHBTex[dr]); - LLOverrideFaceColor override(this, face->getFaceColor().mV); + LLOverrideFaceColor override(this, LLColor4(face->getFaceColor().mV)); face->renderIndexed(); } diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp index 281f852b0a..98c75a64c7 100755 --- a/indra/newview/llface.cpp +++ b/indra/newview/llface.cpp @@ -2346,8 +2346,6 @@ F32 LLFace::calcImportanceToCamera(F32 cos_angle_to_view_dir, F32 dist) return 0.f ; } - //F32 camera_relative_speed = camera_moving_speed * (lookAt * LLViewerCamera::getInstance()->getVelocityDir()) ; - S32 i = 0 ; for(i = 0; i < FACE_IMPORTANCE_LEVEL && dist > FACE_IMPORTANCE_TO_CAMERA_OVER_DISTANCE[i][0]; ++i); i = llmin(i, FACE_IMPORTANCE_LEVEL - 1) ; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index de4d03351c..dda4bc9b3c 100755 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -28,7 +28,6 @@ #define LL_LLFACE_H #include "llstrider.h" - #include "llrender.h" #include "v2math.h" #include "v3math.h" @@ -37,7 +36,6 @@ #include "v4coloru.h" #include "llquaternion.h" #include "xform.h" -#include "lldarrayptr.h" #include "llvertexbuffer.h" #include "llviewertexture.h" #include "lldrawable.h" @@ -47,10 +45,8 @@ class LLFacePool; class LLVolume; class LLViewerTexture; class LLTextureEntry; -class LLVertexProgram; -class LLViewerTexture; -class LLGeometryManager; class LLTextureAtlasSlot; +class LLDrawInfo; const F32 MIN_ALPHA_SIZE = 1024.f; const F32 MIN_TEX_ANIM_SIZE = 512.f; @@ -262,11 +258,11 @@ public: LLVector2 mTexExtents[2]; F32 mDistance; - F32 mLastUpdateTime; - F32 mLastSkinTime; - F32 mLastMoveTime; - LLMatrix4* mTextureMatrix; - LLDrawInfo* mDrawInfo; + F32 mLastUpdateTime; + F32 mLastSkinTime; + F32 mLastMoveTime; + LLMatrix4* mTextureMatrix; + LLDrawInfo* mDrawInfo; private: LLPointer<LLVertexBuffer> mVertexBuffer; diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index fbf72b1a85..40526d3357 100755 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -46,7 +46,6 @@ #include "llviewertexturelist.h" #include "llui.h" #include "llviewercontrol.h" -#include "llstat.h" #include "llfasttimer.h" #include "lltreeiterators.h" @@ -55,24 +54,23 @@ ////////////////////////////////////////////////////////////////////////////// +using namespace LLTrace; + static const S32 MAX_VISIBLE_HISTORY = 10; static const S32 LINE_GRAPH_HEIGHT = 240; +static const S32 MIN_BAR_HEIGHT = 3; -//static const int FTV_DISPLAY_NUM = (sizeof(ft_display_table)/sizeof(ft_display_table[0])); -static S32 FTV_NUM_TIMERS; -const S32 FTV_MAX_DEPTH = 8; - -std::vector<LLFastTimer::NamedTimer*> ft_display_idx; // line of table entry for display purposes (for collapse) +std::vector<TimeBlock*> ft_display_idx; // line of table entry for display purposes (for collapse) -typedef LLTreeDFSIter<LLFastTimer::NamedTimer, LLFastTimer::NamedTimer::child_const_iter> timer_tree_iterator_t; +typedef LLTreeDFSIter<TimeBlock, TimeBlock::child_const_iter> timer_tree_iterator_t; BOOL LLFastTimerView::sAnalyzePerformance = FALSE; -static timer_tree_iterator_t begin_timer_tree(LLFastTimer::NamedTimer& id) +static timer_tree_iterator_t begin_timer_tree(TimeBlock& id) { return timer_tree_iterator_t(&id, - boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::beginChildren), _1), - boost::bind(boost::mem_fn(&LLFastTimer::NamedTimer::endChildren), _1)); + boost::bind(boost::mem_fn(&TimeBlock::beginChildren), _1), + boost::bind(boost::mem_fn(&TimeBlock::endChildren), _1)); } static timer_tree_iterator_t end_timer_tree() @@ -80,37 +78,74 @@ static timer_tree_iterator_t end_timer_tree() return timer_tree_iterator_t(); } +S32 get_depth(const TimeBlock* blockp) +{ + S32 depth = 0; + TimeBlock* timerp = blockp->getParent(); + while(timerp) + { + depth++; + if (timerp->getParent() == timerp) break; + timerp = timerp->getParent(); + } + return depth; +} + LLFastTimerView::LLFastTimerView(const LLSD& key) : LLFloater(key), - mHoverTimer(NULL) + mHoverTimer(NULL), + mDisplayMode(0), + mDisplayCenter(ALIGN_CENTER), + mDisplayCalls(false), + mDisplayHz(false), + mScrollIndex(0), + mHoverID(NULL), + mHoverBarIndex(-1), + mPrintStats(-1), + mRecording(&get_frame_recording()), + mPauseHistory(false) { - mDisplayMode = 0; - mAvgCountTotal = 0; - mMaxCountTotal = 0; - mDisplayCenter = ALIGN_CENTER; - mDisplayCalls = 0; - mDisplayHz = 0; - mScrollIndex = 0; - mHoverID = NULL; - mHoverBarIndex = -1; - FTV_NUM_TIMERS = LLFastTimer::NamedTimer::instanceCount(); - mPrintStats = -1; + mTimerBars = new std::vector<TimerBar>[MAX_VISIBLE_HISTORY + 1]; +} + +LLFastTimerView::~LLFastTimerView() +{ + if (mRecording != &get_frame_recording()) + { + delete mRecording; + } + mRecording = NULL; + delete [] mTimerBars; } void LLFastTimerView::onPause() { - LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory; + setPauseState(!mPauseHistory); +} + +void LLFastTimerView::setPauseState(bool pause_state) +{ + if (pause_state == mPauseHistory) return; + // reset scroll to bottom when unpausing - if (!LLFastTimer::sPauseHistory) + if (!pause_state) { - mScrollIndex = 0; - LLFastTimer::sResetHistory = true; + if (mRecording != &get_frame_recording()) + { + delete mRecording; + } + mRecording = &get_frame_recording(); getChild<LLButton>("pause_btn")->setLabel(getString("pause")); } else { + mRecording = new PeriodicRecording(get_frame_recording()); + mScrollIndex = 0; + getChild<LLButton>("pause_btn")->setLabel(getString("run")); } + + mPauseHistory = pause_state; } BOOL LLFastTimerView::postBuild() @@ -140,15 +175,15 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask) { S32 bar_idx = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight()); bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY); - mPrintStats = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - bar_idx; + mPrintStats = mScrollIndex + bar_idx; return TRUE; } return LLFloater::handleRightMouseDown(x, y, mask); } -LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y) +TimeBlock* LLFastTimerView::getLegendID(S32 y) { - S32 idx = (getRect().getHeight() - y) / (LLFontGL::getFontMonospace()->getLineHeight()+2) - 5; + S32 idx = (mBarRect.mTop - y) / (LLFontGL::getFontMonospace()->getLineHeight()+2) - 1; if (idx >= 0 && idx < (S32)ft_display_idx.size()) { @@ -160,7 +195,7 @@ LLFastTimer::NamedTimer* LLFastTimerView::getLegendID(S32 y) BOOL LLFastTimerView::handleDoubleClick(S32 x, S32 y, MASK mask) { - for(timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); + for(timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); it != end_timer_tree(); ++it) { @@ -173,7 +208,7 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) { if (x < mBarRect.mLeft) { - LLFastTimer::NamedTimer* idp = getLegendID(y); + TimeBlock* idp = getLegendID(y); if (idp) { idp->setCollapsed(!idp->getCollapsed()); @@ -209,16 +244,7 @@ BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask) gFocusMgr.setMouseCapture(this); return TRUE; } - //else - //{ - // // pause/unpause - // LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory; - // // reset scroll to bottom when unpausing - // if (!LLFastTimer::sPauseHistory) - // { - // mScrollIndex = 0; - // } - //} + return LLFloater::handleMouseDown(x, y, mask); } @@ -236,17 +262,18 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) if (hasMouseCapture()) { F32 lerp = llclamp(1.f - (F32) (x - mGraphRect.mLeft) / (F32) mGraphRect.getWidth(), 0.f, 1.f); - mScrollIndex = llround( lerp * (F32)(LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY)); - mScrollIndex = llclamp( mScrollIndex, 0, LLFastTimer::getLastFrameIndex()); + mScrollIndex = llround( lerp * (F32)(mRecording->getNumPeriods() - MAX_VISIBLE_HISTORY)); + mScrollIndex = llclamp( mScrollIndex, 0, (S32)mRecording->getNumPeriods()); return TRUE; } mHoverTimer = NULL; mHoverID = NULL; - if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y)) + if(mPauseHistory && mBarRect.pointInRect(x, y)) { - mHoverBarIndex = llmin(LLFastTimer::getCurFrameIndex() - 1, - MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight())); + mHoverBarIndex = llmin((mBarRect.mTop - y) / (mBarRect.getHeight() / (MAX_VISIBLE_HISTORY + 2)) - 1, + (S32)mRecording->getNumPeriods() - 1, + MAX_VISIBLE_HISTORY); if (mHoverBarIndex == 0) { return TRUE; @@ -257,13 +284,12 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) } S32 i = 0; - for(timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); + for(timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); it != end_timer_tree(); ++it, ++i) { // is mouse over bar for this timer? - if (x > mBarStart[mHoverBarIndex][i] && - x < mBarEnd[mHoverBarIndex][i]) + if (mTimerBars[mHoverBarIndex][i].mVisibleRect.pointInRect(x, y)) { mHoverID = (*it); if (mHoverTimer != *it) @@ -275,10 +301,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) mHoverTimer = (*it); } - mToolTipRect.set(mBarStart[mHoverBarIndex][i], - mBarRect.mBottom + llround(((F32)(MAX_VISIBLE_HISTORY - mHoverBarIndex + 1)) * ((F32)mBarRect.getHeight() / ((F32)MAX_VISIBLE_HISTORY + 2.f))), - mBarEnd[mHoverBarIndex][i], - mBarRect.mBottom + llround((F32)(MAX_VISIBLE_HISTORY - mHoverBarIndex) * ((F32)mBarRect.getHeight() / ((F32)MAX_VISIBLE_HISTORY + 2.f)))); + mToolTipRect = mTimerBars[mHoverBarIndex][i].mVisibleRect; } if ((*it)->getCollapsed()) @@ -289,7 +312,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) } else if (x < mBarRect.mLeft) { - LLFastTimer::NamedTimer* timer_id = getLegendID(y); + TimeBlock* timer_id = getLegendID(y); if (timer_id) { mHoverID = timer_id; @@ -300,9 +323,24 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) } +static std::string get_tooltip(TimeBlock& timer, S32 history_index, PeriodicRecording& frame_recording) +{ + std::string tooltip; + if (history_index == 0) + { + // by default, show average number of call + tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit<LLUnits::Milliseconds, F64>(frame_recording.getPeriodMean(timer)).value(), (S32)frame_recording.getPeriodMean(timer.callCount())); + } + else + { + tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit<LLUnits::Milliseconds, F64>(frame_recording.getPrevRecording(history_index).getSum(timer)).value(), (S32)frame_recording.getPrevRecording(history_index).getSum(timer.callCount())); + } + return tooltip; +} + BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask) { - if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y)) + if(mPauseHistory && mBarRect.pointInRect(x, y)) { // tooltips for timer bars if (mHoverTimer) @@ -310,8 +348,10 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask) LLRect screen_rect; localRectToScreen(mToolTipRect, &screen_rect); + std::string tooltip = get_tooltip(*mHoverTimer, mHoverBarIndex > 0 ? mScrollIndex + mHoverBarIndex : 0, *mRecording); + LLToolTipMgr::instance().show(LLToolTip::Params() - .message(mHoverTimer->getToolTip(LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex)) + .message(tooltip) .sticky_rect(screen_rect) .delay_time(0.f)); @@ -323,10 +363,10 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask) // tooltips for timer legend if (x < mBarRect.mLeft) { - LLFastTimer::NamedTimer* idp = getLegendID(y); + TimeBlock* idp = getLegendID(y); if (idp) { - LLToolTipMgr::instance().show(idp->getToolTip()); + LLToolTipMgr::instance().show(get_tooltip(*idp, 0, *mRecording)); return TRUE; } @@ -338,705 +378,48 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask) BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks) { - LLFastTimer::sPauseHistory = TRUE; + setPauseState(true); mScrollIndex = llclamp( mScrollIndex + clicks, 0, - llmin(LLFastTimer::getLastFrameIndex(), (S32)LLFastTimer::NamedTimer::HISTORY_NUM - MAX_VISIBLE_HISTORY)); + llmin((S32)mRecording->getNumPeriods(), (S32)mRecording->getNumPeriods() - MAX_VISIBLE_HISTORY)); return TRUE; } -static LLFastTimer::DeclareTimer FTM_RENDER_TIMER("Timers", true); +static TimeBlock FTM_RENDER_TIMER("Timers", true); +static const S32 MARGIN = 10; +static const S32 LEGEND_WIDTH = 220; -static std::map<LLFastTimer::NamedTimer*, LLColor4> sTimerColors; +static std::map<TimeBlock*, LLColor4> sTimerColors; void LLFastTimerView::draw() { LLFastTimer t(FTM_RENDER_TIMER); - std::string tdesc; - - F64 clock_freq = (F64)LLFastTimer::countsPerSecond(); - F64 iclock_freq = 1000.0 / clock_freq; - - S32 margin = 10; - S32 height = getRect().getHeight(); - S32 width = getRect().getWidth(); - - LLRect new_rect; - new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); - setRect(new_rect); - - S32 left, top, right, bottom; - S32 x, y, barw, barh, dx, dy; - S32 texth; - LLPointer<LLUIImage> box_imagep = LLUI::getUIImage("Rounded_Square"); + generateUniqueColors(); // Draw the window background gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); - - S32 xleft = margin; - S32 ytop = margin; + gl_rect_2d(getLocalRect(), LLColor4(0.f, 0.f, 0.f, 0.25f)); - // Draw some help - { - - x = xleft; - y = height - ytop; - texth = (S32)LLFontGL::getFontMonospace()->getLineHeight(); - - char modedesc[][32] = { - "2 x Average ", - "Max ", - "Recent Max ", - "100 ms " - }; - char centerdesc[][32] = { - "Left ", - "Centered ", - "Ordered " - }; - - tdesc = llformat("Full bar = %s [Click to pause/reset] [SHIFT-Click to toggle]",modedesc[mDisplayMode]); - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); - - x = xleft, y -= (texth + 2); - tdesc = llformat("Justification = %s [CTRL-Click to toggle]",centerdesc[mDisplayCenter]); - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); - y -= (texth + 2); - - LLFontGL::getFontMonospace()->renderUTF8(std::string("[Right-Click log selected] [ALT-Click toggle counts] [ALT-SHIFT-Click sub hidden]"), - 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); - y -= (texth + 2); - } - - S32 histmax = llmin(LLFastTimer::getLastFrameIndex()+1, MAX_VISIBLE_HISTORY); - - // Draw the legend - xleft = margin; - ytop = y; - - y -= (texth + 2); - - sTimerColors[&getFrameTimer()] = LLColor4::grey; - - F32 hue = 0.f; - - for (timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); - it != timer_tree_iterator_t(); - ++it) - { - LLFastTimer::NamedTimer* idp = (*it); - - const F32 HUE_INCREMENT = 0.23f; - hue = fmodf(hue + HUE_INCREMENT, 1.f); - // saturation increases with depth - F32 saturation = clamp_rescale((F32)idp->getDepth(), 0.f, 3.f, 0.f, 1.f); - // lightness alternates with depth - F32 lightness = idp->getDepth() % 2 ? 0.5f : 0.6f; - - LLColor4 child_color; - child_color.setHSL(hue, saturation, lightness); - - sTimerColors[idp] = child_color; - } - - const S32 LEGEND_WIDTH = 220; - { - LLLocalClipRect clip(LLRect(margin, y, LEGEND_WIDTH, margin)); - S32 cur_line = 0; - ft_display_idx.clear(); - std::map<LLFastTimer::NamedTimer*, S32> display_line; - for (timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); - it != timer_tree_iterator_t(); - ++it) - { - LLFastTimer::NamedTimer* idp = (*it); - display_line[idp] = cur_line; - ft_display_idx.push_back(idp); - cur_line++; - - x = xleft; - - left = x; right = x + texth; - top = y; bottom = y - texth; - S32 scale_offset = 0; - if (idp == mHoverID) - { - scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f); - } - gl_rect_2d(left - scale_offset, top + scale_offset, right + scale_offset, bottom - scale_offset, sTimerColors[idp]); - - F32 ms = 0; - S32 calls = 0; - if (mHoverBarIndex > 0 && mHoverID) - { - S32 hidx = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex - mHoverBarIndex; - U64 ticks = idp->getHistoricalCount(hidx); - ms = (F32)((F64)ticks * iclock_freq); - calls = (S32)idp->getHistoricalCalls(hidx); - } - else - { - U64 ticks = idp->getCountAverage(); - ms = (F32)((F64)ticks * iclock_freq); - calls = (S32)idp->getCallAverage(); - } - - if (mDisplayCalls) - { - tdesc = llformat("%s (%d)",idp->getName().c_str(),calls); - } - else - { - tdesc = llformat("%s [%.1f]",idp->getName().c_str(),ms); - } - dx = (texth+4) + idp->getDepth()*8; - - LLColor4 color = LLColor4::white; - if (idp->getDepth() > 0) - { - S32 line_start_y = (top + bottom) / 2; - S32 line_end_y = line_start_y + ((texth + 2) * (cur_line - display_line[idp->getParent()])) - texth; - gl_line_2d(x + dx - 8, line_start_y, x + dx, line_start_y, color); - S32 line_x = x + (texth + 4) + ((idp->getDepth() - 1) * 8); - gl_line_2d(line_x, line_start_y, line_x, line_end_y, color); - if (idp->getCollapsed() && !idp->getChildren().empty()) - { - gl_line_2d(line_x+4, line_start_y-3, line_x+4, line_start_y+4, color); - } - } - - x += dx; - BOOL is_child_of_hover_item = (idp == mHoverID); - LLFastTimer::NamedTimer* next_parent = idp->getParent(); - while(!is_child_of_hover_item && next_parent) - { - is_child_of_hover_item = (mHoverID == next_parent); - if (next_parent->getParent() == next_parent) break; - next_parent = next_parent->getParent(); - } - - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, - x, y, - color, - LLFontGL::LEFT, LLFontGL::TOP, - is_child_of_hover_item ? LLFontGL::BOLD : LLFontGL::NORMAL); - - y -= (texth + 2); - - if (idp->getCollapsed()) - { - it.skipDescendants(); - } - } - } - - xleft += LEGEND_WIDTH + 8; - // ytop = ytop; + S32 y = drawHelp(getRect().getHeight() - MARGIN); + drawLegend(y - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 2)); // update rectangle that includes timer bars - mBarRect.mLeft = xleft; - mBarRect.mRight = getRect().getWidth(); - mBarRect.mTop = ytop - (LLFontGL::getFontMonospace()->getLineHeight() + 4); - mBarRect.mBottom = margin + LINE_GRAPH_HEIGHT; - - y = ytop; - barh = (ytop - margin - LINE_GRAPH_HEIGHT) / (MAX_VISIBLE_HISTORY + 2); - dy = barh>>2; // spacing between bars - if (dy < 1) dy = 1; - barh -= dy; - barw = width - xleft - margin; - - // Draw the history bars - if (LLFastTimer::getLastFrameIndex() >= 0) - { - LLLocalClipRect clip(LLRect(xleft, ytop, getRect().getWidth() - margin, margin)); - - U64 totalticks; - if (!LLFastTimer::sPauseHistory) - { - U64 ticks = getFrameTimer().getHistoricalCount(mScrollIndex); - - if (LLFastTimer::getCurFrameIndex() >= 10) - { - U64 framec = LLFastTimer::getCurFrameIndex(); - U64 avg = (U64)mAvgCountTotal; - mAvgCountTotal = (avg*framec + ticks) / (framec + 1); - if (ticks > mMaxCountTotal) - { - mMaxCountTotal = ticks; - } - } - - if (ticks < mAvgCountTotal/100 || ticks > mAvgCountTotal*100) - { - LLFastTimer::sResetHistory = true; - } - - if (LLFastTimer::getCurFrameIndex() < 10 || LLFastTimer::sResetHistory) - { - mAvgCountTotal = ticks; - mMaxCountTotal = ticks; - LLFastTimer::sResetHistory = false; - } - } - - if (mDisplayMode == 0) - { - totalticks = mAvgCountTotal*2; - } - else if (mDisplayMode == 1) - { - totalticks = mMaxCountTotal; - } - else if (mDisplayMode == 2) - { - // Calculate the max total ticks for the current history - totalticks = 0; - for (S32 j=0; j<histmax; j++) - { - U64 ticks = getFrameTimer().getHistoricalCount(j); - - if (ticks > totalticks) - totalticks = ticks; - } - } - else - { - totalticks = (U64)(clock_freq * .1); // 100 ms - } - - // Draw MS ticks - { - U32 ms = (U32)((F64)totalticks * iclock_freq) ; - - tdesc = llformat("%.1f ms |", (F32)ms*.25f); - x = xleft + barw/4 - LLFontGL::getFontMonospace()->getWidth(tdesc); - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, - LLFontGL::LEFT, LLFontGL::TOP); - - tdesc = llformat("%.1f ms |", (F32)ms*.50f); - x = xleft + barw/2 - LLFontGL::getFontMonospace()->getWidth(tdesc); - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, - LLFontGL::LEFT, LLFontGL::TOP); - - tdesc = llformat("%.1f ms |", (F32)ms*.75f); - x = xleft + (barw*3)/4 - LLFontGL::getFontMonospace()->getWidth(tdesc); - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, - LLFontGL::LEFT, LLFontGL::TOP); - - tdesc = llformat( "%d ms |", ms); - x = xleft + barw - LLFontGL::getFontMonospace()->getWidth(tdesc); - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, - LLFontGL::LEFT, LLFontGL::TOP); - } - - // Draw borders - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - gGL.color4f(0.5f,0.5f,0.5f,0.5f); - - S32 by = y + 2; - - y -= ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4); - - //heading - gl_rect_2d(xleft-5, by, getRect().getWidth()-5, y+5, FALSE); - - //tree view - gl_rect_2d(5, by, xleft-10, 5, FALSE); - - by = y + 5; - //average bar - gl_rect_2d(xleft-5, by, getRect().getWidth()-5, by-barh-dy-5, FALSE); - - by -= barh*2+dy; - - //current frame bar - gl_rect_2d(xleft-5, by, getRect().getWidth()-5, by-barh-dy-2, FALSE); - - by -= barh+dy+1; - - //history bars - gl_rect_2d(xleft-5, by, getRect().getWidth()-5, LINE_GRAPH_HEIGHT-barh-dy-2, FALSE); - - by = LINE_GRAPH_HEIGHT-barh-dy-7; - - //line graph - mGraphRect = LLRect(xleft-5, by, getRect().getWidth()-5, 5); - - gl_rect_2d(mGraphRect, FALSE); - } - - mBarStart.clear(); - mBarEnd.clear(); - - // Draw bars for each history entry - // Special: -1 = show running average - gGL.getTexUnit(0)->bind(box_imagep->getImage()); - for (S32 j=-1; j<histmax && y > LINE_GRAPH_HEIGHT; j++) - { - mBarStart.push_back(std::vector<S32>()); - mBarEnd.push_back(std::vector<S32>()); - int sublevel_dx[FTV_MAX_DEPTH]; - int sublevel_left[FTV_MAX_DEPTH]; - int sublevel_right[FTV_MAX_DEPTH]; - S32 tidx; - if (j >= 0) - { - tidx = LLFastTimer::NamedTimer::HISTORY_NUM - j - 1 - mScrollIndex; - } - else - { - tidx = -1; - } - - x = xleft; - - // draw the bars for each stat - std::vector<S32> xpos; - std::vector<S32> deltax; - xpos.push_back(xleft); - - LLFastTimer::NamedTimer* prev_id = NULL; - - S32 i = 0; - for(timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); - it != end_timer_tree(); - ++it, ++i) - { - LLFastTimer::NamedTimer* idp = (*it); - F32 frac = tidx == -1 - ? (F32)idp->getCountAverage() / (F32)totalticks - : (F32)idp->getHistoricalCount(tidx) / (F32)totalticks; - - dx = llround(frac * (F32)barw); - S32 prev_delta_x = deltax.empty() ? 0 : deltax.back(); - deltax.push_back(dx); - - int level = idp->getDepth() - 1; - - while ((S32)xpos.size() > level + 1) - { - xpos.pop_back(); - } - left = xpos.back(); - - if (level == 0) - { - sublevel_left[level] = xleft; - sublevel_dx[level] = dx; - sublevel_right[level] = sublevel_left[level] + sublevel_dx[level]; - } - else if (prev_id && prev_id->getDepth() < idp->getDepth()) - { - U64 sublevelticks = 0; - - for (LLFastTimer::NamedTimer::child_const_iter it = prev_id->beginChildren(); - it != prev_id->endChildren(); - ++it) - { - sublevelticks += (tidx == -1) - ? (*it)->getCountAverage() - : (*it)->getHistoricalCount(tidx); - } - - F32 subfrac = (F32)sublevelticks / (F32)totalticks; - sublevel_dx[level] = (int)(subfrac * (F32)barw + .5f); - - if (mDisplayCenter == ALIGN_CENTER) - { - left += (prev_delta_x - sublevel_dx[level])/2; - } - else if (mDisplayCenter == ALIGN_RIGHT) - { - left += (prev_delta_x - sublevel_dx[level]); - } - - sublevel_left[level] = left; - sublevel_right[level] = sublevel_left[level] + sublevel_dx[level]; - } - - right = left + dx; - xpos.back() = right; - xpos.push_back(left); - - mBarStart.back().push_back(left); - mBarEnd.back().push_back(right); - - top = y; - bottom = y - barh; - - if (right > left) - { - //U32 rounded_edges = 0; - LLColor4 color = sTimerColors[idp];//*ft_display_table[i].color; - S32 scale_offset = 0; - - BOOL is_child_of_hover_item = (idp == mHoverID); - LLFastTimer::NamedTimer* next_parent = idp->getParent(); - while(!is_child_of_hover_item && next_parent) - { - is_child_of_hover_item = (mHoverID == next_parent); - if (next_parent->getParent() == next_parent) break; - next_parent = next_parent->getParent(); - } - - if (idp == mHoverID) - { - scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 3.f); - //color = lerp(color, LLColor4::black, -0.4f); - } - else if (mHoverID != NULL && !is_child_of_hover_item) - { - color = lerp(color, LLColor4::grey, 0.8f); - } - - 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); - - } - - if ((*it)->getCollapsed()) - { - it.skipDescendants(); - } - - prev_id = idp; - } - y -= (barh + dy); - if (j < 0) - y -= barh; - } - - //draw line graph history - { - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); - LLLocalClipRect clip(mGraphRect); - - //normalize based on last frame's maximum - static U64 last_max = 0; - static F32 alpha_interp = 0.f; - U64 max_ticks = llmax(last_max, (U64) 1); - F32 ms = (F32)((F64)max_ticks * iclock_freq); - - //display y-axis range - std::string tdesc; - if (mDisplayCalls) - tdesc = llformat("%d calls", (int)max_ticks); - else if (mDisplayHz) - tdesc = llformat("%d Hz", (int)max_ticks); - else - tdesc = llformat("%4.2f ms", ms); - - x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(tdesc)-5; - y = mGraphRect.mTop - LLFontGL::getFontMonospace()->getLineHeight(); - - LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, - LLFontGL::LEFT, LLFontGL::TOP); - - //highlight visible range - { - S32 first_frame = LLFastTimer::NamedTimer::HISTORY_NUM - mScrollIndex; - S32 last_frame = first_frame - MAX_VISIBLE_HISTORY; - - F32 frame_delta = ((F32) (mGraphRect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1); - - F32 right = (F32) mGraphRect.mLeft + frame_delta*first_frame; - F32 left = (F32) mGraphRect.mLeft + frame_delta*last_frame; - - gGL.color4f(0.5f,0.5f,0.5f,0.3f); - gl_rect_2d((S32) left, mGraphRect.mTop, (S32) right, mGraphRect.mBottom); - - if (mHoverBarIndex >= 0) - { - S32 bar_frame = first_frame - mHoverBarIndex; - F32 bar = (F32) mGraphRect.mLeft + frame_delta*bar_frame; - - gGL.color4f(0.5f,0.5f,0.5f,1); - - gGL.begin(LLRender::LINES); - gGL.vertex2i((S32)bar, mGraphRect.mBottom); - gGL.vertex2i((S32)bar, mGraphRect.mTop); - gGL.end(); - } - } - - U64 cur_max = 0; - for(timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); - it != end_timer_tree(); - ++it) - { - LLFastTimer::NamedTimer* idp = (*it); - - //fatten highlighted timer - if (mHoverID == idp) - { - gGL.flush(); - glLineWidth(3); - } - - const F32 * col = sTimerColors[idp].mV;// ft_display_table[idx].color->mV; - - F32 alpha = 1.f; - - if (mHoverID != NULL && - idp != mHoverID) - { //fade out non-highlighted timers - if (idp->getParent() != mHoverID) - { - alpha = alpha_interp; - } - } - - gGL.color4f(col[0], col[1], col[2], alpha); - gGL.begin(LLRender::TRIANGLE_STRIP); - for (U32 j = llmax(0, LLFastTimer::NamedTimer::HISTORY_NUM - LLFastTimer::getLastFrameIndex()); - j < LLFastTimer::NamedTimer::HISTORY_NUM; - j++) - { - U64 ticks = idp->getHistoricalCount(j); - - if (mDisplayHz) - { - F64 tc = (F64) (ticks+1) * iclock_freq; - tc = 1000.f/tc; - ticks = llmin((U64) tc, (U64) 1024); - } - else if (mDisplayCalls) - { - ticks = (S32)idp->getHistoricalCalls(j); - } - - if (alpha == 1.f) - { - //normalize to highlighted timer - cur_max = llmax(cur_max, ticks); - } - F32 x = mGraphRect.mLeft + ((F32) (mGraphRect.getWidth()))/(LLFastTimer::NamedTimer::HISTORY_NUM-1)*j; - F32 y = mGraphRect.mBottom + (F32) mGraphRect.getHeight()/max_ticks*ticks; - gGL.vertex2f(x,y); - gGL.vertex2f(x,mGraphRect.mBottom); - } - gGL.end(); - - if (mHoverID == idp) - { - gGL.flush(); - glLineWidth(1); - } - - if (idp->getCollapsed()) - { - //skip hidden timers - it.skipDescendants(); - } - } - - //interpolate towards new maximum - last_max = (U64) lerp((F32)last_max, (F32) cur_max, LLCriticalDamp::getInterpolant(0.1f)); - if (last_max - cur_max <= 1 || cur_max - last_max <= 1) - { - last_max = cur_max; - } - F32 alpha_target = last_max > cur_max ? - llmin((F32) last_max/ (F32) cur_max - 1.f,1.f) : - llmin((F32) cur_max/ (F32) last_max - 1.f,1.f); - alpha_interp = lerp(alpha_interp, alpha_target, LLCriticalDamp::getInterpolant(0.1f)); - - if (mHoverID != NULL) - { - x = (mGraphRect.mRight + mGraphRect.mLeft)/2; - y = mGraphRect.mBottom + 8; - - LLFontGL::getFontMonospace()->renderUTF8( - mHoverID->getName(), - 0, - x, y, - LLColor4::white, - LLFontGL::LEFT, LLFontGL::BOTTOM); - } - } - } - - // Output stats for clicked bar to log - if (mPrintStats >= 0) - { - std::string legend_stat; - bool first = true; - for(timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); - it != end_timer_tree(); - ++it) - { - LLFastTimer::NamedTimer* idp = (*it); - - if (!first) - { - legend_stat += ", "; - } - first = false; - legend_stat += idp->getName(); - - if (idp->getCollapsed()) - { - it.skipDescendants(); - } - } - llinfos << legend_stat << llendl; - - std::string timer_stat; - first = true; - for(timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); - it != end_timer_tree(); - ++it) - { - LLFastTimer::NamedTimer* idp = (*it); - - if (!first) - { - timer_stat += ", "; - } - first = false; - - U64 ticks; - if (mPrintStats > 0) - { - ticks = idp->getHistoricalCount(mPrintStats); - } - else - { - ticks = idp->getCountAverage(); - } - F32 ms = (F32)((F64)ticks * iclock_freq); + const S32 LEGEND_WIDTH = 220; - timer_stat += llformat("%.1f",ms); + mBarRect.mLeft = MARGIN + LEGEND_WIDTH + 8; + mBarRect.mTop = y; + mBarRect.mRight = getRect().getWidth() - MARGIN; + mBarRect.mBottom = MARGIN + LINE_GRAPH_HEIGHT; - if (idp->getCollapsed()) - { - it.skipDescendants(); - } - } - llinfos << timer_stat << llendl; - mPrintStats = -1; - } + drawBars(); + drawLineGraph(); + printLineStats(); + LLView::draw(); + mAllTimeMax = llmax(mAllTimeMax, mRecording->getLastRecording().getSum(FTM_FRAME)); mHoverID = NULL; mHoverBarIndex = -1; - - LLView::draw(); -} - -F64 LLFastTimerView::getTime(const std::string& name) -{ - const LLFastTimer::NamedTimer* timerp = LLFastTimer::getTimerByName(name); - if (timerp) - { - return (F64)timerp->getCountAverage() / (F64)LLFastTimer::countsPerSecond(); - } - return 0.0; } void saveChart(const std::string& label, const char* suffix, LLImageRaw* scratch) @@ -1533,13 +916,13 @@ void LLFastTimerView::outputAllMetrics() //static void LLFastTimerView::doAnalysis(std::string baseline, std::string target, std::string output) { - if(LLFastTimer::sLog) + if(TimeBlock::sLog) { doAnalysisDefault(baseline, target, output) ; return ; } - if(LLFastTimer::sMetricLog) + if(TimeBlock::sMetricLog) { LLMetricPerformanceTesterBasic::doAnalysisMetrics(baseline, target, output) ; return ; @@ -1550,9 +933,660 @@ void LLFastTimerView::onClickCloseBtn() setVisible(false); } -LLFastTimer::NamedTimer& LLFastTimerView::getFrameTimer() +void LLFastTimerView::printLineStats() +{ + // Output stats for clicked bar to log + if (mPrintStats >= 0) + { + std::string legend_stat; + bool first = true; + for(timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); + it != end_timer_tree(); + ++it) + { + TimeBlock* idp = (*it); + + if (!first) + { + legend_stat += ", "; + } + first = false; + legend_stat += idp->getName(); + + if (idp->getCollapsed()) + { + it.skipDescendants(); + } + } + llinfos << legend_stat << llendl; + + std::string timer_stat; + first = true; + for(timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); + it != end_timer_tree(); + ++it) + { + TimeBlock* idp = (*it); + + if (!first) + { + timer_stat += ", "; + } + first = false; + + LLUnit<LLUnits::Seconds, F32> ticks; + if (mPrintStats > 0) + { + ticks = mRecording->getPrevRecording(mPrintStats).getSum(*idp); + } + else + { + ticks = mRecording->getPeriodMean(*idp); + } + LLUnit<LLUnits::Milliseconds, F32> ms = ticks; + + timer_stat += llformat("%.1f",ms.value()); + + if (idp->getCollapsed()) + { + it.skipDescendants(); + } + } + llinfos << timer_stat << llendl; + mPrintStats = -1; + } +} + +static LLFastTimer::DeclareTimer FTM_DRAW_LINE_GRAPH("Draw line graph"); + +void LLFastTimerView::drawLineGraph() +{ + LLFastTimer _(FTM_DRAW_LINE_GRAPH); + //draw line graph history + S32 x = mBarRect.mLeft; + S32 y = LINE_GRAPH_HEIGHT; + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + LLLocalClipRect clip(mGraphRect); + + //normalize based on last frame's maximum + static LLUnit<LLUnits::Seconds, F32> max_time = 0.000001; + static U32 max_calls = 0; + static F32 alpha_interp = 0.f; + + //display y-axis range + std::string axis_label; + if (mDisplayCalls) + axis_label = llformat("%d calls", (int)max_calls); + else if (mDisplayHz) + axis_label = llformat("%d Hz", (int)(1.f / max_time.value())); + else + axis_label = llformat("%4.2f ms", LLUnit<LLUnits::Milliseconds, F32>(max_time).value()); + + x = mGraphRect.mRight - LLFontGL::getFontMonospace()->getWidth(axis_label)-5; + y = mGraphRect.mTop - LLFontGL::getFontMonospace()->getLineHeight(); + + LLFontGL::getFontMonospace()->renderUTF8(axis_label, 0, x, y, LLColor4::white, + LLFontGL::LEFT, LLFontGL::TOP); + + //highlight visible range + { + S32 first_frame = mRecording->getNumPeriods() - mScrollIndex; + S32 last_frame = first_frame - MAX_VISIBLE_HISTORY; + + F32 frame_delta = ((F32) (mGraphRect.getWidth()))/(mRecording->getNumPeriods()-1); + + F32 right = (F32) mGraphRect.mLeft + frame_delta*first_frame; + F32 left = (F32) mGraphRect.mLeft + frame_delta*last_frame; + + gGL.color4f(0.5f,0.5f,0.5f,0.3f); + gl_rect_2d((S32) left, mGraphRect.mTop, (S32) right, mGraphRect.mBottom); + + if (mHoverBarIndex > 0) + { + S32 bar_frame = first_frame - mHoverBarIndex - 1; + F32 bar = (F32) mGraphRect.mLeft + frame_delta*bar_frame; + + gGL.color4f(0.5f,0.5f,0.5f,1); + + gGL.begin(LLRender::LINES); + gGL.vertex2i((S32)bar, mGraphRect.mBottom); + gGL.vertex2i((S32)bar, mGraphRect.mTop); + gGL.end(); + } + } + + LLUnit<LLUnits::Seconds, F32> cur_max = 0; + U32 cur_max_calls = 0; + for(timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); + it != end_timer_tree(); + ++it) + { + TimeBlock* idp = (*it); + + //fatten highlighted timer + if (mHoverID == idp) + { + gGL.flush(); + glLineWidth(3); + } + + const F32 * col = sTimerColors[idp].mV;// ft_display_table[idx].color->mV; + + F32 alpha = 1.f; + + if (mHoverID != NULL && + mHoverID != idp) + { //fade out non-highlighted timers + if (idp->getParent() != mHoverID) + { + alpha = alpha_interp; + } + } + + gGL.color4f(col[0], col[1], col[2], alpha); + gGL.begin(LLRender::TRIANGLE_STRIP); + for (U32 j = mRecording->getNumPeriods(); + j > 0; + j--) + { + LLUnit<LLUnits::Seconds, F32> time = llmax(mRecording->getPrevRecording(j).getSum(*idp), LLUnit<LLUnits::Seconds, F64>(0.000001)); + U32 calls = mRecording->getPrevRecording(j).getSum(idp->callCount()); + + if (alpha == 1.f) + { + //normalize to highlighted timer + cur_max = llmax(cur_max, time); + cur_max_calls = llmax(cur_max_calls, calls); + } + F32 x = mGraphRect.mRight - j * (F32)(mGraphRect.getWidth())/(mRecording->getNumPeriods()-1); + F32 y = mDisplayHz + ? mGraphRect.mBottom + (1.f / time.value()) * ((F32) mGraphRect.getHeight() / (1.f / max_time.value())) + : mGraphRect.mBottom + time / max_time * (F32)mGraphRect.getHeight(); + gGL.vertex2f(x,y); + gGL.vertex2f(x,mGraphRect.mBottom); + } + gGL.end(); + + if (mHoverID == idp) + { + gGL.flush(); + glLineWidth(1); + } + + if (idp->getCollapsed()) + { + //skip hidden timers + it.skipDescendants(); + } + } + + //interpolate towards new maximum + max_time = lerp(max_time.value(), cur_max.value(), LLSmoothInterpolation::getInterpolant(0.1f)); + if (max_time - cur_max <= 1 || cur_max - max_time <= 1) + { + max_time = llmax(LLUnit<LLUnits::Microseconds, F32>(1), LLUnit<LLUnits::Microseconds, F32>(cur_max)); + } + + max_calls = llround(lerp((F32)max_calls, (F32) cur_max_calls, LLSmoothInterpolation::getInterpolant(0.1f))); + if (llabs((S32)(max_calls - cur_max_calls)) <= 1) + { + max_calls = cur_max_calls; + } + + // TODO: make sure alpha is correct in DisplayHz mode + F32 alpha_target = (max_time > cur_max) + ? llmin(max_time / cur_max - 1.f,1.f) + : llmin(cur_max/ max_time - 1.f,1.f); + alpha_interp = lerp(alpha_interp, alpha_target, LLSmoothInterpolation::getInterpolant(0.1f)); + + if (mHoverID != NULL) + { + x = (mGraphRect.mRight + mGraphRect.mLeft)/2; + y = mGraphRect.mBottom + 8; + + LLFontGL::getFontMonospace()->renderUTF8( + mHoverID->getName(), + 0, + x, y, + LLColor4::white, + LLFontGL::LEFT, LLFontGL::BOTTOM); + } +} + +void LLFastTimerView::drawLegend( S32 y ) +{ + // draw legend + S32 dx; + S32 x = MARGIN; + const S32 TEXT_HEIGHT = (S32)LLFontGL::getFontMonospace()->getLineHeight(); + + { + LLLocalClipRect clip(LLRect(MARGIN, y, LEGEND_WIDTH, MARGIN)); + S32 cur_line = 0; + ft_display_idx.clear(); + std::map<TimeBlock*, S32> display_line; + for (timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); + it != timer_tree_iterator_t(); + ++it) + { + TimeBlock* idp = (*it); + display_line[idp] = cur_line; + ft_display_idx.push_back(idp); + cur_line++; + + x = MARGIN; + + LLRect bar_rect(x, y, x + TEXT_HEIGHT, y - TEXT_HEIGHT); + S32 scale_offset = 0; + if (idp == mHoverID) + { + scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f); + } + bar_rect.stretch(scale_offset); + gl_rect_2d(bar_rect, sTimerColors[idp]); + + LLUnit<LLUnits::Milliseconds, F32> ms = 0; + S32 calls = 0; + if (mHoverBarIndex > 0 && mHoverID) + { + S32 hidx = mScrollIndex + mHoverBarIndex; + ms = mRecording->getPrevRecording(hidx).getSum(*idp); + calls = mRecording->getPrevRecording(hidx).getSum(idp->callCount()); + } + else + { + ms = LLUnit<LLUnits::Seconds, F64>(mRecording->getPeriodMean(*idp)); + calls = (S32)mRecording->getPeriodMean(idp->callCount()); + } + + std::string timer_label; + if (mDisplayCalls) + { + timer_label = llformat("%s (%d)",idp->getName().c_str(),calls); + } + else + { + timer_label = llformat("%s [%.1f]",idp->getName().c_str(),ms.value()); + } + dx = (TEXT_HEIGHT+4) + get_depth(idp)*8; + + LLColor4 color = LLColor4::white; + if (get_depth(idp) > 0) + { + S32 line_start_y = bar_rect.getCenterY(); + S32 line_end_y = line_start_y + ((TEXT_HEIGHT + 2) * (cur_line - display_line[idp->getParent()])) - TEXT_HEIGHT; + gl_line_2d(x + dx - 8, line_start_y, x + dx, line_start_y, color); + S32 line_x = x + (TEXT_HEIGHT + 4) + ((get_depth(idp) - 1) * 8); + gl_line_2d(line_x, line_start_y, line_x, line_end_y, color); + if (idp->getCollapsed() && !idp->getChildren().empty()) + { + gl_line_2d(line_x+4, line_start_y-3, line_x+4, line_start_y+4, color); + } + } + + x += dx; + BOOL is_child_of_hover_item = (idp == mHoverID); + TimeBlock* next_parent = idp->getParent(); + while(!is_child_of_hover_item && next_parent) + { + is_child_of_hover_item = (mHoverID == next_parent); + if (next_parent->getParent() == next_parent) break; + next_parent = next_parent->getParent(); + } + + LLFontGL::getFontMonospace()->renderUTF8(timer_label, 0, + x, y, + color, + LLFontGL::LEFT, LLFontGL::TOP, + is_child_of_hover_item ? LLFontGL::BOLD : LLFontGL::NORMAL); + + y -= (TEXT_HEIGHT + 2); + + if (idp->getCollapsed()) + { + it.skipDescendants(); + } + } + } +} + +void LLFastTimerView::generateUniqueColors() +{ + // generate unique colors + { + sTimerColors[&FTM_FRAME] = LLColor4::grey; + + F32 hue = 0.f; + + for (timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); + it != timer_tree_iterator_t(); + ++it) + { + TimeBlock* idp = (*it); + + const F32 HUE_INCREMENT = 0.23f; + hue = fmodf(hue + HUE_INCREMENT, 1.f); + // saturation increases with depth + F32 saturation = clamp_rescale((F32)get_depth(idp), 0.f, 3.f, 0.f, 1.f); + // lightness alternates with depth + F32 lightness = get_depth(idp) % 2 ? 0.5f : 0.6f; + + LLColor4 child_color; + child_color.setHSL(hue, saturation, lightness); + + sTimerColors[idp] = child_color; + } + } +} + +S32 LLFastTimerView::drawHelp( S32 y ) { - return FTM_FRAME.getNamedTimer(); + // Draw some help + const S32 texth = (S32)LLFontGL::getFontMonospace()->getLineHeight(); + + char modedesc[][32] = { + "2 x Average ", + "Max ", + "Recent Max ", + "100 ms " + }; + char centerdesc[][32] = { + "Left ", + "Centered ", + "Ordered " + }; + + std::string text; + text = llformat("Full bar = %s [Click to pause/reset] [SHIFT-Click to toggle]",modedesc[mDisplayMode]); + LLFontGL::getFontMonospace()->renderUTF8(text, 0, MARGIN, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); + + y -= (texth + 2); + text = llformat("Justification = %s [CTRL-Click to toggle]",centerdesc[mDisplayCenter]); + LLFontGL::getFontMonospace()->renderUTF8(text, 0, MARGIN, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); + y -= (texth + 2); + + LLFontGL::getFontMonospace()->renderUTF8(std::string("[Right-Click log selected] [ALT-Click toggle counts] [ALT-SHIFT-Click sub hidden]"), + 0, MARGIN, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); + y -= (texth + 2); + return y; } +void LLFastTimerView::drawTicks() +{ + // Draw MS ticks + { + LLUnit<LLUnits::Milliseconds, U32> ms = mTotalTimeDisplay; + std::string tick_label; + S32 x; + S32 barw = mBarRect.getWidth(); + + tick_label = llformat("%.1f ms |", (F32)ms.value()*.25f); + x = mBarRect.mLeft + barw/4 - LLFontGL::getFontMonospace()->getWidth(tick_label); + LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, x, mBarRect.mTop, LLColor4::white, + LLFontGL::LEFT, LLFontGL::TOP); + + tick_label = llformat("%.1f ms |", (F32)ms.value()*.50f); + x = mBarRect.mLeft + barw/2 - LLFontGL::getFontMonospace()->getWidth(tick_label); + LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, x, mBarRect.mTop, LLColor4::white, + LLFontGL::LEFT, LLFontGL::TOP); + + tick_label = llformat("%.1f ms |", (F32)ms.value()*.75f); + x = mBarRect.mLeft + (barw*3)/4 - LLFontGL::getFontMonospace()->getWidth(tick_label); + LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, x, mBarRect.mTop, LLColor4::white, + LLFontGL::LEFT, LLFontGL::TOP); + + tick_label = llformat( "%d ms |", (U32)ms.value()); + x = mBarRect.mLeft + barw - LLFontGL::getFontMonospace()->getWidth(tick_label); + LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, x, mBarRect.mTop, LLColor4::white, + LLFontGL::LEFT, LLFontGL::TOP); + } +} +void LLFastTimerView::drawBorders( S32 y, const S32 x_start, S32 bar_height, S32 dy ) +{ + // Draw borders + { + S32 by = y + 6 + (S32)LLFontGL::getFontMonospace()->getLineHeight(); + + //heading + gl_rect_2d(x_start-5, by, getRect().getWidth()-5, y+5, LLColor4::grey, FALSE); + + //tree view + gl_rect_2d(5, by, x_start-10, 5, LLColor4::grey, FALSE); + + by = y + 5; + //average bar + gl_rect_2d(x_start-5, by, getRect().getWidth()-5, by-bar_height-dy-5, LLColor4::grey, FALSE); + + by -= bar_height*2+dy; + + //current frame bar + gl_rect_2d(x_start-5, by, getRect().getWidth()-5, by-bar_height-dy-2, LLColor4::grey, FALSE); + + by -= bar_height+dy+1; + + //history bars + gl_rect_2d(x_start-5, by, getRect().getWidth()-5, LINE_GRAPH_HEIGHT-bar_height-dy-2, LLColor4::grey, FALSE); + + by = LINE_GRAPH_HEIGHT-bar_height-dy-7; + + //line graph + mGraphRect = LLRect(x_start-5, by, getRect().getWidth()-5, 5); + + gl_rect_2d(mGraphRect, FALSE); + } +} + +void LLFastTimerView::updateTotalTime() +{ + switch(mDisplayMode) + { + case 0: + mTotalTimeDisplay = mRecording->getPeriodMean(FTM_FRAME)*2; + break; + case 1: + mTotalTimeDisplay = mAllTimeMax; + break; + case 2: + // Calculate the max total ticks for the current history + mTotalTimeDisplay = mRecording->getPeriodMax(FTM_FRAME); + break; + default: + mTotalTimeDisplay = LLUnit<LLUnits::Milliseconds, F32>(100); + break; + } + + mTotalTimeDisplay = LLUnit<LLUnits::Milliseconds, F32>(llceil(mTotalTimeDisplay.as<LLUnits::Milliseconds>().value() / 20.f) * 20.f); +} + +void LLFastTimerView::drawBars() +{ + updateTotalTime(); + if (mTotalTimeDisplay <= 0.0) return; + + LLLocalClipRect clip(mBarRect); + + S32 bar_height = mBarRect.getHeight() / (MAX_VISIBLE_HISTORY + 2); + S32 vpad = llmax(1, bar_height / 4); // spacing between bars + bar_height -= vpad; + + drawTicks(); + S32 y = mBarRect.mTop - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 4); + drawBorders(y, mBarRect.mLeft, bar_height, vpad); + + // Draw bars for each history entry + // Special: -1 = show running average + LLPointer<LLUIImage> bar_image = LLUI::getUIImage("Rounded_Square"); + gGL.getTexUnit(0)->bind(bar_image->getImage()); + const S32 histmax = llmin((S32)mRecording->getNumPeriods(), MAX_VISIBLE_HISTORY) + 1; + + for (S32 bar_index = 0; bar_index < histmax && y > LINE_GRAPH_HEIGHT; bar_index++) + { + S32 history_index = (bar_index > 0) + ? bar_index + mScrollIndex + : -1; + mTimerBars[bar_index].clear(); + mTimerBars[bar_index].reserve(LLInstanceTracker<LLTrace::TimeBlock>::instanceCount()); + + updateTimerBarWidths(&FTM_FRAME, mTimerBars[bar_index], history_index, true); + LLRect frame_bar_rect(mBarRect.mLeft, y, mBarRect.mLeft + mTimerBars[bar_index][0].mWidth, y-bar_height); + mTimerBars[bar_index][0].mVisibleRect = frame_bar_rect; + updateTimerBarFractions(&FTM_FRAME, 0, mTimerBars[bar_index]); + drawBar(&FTM_FRAME, frame_bar_rect, mTimerBars[bar_index], 0, bar_image); + + y -= (bar_height + vpad); + if (bar_index == 0) + y -= bar_height; + } + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +} + +static LLFastTimer::DeclareTimer FTM_UPDATE_TIMER_BAR_WIDTHS("Update timer bar widths"); + +S32 LLFastTimerView::updateTimerBarWidths(LLTrace::TimeBlock* time_block, std::vector<TimerBar>& bars, S32 history_index, bool visible) +{ + LLFastTimer _(FTM_UPDATE_TIMER_BAR_WIDTHS); + F32 self_time_frame_fraction = history_index == -1 + ? (mRecording->getPeriodMean(time_block->selfTime()) / mTotalTimeDisplay) + : (mRecording->getPrevRecording(history_index).getSum(time_block->selfTime()) / mTotalTimeDisplay); + + S32 self_time_width = llround(self_time_frame_fraction * (F32)mBarRect.getWidth()); + S32 full_width = self_time_width; + + bool children_visible = visible; + + // reserve a spot for this bar to be rendered before its children + // even though we don't know its size yet + S32 bar_rect_index = bars.size(); + if (visible) + { + bars.push_back(TimerBar()); + } + + if (time_block->getCollapsed()) + { + children_visible = false; + } + for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); it != end_it; ++it) + { + full_width += updateTimerBarWidths(*it, bars, history_index, children_visible); + } + + if (visible) + { + TimerBar& timer_bar = bars[bar_rect_index]; + + timer_bar.mWidth = full_width; + timer_bar.mSelfWidth = self_time_width; + timer_bar.mColor = sTimerColors[time_block]; + + BOOL is_child_of_hover_item = (time_block == mHoverID); + TimeBlock* next_parent = time_block->getParent(); + while(!is_child_of_hover_item && next_parent) + { + is_child_of_hover_item = (mHoverID == next_parent); + if (next_parent->getParent() == next_parent) break; + next_parent = next_parent->getParent(); + } + + if (mHoverID != NULL + && time_block != mHoverID + && !is_child_of_hover_item) + { + timer_bar.mColor = lerp(timer_bar.mColor, LLColor4::grey, 0.8f); + } + } + return full_width; +} + +static LLFastTimer::DeclareTimer FTM_UPDATE_TIMER_BAR_FRACTIONS("Update timer bar fractions"); + +S32 LLFastTimerView::updateTimerBarFractions(LLTrace::TimeBlock* time_block, S32 timer_bar_index, std::vector<TimerBar>& bars) +{ + LLFastTimer _(FTM_UPDATE_TIMER_BAR_FRACTIONS); + TimerBar& timer_bar = bars[timer_bar_index]; + S32 child_time_width = timer_bar.mWidth - timer_bar.mSelfWidth; + LLRect children_rect = timer_bar.mVisibleRect; + + if (mDisplayCenter == ALIGN_CENTER) + { + children_rect.mLeft += timer_bar.mSelfWidth / 2; + } + else if (mDisplayCenter == ALIGN_RIGHT) + { + children_rect.mLeft += timer_bar.mSelfWidth; + } + children_rect.mRight = children_rect.mLeft + timer_bar.mWidth - timer_bar.mSelfWidth; + + if (children_rect.getHeight() > MIN_BAR_HEIGHT) + { + children_rect.mTop -= 1; + children_rect.mBottom += 1; + } + timer_bar.mChildrenRect = children_rect; + + //now loop through children and figure out portion of bar image covered by each bar, now that we know the + //sum of all children + if (!time_block->getCollapsed()) + { + F32 bar_fraction_start = 0.f; + for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); + it != end_it; + ++it) + { + timer_bar_index++; + + TimerBar& child_timer_bar = bars[timer_bar_index]; + TimeBlock* child_time_block = *it; + + child_timer_bar.mStartFraction = bar_fraction_start; + child_timer_bar.mEndFraction = child_time_width > 0 + ? bar_fraction_start + (F32)child_timer_bar.mWidth / child_time_width + : 1.f; + child_timer_bar.mVisibleRect.set(children_rect.mLeft + llround(child_timer_bar.mStartFraction * children_rect.getWidth()), + children_rect.mTop, + children_rect.mLeft + llround(child_timer_bar.mEndFraction * children_rect.getWidth()), + children_rect.mBottom); + + timer_bar_index = updateTimerBarFractions(child_time_block, timer_bar_index, bars); + + bar_fraction_start = child_timer_bar.mEndFraction; + } + } + return timer_bar_index; +} + +S32 LLFastTimerView::drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, std::vector<TimerBar>& bars, S32 bar_index, LLPointer<LLUIImage>& bar_image) +{ + TimerBar& timer_bar = bars[bar_index]; + + // animate scale of bar when hovering over that particular timer + if (bar_rect.getWidth() > 0) + { + LLRect render_rect(bar_rect); + S32 scale_offset = 0; + if (time_block == mHoverID) + { + scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 3.f); + render_rect.mTop += scale_offset; + render_rect.mBottom -= scale_offset; + } + + gGL.color4fv(timer_bar.mColor.mV); + gl_segmented_rect_2d_fragment_tex(render_rect, + bar_image->getTextureWidth(), bar_image->getTextureHeight(), + 16, + timer_bar.mStartFraction, timer_bar.mEndFraction); + } + + if (!time_block->getCollapsed()) + { + for (TimeBlock::child_iter it = time_block->beginChildren(), end_it = time_block->endChildren(); it != end_it; ++it) + { + ++bar_index; + bar_index = drawBar(*it, timer_bar.mChildrenRect, bars, bar_index, bar_image); + } + } + + return bar_index; +} diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index 5766cfa0b0..341adacd65 100755 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -29,11 +29,14 @@ #include "llfloater.h" #include "llfasttimer.h" +#include "llunit.h" +#include "lltracerecording.h" class LLFastTimerView : public LLFloater { public: LLFastTimerView(const LLSD&); + ~LLFastTimerView(); BOOL postBuild(); static BOOL sAnalyzePerformance; @@ -46,7 +49,6 @@ private: static LLSD analyzePerformanceLogDefault(std::istream& is) ; static void exportCharts(const std::string& base, const std::string& target); void onPause(); - LLFastTimer::NamedTimer& getFrameTimer(); public: @@ -59,15 +61,47 @@ public: virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); virtual void draw(); - LLFastTimer::NamedTimer* getLegendID(S32 y); - F64 getTime(const std::string& name); + LLTrace::TimeBlock* getLegendID(S32 y); protected: virtual void onClickCloseBtn(); + private: - typedef std::vector<std::vector<S32> > bar_positions_t; - bar_positions_t mBarStart; - bar_positions_t mBarEnd; + void drawTicks(); + void drawLineGraph(); + void drawLegend(S32 y); + S32 drawHelp(S32 y); + void drawBorders( S32 y, const S32 x_start, S32 barh, S32 dy); + void drawBars(); + + void printLineStats(); + void generateUniqueColors(); + void updateTotalTime(); + + struct TimerBar + { + TimerBar() + : mWidth(0), + mSelfWidth(0), + mVisible(true), + mStartFraction(0.f), + mEndFraction(1.f) + {} + S32 mWidth; + S32 mSelfWidth; + LLRect mVisibleRect, + mChildrenRect; + LLColor4 mColor; + bool mVisible; + F32 mStartFraction, + mEndFraction; + }; + S32 updateTimerBarWidths(LLTrace::TimeBlock* time_block, std::vector<TimerBar>& bars, S32 history_index, bool visible); + S32 updateTimerBarFractions(LLTrace::TimeBlock* time_block, S32 timer_bar_index, std::vector<TimerBar>& bars); + S32 drawBar(LLTrace::TimeBlock* time_block, LLRect bar_rect, std::vector<TimerBar>& bars, S32 bar_index, LLPointer<LLUIImage>& bar_image); + void setPauseState(bool pause_state); + + std::vector<TimerBar>* mTimerBars; S32 mDisplayMode; typedef enum child_alignment @@ -79,19 +113,21 @@ private: } ChildAlignment; ChildAlignment mDisplayCenter; - S32 mDisplayCalls; - S32 mDisplayHz; - U64 mAvgCountTotal; - U64 mMaxCountTotal; + bool mDisplayCalls, + mDisplayHz; + LLUnit<LLUnits::Seconds, F64> mAllTimeMax, + mTotalTimeDisplay; LLRect mBarRect; S32 mScrollIndex; - LLFastTimer::NamedTimer* mHoverID; - LLFastTimer::NamedTimer* mHoverTimer; + LLTrace::TimeBlock* mHoverID; + LLTrace::TimeBlock* mHoverTimer; LLRect mToolTipRect; S32 mHoverBarIndex; LLFrameTimer mHighlightTimer; S32 mPrintStats; LLRect mGraphRect; + LLTrace::PeriodicRecording* mRecording; + bool mPauseHistory; }; #endif diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h index 4f602f63f1..4d7b81304a 100755 --- a/indra/newview/llfilepicker.h +++ b/indra/newview/llfilepicker.h @@ -50,6 +50,7 @@ // Need commdlg.h for OPENFILENAMEA #ifdef LL_WINDOWS +#include "llwin32headers.h" #include <commdlg.h> #endif diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp index caad0afec0..83193b2e14 100755 --- a/indra/newview/llflexibleobject.cpp +++ b/indra/newview/llflexibleobject.cpp @@ -339,10 +339,10 @@ void LLVolumeImplFlexible::doIdleUpdate() if (drawablep) { //LLFastTimer ftm(FTM_FLEXIBLE_UPDATE); - + //ensure drawable is active drawablep->makeActive(); - + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) { bool visible = drawablep->isVisible(); diff --git a/indra/newview/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp index 83fb887d81..93502daac7 100755 --- a/indra/newview/llfloaterabout.cpp +++ b/indra/newview/llfloaterabout.cpp @@ -296,7 +296,8 @@ LLSD LLFloaterAbout::getInfo() if (gPacketsIn > 0) { - info["PACKETS_LOST"] = LLViewerStats::getInstance()->mPacketsLostStat.getCurrent(); + LLTrace::Recording cur_frame = LLTrace::get_frame_recording().snapshotCurRecording(); + info["PACKETS_LOST"] = cur_frame.getSum(LLStatViewer::PACKETS_LOST); info["PACKETS_IN"] = F32(gPacketsIn); info["PACKETS_PCT"] = 100.f*info["PACKETS_LOST"].asReal() / info["PACKETS_IN"].asReal(); } diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 113aa9a8f2..76773f914d 100755 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -405,11 +405,11 @@ void LLFloaterAvatarPicker::drawFrustum() if (gFocusMgr.childHasMouseCapture(getDragHandle())) { - mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(mContextConeFadeTime)); + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(mContextConeFadeTime)); } else { - mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime)); + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(mContextConeFadeTime)); } } } diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp index 048837acfe..317bdd8d46 100755 --- a/indra/newview/llfloateravatartextures.cpp +++ b/indra/newview/llfloateravatartextures.cpp @@ -37,6 +37,7 @@ #include "lluictrlfactory.h" #include "llviewerobjectlist.h" #include "llvoavatarself.h" +#include "lllocaltextureobject.h" using namespace LLAvatarAppearanceDefines; diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp index 42857b2aa2..84e2956b29 100755 --- a/indra/newview/llfloaterbuyland.cpp +++ b/indra/newview/llfloaterbuyland.cpp @@ -202,7 +202,7 @@ public: virtual void draw(); virtual BOOL canClose(); - void onVisibilityChange ( const LLSD& new_visibility ); + void onVisibilityChanged ( const LLSD& new_visibility ); }; @@ -1008,7 +1008,7 @@ BOOL LLFloaterBuyLandUI::canClose() return can_close; } -void LLFloaterBuyLandUI::onVisibilityChange ( const LLSD& new_visibility ) +void LLFloaterBuyLandUI::onVisibilityChanged ( const LLSD& new_visibility ) { if (new_visibility.asBoolean()) { diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp index a03425649f..6aebe85e7a 100755 --- a/indra/newview/llfloatercolorpicker.cpp +++ b/indra/newview/llfloatercolorpicker.cpp @@ -529,11 +529,11 @@ void LLFloaterColorPicker::draw() if (gFocusMgr.childHasMouseCapture(getDragHandle())) { mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), - LLCriticalDamp::getInterpolant(mContextConeFadeTime)); + LLSmoothInterpolation::getInterpolant(mContextConeFadeTime)); } else { - mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(mContextConeFadeTime)); + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(mContextConeFadeTime)); } mPipetteBtn->setToggleState(LLToolMgr::getInstance()->getCurrentTool() == LLToolPipette::getInstance()); diff --git a/indra/newview/llfloaterimnearbychat.cpp b/indra/newview/llfloaterimnearbychat.cpp index 49f36a2f32..2287277acf 100755 --- a/indra/newview/llfloaterimnearbychat.cpp +++ b/indra/newview/llfloaterimnearbychat.cpp @@ -841,7 +841,7 @@ void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 gAgent.sendReliableMessage(); - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CHAT_COUNT); + add(LLStatViewer::CHAT_COUNT, 1); } class LLChatCommandHandler : public LLCommandHandler diff --git a/indra/newview/llfloaterimsession.cpp b/indra/newview/llfloaterimsession.cpp index 8ec85e1160..1b3318a730 100755..100644 --- a/indra/newview/llfloaterimsession.cpp +++ b/indra/newview/llfloaterimsession.cpp @@ -41,6 +41,7 @@ #include "llchicletbar.h" #include "lldonotdisturbnotificationstorage.h" #include "llfloaterreg.h" +#include "llhttpclient.h" #include "llfloateravatarpicker.h" #include "llfloaterimcontainer.h" // to replace separate IM Floaters with multifloater container #include "llinventoryfunctions.h" @@ -52,6 +53,7 @@ #include "lltrans.h" #include "llchathistory.h" #include "llnotifications.h" +#include "llviewerregion.h" #include "llviewerwindow.h" #include "lltransientfloatermgr.h" #include "llinventorymodel.h" @@ -109,7 +111,7 @@ void LLFloaterIMSession::refresh() void LLFloaterIMSession::onTearOffClicked() { LLFloaterIMSessionTab::onTearOffClicked(); - + if(mIsP2PChat) { if(isTornOff()) @@ -170,7 +172,7 @@ void LLFloaterIMSession::newIMCallback(const LLSD& data) } } -void LLFloaterIMSession::onVisibilityChange(const LLSD& new_visibility) +void LLFloaterIMSession::onVisibilityChanged(const LLSD& new_visibility) { bool visible = new_visibility.asBoolean(); @@ -331,7 +333,7 @@ void LLFloaterIMSession::initIMFloater() BOOL LLFloaterIMSession::postBuild() { BOOL result = LLFloaterIMSessionTab::postBuild(); - + mInputEditor->setMaxTextLength(1023); mInputEditor->setAutoreplaceCallback(boost::bind(&LLAutoReplace::autoreplaceCallback, LLAutoReplace::getInstance(), _1, _2, _3, _4, _5)); mInputEditor->setFocusReceivedCallback( boost::bind(onInputEditorFocusReceived, _1, this) ); @@ -358,7 +360,7 @@ BOOL LLFloaterIMSession::postBuild() return result; } - + void LLFloaterIMSession::onAddButtonClicked() { LLView * button = findChild<LLView>("toolbar_panel")->findChild<LLButton>("add_btn"); @@ -371,7 +373,7 @@ void LLFloaterIMSession::onAddButtonClicked() // Need to disable 'ok' button when selected users are already in conversation. picker->setOkBtnEnableCb(boost::bind(&LLFloaterIMSession::canAddSelectedToChat, this, _1)); - + if (root_floater) { root_floater->addDependentFloater(picker); @@ -426,7 +428,7 @@ bool LLFloaterIMSession::canAddSelectedToChat(const uuid_vec_t& uuids) } } } - + return true; } @@ -600,7 +602,7 @@ LLFloaterIMSession* LLFloaterIMSession::findInstance(const LLUUID& session_id) return conversation; } - + LLFloaterIMSession* LLFloaterIMSession::getInstance(const LLUUID& session_id) { LLFloaterIMSession* conversation = @@ -780,7 +782,7 @@ void LLFloaterIMSession::sessionInitReplyReceived(const LLUUID& im_session_id) initIMSession(im_session_id); buildConversationViewParticipant(); } - + initIMFloater(); LLFloaterIMSessionTab::updateGearBtn(); //*TODO here we should remove "starting session..." warning message if we added it in postBuild() (IB) diff --git a/indra/newview/llfloaterimsession.h b/indra/newview/llfloaterimsession.h index a0e0171b34..84abb2435a 100755..100644 --- a/indra/newview/llfloaterimsession.h +++ b/indra/newview/llfloaterimsession.h @@ -62,7 +62,7 @@ public: void initIMSession(const LLUUID& session_id); void initIMFloater(); - + // LLView overrides /*virtual*/ BOOL postBuild(); /*virtual*/ void setMinimized(BOOL b); @@ -107,7 +107,7 @@ public: // called when docked floater's position has been set by chiclet void setPositioned(bool b) { mPositioned = b; }; - void onVisibilityChange(const LLSD& new_visibility); + void onVisibilityChanged(const LLSD& new_visibility); bool enableGearMenuItem(const LLSD& userdata); void GearDoToSelected(const LLSD& userdata); bool checkGearMenuItem(const LLSD& userdata); @@ -142,10 +142,10 @@ private: /*virtual*/ void onTearOffClicked(); /*virtual*/ void onClickCloseBtn(); - + // Update the window title and input field help text /*virtual*/ void updateSessionName(const std::string& name); - + bool dropPerson(LLUUID* person_id, bool drop); BOOL isInviteAllowed() const; @@ -161,7 +161,7 @@ private: bool canAddSelectedToChat(const uuid_vec_t& uuids); void onCallButtonClicked(); - + void boundVoiceChannel(); // Add the "User is typing..." indicator. diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index d0c22d25f2..b71ab4c53b 100755 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -33,7 +33,7 @@ #include "llerror.h" #include "llrect.h" #include "llstring.h" -#include "llstat.h" +#include "lltrace.h" // project includes #include "lluictrlfactory.h" @@ -42,6 +42,22 @@ #include "llviewerjoystick.h" #include "llcheckboxctrl.h" +static LLTrace::SampleStatHandle<> sJoystickAxis1("Joystick axis 1"), + sJoystickAxis2("Joystick axis 2"), + sJoystickAxis3("Joystick axis 3"), + sJoystickAxis4("Joystick axis 4"), + sJoystickAxis5("Joystick axis 5"), + sJoystickAxis6("Joystick axis 6"); +static LLTrace::SampleStatHandle<>* sJoystickAxes[6] = +{ + &sJoystickAxis1, + &sJoystickAxis2, + &sJoystickAxis3, + &sJoystickAxis4, + &sJoystickAxis5, + &sJoystickAxis6 +}; + LLFloaterJoystick::LLFloaterJoystick(const LLSD& data) : LLFloater(data) { @@ -61,7 +77,7 @@ void LLFloaterJoystick::draw() for (U32 i = 0; i < 6; i++) { F32 value = joystick->getJoystickAxis(i); - mAxisStats[i]->addValue(value * gFrameIntervalSeconds); + sample(*sJoystickAxes[i], value * gFrameIntervalSeconds.value()); if (mAxisStatsBar[i]) { F32 minbar, maxbar; @@ -69,7 +85,7 @@ void LLFloaterJoystick::draw() if (llabs(value) > maxbar) { F32 range = llabs(value); - mAxisStatsBar[i]->setRange(-range, range, range * 0.25f, range * 0.5f); + mAxisStatsBar[i]->setRange(-range, range, range * 0.25f); } } } @@ -85,13 +101,12 @@ BOOL LLFloaterJoystick::postBuild() for (U32 i = 0; i < 6; i++) { std::string stat_name(llformat("Joystick axis %d", i)); - mAxisStats[i] = new LLStat(stat_name, 4); std::string axisname = llformat("axis%d", i); mAxisStatsBar[i] = getChild<LLStatBar>(axisname); if (mAxisStatsBar[i]) { - mAxisStatsBar[i]->setStat(mAxisStats[i]); - mAxisStatsBar[i]->setRange(-range, range, range * 0.25f, range * 0.5f); + mAxisStatsBar[i]->setStat(stat_name); + mAxisStatsBar[i]->setRange(-range, range, range * 0.25f); } } diff --git a/indra/newview/llfloaterjoystick.h b/indra/newview/llfloaterjoystick.h index dfdb108ff8..9c3752540d 100755 --- a/indra/newview/llfloaterjoystick.h +++ b/indra/newview/llfloaterjoystick.h @@ -84,7 +84,6 @@ private: LLCheckBoxCtrl *mCheckFlycamEnabled; // stats view - LLStat* mAxisStats[6]; LLStatBar* mAxisStatsBar[6]; }; diff --git a/indra/newview/llfloaterlagmeter.cpp b/indra/newview/llfloaterlagmeter.cpp deleted file mode 100755 index 68b1770bb2..0000000000 --- a/indra/newview/llfloaterlagmeter.cpp +++ /dev/null @@ -1,375 +0,0 @@ -/** - * @file llfloaterlagmeter.cpp - * @brief The "Lag-o-Meter" floater used to tell users what is causing lag. - * - * $LicenseInfo:firstyear=2007&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 "llviewerprecompiledheaders.h" - -#include "llfloaterlagmeter.h" - -#include "lluictrlfactory.h" -#include "llviewerstats.h" -#include "llviewertexture.h" -#include "llviewercontrol.h" -#include "llappviewer.h" - -#include "lltexturefetch.h" - -#include "llbutton.h" -#include "llfocusmgr.h" -#include "lltextbox.h" - -const std::string LAG_CRITICAL_IMAGE_NAME = "lag_status_critical.tga"; -const std::string LAG_WARNING_IMAGE_NAME = "lag_status_warning.tga"; -const std::string LAG_GOOD_IMAGE_NAME = "lag_status_good.tga"; - -LLFloaterLagMeter::LLFloaterLagMeter(const LLSD& key) - : LLFloater(key) -{ - mCommitCallbackRegistrar.add("LagMeter.ClickShrink", boost::bind(&LLFloaterLagMeter::onClickShrink, this)); -} - -BOOL LLFloaterLagMeter::postBuild() -{ - // Don't let this window take keyboard focus -- it's confusing to - // lose arrow-key driving when testing lag. - setIsChrome(TRUE); - - // were we shrunk last time? - if (isShrunk()) - { - onClickShrink(); - } - - mClientButton = getChild<LLButton>("client_lagmeter"); - mClientText = getChild<LLTextBox>("client_text"); - mClientCause = getChild<LLTextBox>("client_lag_cause"); - - mNetworkButton = getChild<LLButton>("network_lagmeter"); - mNetworkText = getChild<LLTextBox>("network_text"); - mNetworkCause = getChild<LLTextBox>("network_lag_cause"); - - mServerButton = getChild<LLButton>("server_lagmeter"); - mServerText = getChild<LLTextBox>("server_text"); - mServerCause = getChild<LLTextBox>("server_lag_cause"); - - std::string config_string = getString("client_frame_rate_critical_fps", mStringArgs); - mClientFrameTimeCritical = 1.0f / (float)atof( config_string.c_str() ); - config_string = getString("client_frame_rate_warning_fps", mStringArgs); - mClientFrameTimeWarning = 1.0f / (float)atof( config_string.c_str() ); - - config_string = getString("network_packet_loss_critical_pct", mStringArgs); - mNetworkPacketLossCritical = (float)atof( config_string.c_str() ); - config_string = getString("network_packet_loss_warning_pct", mStringArgs); - mNetworkPacketLossWarning = (float)atof( config_string.c_str() ); - - config_string = getString("network_ping_critical_ms", mStringArgs); - mNetworkPingCritical = (float)atof( config_string.c_str() ); - config_string = getString("network_ping_warning_ms", mStringArgs); - mNetworkPingWarning = (float)atof( config_string.c_str() ); - config_string = getString("server_frame_rate_critical_fps", mStringArgs); - - mServerFrameTimeCritical = 1000.0f / (float)atof( config_string.c_str() ); - config_string = getString("server_frame_rate_warning_fps", mStringArgs); - mServerFrameTimeWarning = 1000.0f / (float)atof( config_string.c_str() ); - config_string = getString("server_single_process_max_time_ms", mStringArgs); - mServerSingleProcessMaxTime = (float)atof( config_string.c_str() ); - -// mShrunk = false; - config_string = getString("max_width_px", mStringArgs); - mMaxWidth = atoi( config_string.c_str() ); - config_string = getString("min_width_px", mStringArgs); - mMinWidth = atoi( config_string.c_str() ); - - mStringArgs["[CLIENT_FRAME_RATE_CRITICAL]"] = getString("client_frame_rate_critical_fps"); - mStringArgs["[CLIENT_FRAME_RATE_WARNING]"] = getString("client_frame_rate_warning_fps"); - - mStringArgs["[NETWORK_PACKET_LOSS_CRITICAL]"] = getString("network_packet_loss_critical_pct"); - mStringArgs["[NETWORK_PACKET_LOSS_WARNING]"] = getString("network_packet_loss_warning_pct"); - - mStringArgs["[NETWORK_PING_CRITICAL]"] = getString("network_ping_critical_ms"); - mStringArgs["[NETWORK_PING_WARNING]"] = getString("network_ping_warning_ms"); - - mStringArgs["[SERVER_FRAME_RATE_CRITICAL]"] = getString("server_frame_rate_critical_fps"); - mStringArgs["[SERVER_FRAME_RATE_WARNING]"] = getString("server_frame_rate_warning_fps"); - -// childSetAction("minimize", onClickShrink, this); - updateControls(isShrunk()); // if expanded append colon to the labels (EXT-4079) - - return TRUE; -} -LLFloaterLagMeter::~LLFloaterLagMeter() -{ - // save shrunk status for next time -// gSavedSettings.setBOOL("LagMeterShrunk", mShrunk); - // expand so we save the large window rectangle - if (isShrunk()) - { - onClickShrink(); - } -} - -void LLFloaterLagMeter::draw() -{ - determineClient(); - determineNetwork(); - determineServer(); - - LLFloater::draw(); -} - -void LLFloaterLagMeter::determineClient() -{ - F32 client_frame_time = LLViewerStats::getInstance()->mFPSStat.getMeanDuration(); - bool find_cause = false; - - if (!gFocusMgr.getAppHasFocus()) - { - mClientButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME)); - mClientText->setText( getString("client_frame_time_window_bg_msg", mStringArgs) ); - mClientCause->setText( LLStringUtil::null ); - } - else if(client_frame_time >= mClientFrameTimeCritical) - { - mClientButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME)); - mClientText->setText( getString("client_frame_time_critical_msg", mStringArgs) ); - find_cause = true; - } - else if(client_frame_time >= mClientFrameTimeWarning) - { - mClientButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME)); - mClientText->setText( getString("client_frame_time_warning_msg", mStringArgs) ); - find_cause = true; - } - else - { - mClientButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME)); - mClientText->setText( getString("client_frame_time_normal_msg", mStringArgs) ); - mClientCause->setText( LLStringUtil::null ); - } - - if(find_cause) - { - if(gSavedSettings.getF32("RenderFarClip") > 128) - { - mClientCause->setText( getString("client_draw_distance_cause_msg", mStringArgs) ); - } - else if(LLAppViewer::instance()->getTextureFetch()->getNumRequests() > 2) - { - mClientCause->setText( getString("client_texture_loading_cause_msg", mStringArgs) ); - } - else if((BYTES_TO_MEGA_BYTES(LLViewerTexture::sBoundTextureMemoryInBytes)) > LLViewerTexture::sMaxBoundTextureMemInMegaBytes) - { - mClientCause->setText( getString("client_texture_memory_cause_msg", mStringArgs) ); - } - else - { - mClientCause->setText( getString("client_complex_objects_cause_msg", mStringArgs) ); - } - } -} - -void LLFloaterLagMeter::determineNetwork() -{ - F32 packet_loss = LLViewerStats::getInstance()->mPacketsLostPercentStat.getMean(); - F32 ping_time = LLViewerStats::getInstance()->mSimPingStat.getMean(); - bool find_cause_loss = false; - bool find_cause_ping = false; - - // *FIXME: We can't blame a large ping time on anything in - // particular if the frame rate is low, because a low frame - // rate is a sure recipe for bad ping times right now until - // the network handlers are de-synched from the rendering. - F32 client_frame_time_ms = 1000.0f * LLViewerStats::getInstance()->mFPSStat.getMeanDuration(); - - if(packet_loss >= mNetworkPacketLossCritical) - { - mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME)); - mNetworkText->setText( getString("network_packet_loss_critical_msg", mStringArgs) ); - find_cause_loss = true; - } - else if(ping_time >= mNetworkPingCritical) - { - mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME)); - if (client_frame_time_ms < mNetworkPingCritical) - { - mNetworkText->setText( getString("network_ping_critical_msg", mStringArgs) ); - find_cause_ping = true; - } - } - else if(packet_loss >= mNetworkPacketLossWarning) - { - mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME)); - mNetworkText->setText( getString("network_packet_loss_warning_msg", mStringArgs) ); - find_cause_loss = true; - } - else if(ping_time >= mNetworkPingWarning) - { - mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME)); - if (client_frame_time_ms < mNetworkPingWarning) - { - mNetworkText->setText( getString("network_ping_warning_msg", mStringArgs) ); - find_cause_ping = true; - } - } - else - { - mNetworkButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME)); - mNetworkText->setText( getString("network_performance_normal_msg", mStringArgs) ); - } - - if(find_cause_loss) - { - mNetworkCause->setText( getString("network_packet_loss_cause_msg", mStringArgs) ); - } - else if(find_cause_ping) - { - mNetworkCause->setText( getString("network_ping_cause_msg", mStringArgs) ); - } - else - { - mNetworkCause->setText( LLStringUtil::null ); - } -} - -void LLFloaterLagMeter::determineServer() -{ - F32 sim_frame_time = LLViewerStats::getInstance()->mSimFrameMsec.getCurrent(); - bool find_cause = false; - - if(sim_frame_time >= mServerFrameTimeCritical) - { - mServerButton->setImageUnselected(LLUI::getUIImage(LAG_CRITICAL_IMAGE_NAME)); - mServerText->setText( getString("server_frame_time_critical_msg", mStringArgs) ); - find_cause = true; - } - else if(sim_frame_time >= mServerFrameTimeWarning) - { - mServerButton->setImageUnselected(LLUI::getUIImage(LAG_WARNING_IMAGE_NAME)); - mServerText->setText( getString("server_frame_time_warning_msg", mStringArgs) ); - find_cause = true; - } - else - { - mServerButton->setImageUnselected(LLUI::getUIImage(LAG_GOOD_IMAGE_NAME)); - mServerText->setText( getString("server_frame_time_normal_msg", mStringArgs) ); - mServerCause->setText( LLStringUtil::null ); - } - - if(find_cause) - { - if(LLViewerStats::getInstance()->mSimSimPhysicsMsec.getCurrent() > mServerSingleProcessMaxTime) - { - mServerCause->setText( getString("server_physics_cause_msg", mStringArgs) ); - } - else if(LLViewerStats::getInstance()->mSimScriptMsec.getCurrent() > mServerSingleProcessMaxTime) - { - mServerCause->setText( getString("server_scripts_cause_msg", mStringArgs) ); - } - else if(LLViewerStats::getInstance()->mSimNetMsec.getCurrent() > mServerSingleProcessMaxTime) - { - mServerCause->setText( getString("server_net_cause_msg", mStringArgs) ); - } - else if(LLViewerStats::getInstance()->mSimAgentMsec.getCurrent() > mServerSingleProcessMaxTime) - { - mServerCause->setText( getString("server_agent_cause_msg", mStringArgs) ); - } - else if(LLViewerStats::getInstance()->mSimImagesMsec.getCurrent() > mServerSingleProcessMaxTime) - { - mServerCause->setText( getString("server_images_cause_msg", mStringArgs) ); - } - else - { - mServerCause->setText( getString("server_generic_cause_msg", mStringArgs) ); - } - } -} - -void LLFloaterLagMeter::updateControls(bool shrink) -{ -// LLFloaterLagMeter * self = (LLFloaterLagMeter*)data; - - LLButton * button = getChild<LLButton>("minimize"); - S32 delta_width = mMaxWidth -mMinWidth; - LLRect r = getRect(); - - if(!shrink) - { - setTitle(getString("max_title_msg", mStringArgs) ); - // make left edge appear to expand - r.translate(-delta_width, 0); - setRect(r); - reshape(mMaxWidth, getRect().getHeight()); - - getChild<LLUICtrl>("client")->setValue(getString("client_text_msg", mStringArgs) + ":"); - getChild<LLUICtrl>("network")->setValue(getString("network_text_msg",mStringArgs) + ":"); - getChild<LLUICtrl>("server")->setValue(getString("server_text_msg", mStringArgs) + ":"); - - // usually "<<" - button->setLabel( getString("smaller_label", mStringArgs) ); - } - else - { - setTitle( getString("min_title_msg", mStringArgs) ); - // make left edge appear to collapse - r.translate(delta_width, 0); - setRect(r); - reshape(mMinWidth, getRect().getHeight()); - - getChild<LLUICtrl>("client")->setValue(getString("client_text_msg", mStringArgs) ); - getChild<LLUICtrl>("network")->setValue(getString("network_text_msg",mStringArgs) ); - getChild<LLUICtrl>("server")->setValue(getString("server_text_msg", mStringArgs) ); - - // usually ">>" - button->setLabel( getString("bigger_label", mStringArgs) ); - } - // Don't put keyboard focus on the button - button->setFocus(FALSE); - -// self->mClientText->setVisible(self->mShrunk); -// self->mClientCause->setVisible(self->mShrunk); -// self->getChildView("client_help")->setVisible( self->mShrunk); - -// self->mNetworkText->setVisible(self->mShrunk); -// self->mNetworkCause->setVisible(self->mShrunk); -// self->getChildView("network_help")->setVisible( self->mShrunk); - -// self->mServerText->setVisible(self->mShrunk); -// self->mServerCause->setVisible(self->mShrunk); -// self->getChildView("server_help")->setVisible( self->mShrunk); - -// self->mShrunk = !self->mShrunk; -} - -BOOL LLFloaterLagMeter::isShrunk() -{ - return gSavedSettings.getBOOL("LagMeterShrunk"); -} - -void LLFloaterLagMeter::onClickShrink() // toggle "LagMeterShrunk" -{ - bool shrunk = isShrunk(); - updateControls(!shrunk); - gSavedSettings.setBOOL("LagMeterShrunk", !shrunk); -} diff --git a/indra/newview/llfloaterlagmeter.h b/indra/newview/llfloaterlagmeter.h deleted file mode 100755 index eef6955601..0000000000 --- a/indra/newview/llfloaterlagmeter.h +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file llfloaterlagmeter.h - * @brief The "Lag-o-Meter" floater used to tell users what is causing lag. - * - * $LicenseInfo:firstyear=2007&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 LLFLOATERLAGMETER_H -#define LLFLOATERLAGMETER_H - -#include "llfloater.h" - -class LLTextBox; - -class LLFloaterLagMeter : public LLFloater -{ - friend class LLFloaterReg; - -public: - /*virtual*/ void draw(); - /*virtual*/ BOOL postBuild(); -private: - - LLFloaterLagMeter(const LLSD& key); - /*virtual*/ ~LLFloaterLagMeter(); - void determineClient(); - void determineNetwork(); - void determineServer(); - void updateControls(bool shrink); - BOOL isShrunk(); - - void onClickShrink(); - - bool mShrunk; - S32 mMaxWidth, mMinWidth; - - F32 mClientFrameTimeCritical; - F32 mClientFrameTimeWarning; - LLButton * mClientButton; - LLTextBox * mClientText; - LLTextBox * mClientCause; - - F32 mNetworkPacketLossCritical; - F32 mNetworkPacketLossWarning; - F32 mNetworkPingCritical; - F32 mNetworkPingWarning; - LLButton * mNetworkButton; - LLTextBox * mNetworkText; - LLTextBox * mNetworkCause; - - F32 mServerFrameTimeCritical; - F32 mServerFrameTimeWarning; - F32 mServerSingleProcessMaxTime; - LLButton * mServerButton; - LLTextBox * mServerText; - LLTextBox * mServerCause; - - LLStringUtil::format_map_t mStringArgs; -}; - -#endif diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp index 8290494c22..2194c1112a 100755 --- a/indra/newview/llfloaterland.cpp +++ b/indra/newview/llfloaterland.cpp @@ -225,7 +225,7 @@ void LLFloaterLand::onOpen(const LLSD& key) refresh(); } -void LLFloaterLand::onVisibilityChange(const LLSD& visible) +void LLFloaterLand::onVisibilityChanged(const LLSD& visible) { if (!visible.asBoolean()) { @@ -255,7 +255,7 @@ LLFloaterLand::LLFloaterLand(const LLSD& seed) BOOL LLFloaterLand::postBuild() { - setVisibleCallback(boost::bind(&LLFloaterLand::onVisibilityChange, this, _2)); + setVisibleCallback(boost::bind(&LLFloaterLand::onVisibilityChanged, this, _2)); LLTabContainer* tab = getChild<LLTabContainer>("landtab"); diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h index 4f1c10274a..dccdfc9acb 100755 --- a/indra/newview/llfloaterland.h +++ b/indra/newview/llfloaterland.h @@ -88,7 +88,7 @@ private: LLFloaterLand(const LLSD& seed); virtual ~LLFloaterLand(); - void onVisibilityChange(const LLSD& visible); + void onVisibilityChanged(const LLSD& visible); protected: diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 100f1d580b..85fe901fde 100755 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -113,8 +113,6 @@ #include "llviewernetwork.h" #include "llviewershadermgr.h" #include "glod/glod.h" -#include <boost/algorithm/string.hpp> - const S32 SLM_SUPPORTED_VERSION = 3; @@ -3884,14 +3882,14 @@ void LLModelPreview::genLODs(S32 which_lod, U32 decimation, bool enforce_tri_lim for (LLModelLoader::scene::iterator iter = mBaseScene.begin(), endIter = mBaseScene.end(); iter != endIter; ++iter) { for (LLModelLoader::model_instance_list::iterator instance = iter->second.begin(), end_instance = iter->second.end(); instance != end_instance; ++instance) - { + { LLModel* mdl = instance->mModel; if (mdl) - { + { instanced_triangle_count += mdl->getNumTriangles(); } } - } + } //get the triangle count for the non-instanced set of models for (U32 i = 0; i < mBaseModel.size(); ++i) @@ -4232,28 +4230,28 @@ void LLModelPreview::updateStatusMessages() if (model) { //for each model in the lod - S32 cur_tris = 0; - S32 cur_verts = 0; + S32 cur_tris = 0; + S32 cur_verts = 0; S32 cur_submeshes = model->getNumVolumeFaces(); - for (S32 j = 0; j < cur_submeshes; ++j) - { //for each submesh (face), add triangles and vertices to current total + for (S32 j = 0; j < cur_submeshes; ++j) + { //for each submesh (face), add triangles and vertices to current total const LLVolumeFace& face = model->getVolumeFace(j); - cur_tris += face.mNumIndices/3; - cur_verts += face.mNumVertices; - } + cur_tris += face.mNumIndices/3; + cur_verts += face.mNumVertices; + } - //add this model to the lod total - total_tris[lod] += cur_tris; - total_verts[lod] += cur_verts; - total_submeshes[lod] += cur_submeshes; + //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); - } - } + //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); + } + } } } @@ -4442,28 +4440,28 @@ void LLModelPreview::updateStatusMessages() LLModel* model = instance->mModel; if (model) { - S32 cur_submeshes = model->getNumVolumeFaces(); + S32 cur_submeshes = model->getNumVolumeFaces(); - LLModel::convex_hull_decomposition& decomp = model->mPhysics.mHull; + LLModel::convex_hull_decomposition& decomp = model->mPhysics.mHull; - if (!decomp.empty()) - { - phys_hulls += decomp.size(); - for (U32 i = 0; i < decomp.size(); ++i) - { - phys_points += decomp[i].size(); - } - } - else - { //choose physics shape OR decomposition, can't use both - for (S32 j = 0; j < cur_submeshes; ++j) - { //for each submesh (face), add triangles and vertices to current total - const LLVolumeFace& face = model->getVolumeFace(j); - phys_tris += face.mNumIndices/3; - } - } + if (!decomp.empty()) + { + phys_hulls += decomp.size(); + for (U32 i = 0; i < decomp.size(); ++i) + { + phys_points += decomp[i].size(); } } + else + { //choose physics shape OR decomposition, can't use both + for (S32 j = 0; j < cur_submeshes; ++j) + { //for each submesh (face), add triangles and vertices to current total + const LLVolumeFace& face = model->getVolumeFace(j); + phys_tris += face.mNumIndices/3; + } + } + } + } } if (phys_tris > 0) diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp index 50c013a49d..bc8a208030 100755 --- a/indra/newview/llfloaterregioninfo.cpp +++ b/indra/newview/llfloaterregioninfo.cpp @@ -2545,8 +2545,6 @@ void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs, } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { @@ -2921,7 +2919,7 @@ void LLPanelEnvironmentInfo::onOpen(const LLSD& key) } // virtual -void LLPanelEnvironmentInfo::handleVisibilityChange(BOOL new_visibility) +void LLPanelEnvironmentInfo::onVisibilityChange(BOOL new_visibility) { // If hiding (user switched to another tab or closed the floater), // display user's preferred environment. diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h index f0499f1903..dd961e21b2 100755 --- a/indra/newview/llfloaterregioninfo.h +++ b/indra/newview/llfloaterregioninfo.h @@ -402,7 +402,7 @@ public: /*virtual*/ void onOpen(const LLSD& key); // LLView - /*virtual*/ void handleVisibilityChange(BOOL new_visibility); + /*virtual*/ void onVisibilityChange(BOOL new_visibility); // LLPanelRegionInfo /*virtual*/ bool refreshFromRegion(LLViewerRegion* region); diff --git a/indra/newview/llfloatersceneloadstats.cpp b/indra/newview/llfloatersceneloadstats.cpp new file mode 100644 index 0000000000..8aa93eae96 --- /dev/null +++ b/indra/newview/llfloatersceneloadstats.cpp @@ -0,0 +1,40 @@ +/** + * @file llfloatersceneloadstats.cpp + * @author Richard Nelson + * @brief debug floater for measuring various scene load statistics + * + * $LicenseInfo:firstyear=2001&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$ + */ + +#include "llviewerprecompiledheaders.h" + +#include "llfloatersceneloadstats.h" + + +LLFloaterSceneLoadStats::LLFloaterSceneLoadStats( const LLSD& key ) +: LLFloater(key) +{} + +BOOL LLFloaterSceneLoadStats::postBuild() +{ + return TRUE; +} diff --git a/indra/llprimitive/llvolumexml.h b/indra/newview/llfloatersceneloadstats.h index 9d4d989475..aa414bf544 100755..100644 --- a/indra/llprimitive/llvolumexml.h +++ b/indra/newview/llfloatersceneloadstats.h @@ -1,10 +1,10 @@ /** - * @file llvolumexml.h - * @brief LLVolumeXml base class + * @file llfloatersceneloadstats.h + * @brief debug floater for measuring various scene load statistics * * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. + * 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 @@ -24,22 +24,20 @@ * $/LicenseInfo$ */ -#ifndef LL_LLVOLUMEXML_H -#define LL_LLVOLUMEXML_H +#ifndef LL_FLOATERSCENELOADSTATS_H +#define LL_FLOATERSCENELOADSTATS_H -#include "llvolume.h" -#include "llxmlnode.h" +#include "llfloater.h" -// wrapper class for some volume/message functions -class LLVolumeXml +class LLFloaterSceneLoadStats : public LLFloater { -public: - static LLPointer<LLXMLNode> exportProfileParams(const LLProfileParams* params); + friend class LLFloaterReg; +private: + LLFloaterSceneLoadStats(const LLSD& key); - static LLPointer<LLXMLNode> exportPathParams(const LLPathParams* params); +public: + BOOL postBuild(); - static LLPointer<LLXMLNode> exportVolumeParams(const LLVolumeParams* params); }; -#endif // LL_LLVOLUMEXML_H - +#endif // LL_FLOATERSCENELOADSTATS_H diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp index d8d62e5bbb..285f52fcd6 100755 --- a/indra/newview/llfloatersnapshot.cpp +++ b/indra/newview/llfloatersnapshot.cpp @@ -478,7 +478,7 @@ void LLSnapshotLivePreview::draw() { if (mFlashAlpha < 1.f) { - mFlashAlpha = lerp(mFlashAlpha, 1.f, LLCriticalDamp::getInterpolant(0.02f)); + mFlashAlpha = lerp(mFlashAlpha, 1.f, LLSmoothInterpolation::getInterpolant(0.02f)); } else { @@ -487,7 +487,7 @@ void LLSnapshotLivePreview::draw() } else { - mFlashAlpha = lerp(mFlashAlpha, 0.f, LLCriticalDamp::getInterpolant(0.15f)); + mFlashAlpha = lerp(mFlashAlpha, 0.f, LLSmoothInterpolation::getInterpolant(0.15f)); } // Draw shining animation if appropriate. @@ -992,7 +992,7 @@ void LLSnapshotLivePreview::saveTexture() llwarns << "Error encoding snapshot" << llendl; } - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_SNAPSHOT_COUNT ); + add(LLStatViewer::SNAPSHOT, 1); mDataSize = 0; } diff --git a/indra/newview/llfollowcam.cpp b/indra/newview/llfollowcam.cpp index 47612fe25c..3110d0391f 100755 --- a/indra/newview/llfollowcam.cpp +++ b/indra/newview/llfollowcam.cpp @@ -327,11 +327,11 @@ void LLFollowCam::update() F32 force = focusOffsetDistance - focusThresholdNormalizedByDistance; */ - F32 focusLagLerp = LLCriticalDamp::getInterpolant( mFocusLag ); + F32 focusLagLerp = LLSmoothInterpolation::getInterpolant( mFocusLag ); focus_pt_agent = lerp( focus_pt_agent, whereFocusWantsToBe, focusLagLerp ); mSimulatedFocusGlobal = gAgent.getPosGlobalFromAgent(focus_pt_agent); } - mRelativeFocus = lerp(mRelativeFocus, (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation, LLCriticalDamp::getInterpolant(0.05f)); + mRelativeFocus = lerp(mRelativeFocus, (focus_pt_agent - mSubjectPosition) * ~mSubjectRotation, LLSmoothInterpolation::getInterpolant(0.05f)); }// if focus is not locked --------------------------------------------- @@ -414,7 +414,7 @@ void LLFollowCam::update() //------------------------------------------------------------------------------------------------- if ( distanceFromPositionToIdealPosition > mPositionThreshold ) { - F32 positionPullLerp = LLCriticalDamp::getInterpolant( mPositionLag ); + F32 positionPullLerp = LLSmoothInterpolation::getInterpolant( mPositionLag ); simulated_pos_agent = lerp( simulated_pos_agent, whereCameraPositionWantsToBe, positionPullLerp ); } @@ -434,7 +434,7 @@ void LLFollowCam::update() updateBehindnessConstraint(gAgent.getPosAgentFromGlobal(mSimulatedFocusGlobal), simulated_pos_agent); mSimulatedPositionGlobal = gAgent.getPosGlobalFromAgent(simulated_pos_agent); - mRelativePos = lerp(mRelativePos, (simulated_pos_agent - mSubjectPosition) * ~mSubjectRotation, LLCriticalDamp::getInterpolant(0.05f)); + mRelativePos = lerp(mRelativePos, (simulated_pos_agent - mSubjectPosition) * ~mSubjectRotation, LLSmoothInterpolation::getInterpolant(0.05f)); } // if position is not locked ----------------------------------------------------------- @@ -489,7 +489,7 @@ BOOL LLFollowCam::updateBehindnessConstraint(LLVector3 focus, LLVector3& cam_pos if ( cameraOffsetAngle > mBehindnessMaxAngle ) { - F32 fraction = ((cameraOffsetAngle - mBehindnessMaxAngle) / cameraOffsetAngle) * LLCriticalDamp::getInterpolant(mBehindnessLag); + F32 fraction = ((cameraOffsetAngle - mBehindnessMaxAngle) / cameraOffsetAngle) * LLSmoothInterpolation::getInterpolant(mBehindnessLag); cam_position = focus + horizontalSubjectBack * (slerp(fraction, camera_offset_rotation, LLQuaternion::DEFAULT)); cam_position.mV[VZ] = cameraZ; // clamp z value back to what it was before we started messing with it constraint_active = TRUE; diff --git a/indra/newview/llgesturemgr.cpp b/indra/newview/llgesturemgr.cpp index 9aa86297fc..876db96085 100755 --- a/indra/newview/llgesturemgr.cpp +++ b/indra/newview/llgesturemgr.cpp @@ -1139,8 +1139,6 @@ void LLGestureMgr::onLoadComplete(LLVFS *vfs, } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp index cbd844cdac..ba4927e622 100755 --- a/indra/newview/llgroupmgr.cpp +++ b/indra/newview/llgroupmgr.cpp @@ -41,6 +41,7 @@ #include "llui.h" #include "message.h" #include "roles_constants.h" +#include "llhttpclient.h" #include "lltransactiontypes.h" #include "llstatusbar.h" #include "lleconomy.h" @@ -50,6 +51,7 @@ #include "llnotificationsutil.h" #include "lluictrlfactory.h" #include "lltrans.h" +#include "llviewerregion.h" #include <boost/regex.hpp> #if LL_MSVC diff --git a/indra/newview/llhudicon.h b/indra/newview/llhudicon.h index 644daa0299..2bbc9c839d 100755 --- a/indra/newview/llhudicon.h +++ b/indra/newview/llhudicon.h @@ -28,7 +28,6 @@ #define LL_LLHUDICON_H #include "llpointer.h" -#include "lldarrayptr.h" #include "llhudobject.h" #include "v4color.h" @@ -42,8 +41,6 @@ #include "lldarray.h" // Renders a 2D icon billboard floating at the location specified. -class LLDrawable; -class LLViewerObject; class LLViewerTexture; class LLHUDIcon : public LLHUDObject diff --git a/indra/newview/llhudmanager.h b/indra/newview/llhudmanager.h index 09e79acbfc..effea8f034 100755 --- a/indra/newview/llhudmanager.h +++ b/indra/newview/llhudmanager.h @@ -30,13 +30,9 @@ // Responsible for managing all HUD elements. #include "llhudobject.h" -#include "lldarrayptr.h" +#include "lldarray.h" -class LLViewerObject; class LLHUDEffect; -//Ventrella 9/16/05 -class LLHUDAnimalControls; -// End Ventrella class LLMessageSystem; class LLHUDManager : public LLSingleton<LLHUDManager> @@ -59,7 +55,7 @@ public: static LLColor4 sChildColor; protected: - LLDynamicArrayPtr<LLPointer<LLHUDEffect> > mHUDEffects; + LLDynamicArray<LLPointer<LLHUDEffect>, 32> mHUDEffects; }; #endif // LL_LLHUDMANAGER_H diff --git a/indra/newview/llhudnametag.cpp b/indra/newview/llhudnametag.cpp index 3336097955..f43b478f60 100755 --- a/indra/newview/llhudnametag.cpp +++ b/indra/newview/llhudnametag.cpp @@ -30,6 +30,7 @@ #include "llhudnametag.h" #include "llrender.h" +#include "lltracerecording.h" #include "llagent.h" #include "llviewercontrol.h" @@ -310,7 +311,7 @@ void LLHUDNameTag::renderText(BOOL for_select) label_top_rect.mBottom = label_top_rect.mTop - label_height; LLColor4 label_top_color = text_color; label_top_color.mV[VALPHA] = gSavedSettings.getF32("ChatBubbleOpacity") * alpha_factor; - + rect_top_image->draw3D(render_position, x_pixel_vec, y_pixel_vec, label_top_rect, label_top_color); } @@ -737,8 +738,8 @@ void LLHUDNameTag::updateAll() current_screen_area += (F32)(textp->mSoftScreenRect.getWidth() * textp->mSoftScreenRect.getHeight()); } - LLStat* camera_vel_stat = LLViewerCamera::getInstance()->getVelocityStat(); - F32 camera_vel = camera_vel_stat->getCurrent(); + LLTrace::CountStatHandle<>* camera_vel_stat = LLViewerCamera::getVelocityStat(); + F32 camera_vel = LLTrace::get_frame_recording().getLastRecording().getPerSec(*camera_vel_stat); if (camera_vel > MAX_STABLE_CAMERA_VELOCITY) { return; @@ -806,7 +807,7 @@ void LLHUDNameTag::updateAll() VisibleTextObjectIterator this_object_it; for (this_object_it = sVisibleTextObjects.begin(); this_object_it != sVisibleTextObjects.end(); ++this_object_it) { - (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLCriticalDamp::getInterpolant(POSITION_DAMPING_TC)); + (*this_object_it)->mPositionOffset = lerp((*this_object_it)->mPositionOffset, (*this_object_it)->mTargetPositionOffset, LLSmoothInterpolation::getInterpolant(POSITION_DAMPING_TC)); } } diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp index 2c20409381..c62871236b 100755 --- a/indra/newview/llimview.cpp +++ b/indra/newview/llimview.cpp @@ -68,6 +68,7 @@ #include "llviewerparcelmgr.h" #include "llconversationlog.h" #include "message.h" +#include "llviewerregion.h" const static std::string ADHOC_NAME_SUFFIX(" Conference"); @@ -1051,7 +1052,7 @@ const std::string LLIMModel::getName(const LLUUID& session_id) const { LLIMSession* session = findIMSession(session_id); - if (!session) + if (!session) { llwarns << "session " << session_id << "does not exist " << llendl; return LLTrans::getString("no_session_message"); @@ -1561,7 +1562,7 @@ public: } void errorWithContent(U32 statusNum, const std::string& reason, const LLSD& content) - { + { llwarns << "LLViewerChatterBoxInvitationAcceptResponder error [status:" << statusNum << "]: " << content << llendl; //throw something back to the viewer here? @@ -2684,7 +2685,7 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess LLChat chat(message); chat.mSourceType = CHAT_SOURCE_SYSTEM; - + LLFloaterIMNearbyChat* nearby_chat = LLFloaterReg::findTypedInstance<LLFloaterIMNearbyChat>("nearby_chat"); if (nearby_chat) { diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h index da6039a3ae..2d036cbc2f 100755 --- a/indra/newview/llimview.h +++ b/indra/newview/llimview.h @@ -33,13 +33,12 @@ #include "lllogchat.h" #include "llvoicechannel.h" - +#include "lldarray.h" class LLAvatarName; class LLFriendObserver; class LLCallDialogManager; class LLIMSpeakerMgr; - /** * Timeout Timer for outgoing Ad-Hoc/Group IM sessions which being initialized by the server */ @@ -557,7 +556,7 @@ public: mAvatarNameCacheConnection.disconnect(); } } - + /*virtual*/ BOOL postBuild(); /*virtual*/ void onOpen(const LLSD& key); diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp index 9c6db3676f..ce9f17663c 100755 --- a/indra/newview/llinspectavatar.cpp +++ b/indra/newview/llinspectavatar.cpp @@ -67,7 +67,7 @@ public: // Inspector will be positioned relative to current mouse position LLInspectAvatar(const LLSD& avatar_id); virtual ~LLInspectAvatar(); - + /*virtual*/ BOOL postBuild(void); // Because floater is single instance, need to re-parse data on each spawn @@ -83,7 +83,7 @@ private: // Make network requests for all the data to display in this view. // Used on construction and if avatar id changes. void requestUpdate(); - + // Set the volume slider to this user's current client-side volume setting, // hiding/disabling if the user is not nearby. void updateVolumeSlider(); @@ -221,7 +221,7 @@ void LLInspectAvatar::onOpen(const LLSD& data) requestUpdate(); updateVolumeSlider(); -} +} void LLInspectAvatar::requestUpdate() { diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index a5043a30ac..d05bdd0a6d 100755 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -70,6 +70,7 @@ #include "llviewermenu.h" #include "llviewermessage.h" #include "llviewerobjectlist.h" +#include "llviewerregion.h" #include "llviewerwindow.h" #include "llvoavatarself.h" #include "llwearablelist.h" @@ -3222,7 +3223,7 @@ void LLFolderBridge::pasteFromClipboard() LLViewerInventoryCategory* vicat = (LLViewerInventoryCategory *) model->getCategory(item_id); llassert(vicat); if (vicat) - { + { //changeCategoryParent() implicity calls dirtyFilter changeCategoryParent(model, vicat, parent_id, FALSE); } diff --git a/indra/newview/llinventoryicon.cpp b/indra/newview/llinventoryicon.cpp index 02a2475cfd..b7c4ec6f8b 100755 --- a/indra/newview/llinventoryicon.cpp +++ b/indra/newview/llinventoryicon.cpp @@ -32,6 +32,7 @@ #include "lldictionary.h" #include "llinventorydefines.h" #include "llui.h" +#include "lluiimage.h" #include "llwearabletype.h" struct IconEntry : public LLDictionaryEntry @@ -49,6 +50,8 @@ public: LLIconDictionary(); }; +typedef LLPointer<LLUIImage> LLUIImagePtr; + LLIconDictionary::LLIconDictionary() { addEntry(LLInventoryType::ICONNAME_TEXTURE, new IconEntry("Inv_Texture")); diff --git a/indra/newview/llinventoryicon.h b/indra/newview/llinventoryicon.h index 2197c53bb8..bc09e32087 100755 --- a/indra/newview/llinventoryicon.h +++ b/indra/newview/llinventoryicon.h @@ -30,7 +30,6 @@ #include "llassettype.h" #include "llinventorytype.h" -#include "lluiimage.h" class LLInventoryIcon { @@ -41,11 +40,11 @@ public: BOOL item_is_multi = FALSE); static const std::string& getIconName(LLInventoryType::EIconName idx); - static LLUIImagePtr getIcon(LLAssetType::EType asset_type, + static LLPointer<class LLUIImage> getIcon(LLAssetType::EType asset_type, LLInventoryType::EType inventory_type = LLInventoryType::IT_NONE, U32 misc_flag = 0, // different meanings depending on item type BOOL item_is_multi = FALSE); - static LLUIImagePtr getIcon(LLInventoryType::EIconName idx); + static LLPointer<class LLUIImage> getIcon(LLInventoryType::EIconName idx); protected: static LLInventoryType::EIconName assignWearableIcon(U32 misc_flag); diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h index 8aac879a93..964adf5e50 100755 --- a/indra/newview/llinventorymodel.h +++ b/indra/newview/llinventorymodel.h @@ -31,7 +31,7 @@ #include "llfoldertype.h" #include "lldarray.h" #include "llframetimer.h" -#include "llhttpclient.h" +#include "llcurl.h" #include "lluuid.h" #include "llpermissionsflags.h" #include "llstring.h" @@ -79,7 +79,7 @@ public: typedef LLDynamicArray<LLPointer<LLViewerInventoryItem> > item_array_t; typedef std::set<LLUUID> changed_items_t; - class fetchInventoryResponder : public LLHTTPClient::Responder + class fetchInventoryResponder : public LLCurl::Responder { public: fetchInventoryResponder(const LLSD& request_sd) : mRequestSD(request_sd) {}; diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp index cf1fd4c0d0..bd3c70b7f5 100755 --- a/indra/newview/llinventorypanel.cpp +++ b/indra/newview/llinventorypanel.cpp @@ -396,9 +396,10 @@ LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState() return getFilter().getShowFolderState(); } +static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh"); + void LLInventoryPanel::modelChanged(U32 mask) { - static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh"); LLFastTimer t2(FTM_REFRESH); if (!mViewsInitialized) return; @@ -733,7 +734,7 @@ LLFolderViewItem * LLInventoryPanel::createFolderViewItem(LLInvFVBridge * bridge params.listener = bridge; params.rect = LLRect (0, 0, 0, 0); params.tool_tip = params.name; - + params.font_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultColor)); params.font_highlight_color = (bridge->isLibraryItem() ? sLibraryColor : (bridge->isLink() ? sLinkColor : sDefaultHighlightColor)); diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index dd402de394..2a131eff58 100755 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -141,7 +141,6 @@ void LLLandmarkList::processGetAssetReply( } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); // SJB: No use case for a notification here. Use lldebugs instead if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status ) { diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 25df4889b0..33143b4671 100755 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -48,6 +48,7 @@ /* misc headers */ #include "llscrolllistctrl.h" #include "llfilepicker.h" +#include "lllocaltextureobject.h" #include "llviewertexturelist.h" #include "llviewerobjectlist.h" #include "llviewerobject.h" diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index 580b6dfa7e..b404345799 100755 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -30,11 +30,11 @@ #include "llavatarappearancedefines.h" #include "lleventtimer.h" -#include "llimage.h" #include "llpointer.h" #include "llwearabletype.h" class LLScrollListCtrl; +class LLImageRaw; class LLViewerObject; class LLLocalBitmap diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp index d79f1040bb..9b05c75617 100755 --- a/indra/newview/llmaniprotate.cpp +++ b/indra/newview/llmaniprotate.cpp @@ -240,7 +240,7 @@ void LLManipRotate::render() if (mManipPart == LL_ROT_Z) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.pushMatrix(); { // selected part @@ -251,7 +251,7 @@ void LLManipRotate::render() } else if (mManipPart == LL_ROT_Y) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.pushMatrix(); { gGL.rotatef( 90.f, 1.f, 0.f, 0.f ); @@ -262,7 +262,7 @@ void LLManipRotate::render() } else if (mManipPart == LL_ROT_X) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.pushMatrix(); { gGL.rotatef( 90.f, 0.f, 1.f, 0.f ); @@ -273,13 +273,13 @@ void LLManipRotate::render() } else if (mManipPart == LL_ROT_ROLL) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); } else if (mManipPart == LL_NO_PART) { if (mHighlightedPart == LL_NO_PART) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); } LLGLEnable cull_face(GL_CULL_FACE); @@ -294,7 +294,7 @@ void LLManipRotate::render() { if (mHighlightedPart == LL_ROT_Z) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.scalef(mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ], mManipulatorScales.mV[VZ]); // hovering over part gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 0.f, 1.f, 1.f ), LLColor4( 0.f, 0.f, 1.f, 0.5f ), CIRCLE_STEPS, i); @@ -312,7 +312,7 @@ void LLManipRotate::render() gGL.rotatef( 90.f, 1.f, 0.f, 0.f ); if (mHighlightedPart == LL_ROT_Y) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.scalef(mManipulatorScales.mV[VY], mManipulatorScales.mV[VY], mManipulatorScales.mV[VY]); // hovering over part gl_ring( mRadiusMeters, width_meters, LLColor4( 0.f, 1.f, 0.f, 1.f ), LLColor4( 0.f, 1.f, 0.f, 0.5f ), CIRCLE_STEPS, i); @@ -330,7 +330,7 @@ void LLManipRotate::render() gGL.rotatef( 90.f, 0.f, 1.f, 0.f ); if (mHighlightedPart == LL_ROT_X) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); gGL.scalef(mManipulatorScales.mV[VX], mManipulatorScales.mV[VX], mManipulatorScales.mV[VX]); // hovering over part @@ -346,7 +346,7 @@ void LLManipRotate::render() if (mHighlightedPart == LL_ROT_ROLL) { - mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales = lerp(mManipulatorScales, LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE), LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); } } diff --git a/indra/newview/llmanipscale.cpp b/indra/newview/llmanipscale.cpp index ae0884ac5d..15788d6ffd 100755 --- a/indra/newview/llmanipscale.cpp +++ b/indra/newview/llmanipscale.cpp @@ -535,11 +535,11 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) { if (mHighlightedPart == MANIPULATOR_IDS[i]) { - mManipulatorScales[i] = lerp(mManipulatorScales[i], SELECTED_MANIPULATOR_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales[i] = lerp(mManipulatorScales[i], SELECTED_MANIPULATOR_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); } else { - mManipulatorScales[i] = lerp(mManipulatorScales[i], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); + mManipulatorScales[i] = lerp(mManipulatorScales[i], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE)); } } diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp index b62db70ec8..01337cfaed 100755 --- a/indra/newview/llmaniptranslate.cpp +++ b/indra/newview/llmaniptranslate.cpp @@ -1904,18 +1904,18 @@ void LLManipTranslate::renderTranslationHandles() { if (index == mManipPart - LL_X_ARROW || index == mHighlightedPart - LL_X_ARROW) { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); } else if (index == mManipPart - LL_YZ_PLANE || index == mHighlightedPart - LL_YZ_PLANE) { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], SELECTED_ARROW_SCALE, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); } else { - mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); - mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mArrowScales.mV[index] = lerp(mArrowScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); + mPlaneScales.mV[index] = lerp(mPlaneScales.mV[index], 1.f, LLSmoothInterpolation::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE )); } } diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp index 2075aeed63..9298d6952f 100755 --- a/indra/newview/llmediactrl.cpp +++ b/indra/newview/llmediactrl.cpp @@ -392,7 +392,7 @@ BOOL LLMediaCtrl::postBuild () mContextMenu = LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>( "menu_media_ctrl.xml", LLMenuGL::sMenuContainer, LLViewerMenuHolderGL::child_registry_t::instance()); - setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChange, this, _2)); + setVisibleCallback(boost::bind(&LLMediaCtrl::onVisibilityChanged, this, _2)); return TRUE; } @@ -422,7 +422,7 @@ BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask ) //////////////////////////////////////////////////////////////////////////////// // -void LLMediaCtrl::handleVisibilityChange ( BOOL new_visibility ) +void LLMediaCtrl::onVisibilityChange ( BOOL new_visibility ) { llinfos << "visibility changed to " << (new_visibility?"true":"false") << llendl; if(mMediaSource) @@ -450,7 +450,7 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char) //////////////////////////////////////////////////////////////////////////////// // -void LLMediaCtrl::onVisibilityChange ( const LLSD& new_visibility ) +void LLMediaCtrl::onVisibilityChanged ( const LLSD& new_visibility ) { // set state of frequent updates automatically if visibility changes if ( new_visibility.asBoolean() ) diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h index 7f2a5e1642..db501cdb8c 100755 --- a/indra/newview/llmediactrl.h +++ b/indra/newview/llmediactrl.h @@ -149,7 +149,7 @@ public: // over-rides virtual BOOL handleKeyHere( KEY key, MASK mask); - virtual void handleVisibilityChange ( BOOL new_visibility ); + virtual void onVisibilityChange ( BOOL new_visibility ); virtual BOOL handleUnicodeCharHere(llwchar uni_char); virtual void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE); virtual void draw(); @@ -171,7 +171,7 @@ public: void convertInputCoords(S32& x, S32& y); private: - void onVisibilityChange ( const LLSD& new_visibility ); + void onVisibilityChanged ( const LLSD& new_visibility ); void onPopup(const LLSD& notification, const LLSD& response); const S32 mTextureDepthBytes; diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp index b47fe9d4b1..55347039ac 100755 --- a/indra/newview/llmeshrepository.cpp +++ b/indra/newview/llmeshrepository.cpp @@ -26,8 +26,7 @@ #include "llviewerprecompiledheaders.h" -#include "apr_pools.h" -#include "apr_dso.h" +#include "llapr.h" #include "llhttpstatuscodes.h" #include "llmeshrepository.h" diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp index dea90b9042..7cf1d177ac 100755 --- a/indra/newview/llnetmap.cpp +++ b/indra/newview/llnetmap.cpp @@ -162,7 +162,7 @@ void LLNetMap::draw() static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); if (auto_center) { - mCurPan = lerp(mCurPan, mTargetPan, LLCriticalDamp::getInterpolant(0.1f)); + mCurPan = lerp(mCurPan, mTargetPan, LLSmoothInterpolation::getInterpolant(0.1f)); } // Prepare a scissor region diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp index 862e4be203..50d0b4256b 100755 --- a/indra/newview/llpanelclassified.cpp +++ b/indra/newview/llpanelclassified.cpp @@ -52,6 +52,7 @@ #include "llfloaterworldmap.h" #include "llviewergenericmessage.h" // send_generic_message #include "llviewerregion.h" +#include "llviewertexture.h" #include "lltrans.h" #include "llscrollcontainer.h" #include "llstatusbar.h" diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index e71dba5cae..a499fa1d87 100755 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -30,6 +30,7 @@ #include "llpanel.h" #include "llviewerwearable.h" #include "lluictrl.h" +#include "lllocaltextureobject.h" #include "llscrollingpanellist.h" #include "llvisualparam.h" #include "lltoolmorph.h" diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index 445c0d811f..ef5b803f70 100755 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -1048,7 +1048,7 @@ BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item) void LLPanelFace::onCommitTexture( const LLSD& data ) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); + add(LLStatViewer::EDIT_TEXTURE, 1); sendTexture(); } diff --git a/indra/newview/llpanelnearbymedia.cpp b/indra/newview/llpanelnearbymedia.cpp index a50d9074f7..74c810ea79 100755 --- a/indra/newview/llpanelnearbymedia.cpp +++ b/indra/newview/llpanelnearbymedia.cpp @@ -202,7 +202,7 @@ void LLPanelNearByMedia::onTopLost() /*virtual*/ -void LLPanelNearByMedia::handleVisibilityChange ( BOOL new_visibility ) +void LLPanelNearByMedia::onVisibilityChange ( BOOL new_visibility ) { if (new_visibility) { diff --git a/indra/newview/llpanelnearbymedia.h b/indra/newview/llpanelnearbymedia.h index c3634de9b4..a9c1b190cf 100755 --- a/indra/newview/llpanelnearbymedia.h +++ b/indra/newview/llpanelnearbymedia.h @@ -48,7 +48,7 @@ public: /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); /*virtual*/ void onTopLost(); - /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); + /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index c09d4393c8..7648e12f96 100755 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -169,7 +169,7 @@ public: return menu; } - + private: static void onCreate(const LLSD& param) { @@ -481,7 +481,7 @@ BOOL LLPanelOutfitEdit::postBuild() childSetCommitCallback("shop_btn_1", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL); childSetCommitCallback("shop_btn_2", boost::bind(&LLPanelOutfitEdit::onShopButtonClicked, this), NULL); - setVisibleCallback(boost::bind(&LLPanelOutfitEdit::onVisibilityChange, this, _2)); + setVisibleCallback(boost::bind(&LLPanelOutfitEdit::onVisibilityChanged, this, _2)); mWearablesGearMenuBtn = getChild<LLMenuButton>("wearables_gear_menu_btn"); mGearMenuBtn = getChild<LLMenuButton>("gear_menu_btn"); @@ -767,7 +767,7 @@ void LLPanelOutfitEdit::onPlusBtnClicked(void) } } -void LLPanelOutfitEdit::onVisibilityChange(const LLSD &in_visible_chain) +void LLPanelOutfitEdit::onVisibilityChanged(const LLSD &in_visible_chain) { showAddWearablesPanel(false); mWearableItemsList->resetSelection(); diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 5d4b8d4644..30870daf40 100755 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -145,7 +145,7 @@ public: void updatePlusButton(); void onPlusBtnClicked(void); - void onVisibilityChange(const LLSD &in_visible_chain); + void onVisibilityChanged(const LLSD &in_visible_chain); void applyFolderViewFilter(EFolderViewItemType type); void applyListViewFilter(EListViewItemType type); diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h index 4740964dee..123e2891d6 100755 --- a/indra/newview/llpanelpeople.h +++ b/indra/newview/llpanelpeople.h @@ -38,6 +38,7 @@ class LLFilterEditor; class LLGroupList; class LLMenuButton; class LLTabContainer; +class LLNetMap; class LLPanelPeople : public LLPanel diff --git a/indra/newview/llpanelpermissions.cpp b/indra/newview/llpanelpermissions.cpp index 131e8e9359..79bcf15c1d 100755 --- a/indra/newview/llpanelpermissions.cpp +++ b/indra/newview/llpanelpermissions.cpp @@ -913,7 +913,6 @@ bool callback_deed_to_group(const LLSD& notification, const LLSD& response) if(group_id.notNull() && groups_identical && (gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED))) { LLSelectMgr::getInstance()->sendOwner(LLUUID::null, group_id, FALSE); -// LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT); } } return false; diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp index 5d9971c16c..da201ca36a 100755 --- a/indra/newview/llpanelplaceprofile.cpp +++ b/indra/newview/llpanelplaceprofile.cpp @@ -302,9 +302,9 @@ void LLPanelPlaceProfile::processParcelInfo(const LLParcelData& parcel_data) } // virtual -void LLPanelPlaceProfile::handleVisibilityChange(BOOL new_visibility) +void LLPanelPlaceProfile::onVisibilityChange(BOOL new_visibility) { - LLPanel::handleVisibilityChange(new_visibility); + LLPanel::onVisibilityChange(new_visibility); LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance(); if (!parcel_mgr) diff --git a/indra/newview/llpanelplaceprofile.h b/indra/newview/llpanelplaceprofile.h index f4c6145881..01adfd4940 100755 --- a/indra/newview/llpanelplaceprofile.h +++ b/indra/newview/llpanelplaceprofile.h @@ -38,7 +38,7 @@ class LLPanelPlaceProfile : public LLPanelPlaceInfo public: LLPanelPlaceProfile(); /*virtual*/ ~LLPanelPlaceProfile(); - + /*virtual*/ BOOL postBuild(); /*virtual*/ void resetLocation(); @@ -47,7 +47,7 @@ public: /*virtual*/ void processParcelInfo(const LLParcelData& parcel_data); - /*virtual*/ void handleVisibilityChange(BOOL new_visibility); + /*virtual*/ void onVisibilityChange(BOOL new_visibility); // Displays information about the currently selected parcel // without sending a request to the server. diff --git a/indra/newview/llpanelplaces.cpp b/indra/newview/llpanelplaces.cpp index 6c2a01fc82..dc18cc6081 100755 --- a/indra/newview/llpanelplaces.cpp +++ b/indra/newview/llpanelplaces.cpp @@ -998,9 +998,9 @@ void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible) } // virtual -void LLPanelPlaces::handleVisibilityChange(BOOL new_visibility) +void LLPanelPlaces::onVisibilityChange(BOOL new_visibility) { - LLPanel::handleVisibilityChange(new_visibility); + LLPanel::onVisibilityChange(new_visibility); if (!new_visibility && mPlaceInfoType == AGENT_INFO_TYPE) { diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h index 85bdc2c4e1..b6019ca32e 100755 --- a/indra/newview/llpanelplaces.h +++ b/indra/newview/llpanelplaces.h @@ -102,7 +102,7 @@ private: void togglePickPanel(BOOL visible); void togglePlaceInfoPanel(BOOL visible); - /*virtual*/ void handleVisibilityChange(BOOL new_visibility); + /*virtual*/ void onVisibilityChange(BOOL new_visibility); void updateVerbs(); diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index e2e7006773..435797bf80 100755 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -36,6 +36,7 @@ #include "lltabcontainer.h" #include "llviewercontrol.h" #include "llviewernetwork.h" +#include "llweb.h" static const std::string PANEL_PICKS = "panel_picks"; diff --git a/indra/newview/llpaneltopinfobar.cpp b/indra/newview/llpaneltopinfobar.cpp index 9dd665198f..3830847d74 100755 --- a/indra/newview/llpaneltopinfobar.cpp +++ b/indra/newview/llpaneltopinfobar.cpp @@ -169,7 +169,7 @@ BOOL LLPanelTopInfoBar::postBuild() mParcelMgrConnection = LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback( boost::bind(&LLPanelTopInfoBar::onAgentParcelChange, this)); - setVisibleCallback(boost::bind(&LLPanelTopInfoBar::onVisibilityChange, this, _2)); + setVisibleCallback(boost::bind(&LLPanelTopInfoBar::onVisibilityChanged, this, _2)); return TRUE; } @@ -186,7 +186,7 @@ void LLPanelTopInfoBar::onNavBarShowParcelPropertiesCtrlChanged() // when panel is shown, all minimized floaters should be shifted downwards to prevent overlapping of // PanelTopInfoBar. See EXT-7951. -void LLPanelTopInfoBar::onVisibilityChange(const LLSD& show) +void LLPanelTopInfoBar::onVisibilityChanged(const LLSD& show) { // this height is used as a vertical offset for ALREADY MINIMIZED floaters // when PanelTopInfoBar visibility changes diff --git a/indra/newview/llpaneltopinfobar.h b/indra/newview/llpaneltopinfobar.h index d58d95be90..f37bd9c048 100755 --- a/indra/newview/llpaneltopinfobar.h +++ b/indra/newview/llpaneltopinfobar.h @@ -57,7 +57,7 @@ public: /** * Called when the top info bar gets shown or hidden */ - void onVisibilityChange(const LLSD& show); + void onVisibilityChanged(const LLSD& show); boost::signals2::connection setResizeCallback( const resize_signal_t::slot_type& cb ); diff --git a/indra/newview/llpanelvoicedevicesettings.cpp b/indra/newview/llpanelvoicedevicesettings.cpp index 6be2ea6481..1782afddd9 100755 --- a/indra/newview/llpanelvoicedevicesettings.cpp +++ b/indra/newview/llpanelvoicedevicesettings.cpp @@ -85,7 +85,7 @@ BOOL LLPanelVoiceDeviceSettings::postBuild() } // virtual -void LLPanelVoiceDeviceSettings::handleVisibilityChange ( BOOL new_visibility ) +void LLPanelVoiceDeviceSettings::onVisibilityChange ( BOOL new_visibility ) { if (new_visibility) { diff --git a/indra/newview/llpanelvoicedevicesettings.h b/indra/newview/llpanelvoicedevicesettings.h index ba3bcad0dc..83464f476a 100755 --- a/indra/newview/llpanelvoicedevicesettings.h +++ b/indra/newview/llpanelvoicedevicesettings.h @@ -44,7 +44,7 @@ public: void initialize(); void cleanup(); - /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); + /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); void setUseTuningMode(bool use) { mUseTuningMode = use; }; diff --git a/indra/newview/llpanelvoiceeffect.cpp b/indra/newview/llpanelvoiceeffect.cpp index 5fec6d967d..59ed53815b 100755 --- a/indra/newview/llpanelvoiceeffect.cpp +++ b/indra/newview/llpanelvoiceeffect.cpp @@ -35,6 +35,7 @@ #include "lltrans.h" #include "lltransientfloatermgr.h" #include "llvoiceclient.h" +#include "llweb.h" static LLRegisterPanelClassWrapper<LLPanelVoiceEffect> t_panel_voice_effect("panel_voice_effect"); diff --git a/indra/newview/llpanelvolumepulldown.cpp b/indra/newview/llpanelvolumepulldown.cpp index aea7b33d7f..cb00f742cc 100755 --- a/indra/newview/llpanelvolumepulldown.cpp +++ b/indra/newview/llpanelvolumepulldown.cpp @@ -87,7 +87,7 @@ void LLPanelVolumePulldown::onMouseLeave(S32 x, S32 y, MASK mask) } /*virtual*/ -void LLPanelVolumePulldown::handleVisibilityChange ( BOOL new_visibility ) +void LLPanelVolumePulldown::onVisibilityChange ( BOOL new_visibility ) { if (new_visibility) { diff --git a/indra/newview/llpanelvolumepulldown.h b/indra/newview/llpanelvolumepulldown.h index 0d86e6bd28..b843fab756 100755 --- a/indra/newview/llpanelvolumepulldown.h +++ b/indra/newview/llpanelvolumepulldown.h @@ -42,7 +42,7 @@ class LLPanelVolumePulldown : public LLPanel /*virtual*/ void onMouseEnter(S32 x, S32 y, MASK mask); /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask); /*virtual*/ void onTopLost(); - /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); + /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); /*virtual*/ BOOL postBuild(); private: diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp index f47928b131..bda603262d 100755 --- a/indra/newview/llpreviewgesture.cpp +++ b/indra/newview/llpreviewgesture.cpp @@ -253,7 +253,7 @@ void LLPreviewGesture::onUpdateSucceeded() refresh(); } -void LLPreviewGesture::onVisibilityChange ( const LLSD& new_visibility ) +void LLPreviewGesture::onVisibilityChanged ( const LLSD& new_visibility ) { if (new_visibility.asBoolean()) { @@ -333,7 +333,7 @@ LLPreviewGesture::~LLPreviewGesture() BOOL LLPreviewGesture::postBuild() { - setVisibleCallback(boost::bind(&LLPreviewGesture::onVisibilityChange, this, _2)); + setVisibleCallback(boost::bind(&LLPreviewGesture::onVisibilityChanged, this, _2)); LLLineEditor* edit; LLComboBox* combo; @@ -883,8 +883,6 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs, } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { diff --git a/indra/newview/llpreviewgesture.h b/indra/newview/llpreviewgesture.h index fd4fcf9d8f..7ce5706a0d 100755 --- a/indra/newview/llpreviewgesture.h +++ b/indra/newview/llpreviewgesture.h @@ -102,7 +102,7 @@ protected: // "Sound", "Chat", or "Wait" LLScrollListItem* addStep(const enum EStepType step_type); - void onVisibilityChange ( const LLSD& new_visibility ); + void onVisibilityChanged ( const LLSD& new_visibility ); static std::string getLabel(std::vector<std::string> labels); static void updateLabel(LLScrollListItem* item); diff --git a/indra/newview/llpreviewnotecard.cpp b/indra/newview/llpreviewnotecard.cpp index 3a9360fd23..97c9de4b72 100755 --- a/indra/newview/llpreviewnotecard.cpp +++ b/indra/newview/llpreviewnotecard.cpp @@ -339,8 +339,6 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs, } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp index 968a912ea2..516ecedbc8 100755 --- a/indra/newview/llpreviewscript.cpp +++ b/indra/newview/llpreviewscript.cpp @@ -946,7 +946,7 @@ void LLScriptEdCore::onBtnInsertFunction(LLUICtrl *ui, void* userdata) void LLScriptEdCore::doSave( BOOL close_after_save ) { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_LSL_SAVE_COUNT ); + add(LLStatViewer::LSL_SAVES, 1); if( mSaveCallback ) { @@ -1150,8 +1150,7 @@ void LLScriptEdCore::onBtnLoadFromFile( void* data ) void LLScriptEdCore::onBtnSaveToFile( void* userdata ) { - - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_LSL_SAVE_COUNT ); + add(LLStatViewer::LSL_SAVES, 1); LLScriptEdCore* self = (LLScriptEdCore*) userdata; @@ -1674,8 +1673,6 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { @@ -1906,8 +1903,6 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id, } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { diff --git a/indra/newview/llscenemonitor.cpp b/indra/newview/llscenemonitor.cpp new file mode 100644 index 0000000000..dccf8a2a17 --- /dev/null +++ b/indra/newview/llscenemonitor.cpp @@ -0,0 +1,698 @@ +/** + * @file llscenemonitor.cpp + * @brief monitor the scene loading process. + * + * $LicenseInfo:firstyear=2003&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 "llviewerprecompiledheaders.h" +#include "llrendertarget.h" +#include "llscenemonitor.h" +#include "llviewerwindow.h" +#include "llviewerdisplay.h" +#include "llviewercontrol.h" +#include "llviewershadermgr.h" +#include "llui.h" +#include "llstartup.h" +#include "llappviewer.h" +#include "llwindow.h" +#include "llpointer.h" +#include "llspatialpartition.h" +#include "llagent.h" +#include "pipeline.h" +#include "llviewerpartsim.h" + +LLSceneMonitorView* gSceneMonitorView = NULL; + +// +//The procedures of monitoring when the scene finishes loading visually, +//i.e., no pixel differences among frames, are: +//1, freeze all dynamic objects and avatars; +//2, (?) disable all sky and water; +//3, capture frames periodically, by calling "capture()"; +//4, compute pixel differences between two latest captured frames, by calling "compare()", results are stored at mDiff; +//5, compute the number of pixels in mDiff above some tolerance threshold in GPU, by calling "calcDiffAggregate()"; +//6, use gl occlusion query to fetch the result from GPU, by calling "fetchQueryResult()"; +//END. +// + +LLSceneMonitor::LLSceneMonitor() : + mEnabled(false), + mDiff(NULL), + mDiffResult(0.f), + mDiffTolerance(0.1f), + mDiffState(WAITING_FOR_NEXT_DIFF), + mDebugViewerVisible(false), + mQueryObject(0), + mDiffPixelRatio(0.5f) +{ + mFrames[0] = NULL; + mFrames[1] = NULL; +} + +LLSceneMonitor::~LLSceneMonitor() +{ + mDiffState = VIEWER_QUITTING; + reset(); + + mDitheringTexture = NULL; +} + +void LLSceneMonitor::reset() +{ + delete mFrames[0]; + delete mFrames[1]; + delete mDiff; + + mFrames[0] = NULL; + mFrames[1] = NULL; + mDiff = NULL; + + mMonitorRecording.reset(); + mSceneLoadRecording.reset(); + + unfreezeScene(); + + if(mQueryObject > 0) + { + LLOcclusionCullingGroup::releaseOcclusionQueryObjectName(mQueryObject); + mQueryObject = 0; + } +} + +void LLSceneMonitor::generateDitheringTexture(S32 width, S32 height) +{ +#if 1 + //4 * 4 matrix + mDitherMatrixWidth = 4; + S32 dither_matrix[4][4] = + { + {1, 9, 3, 11}, + {13, 5, 15, 7}, + {4, 12, 2, 10}, + {16, 8, 14, 6} + }; + + mDitherScale = 255.f / 17; +#else + //8 * 8 matrix + mDitherMatrixWidth = 16; + S32 dither_matrix[16][16] = + { + {1, 49, 13, 61, 4, 52, 16, 64, 1, 49, 13, 61, 4, 52, 16, 64}, + {33, 17, 45, 29, 36, 20, 48, 32, 33, 17, 45, 29, 36, 20, 48, 32}, + {9, 57, 5, 53, 12, 60, 8, 56, 9, 57, 5, 53, 12, 60, 8, 56}, + {41, 25, 37, 21, 44, 28, 40, 24, 41, 25, 37, 21, 44, 28, 40, 24}, + {3, 51, 15, 63, 2, 50, 14, 62, 3, 51, 15, 63, 2, 50, 14, 62}, + {35, 19, 47, 31, 34, 18, 46, 30, 35, 19, 47, 31, 34, 18, 46, 30}, + {11, 59, 7, 55, 10, 58, 6, 54, 11, 59, 7, 55, 10, 58, 6, 54}, + {43, 27, 39, 23, 42, 26, 38, 22, 43, 27, 39, 23, 42, 26, 38, 22}, + {1, 49, 13, 61, 4, 52, 16, 64, 1, 49, 13, 61, 4, 52, 16, 64}, + {33, 17, 45, 29, 36, 20, 48, 32, 33, 17, 45, 29, 36, 20, 48, 32}, + {9, 57, 5, 53, 12, 60, 8, 56, 9, 57, 5, 53, 12, 60, 8, 56}, + {41, 25, 37, 21, 44, 28, 40, 24, 41, 25, 37, 21, 44, 28, 40, 24}, + {3, 51, 15, 63, 2, 50, 14, 62, 3, 51, 15, 63, 2, 50, 14, 62}, + {35, 19, 47, 31, 34, 18, 46, 30, 35, 19, 47, 31, 34, 18, 46, 30}, + {11, 59, 7, 55, 10, 58, 6, 54, 11, 59, 7, 55, 10, 58, 6, 54}, + {43, 27, 39, 23, 42, 26, 38, 22, 43, 27, 39, 23, 42, 26, 38, 22} + }; + + mDitherScale = 255.f / 65; +#endif + + LLPointer<LLImageRaw> image_raw = new LLImageRaw(mDitherMatrixWidth, mDitherMatrixWidth, 3); + U8* data = image_raw->getData(); + for (S32 i = 0; i < mDitherMatrixWidth; i++) + { + for (S32 j = 0; j < mDitherMatrixWidth; j++) + { + U8 val = dither_matrix[i][j]; + *data++ = val; + *data++ = val; + *data++ = val; + } + } + + mDitheringTexture = LLViewerTextureManager::getLocalTexture(image_raw.get(), FALSE) ; + mDitheringTexture->setAddressMode(LLTexUnit::TAM_WRAP); + mDitheringTexture->setFilteringOption(LLTexUnit::TFO_POINT); + + mDitherScaleS = (F32)width / mDitherMatrixWidth; + mDitherScaleT = (F32)height / mDitherMatrixWidth; +} + +void LLSceneMonitor::setDebugViewerVisible(bool visible) +{ + mDebugViewerVisible = visible; +} + +LLRenderTarget& LLSceneMonitor::getCaptureTarget() +{ + LLRenderTarget* cur_target = NULL; + + S32 width = gViewerWindow->getWorldViewWidthRaw(); + S32 height = gViewerWindow->getWorldViewHeightRaw(); + + if(!mFrames[0]) + { + mFrames[0] = new LLRenderTarget(); + mFrames[0]->allocate(width, height, GL_RGB, false, false, LLTexUnit::TT_TEXTURE, true); + gGL.getTexUnit(0)->bind(mFrames[0]); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + cur_target = mFrames[0]; + } + else if(!mFrames[1]) + { + mFrames[1] = new LLRenderTarget(); + mFrames[1]->allocate(width, height, GL_RGB, false, false, LLTexUnit::TT_TEXTURE, true); + gGL.getTexUnit(0)->bind(mFrames[1]); + gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_POINT); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + cur_target = mFrames[1]; + } + else //swap + { + cur_target = mFrames[0]; + mFrames[0] = mFrames[1]; + mFrames[1] = cur_target; + } + + if(cur_target->getWidth() != width || cur_target->getHeight() != height) //size changed + { + cur_target->resize(width, height, GL_RGB); + } + + // we're promising the target exists + return *cur_target; +} + +void LLSceneMonitor::freezeAvatar(LLCharacter* avatarp) +{ + mAvatarPauseHandles.push_back(avatarp->requestPause()); +} + +void LLSceneMonitor::freezeScene() +{ + //freeze all avatars + for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) + { + freezeAvatar((LLCharacter*)(*iter)); + } + + // freeze everything else + gSavedSettings.setBOOL("FreezeTime", TRUE); + + //disable sky, water and clouds + gPipeline.clearRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::END_RENDER_TYPES); + + //disable particle system + LLViewerPartSim::getInstance()->enable(false); +} + +void LLSceneMonitor::unfreezeScene() +{ + //thaw all avatars + mAvatarPauseHandles.clear(); + + if(mDiffState == VIEWER_QUITTING) + { + return; + } + + // thaw everything else + gSavedSettings.setBOOL("FreezeTime", FALSE); + + //enable sky, water and clouds + gPipeline.setRenderTypeMask(LLPipeline::RENDER_TYPE_SKY, LLPipeline::RENDER_TYPE_WL_SKY, + LLPipeline::RENDER_TYPE_WATER, LLPipeline::RENDER_TYPE_CLOUDS, LLPipeline::END_RENDER_TYPES); + + //enable particle system + LLViewerPartSim::getInstance()->enable(true); +} + +void LLSceneMonitor::capture() +{ + static U32 last_capture_time = 0; + static LLCachedControl<bool> monitor_enabled(gSavedSettings, "SceneLoadingMonitorEnabled"); + static LLCachedControl<F32> scene_load_sample_time(gSavedSettings, "SceneLoadingMonitorSampleTime"); + static LLFrameTimer timer; + + if (mEnabled + && (mMonitorRecording.getSum(*LLViewerCamera::getVelocityStat()) > 0.1f + || mMonitorRecording.getSum(*LLViewerCamera::getAngularVelocityStat()) > 0.05f)) + { + reset(); + freezeScene(); + } + + bool enabled = monitor_enabled || mDebugViewerVisible; + if(mEnabled != enabled) + { + if(mEnabled) + { + unfreezeScene(); + } + else + { + reset(); + freezeScene(); + } + + mEnabled = enabled; + } + + if(timer.getElapsedTimeF32() > scene_load_sample_time() + && mEnabled + && LLGLSLShader::sNoFixedFunction + && last_capture_time != gFrameCount) + { + mSceneLoadRecording.resume(); + mMonitorRecording.resume(); + + timer.reset(); + + last_capture_time = gFrameCount; + + LLRenderTarget& cur_target = getCaptureTarget(); + + U32 old_FBO = LLRenderTarget::sCurFBO; + + gGL.getTexUnit(0)->bind(&cur_target); + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); //point to the main frame buffer. + + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, cur_target.getWidth(), cur_target.getHeight()); //copy the content + + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBindFramebuffer(GL_FRAMEBUFFER, old_FBO); + + mDiffState = NEED_DIFF; + } +} + +bool LLSceneMonitor::needsUpdate() const +{ + return mDiffState == NEED_DIFF; +} + +static LLFastTimer::DeclareTimer FTM_GENERATE_SCENE_LOAD_DITHER_TEXTURE("Generate Scene Load Dither Texture"); +static LLFastTimer::DeclareTimer FTM_SCENE_LOAD_IMAGE_DIFF("Scene Load Image Diff"); + +void LLSceneMonitor::compare() +{ + if(mDiffState != NEED_DIFF) + { + return; + } + + if(!mFrames[0] || !mFrames[1]) + { + return; + } + if(mFrames[0]->getWidth() != mFrames[1]->getWidth() || mFrames[0]->getHeight() != mFrames[1]->getHeight()) + { //size does not match + return; + } + + LLFastTimer _(FTM_SCENE_LOAD_IMAGE_DIFF); + mDiffState = EXECUTE_DIFF; + + S32 width = gViewerWindow->getWindowWidthRaw(); + S32 height = gViewerWindow->getWindowHeightRaw(); + if(!mDiff) + { + LLFastTimer _(FTM_GENERATE_SCENE_LOAD_DITHER_TEXTURE); + mDiff = new LLRenderTarget(); + mDiff->allocate(width, height, GL_RGBA, false, false, LLTexUnit::TT_TEXTURE, true); + + generateDitheringTexture(width, height); + } + else if(mDiff->getWidth() != width || mDiff->getHeight() != height) + { + LLFastTimer _(FTM_GENERATE_SCENE_LOAD_DITHER_TEXTURE); + mDiff->resize(width, height, GL_RGBA); + generateDitheringTexture(width, height); + } + + mDiff->bindTarget(); + mDiff->clear(); + + gTwoTextureCompareProgram.bind(); + + gTwoTextureCompareProgram.uniform1f("dither_scale", mDitherScale); + gTwoTextureCompareProgram.uniform1f("dither_scale_s", mDitherScaleS); + gTwoTextureCompareProgram.uniform1f("dither_scale_t", mDitherScaleT); + + gGL.getTexUnit(0)->activate(); + gGL.getTexUnit(0)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(0)->bind(mFrames[0]); + gGL.getTexUnit(0)->activate(); + + gGL.getTexUnit(1)->activate(); + gGL.getTexUnit(1)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->bind(mFrames[1]); + gGL.getTexUnit(1)->activate(); + + gGL.getTexUnit(2)->activate(); + gGL.getTexUnit(2)->enable(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(2)->bind(mDitheringTexture); + gGL.getTexUnit(2)->activate(); + + gl_rect_2d_simple_tex(width, height); + + mDiff->flush(); + + gTwoTextureCompareProgram.unbind(); + + gGL.getTexUnit(0)->disable(); + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(1)->disable(); + gGL.getTexUnit(1)->unbind(LLTexUnit::TT_TEXTURE); + gGL.getTexUnit(2)->disable(); + gGL.getTexUnit(2)->unbind(LLTexUnit::TT_TEXTURE); + + if (!mDebugViewerVisible) + { + calcDiffAggregate(); + } +} + +//calculate Diff aggregate information in GPU, and enable gl occlusion query to capture it. +void LLSceneMonitor::calcDiffAggregate() +{ + LLFastTimer _(FTM_SCENE_LOAD_IMAGE_DIFF); + + if(mDiffState != EXECUTE_DIFF && !mDebugViewerVisible) + { + return; + } + + if(!mQueryObject) + { + mQueryObject = LLOcclusionCullingGroup::getNewOcclusionQueryObjectName(); + } + + LLGLDepthTest depth(true, false, GL_ALWAYS); + if(!mDebugViewerVisible) + { + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + } + + LLGLSLShader* cur_shader = NULL; + + cur_shader = LLGLSLShader::sCurBoundShaderPtr; + gOneTextureFilterProgram.bind(); + gOneTextureFilterProgram.uniform1f("tolerance", mDiffTolerance); + + if(mDiffState == EXECUTE_DIFF) + { + glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mQueryObject); + } + + gl_draw_scaled_target(0, 0, S32(mDiff->getWidth() * mDiffPixelRatio), S32(mDiff->getHeight() * mDiffPixelRatio), mDiff); + + if(mDiffState == EXECUTE_DIFF) + { + glEndQueryARB(GL_SAMPLES_PASSED_ARB); + mDiffState = WAIT_ON_RESULT; + } + + gOneTextureFilterProgram.unbind(); + + if(cur_shader != NULL) + { + cur_shader->bind(); + } + + if(!mDebugViewerVisible) + { + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } +} + +static LLTrace::EventStatHandle<> sFramePixelDiff("FramePixelDifference"); +void LLSceneMonitor::fetchQueryResult() +{ + LLFastTimer _(FTM_SCENE_LOAD_IMAGE_DIFF); + + if(mDiffState == WAIT_ON_RESULT) + { + mDiffState = WAITING_FOR_NEXT_DIFF; + + GLuint available = 0; + glGetQueryObjectuivARB(mQueryObject, GL_QUERY_RESULT_AVAILABLE_ARB, &available); + if(available) + { + GLuint count = 0; + glGetQueryObjectuivARB(mQueryObject, GL_QUERY_RESULT_ARB, &count); + + mDiffResult = count * 0.5f / (mDiff->getWidth() * mDiff->getHeight() * mDiffPixelRatio * mDiffPixelRatio); //0.5 -> (front face + back face) + + LL_DEBUGS("SceneMonitor") << "Frame difference: " << std::setprecision(4) << mDiffResult << LL_ENDL; + record(sFramePixelDiff, mDiffResult); + + static LLCachedControl<F32> diff_threshold(gSavedSettings,"SceneLoadingPixelDiffThreshold"); + if(mDiffResult > diff_threshold()) + { + mSceneLoadRecording.extend(); + llassert(mSceneLoadRecording.getAcceptedRecording().getLastRecording().getSum(LLStatViewer::FPS)); + } + else + { + mSceneLoadRecording.getPotentialRecording().nextPeriod(); + llassert(mSceneLoadRecording.getPotentialRecording().getLastRecording().getSum(LLStatViewer::FPS)); + } + } + } +} + +//dump results to a file _scene_xmonitor_results.csv +void LLSceneMonitor::dumpToFile(std::string file_name) +{ using namespace LLTrace; + + if (!hasResults()) return; + + LL_INFOS("SceneMonitor") << "Saving scene load stats to " << file_name << LL_ENDL; + + std::ofstream os(file_name.c_str()); + + os << std::setprecision(3); + + PeriodicRecording& scene_load_recording = mSceneLoadRecording.getAcceptedRecording(); + const U32 frame_count = scene_load_recording.getNumPeriods(); + + LLUnit<LLUnits::Seconds, F64> frame_time; + + os << "Stat"; + for (S32 frame = 0; frame < frame_count; frame++) + { + frame_time += scene_load_recording.getPrevRecording(frame_count - frame).getDuration(); + os << ", " << frame_time.value(); + } + os << std::endl; + + typedef TraceType<CountAccumulator> trace_count; + for (trace_count::instance_iter it = trace_count::beginInstances(), end_it = trace_count::endInstances(); + it != end_it; + ++it) + { + std::ostringstream row; + row << it->getName(); + + const char* unit_label = it->getUnitLabel(); + if(unit_label[0]) + { + row << "(" << unit_label << ")"; + } + + S32 samples = 0; + + for (S32 frame = 0; frame < frame_count; frame++) + { + samples += scene_load_recording.getPrevRecording(frame_count - frame).getSampleCount(*it); + row << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getSum(*it); + } + + row << std::endl; + + if (samples > 0) + { + os << row.str(); + } + } + + typedef TraceType<EventAccumulator> trace_event; + + for (trace_event::instance_iter it = trace_event::beginInstances(), end_it = trace_event::endInstances(); + it != end_it; + ++it) + { + std::ostringstream row; + row << it->getName(); + + const char* unit_label = it->getUnitLabel(); + if(unit_label[0]) + { + row << "(" << unit_label << ")"; + } + + S32 samples = 0; + + for (S32 frame = 0; frame < frame_count; frame++) + { + samples += scene_load_recording.getPrevRecording(frame_count - frame).getSampleCount(*it); + row << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMean(*it); + } + + row << std::endl; + + if (samples > 0) + { + os << row.str(); + } + } + + typedef TraceType<SampleAccumulator> trace_sample; + + for (trace_sample::instance_iter it = trace_sample::beginInstances(), end_it = trace_sample::endInstances(); + it != end_it; + ++it) + { + std::ostringstream row; + row << it->getName(); + + const char* unit_label = it->getUnitLabel(); + if(unit_label[0]) + { + row << "(" << unit_label << ")"; + } + + S32 samples = 0; + + for (S32 frame = 0; frame < frame_count; frame++) + { + samples += scene_load_recording.getPrevRecording(frame_count - frame).getSampleCount(*it); + row << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMean(*it); + } + + row << std::endl; + + if (samples > 0) + { + os << row.str(); + } + } + + typedef TraceType<MemStatAccumulator> trace_mem; + for (trace_mem::instance_iter it = trace_mem::beginInstances(), end_it = trace_mem::endInstances(); + it != end_it; + ++it) + { + os << it->getName() << "(KiB)"; + + for (S32 frame = 0; frame < frame_count; frame++) + { + os << ", " << scene_load_recording.getPrevRecording(frame_count - frame).getMax(*it).as<LLUnits::Kibibytes>().value(); + } + + os << std::endl; + } + + os.flush(); + os.close(); +} + +//------------------------------------------------------------------------------------------------------------- +//definition of class LLSceneMonitorView +//------------------------------------------------------------------------------------------------------------- +LLSceneMonitorView::LLSceneMonitorView(const LLRect& rect) + : LLFloater(LLSD()) +{ + setRect(rect); + setVisible(FALSE); + + setCanMinimize(false); + setCanClose(true); +} + +void LLSceneMonitorView::onClickCloseBtn() +{ + setVisible(false); +} + +void LLSceneMonitorView::onVisibilityChange(BOOL visible) +{ + visible = visible && LLGLSLShader::sNoFixedFunction; + LLSceneMonitor::getInstance()->setDebugViewerVisible(visible); +} + +void LLSceneMonitorView::draw() +{ + const LLRenderTarget* target = LLSceneMonitor::getInstance()->getDiffTarget(); + if(!target) + { + return; + } + + F32 ratio = LLSceneMonitor::getInstance()->getDiffPixelRatio(); + S32 height = (S32)(target->getHeight() * ratio); + S32 width = (S32)(target->getWidth() * ratio); + + LLRect new_rect; + new_rect.setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height); + setRect(new_rect); + + //draw background + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); + + LLSceneMonitor::getInstance()->calcDiffAggregate(); + + //show some texts + LLColor4 color = LLColor4::white; + S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); + + S32 lines = 0; + std::string num_str = llformat("Frame difference: %.6f", LLSceneMonitor::getInstance()->getDiffResult()); + LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, 5, getRect().getHeight() - line_height * lines, color, LLFontGL::LEFT, LLFontGL::TOP); + lines++; + + num_str = llformat("Pixel tolerance: (R+G+B) < %.4f", LLSceneMonitor::getInstance()->getDiffTolerance()); + LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, 5, getRect().getHeight() - line_height * lines, color, LLFontGL::LEFT, LLFontGL::TOP); + lines++; + + num_str = llformat("Sampling time: %.3f seconds", gSavedSettings.getF32("SceneLoadingMonitorSampleTime")); + LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, 5, getRect().getHeight() - line_height * lines, color, LLFontGL::LEFT, LLFontGL::TOP); + lines++; + + num_str = llformat("Scene Loading time: %.3f seconds", (F32)LLSceneMonitor::getInstance()->getRecording()->getAcceptedRecording().getDuration().value()); + LLFontGL::getFontMonospace()->renderUTF8(num_str, 0, 5, getRect().getHeight() - line_height * lines, color, LLFontGL::LEFT, LLFontGL::TOP); + lines++; + + LLView::draw(); +} + diff --git a/indra/newview/llscenemonitor.h b/indra/newview/llscenemonitor.h new file mode 100644 index 0000000000..6af58b707a --- /dev/null +++ b/indra/newview/llscenemonitor.h @@ -0,0 +1,124 @@ +/** + * @file llscenemonitor.h + * @brief monitor the process of scene loading + * + * $LicenseInfo:firstyear=2003&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_LLSCENE_MONITOR_H +#define LL_LLSCENE_MONITOR_H + +#include "llsingleton.h" +#include "llmath.h" +#include "llfloater.h" +#include "llcharacter.h" +#include "lltracerecording.h" + +class LLCharacter; +class LLRenderTarget; +class LLViewerTexture; + +class LLSceneMonitor : public LLSingleton<LLSceneMonitor> +{ + LOG_CLASS(LLSceneMonitor); +public: + LLSceneMonitor(); + ~LLSceneMonitor(); + + void freezeAvatar(LLCharacter* avatarp); + void setDebugViewerVisible(bool visible); + + void capture(); //capture the main frame buffer + void compare(); //compare the stored two buffers. + void fetchQueryResult(); + void calcDiffAggregate(); + void setDiffTolerance(F32 tol) {mDiffTolerance = tol;} + + const LLRenderTarget* getDiffTarget() const {return mDiff;} + F32 getDiffTolerance() const {return mDiffTolerance;} + F32 getDiffResult() const { return mDiffResult;} + F32 getDiffPixelRatio() const { return mDiffPixelRatio;} + bool isEnabled()const {return mEnabled;} + bool needsUpdate() const; + + const LLTrace::ExtendablePeriodicRecording* getRecording() const {return &mSceneLoadRecording;} + void dumpToFile(std::string file_name); + bool hasResults() const { return mSceneLoadRecording.getAcceptedRecording().getDuration() != 0;} + +private: + void freezeScene(); + void unfreezeScene(); + void reset(); + LLRenderTarget& getCaptureTarget(); + void generateDitheringTexture(S32 width, S32 height); + +private: + bool mEnabled; + bool mDebugViewerVisible; + + enum EDiffState + { + WAITING_FOR_NEXT_DIFF, + NEED_DIFF, + EXECUTE_DIFF, + WAIT_ON_RESULT, + VIEWER_QUITTING + } mDiffState; + + LLRenderTarget* mFrames[2]; + LLRenderTarget* mDiff; + + GLuint mQueryObject; //used for glQuery + F32 mDiffResult; //aggregate results of mDiff. + F32 mDiffTolerance; //pixels are filtered out when R+G+B < mDiffTolerance + + F32 mDiffPixelRatio; //ratio of pixels used for comparison against the original mDiff size along one dimension + + LLPointer<LLViewerTexture> mDitheringTexture; + S32 mDitherMatrixWidth; + F32 mDitherScale; + F32 mDitherScaleS; + F32 mDitherScaleT; + + std::vector<LLAnimPauseRequest> mAvatarPauseHandles; + + LLTrace::ExtendablePeriodicRecording mSceneLoadRecording; + LLTrace::Recording mMonitorRecording; +}; + +class LLSceneMonitorView : public LLFloater +{ +public: + LLSceneMonitorView(const LLRect& rect); + + virtual void draw(); + + virtual void onVisibilityChange(BOOL visible); + +protected: + virtual void onClickCloseBtn(); +}; + +extern LLSceneMonitorView* gSceneMonitorView; + +#endif + diff --git a/indra/newview/llsecapi.h b/indra/newview/llsecapi.h index db57848320..28765fbfb1 100755 --- a/indra/newview/llsecapi.h +++ b/indra/newview/llsecapi.h @@ -30,6 +30,7 @@ #include <vector> #include <openssl/x509.h> #include <ostream> +#include "llthread.h" #ifdef LL_WINDOWS #pragma warning(disable:4250) diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index 4681efd3e5..da6ca8964a 100755 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1545,7 +1545,7 @@ void LLObjectSelection::applyNoCopyTextureToTEs(LLViewerInventoryItem* item) } // apply texture for the selected faces - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); + add(LLStatViewer::EDIT_TEXTURE, 1); object->setTEImage(te, image); dialog_refresh_all(); @@ -2980,18 +2980,18 @@ private: void LLSelectMgr::getFirst(LLSelectGetFirstTest* test) { if (gSavedSettings.getBOOL("EditLinkedParts")) - { +{ for (LLObjectSelection::valid_iterator iter = getSelection()->valid_begin(); iter != getSelection()->valid_end(); ++iter ) - { + { if (!test->checkMatchingNode(*iter)) - { + { break; } } - } - else - { + } + else + { for (LLObjectSelection::root_object_iterator iter = getSelection()->root_object_begin(); iter != getSelection()->root_object_end(); ++iter ) { @@ -3001,31 +3001,31 @@ void LLSelectMgr::getFirst(LLSelectGetFirstTest* test) } } } -} + } //----------------------------------------------------------------------------- // selectGetCreator() // Creator information only applies to roots unless editing linked parts. //----------------------------------------------------------------------------- struct LLSelectGetFirstCreator : public LLSelectGetFirstTest -{ + { protected: virtual const LLUUID& getValueFromNode(LLSelectNode* node) - { + { return node->mPermissions->getCreator(); - } + } }; BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name) -{ + { LLSelectGetFirstCreator test; getFirst(&test); if (test.mFirstValue.isNull()) - { - name = LLTrans::getString("AvatarNameNobody"); + { + name = LLTrans::getString("AvatarNameNobody"); return FALSE; - } + } result_id = test.mFirstValue; @@ -3046,18 +3046,18 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& result_id, std::string& name) // Owner information only applies to roots unless editing linked parts. //----------------------------------------------------------------------------- struct LLSelectGetFirstOwner : public LLSelectGetFirstTest -{ + { protected: virtual const LLUUID& getValueFromNode(LLSelectNode* node) - { + { // Don't use 'getOwnership' since we return a reference, not a copy. // Will return LLUUID::null if unowned (which is not allowed and should never happen.) return node->mPermissions->isGroupOwned() ? node->mPermissions->getGroup() : node->mPermissions->getOwner(); - } + } }; BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name) -{ + { LLSelectGetFirstOwner test; getFirst(&test); @@ -3096,34 +3096,34 @@ struct LLSelectGetFirstLastOwner : public LLSelectGetFirstTest { protected: virtual const LLUUID& getValueFromNode(LLSelectNode* node) - { +{ return node->mPermissions->getLastOwner(); } }; BOOL LLSelectMgr::selectGetLastOwner(LLUUID& result_id, std::string& name) -{ + { LLSelectGetFirstLastOwner test; getFirst(&test); if (test.mFirstValue.isNull()) - { - return FALSE; - } + { + return FALSE; + } result_id = test.mFirstValue; if (test.mIdentical) - { + { name = LLSLURL("agent", test.mFirstValue, "inspect").getSLURLString(); - } - else - { + } + else + { name.assign( "" ); - } + } return test.mIdentical; -} + } //----------------------------------------------------------------------------- // selectGetGroup() @@ -3153,10 +3153,10 @@ BOOL LLSelectMgr::selectGetGroup(LLUUID& result_id) // Returns TRUE if the first selected is group owned. //----------------------------------------------------------------------------- struct LLSelectGetFirstGroupOwner : public LLSelectGetFirstTest -{ + { protected: virtual const LLUUID& getValueFromNode(LLSelectNode* node) - { + { if (node->mPermissions->isGroupOwned()) { return node->mPermissions->getGroup(); @@ -3412,9 +3412,7 @@ bool LLSelectMgr::confirmDelete(const LLSD& notification, const LLSD& response, gAgentCamera.setLookAt(LOOKAT_TARGET_CLEAR); // Keep track of how many objects have been deleted. - F64 obj_delete_count = LLViewerStats::getInstance()->getStat(LLViewerStats::ST_OBJECT_DELETE_COUNT); - obj_delete_count += LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount(); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_OBJECT_DELETE_COUNT, obj_delete_count ); + add(LLStatViewer::DELETE_OBJECT, LLSelectMgr::getInstance()->mSelectedObjects->getObjectCount()); } break; case 1: diff --git a/indra/newview/llsidepanelappearance.cpp b/indra/newview/llsidepanelappearance.cpp index 74fa5a87bb..efef422bfb 100755 --- a/indra/newview/llsidepanelappearance.cpp +++ b/indra/newview/llsidepanelappearance.cpp @@ -142,7 +142,7 @@ BOOL LLSidepanelAppearance::postBuild() mCurrOutfitPanel = getChild<LLPanel>("panel_currentlook"); - setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChange,this,_2)); + setVisibleCallback(boost::bind(&LLSidepanelAppearance::onVisibilityChanged,this,_2)); return TRUE; } @@ -181,7 +181,7 @@ void LLSidepanelAppearance::onOpen(const LLSD& key) mOpened = true; } -void LLSidepanelAppearance::onVisibilityChange(const LLSD &new_visibility) +void LLSidepanelAppearance::onVisibilityChanged(const LLSD &new_visibility) { LLSD visibility; visibility["visible"] = new_visibility.asBoolean(); @@ -231,7 +231,7 @@ void LLSidepanelAppearance::updateToVisibility(const LLSD &new_visibility) { gAgentCamera.changeCameraToDefault(); gAgentCamera.resetView(); - } + } } } diff --git a/indra/newview/llsidepanelappearance.h b/indra/newview/llsidepanelappearance.h index 762f557a80..6359d6e86e 100755 --- a/indra/newview/llsidepanelappearance.h +++ b/indra/newview/llsidepanelappearance.h @@ -47,7 +47,7 @@ public: virtual ~LLSidepanelAppearance(); /*virtual*/ BOOL postBuild(); - /*virtual*/ void onOpen(const LLSD& key); + /*virtual*/ void onOpen(const LLSD& key); void refreshCurrentOutfitName(const std::string& name = ""); @@ -68,7 +68,7 @@ public: private: void onFilterEdit(const std::string& search_string); - void onVisibilityChange ( const LLSD& new_visibility ); + void onVisibilityChanged ( const LLSD& new_visibility ); void onOpenOutfitButtonClicked(); void onEditAppearanceButtonClicked(); diff --git a/indra/newview/llsidepaneltaskinfo.cpp b/indra/newview/llsidepaneltaskinfo.cpp index ad7c939728..090ee64801 100755 --- a/indra/newview/llsidepaneltaskinfo.cpp +++ b/indra/newview/llsidepaneltaskinfo.cpp @@ -162,7 +162,7 @@ BOOL LLSidepanelTaskInfo::postBuild() return TRUE; } -/*virtual*/ void LLSidepanelTaskInfo::handleVisibilityChange ( BOOL visible ) +/*virtual*/ void LLSidepanelTaskInfo::onVisibilityChange ( BOOL visible ) { if (visible) { @@ -945,7 +945,6 @@ static bool callback_deed_to_group(const LLSD& notification, const LLSD& respons if (group_id.notNull() && groups_identical && (gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED))) { LLSelectMgr::getInstance()->sendOwner(LLUUID::null, group_id, FALSE); -// LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT); } } return FALSE; diff --git a/indra/newview/llsidepaneltaskinfo.h b/indra/newview/llsidepaneltaskinfo.h index 05edcda5ed..a1479ef0e7 100755 --- a/indra/newview/llsidepaneltaskinfo.h +++ b/indra/newview/llsidepaneltaskinfo.h @@ -50,7 +50,7 @@ public: virtual ~LLSidepanelTaskInfo(); /*virtual*/ BOOL postBuild(); - /*virtual*/ void handleVisibilityChange ( BOOL new_visibility ); + /*virtual*/ void onVisibilityChange ( BOOL new_visibility ); void setObjectSelection(LLObjectSelectionHandle selection); diff --git a/indra/newview/llsimplestat.h b/indra/newview/llsimplestat.h index 9d7780c4f9..80ce99b774 100755 --- a/indra/newview/llsimplestat.h +++ b/indra/newview/llsimplestat.h @@ -99,43 +99,43 @@ public: * values back to zero. */ void reset() - { - mCount = 0; - mMin = Value(0); - mMax = Value(0); - mTotal = Value(0); - } + { + mCount = 0; + mMin = Value(0); + mMax = Value(0); + mTotal = Value(0); + } void record(Value v) + { + if (mCount) + { + mMin = llmin(mMin, v); + mMax = llmax(mMax, v); + } + else { - if (mCount) - { - mMin = llmin(mMin, v); - mMax = llmax(mMax, v); - } - else - { - mMin = v; - mMax = v; - } - mTotal += v; - ++mCount; + mMin = v; + mMax = v; } + mTotal += v; + ++mCount; + } void merge(const LLSimpleStatMMM<VALUE_T> & src) + { + if (! mCount) + { + *this = src; + } + else if (src.mCount) { - if (! mCount) - { - *this = src; - } - else if (src.mCount) - { - mMin = llmin(mMin, src.mMin); - mMax = llmax(mMax, src.mMax); - mCount += src.mCount; - mTotal += src.mTotal; - } + mMin = llmin(mMin, src.mMin); + mMax = llmax(mMax, src.mMax); + mCount += src.mCount; + mTotal += src.mTotal; } + } inline U32 getCount() const { return mCount; } inline Value getMin() const { return mMin; } diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp index f85e855fd3..45130efeb9 100755 --- a/indra/newview/llspatialpartition.cpp +++ b/indra/newview/llspatialpartition.cpp @@ -51,32 +51,16 @@ #include "llvoavatar.h" #include "llvolumemgr.h" #include "lltextureatlas.h" -#include "llglslshader.h" #include "llviewershadermgr.h" static LLFastTimer::DeclareTimer FTM_FRUSTUM_CULL("Frustum Culling"); static LLFastTimer::DeclareTimer FTM_CULL_REBOUND("Cull Rebound Partition"); -const F32 SG_OCCLUSION_FUDGE = 0.25f; -#define SG_DISCARD_TOLERANCE 0.01f - -#if LL_OCTREE_PARANOIA_CHECK -#define assert_octree_valid(x) x->validate() -#define assert_states_valid(x) ((LLSpatialGroup*) x->mSpatialPartition->mOctree->getListener(0))->checkStates() -#else -#define assert_octree_valid(x) -#define assert_states_valid(x) -#endif - extern bool gShiftFrame; static U32 sZombieGroups = 0; U32 LLSpatialGroup::sNodeCount = 0; -#define LL_TRACK_PENDING_OCCLUSION_QUERIES 0 - -std::set<GLuint> LLSpatialGroup::sPendingQueries; - U32 gOctreeMaxCapacity; BOOL LLSpatialGroup::sNoDelete = FALSE; @@ -84,47 +68,6 @@ BOOL LLSpatialGroup::sNoDelete = FALSE; static F32 sLastMaxTexPriority = 1.f; static F32 sCurMaxTexPriority = 1.f; -class LLOcclusionQueryPool : public LLGLNamePool -{ -public: - LLOcclusionQueryPool() - { - mCurQuery = 1; - } - -protected: - - std::list<GLuint> mAvailableName; - GLuint mCurQuery; - - virtual GLuint allocateName() - { - GLuint ret = 0; - - if (!mAvailableName.empty()) - { - ret = mAvailableName.front(); - mAvailableName.pop_front(); - } - else - { - ret = mCurQuery++; - } - - return ret; - } - - virtual void releaseName(GLuint name) - { -#if LL_TRACK_PENDING_OCCLUSION_QUERIES - LLSpatialGroup::sPendingQueries.erase(name); -#endif - llassert(std::find(mAvailableName.begin(), mAvailableName.end(), name) == mAvailableName.end()); - mAvailableName.push_back(name); - } -}; - -static LLOcclusionQueryPool sQueryPool; //static counter for frame to switch LOD on @@ -138,185 +81,6 @@ void sg_assert(BOOL expr) #endif } -S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad) -{ - return AABBSphereIntersectR2(min, max, origin, rad*rad); -} - -S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &r) -{ - F32 d = 0.f; - F32 t; - - if ((min-origin).magVecSquared() < r && - (max-origin).magVecSquared() < r) - { - return 2; - } - - for (U32 i = 0; i < 3; i++) - { - if (origin.mV[i] < min.mV[i]) - { - t = min.mV[i] - origin.mV[i]; - d += t*t; - } - else if (origin.mV[i] > max.mV[i]) - { - t = origin.mV[i] - max.mV[i]; - d += t*t; - } - - if (d > r) - { - return 0; - } - } - - return 1; -} - - -S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad) -{ - return AABBSphereIntersectR2(min, max, origin, rad*rad); -} - -S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &r) -{ - F32 d = 0.f; - F32 t; - - LLVector4a origina; - origina.load3(origin.mV); - - LLVector4a v; - v.setSub(min, origina); - - if (v.dot3(v) < r) - { - v.setSub(max, origina); - if (v.dot3(v) < r) - { - return 2; - } - } - - - for (U32 i = 0; i < 3; i++) - { - if (origin.mV[i] < min[i]) - { - t = min[i] - origin.mV[i]; - d += t*t; - } - else if (origin.mV[i] > max[i]) - { - t = origin.mV[i] - max[i]; - d += t*t; - } - - if (d > r) - { - return 0; - } - } - - return 1; -} - - -typedef enum -{ - b000 = 0x00, - b001 = 0x01, - b010 = 0x02, - b011 = 0x03, - b100 = 0x04, - b101 = 0x05, - b110 = 0x06, - b111 = 0x07, -} eLoveTheBits; - -//contact Runitai Linden for a copy of the SL object used to write this table -//basically, you give the table a bitmask of the look-at vector to a node and it -//gives you a triangle fan index array -static U16 sOcclusionIndices[] = -{ - //000 - b111, b110, b010, b011, b001, b101, b100, b110, - //001 - b011, b010, b000, b001, b101, b111, b110, b010, - //010 - b101, b100, b110, b111, b011, b001, b000, b100, - //011 - b001, b000, b100, b101, b111, b011, b010, b000, - //100 - b110, b000, b010, b011, b111, b101, b100, b000, - //101 - b010, b100, b000, b001, b011, b111, b110, b100, - //110 - b100, b010, b110, b111, b101, b001, b000, b010, - //111 - b000, b110, b100, b101, b001, b011, b010, b110, -}; - -U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center) -{ - LLVector4a origin; - origin.load3(camera->getOrigin().mV); - - S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7; - - return cypher*8; -} - -U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center) -{ - LLVector4a origin; - origin.load3(camera->getOrigin().mV); - - S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7; - - return (U8*) (sOcclusionIndices+cypher*8); -} - -//create a vertex buffer for efficiently rendering cubes -LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage) -{ - LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage); - - ret->allocateBuffer(8, 64, true); - - LLStrider<LLVector3> pos; - LLStrider<U16> idx; - - ret->getVertexStrider(pos); - ret->getIndexStrider(idx); - - pos[0] = LLVector3(-1,-1,-1); - pos[1] = LLVector3(-1,-1, 1); - pos[2] = LLVector3(-1, 1,-1); - pos[3] = LLVector3(-1, 1, 1); - pos[4] = LLVector3( 1,-1,-1); - pos[5] = LLVector3( 1,-1, 1); - pos[6] = LLVector3( 1, 1,-1); - pos[7] = LLVector3( 1, 1, 1); - - for (U32 i = 0; i < 64; i++) - { - idx[i] = sOcclusionIndices[i]; - } - - ret->flush(); - - return ret; -} - -static LLFastTimer::DeclareTimer FTM_BUILD_OCCLUSION("Build Occlusion"); - -BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group); - //returns: // 0 if sphere and AABB are not intersecting // 1 if they are @@ -358,24 +122,13 @@ LLSpatialGroup::~LLSpatialGroup() gPipeline.checkReferences(this); } - if (isState(DEAD)) + if (hasState(DEAD)) { sZombieGroups--; } sNodeCount--; - if (gGLManager.mHasOcclusionQuery) - { - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i) - { - if (mOcclusionQuery[i]) - { - sQueryPool.release(mOcclusionQuery[i]); - } - } - } - clearDrawMap(); clearAtlasList() ; } @@ -509,22 +262,13 @@ void LLSpatialGroup::clearDrawMap() BOOL LLSpatialGroup::isHUDGroup() { - return mSpatialPartition && mSpatialPartition->isHUDPartition() ; + return getSpatialPartition() && getSpatialPartition()->isHUDPartition() ; } BOOL LLSpatialGroup::isRecentlyVisible() const { - return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < LLDrawable::getMinVisFrameRange() ; -} - -BOOL LLSpatialGroup::isVisible() const -{ - return mVisible[LLViewerCamera::sCurCameraID] >= LLDrawable::getCurrentFrame() ? TRUE : FALSE; -} - -void LLSpatialGroup::setVisible() -{ - mVisible[LLViewerCamera::sCurCameraID] = LLDrawable::getCurrentFrame(); + const S32 MIN_VIS_FRAME_RANGE = 2; + return (LLDrawable::getCurrentFrame() - mVisible[LLViewerCamera::sCurCameraID]) < MIN_VIS_FRAME_RANGE ; } void LLSpatialGroup::validate() @@ -548,7 +292,7 @@ void LLSpatialGroup::validate() sg_assert(drawable->getSpatialGroup() == this); if (drawable->getSpatialBridge()) { - sg_assert(drawable->getSpatialBridge() == mSpatialPartition->asBridge()); + sg_assert(drawable->getSpatialBridge() == getSpatialPartition()->asBridge()); } /*if (drawable->isSpatialBridge()) @@ -588,14 +332,6 @@ void LLSpatialGroup::validate() #endif } -void LLSpatialGroup::checkStates() -{ -#if LL_OCTREE_PARANOIA_CHECK - //LLOctreeStateCheck checker; - //checker.traverse(mOctreeNode); -#endif -} - void LLSpatialGroup::validateDrawMap() { #if LL_OCTREE_PARANOIA_CHECK @@ -619,7 +355,7 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) OctreeNode* parent = mOctreeNode->getOctParent(); if (mOctreeNode->isInside(drawablep->getPositionGroup()) && - (mOctreeNode->contains(drawablep) || + (mOctreeNode->contains(drawablep->getEntry()) || (drawablep->getBinRadius() > mOctreeNode->getSize()[0] && parent && parent->getElementCount() >= gOctreeMaxCapacity))) { @@ -633,15 +369,14 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) } -BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_octree) +BOOL LLSpatialGroup::addObject(LLDrawable *drawablep) { - if (!from_octree) + if(!drawablep) { - mOctreeNode->insert(drawablep); + return FALSE; } - else { - drawablep->setSpatialGroup(this); + drawablep->setGroup(this); setState(OBJECT_DIRTY | GEOM_DIRTY); setOcclusionState(LLSpatialGroup::DISCARD_QUERY, LLSpatialGroup::STATE_MODE_ALL_CAMERAS); gPipeline.markRebuild(this, TRUE); @@ -662,9 +397,9 @@ void LLSpatialGroup::rebuildGeom() { if (!isDead()) { - mSpatialPartition->rebuildGeom(this); + getSpatialPartition()->rebuildGeom(this); - if (isState(LLSpatialGroup::MESH_DIRTY)) + if (hasState(LLSpatialGroup::MESH_DIRTY)) { gPipeline.markMeshDirty(this); } @@ -675,7 +410,7 @@ void LLSpatialGroup::rebuildMesh() { if (!isDead()) { - mSpatialPartition->rebuildMesh(this); + getSpatialPartition()->rebuildMesh(this); } } @@ -686,7 +421,7 @@ static LLFastTimer::DeclareTimer FTM_GET_GEOMETRY("Get Geometry"); void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) { - if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) + if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY)) { return; } @@ -751,137 +486,26 @@ void LLSpatialPartition::rebuildMesh(LLSpatialGroup* group) } -BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut) +LLSpatialGroup* LLSpatialGroup::getParent() { - const OctreeNode* node = mOctreeNode; - - if (node->isEmpty()) - { //don't do anything if there are no objects - if (empty && mOctreeNode->getParent()) - { //only root is allowed to be empty - OCT_ERRS << "Empty leaf found in octree." << llendl; - } - return FALSE; - } - - LLVector4a& newMin = mObjectExtents[0]; - LLVector4a& newMax = mObjectExtents[1]; - - if (isState(OBJECT_DIRTY)) - { //calculate new bounding box - clearState(OBJECT_DIRTY); - - //initialize bounding box to first element - OctreeNode::const_element_iter i = node->getDataBegin(); - LLDrawable* drawablep = *i; - const LLVector4a* minMax = drawablep->getSpatialExtents(); - - newMin = minMax[0]; - newMax = minMax[1]; - - for (++i; i != node->getDataEnd(); ++i) - { - drawablep = *i; - minMax = drawablep->getSpatialExtents(); - - update_min_max(newMin, newMax, minMax[0]); - update_min_max(newMin, newMax, minMax[1]); - - //bin up the object - /*for (U32 i = 0; i < 3; i++) - { - if (minMax[0].mV[i] < newMin.mV[i]) - { - newMin.mV[i] = minMax[0].mV[i]; - } - if (minMax[1].mV[i] > newMax.mV[i]) - { - newMax.mV[i] = minMax[1].mV[i]; - } - }*/ - } - - mObjectBounds[0].setAdd(newMin, newMax); - mObjectBounds[0].mul(0.5f); - mObjectBounds[1].setSub(newMax, newMin); - mObjectBounds[1].mul(0.5f); - } - - if (empty) - { - minOut = newMin; - maxOut = newMax; - } - else - { - minOut.setMin(minOut, newMin); - maxOut.setMax(maxOut, newMax); - } - - return TRUE; + return (LLSpatialGroup*)LLviewerOctreeGroup::getParent(); } -void LLSpatialGroup::unbound() -{ - if (isState(DIRTY)) - { - return; - } - - setState(DIRTY); - - //all the parent nodes need to rebound this child - if (mOctreeNode) - { - OctreeNode* parent = (OctreeNode*) mOctreeNode->getParent(); - while (parent != NULL) - { - LLSpatialGroup* group = (LLSpatialGroup*) parent->getListener(0); - if (group->isState(DIRTY)) - { - return; - } - - group->setState(DIRTY); - parent = (OctreeNode*) parent->getParent(); - } - } -} - -LLSpatialGroup* LLSpatialGroup::getParent() +BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) { - if (isDead()) + if(!drawablep) { - return NULL; - } - - if(!mOctreeNode) - { - return NULL; - } - OctreeNode* parent = mOctreeNode->getOctParent(); - - if (parent) - { - return (LLSpatialGroup*) parent->getListener(0); + return FALSE; } - return NULL; -} - -BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) -{ unbound(); if (mOctreeNode && !from_octree) { - if (!mOctreeNode->remove(drawablep)) - { - OCT_ERRS << "Could not remove drawable from spatial group" << llendl; - } + drawablep->setGroup(NULL); } else { - drawablep->setSpatialGroup(NULL); + drawablep->setGroup(NULL); setState(GEOM_DIRTY); gPipeline.markRebuild(this, TRUE); @@ -918,22 +542,22 @@ void LLSpatialGroup::shift(const LLVector4a &offset) mObjectExtents[0].add(offset); mObjectExtents[1].add(offset); - if (!mSpatialPartition->mRenderByGroup && - mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TREE && - mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && - mSpatialPartition->mPartitionType != LLViewerRegion::PARTITION_BRIDGE) + if (!getSpatialPartition()->mRenderByGroup && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TREE && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_TERRAIN && + getSpatialPartition()->mPartitionType != LLViewerRegion::PARTITION_BRIDGE) { setState(GEOM_DIRTY); gPipeline.markRebuild(this, TRUE); } } -class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler +class LLSpatialSetState : public OctreeTraveler { public: U32 mState; LLSpatialSetState(U32 state) : mState(state) { } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } + virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setState(mState); } }; class LLSpatialSetStateDiff : public LLSpatialSetState @@ -941,24 +565,17 @@ class LLSpatialSetStateDiff : public LLSpatialSetState public: LLSpatialSetStateDiff(U32 state) : LLSpatialSetState(state) { } - virtual void traverse(const LLSpatialGroup::OctreeNode* n) + virtual void traverse(const OctreeNode* n) { LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - if (!group->isState(mState)) + if (!group->hasState(mState)) { - LLSpatialGroup::OctreeTraveler::traverse(n); + OctreeTraveler::traverse(n); } } }; -void LLSpatialGroup::setState(U32 state) -{ - mState |= state; - - llassert(state <= LLSpatialGroup::STATE_MASK); -} - void LLSpatialGroup::setState(U32 state, S32 mode) { llassert(state <= LLSpatialGroup::STATE_MASK); @@ -982,12 +599,12 @@ void LLSpatialGroup::setState(U32 state, S32 mode) } } -class LLSpatialClearState : public LLSpatialGroup::OctreeTraveler +class LLSpatialClearState : public OctreeTraveler { public: U32 mState; LLSpatialClearState(U32 state) : mState(state) { } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } + virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearState(mState); } }; class LLSpatialClearStateDiff : public LLSpatialClearState @@ -995,24 +612,17 @@ class LLSpatialClearStateDiff : public LLSpatialClearState public: LLSpatialClearStateDiff(U32 state) : LLSpatialClearState(state) { } - virtual void traverse(const LLSpatialGroup::OctreeNode* n) + virtual void traverse(const OctreeNode* n) { LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - if (group->isState(mState)) + if (group->hasState(mState)) { - LLSpatialGroup::OctreeTraveler::traverse(n); + OctreeTraveler::traverse(n); } } }; -void LLSpatialGroup::clearState(U32 state) -{ - llassert(state <= LLSpatialGroup::STATE_MASK); - - mState &= ~state; -} - void LLSpatialGroup::clearState(U32 state, S32 mode) { llassert(state <= LLSpatialGroup::STATE_MASK); @@ -1036,144 +646,15 @@ void LLSpatialGroup::clearState(U32 state, S32 mode) } } -BOOL LLSpatialGroup::isState(U32 state) const -{ - llassert(state <= LLSpatialGroup::STATE_MASK); - - return mState & state ? TRUE : FALSE; -} - -//===================================== -// Occlusion State Set/Clear -//===================================== -class LLSpatialSetOcclusionState : public LLSpatialGroup::OctreeTraveler -{ -public: - U32 mState; - LLSpatialSetOcclusionState(U32 state) : mState(state) { } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->setOcclusionState(mState); } -}; - -class LLSpatialSetOcclusionStateDiff : public LLSpatialSetOcclusionState -{ -public: - LLSpatialSetOcclusionStateDiff(U32 state) : LLSpatialSetOcclusionState(state) { } - - virtual void traverse(const LLSpatialGroup::OctreeNode* n) - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (!group->isOcclusionState(mState)) - { - LLSpatialGroup::OctreeTraveler::traverse(n); - } - } -}; - - -void LLSpatialGroup::setOcclusionState(U32 state, S32 mode) -{ - if (mode > STATE_MODE_SINGLE) - { - if (mode == STATE_MODE_DIFF) - { - LLSpatialSetOcclusionStateDiff setter(state); - setter.traverse(mOctreeNode); - } - else if (mode == STATE_MODE_BRANCH) - { - LLSpatialSetOcclusionState setter(state); - setter.traverse(mOctreeNode); - } - else - { - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - mOcclusionState[i] |= state; - - if ((state & DISCARD_QUERY) && mOcclusionQuery[i]) - { - sQueryPool.release(mOcclusionQuery[i]); - mOcclusionQuery[i] = 0; - } - } - } - } - else - { - mOcclusionState[LLViewerCamera::sCurCameraID] |= state; - if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { - sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]); - mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; - } - } -} - -class LLSpatialClearOcclusionState : public LLSpatialGroup::OctreeTraveler -{ -public: - U32 mState; - - LLSpatialClearOcclusionState(U32 state) : mState(state) { } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->clearOcclusionState(mState); } -}; - -class LLSpatialClearOcclusionStateDiff : public LLSpatialClearOcclusionState -{ -public: - LLSpatialClearOcclusionStateDiff(U32 state) : LLSpatialClearOcclusionState(state) { } - - virtual void traverse(const LLSpatialGroup::OctreeNode* n) - { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (group->isOcclusionState(mState)) - { - LLSpatialGroup::OctreeTraveler::traverse(n); - } - } -}; - -void LLSpatialGroup::clearOcclusionState(U32 state, S32 mode) -{ - if (mode > STATE_MODE_SINGLE) - { - if (mode == STATE_MODE_DIFF) - { - LLSpatialClearOcclusionStateDiff clearer(state); - clearer.traverse(mOctreeNode); - } - else if (mode == STATE_MODE_BRANCH) - { - LLSpatialClearOcclusionState clearer(state); - clearer.traverse(mOctreeNode); - } - else - { - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - mOcclusionState[i] &= ~state; - } - } - } - else - { - mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state; - } -} //====================================== // Octree Listener Implementation //====================================== -LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : +LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : LLOcclusionCullingGroup(node, part), mObjectBoxSize(1.f), - mState(0), mGeometryBytes(0), mSurfaceArea(0.f), mBuilt(0.f), - mOctreeNode(node), - mSpatialPartition(part), mVertexBuffer(NULL), mBufferUsage(part->mBufferUsage), mDistance(0.f), @@ -1191,32 +672,11 @@ LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : mViewAngle.splat(0.f); mLastUpdateViewAngle.splat(-1.f); - mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] = - mObjectExtents[0] = mObjectExtents[1] = mViewAngle; sg_assert(mOctreeNode->getListenerCount() == 0); - mOctreeNode->addListener(this); setState(SG_INITIAL_STATE_MASK); gPipeline.markRebuild(this, TRUE); - mBounds[0] = node->getCenter(); - mBounds[1] = node->getSize(); - - part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod; - mLODHash = part->mLODSeed; - - OctreeNode* oct_parent = node->getOctParent(); - - LLSpatialGroup* parent = oct_parent ? (LLSpatialGroup*) oct_parent->getListener(0) : NULL; - - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - mOcclusionQuery[i] = 0; - mOcclusionIssued[i] = 0; - mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0; - mVisible[i] = 0; - } - mRadius = 1; mPixelArea = 1024.f; } @@ -1235,17 +695,17 @@ void LLSpatialGroup::updateDistance(LLCamera &camera) } #if !LL_RELEASE_FOR_DOWNLOAD - if (isState(LLSpatialGroup::OBJECT_DIRTY)) + if (hasState(LLSpatialGroup::OBJECT_DIRTY)) { llerrs << "Spatial group dirty on distance update." << llendl; } #endif if (!isEmpty()) { - mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : + mRadius = getSpatialPartition()->mRenderByGroup ? mObjectBounds[1].getLength3().getF32() : (F32) mOctreeNode->getSize().getLength3().getF32(); - mDistance = mSpatialPartition->calcDistance(this, camera); - mPixelArea = mSpatialPartition->calcPixelArea(this, camera); + mDistance = getSpatialPartition()->calcDistance(this, camera); + mPixelArea = getSpatialPartition()->calcPixelArea(this, camera); } } @@ -1266,9 +726,9 @@ F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) dist = eye.getLength3().getF32(); eye.normalize3fast(); - if (!group->isState(LLSpatialGroup::ALPHA_DIRTY)) + if (!group->hasState(LLSpatialGroup::ALPHA_DIRTY)) { - if (!group->mSpatialPartition->isBridge()) + if (!group->getSpatialPartition()->isBridge()) { LLVector4a view_angle = eye; @@ -1336,23 +796,18 @@ F32 LLSpatialGroup::getUpdateUrgency() const } } -BOOL LLSpatialGroup::needsUpdate() -{ - return (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE; -} - BOOL LLSpatialGroup::changeLOD() { - if (isState(ALPHA_DIRTY | OBJECT_DIRTY)) + if (hasState(ALPHA_DIRTY | OBJECT_DIRTY)) { ///a rebuild is going to happen, update distance and LoD return TRUE; } - if (mSpatialPartition->mSlopRatio > 0.f) + if (getSpatialPartition()->mSlopRatio > 0.f) { F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius)); - if (fabsf(ratio) >= mSpatialPartition->mSlopRatio) + if (fabsf(ratio) >= getSpatialPartition()->mSlopRatio) { return TRUE; } @@ -1371,17 +826,17 @@ BOOL LLSpatialGroup::changeLOD() return FALSE; } -void LLSpatialGroup::handleInsertion(const TreeNode* node, LLDrawable* drawablep) +void LLSpatialGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* entry) { - addObject(drawablep, FALSE, TRUE); + addObject((LLDrawable*)entry->getDrawable()); unbound(); setState(OBJECT_DIRTY); } -void LLSpatialGroup::handleRemoval(const TreeNode* node, LLDrawable* drawable) +void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* entry) { - removeObject(drawable, TRUE); - setState(OBJECT_DIRTY); + removeObject((LLDrawable*)entry->getDrawable(), TRUE); + LLviewerOctreeGroup::handleRemoval(node, entry); } void LLSpatialGroup::handleDestruction(const TreeNode* node) @@ -1390,15 +845,22 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) for (element_iter i = getDataBegin(); i != getDataEnd(); ++i) { - LLDrawable* drawable = *i; - if (drawable->getSpatialGroup() == this) + LLViewerOctreeEntry* entry = *i; + if (entry->getGroup() == this) { - drawable->setSpatialGroup(NULL); + if(entry->hasDrawable()) + { + ((LLDrawable*)entry->getDrawable())->setGroup(NULL); + } + else + { + llerrs << "No Drawable found in the entry." << llendl; + } } } //clean up avatar attachment stats - LLSpatialBridge* bridge = mSpatialPartition->asBridge(); + LLSpatialBridge* bridge = getSpatialPartition()->asBridge(); if (bridge) { if (bridge->mAvatar.notNull()) @@ -1415,21 +877,11 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node) mOctreeNode = NULL; } -void LLSpatialGroup::handleStateChange(const TreeNode* node) -{ - //drop bounding box upon state change - if (mOctreeNode != node) - { - mOctreeNode = (OctreeNode*) node; - } - unbound(); -} - void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) { if (child->getListenerCount() == 0) { - new LLSpatialGroup(child, mSpatialPartition); + new LLSpatialGroup(child, getSpatialPartition()); } else { @@ -1441,11 +893,6 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c assert_states_valid(this); } -void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child) -{ - unbound(); -} - void LLSpatialGroup::destroyGL(bool keep_occlusion) { setState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::IMAGE_DIRTY); @@ -1463,20 +910,17 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion) if (!keep_occlusion) { - for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) - { - if (mOcclusionQuery[i]) - { - sQueryPool.release(mOcclusionQuery[i]); - mOcclusionQuery[i] = 0; - } - } + releaseOcclusionQueryObjectNames(); } for (LLSpatialGroup::element_iter i = getDataBegin(); i != getDataEnd(); ++i) { - LLDrawable* drawable = *i; + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } for (S32 j = 0; j < drawable->getNumFaces(); j++) { LLFace* facep = drawable->getFace(j); @@ -1488,318 +932,27 @@ void LLSpatialGroup::destroyGL(bool keep_occlusion) } } -BOOL LLSpatialGroup::rebound() -{ - if (!isState(DIRTY)) - { //return TRUE if we're not empty - return TRUE; - } - - if (mOctreeNode->getChildCount() == 1 && mOctreeNode->getElementCount() == 0) - { - LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0); - group->rebound(); - - //copy single child's bounding box - mBounds[0] = group->mBounds[0]; - mBounds[1] = group->mBounds[1]; - mExtents[0] = group->mExtents[0]; - mExtents[1] = group->mExtents[1]; - - group->setState(SKIP_FRUSTUM_CHECK); - } - else if (mOctreeNode->isLeaf()) - { //copy object bounding box if this is a leaf - boundObjects(TRUE, mExtents[0], mExtents[1]); - mBounds[0] = mObjectBounds[0]; - mBounds[1] = mObjectBounds[1]; - } - else - { - LLVector4a& newMin = mExtents[0]; - LLVector4a& newMax = mExtents[1]; - LLSpatialGroup* group = (LLSpatialGroup*) mOctreeNode->getChild(0)->getListener(0); - group->clearState(SKIP_FRUSTUM_CHECK); - group->rebound(); - //initialize to first child - newMin = group->mExtents[0]; - newMax = group->mExtents[1]; - - //first, rebound children - for (U32 i = 1; i < mOctreeNode->getChildCount(); i++) - { - group = (LLSpatialGroup*) mOctreeNode->getChild(i)->getListener(0); - group->clearState(SKIP_FRUSTUM_CHECK); - group->rebound(); - const LLVector4a& max = group->mExtents[1]; - const LLVector4a& min = group->mExtents[0]; - - newMax.setMax(newMax, max); - newMin.setMin(newMin, min); - } - - boundObjects(FALSE, newMin, newMax); - - mBounds[0].setAdd(newMin, newMax); - mBounds[0].mul(0.5f); - mBounds[1].setSub(newMax, newMin); - mBounds[1].mul(0.5f); - } - - clearState(DIRTY); - - return TRUE; -} - -static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Occlusion Wait"); - -void LLSpatialGroup::checkOcclusion() -{ - if (LLPipeline::sUseOcclusion > 1) - { - LLFastTimer t(FTM_OCCLUSION_READBACK); - LLSpatialGroup* parent = getParent(); - if (parent && parent->isOcclusionState(LLSpatialGroup::OCCLUDED)) - { //if the parent has been marked as occluded, the child is implicitly occluded - clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); - } - else if (isOcclusionState(QUERY_PENDING)) - { //otherwise, if a query is pending, read it back - - GLuint available = 0; - if (mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { - glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); - - static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion"); - - if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) - { //query was issued last frame, wait until it's available - S32 max_loop = 1024; - LLFastTimer t(FTM_OCCLUSION_WAIT); - while (!available && max_loop-- > 0) - { - F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f); - //do some usefu work while we wait - LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread - LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread - LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread - - glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); - } - } - } - else - { - available = 1; - } - - if (available) - { //result is available, read it back, otherwise wait until next frame - GLuint res = 1; - if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { - glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res); -#if LL_TRACK_PENDING_OCCLUSION_QUERIES - sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]); -#endif - } - else if (mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { //delete the query to avoid holding onto hundreds of pending queries - sQueryPool.release(mOcclusionQuery[LLViewerCamera::sCurCameraID]); - mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; - } - - if (isOcclusionState(DISCARD_QUERY)) - { - res = 2; - } - - if (res > 0) - { - assert_states_valid(this); - clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); - assert_states_valid(this); - } - else - { - assert_states_valid(this); - - setOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); - - assert_states_valid(this); - } - - clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); - } - } - else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLSpatialGroup::OCCLUDED)) - { //check occlusion has been issued for occluded node that has not had a query issued - assert_states_valid(this); - clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); - assert_states_valid(this); - } - } -} - -static LLFastTimer::DeclareTimer FTM_PUSH_OCCLUSION_VERTS("Push Occlusion"); -static LLFastTimer::DeclareTimer FTM_SET_OCCLUSION_STATE("Occlusion State"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_EARLY_FAIL("Occlusion Early Fail"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_ALLOCATE("Allocate"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_BUILD("Build"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_BEGIN_QUERY("Begin Query"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_END_QUERY("End Query"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_SET_BUFFER("Set Buffer"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW_WATER("Draw Water"); -static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW("Draw"); - - - -void LLSpatialGroup::doOcclusion(LLCamera* camera) -{ - if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1) - { - // Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension - if (earlyFail(camera, this)) - { - LLFastTimer t(FTM_OCCLUSION_EARLY_FAIL); - setOcclusionState(LLSpatialGroup::DISCARD_QUERY); - assert_states_valid(this); - clearOcclusionState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); - assert_states_valid(this); - } - else - { - if (!isOcclusionState(QUERY_PENDING) || isOcclusionState(DISCARD_QUERY)) - { - { //no query pending, or previous query to be discarded - LLFastTimer t(FTM_RENDER_OCCLUSION); - - if (!mOcclusionQuery[LLViewerCamera::sCurCameraID]) - { - LLFastTimer t(FTM_OCCLUSION_ALLOCATE); - mOcclusionQuery[LLViewerCamera::sCurCameraID] = sQueryPool.allocate(); - } - - // Depth clamp all water to avoid it being culled as a result of being - // behind the far clip plane, and in the case of edge water to avoid - // it being culled while still visible. - bool const use_depth_clamp = gGLManager.mHasDepthClamp && - (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER || - mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER); - - LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0); - -#if !LL_DARWIN - U32 mode = gGLManager.mHasOcclusionQuery2 ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED_ARB; -#else - U32 mode = GL_SAMPLES_PASSED_ARB; -#endif - -#if LL_TRACK_PENDING_OCCLUSION_QUERIES - sPendingQueries.insert(mOcclusionQuery[LLViewerCamera::sCurCameraID]); -#endif - - { - LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS); - - //store which frame this query was issued on - mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount; - - { - LLFastTimer t(FTM_OCCLUSION_BEGIN_QUERY); - glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); - } - - LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; - llassert(shader); - - shader->uniform3fv(LLShaderMgr::BOX_CENTER, 1, mBounds[0].getF32ptr()); - shader->uniform3f(LLShaderMgr::BOX_SIZE, mBounds[1][0]+SG_OCCLUSION_FUDGE, - mBounds[1][1]+SG_OCCLUSION_FUDGE, - mBounds[1][2]+SG_OCCLUSION_FUDGE); - - if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER) - { - LLFastTimer t(FTM_OCCLUSION_DRAW_WATER); - - LLGLSquashToFarClip squash(glh_get_current_projection(), 1); - if (camera->getOrigin().isExactlyZero()) - { //origin is invalid, draw entire box - gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); - gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); - } - else - { - gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); - } - } - else - { - LLFastTimer t(FTM_OCCLUSION_DRAW); - if (camera->getOrigin().isExactlyZero()) - { //origin is invalid, draw entire box - gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); - gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); - } - else - { - gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); - } - } - - - { - LLFastTimer t(FTM_OCCLUSION_END_QUERY); - glEndQueryARB(mode); - } - } - } - - { - LLFastTimer t(FTM_SET_OCCLUSION_STATE); - setOcclusionState(LLSpatialGroup::QUERY_PENDING); - clearOcclusionState(LLSpatialGroup::DISCARD_QUERY); - } - } - } - } -} - //============================================== -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) { - mOcclusionEnabled = TRUE; - mDrawableType = 0; + mRegionp = regionp; mPartitionType = LLViewerRegion::PARTITION_NONE; - mLODSeed = 0; - mLODPeriod = 1; mVertexDataMask = data_mask; mBufferUsage = buffer_usage; mDepthMask = FALSE; mSlopRatio = 0.25f; mInfiniteFarClip = FALSE; - LLVector4a center, size; - center.splat(0.f); - size.splat(1.f); - - mOctree = new LLSpatialGroup::OctreeRoot(center,size, - NULL); new LLSpatialGroup(mOctree, this); } LLSpatialPartition::~LLSpatialPartition() { - delete mOctree; - mOctree = NULL; } - LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) { drawablep->updateSpatialExtents(); @@ -1807,11 +960,15 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) //keep drawable from being garbage collected LLPointer<LLDrawable> ptr = drawablep; + if(!drawablep->getGroup()) + { assert_octree_valid(mOctree); - mOctree->insert(drawablep); + mOctree->insert(drawablep->getEntry()); assert_octree_valid(mOctree); + } LLSpatialGroup* group = drawablep->getSpatialGroup(); + llassert(group != NULL); if (group && was_visible && group->isOcclusionState(LLSpatialGroup::QUERY_PENDING)) { @@ -1829,11 +986,9 @@ BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) } else { - drawablep->setSpatialGroup(NULL); + drawablep->setGroup(NULL); } - drawablep->setSpatialGroup(NULL); - assert_octree_valid(mOctree); return TRUE; @@ -1851,11 +1006,11 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL BOOL was_visible = curp ? curp->isVisible() : FALSE; - if (curp && curp->mSpatialPartition != this) + if (curp && curp->getSpatialPartition() != this) { //keep drawable from being garbage collected LLPointer<LLDrawable> ptr = drawablep; - if (curp->mSpatialPartition->remove(drawablep, curp)) + if (curp->getSpatialPartition()->remove(drawablep, curp)) { put(drawablep, was_visible); return; @@ -1883,13 +1038,13 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL put(drawablep, was_visible); } -class LLSpatialShift : public LLSpatialGroup::OctreeTraveler +class LLSpatialShift : public OctreeTraveler { public: const LLVector4a& mOffset; LLSpatialShift(const LLVector4a& offset) : mOffset(offset) { } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) + virtual void visit(const OctreeNode* branch) { ((LLSpatialGroup*) branch->getListener(0))->shift(mOffset); } @@ -1901,17 +1056,17 @@ void LLSpatialPartition::shift(const LLVector4a &offset) shifter.traverse(mOctree); } -class LLOctreeCull : public LLSpatialGroup::OctreeTraveler +class LLOctreeCull : public LLViewerOctreeCull { public: - LLOctreeCull(LLCamera* camera) - : mCamera(camera), mRes(0) { } + LLOctreeCull(LLCamera* camera) : LLViewerOctreeCull(camera) {} - virtual bool earlyFail(LLSpatialGroup* group) + virtual bool earlyFail(LLviewerOctreeGroup* base_group) { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; group->checkOcclusion(); - if (group->mOctreeNode->getParent() && //never occlusion cull the root node + if (group->getOctreeNode()->getParent() && //never occlusion cull the root node LLPipeline::sUseOcclusion && //ignore occlusion if disabled group->isOcclusionState(LLSpatialGroup::OCCLUDED)) { @@ -1922,78 +1077,29 @@ public: return false; } - virtual void traverse(const LLSpatialGroup::OctreeNode* n) + virtual S32 frustumCheck(const LLviewerOctreeGroup* group) { - LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); - - if (earlyFail(group)) - { - return; - } - - if (mRes == 2 || - (mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK))) - { //fully in, just add everything - LLSpatialGroup::OctreeTraveler::traverse(n); - } - else - { - mRes = frustumCheck(group); - - if (mRes) - { //at least partially in, run on down - LLSpatialGroup::OctreeTraveler::traverse(n); - } - - mRes = 0; - } - } - - virtual S32 frustumCheck(const LLSpatialGroup* group) - { - S32 res = mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]); + S32 res = AABBInFrustumNoFarClipGroupBounds(group); if (res != 0) { - res = llmin(res, AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist)); + res = llmin(res, AABBSphereIntersectGroupExtents(group)); } return res; } - virtual S32 frustumCheckObjects(const LLSpatialGroup* group) + virtual S32 frustumCheckObjects(const LLviewerOctreeGroup* group) { - S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]); + S32 res = AABBInFrustumNoFarClipObjectBounds(group); if (res != 0) { - res = llmin(res, AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist)); + res = llmin(res, AABBSphereIntersectObjectExtents(group)); } return res; } - virtual bool checkObjects(const LLSpatialGroup::OctreeNode* branch, const LLSpatialGroup* 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; - } - - return true; - } - - virtual void preprocess(LLSpatialGroup* group) - { - - } - - virtual void processGroup(LLSpatialGroup* group) + virtual void processGroup(LLviewerOctreeGroup* base_group) { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; if (group->needsUpdate() || group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1) { @@ -2001,21 +1107,6 @@ public: } gPipeline.markNotCulled(group, *mCamera); } - - virtual void visit(const LLSpatialGroup::OctreeNode* branch) - { - LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); - - preprocess(group); - - if (checkObjects(branch, group)) - { - processGroup(group); - } - } - - LLCamera *mCamera; - S32 mRes; }; class LLOctreeCullNoFarClip : public LLOctreeCull @@ -2024,14 +1115,14 @@ public: LLOctreeCullNoFarClip(LLCamera* camera) : LLOctreeCull(camera) { } - virtual S32 frustumCheck(const LLSpatialGroup* group) + virtual S32 frustumCheck(const LLviewerOctreeGroup* group) { - return mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]); + return AABBInFrustumNoFarClipGroupBounds(group); } - virtual S32 frustumCheckObjects(const LLSpatialGroup* group) + virtual S32 frustumCheckObjects(const LLviewerOctreeGroup* group) { - S32 res = mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]); + S32 res = AABBInFrustumNoFarClipObjectBounds(group); return res; } }; @@ -2042,14 +1133,14 @@ public: LLOctreeCullShadow(LLCamera* camera) : LLOctreeCull(camera) { } - virtual S32 frustumCheck(const LLSpatialGroup* group) + virtual S32 frustumCheck(const LLviewerOctreeGroup* group) { - return mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]); + return AABBInFrustumGroupBounds(group); } - virtual S32 frustumCheckObjects(const LLSpatialGroup* group) + virtual S32 frustumCheckObjects(const LLviewerOctreeGroup* group) { - return mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]); + return AABBInFrustumObjectBounds(group); } }; @@ -2059,9 +1150,11 @@ public: LLOctreeCullVisExtents(LLCamera* camera, LLVector4a& min, LLVector4a& max) : LLOctreeCullShadow(camera), mMin(min), mMax(max), mEmpty(TRUE) { } - virtual bool earlyFail(LLSpatialGroup* group) + virtual bool earlyFail(LLviewerOctreeGroup* base_group) { - if (group->mOctreeNode->getParent() && //never occlusion cull the root node + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + + if (group->getOctreeNode()->getParent() && //never occlusion cull the root node LLPipeline::sUseOcclusion && //ignore occlusion if disabled group->isOcclusionState(LLSpatialGroup::OCCLUDED)) { @@ -2071,7 +1164,7 @@ public: return false; } - virtual void traverse(const LLSpatialGroup::OctreeNode* n) + virtual void traverse(const OctreeNode* n) { LLSpatialGroup* group = (LLSpatialGroup*) n->getListener(0); @@ -2080,10 +1173,10 @@ public: return; } - if ((mRes && group->isState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) || + if ((mRes && group->hasState(LLSpatialGroup::SKIP_FRUSTUM_CHECK)) || mRes == 2) { //don't need to do frustum check - LLSpatialGroup::OctreeTraveler::traverse(n); + OctreeTraveler::traverse(n); } else { @@ -2091,31 +1184,35 @@ public: if (mRes) { //at least partially in, run on down - LLSpatialGroup::OctreeTraveler::traverse(n); + OctreeTraveler::traverse(n); } mRes = 0; } } - virtual void processGroup(LLSpatialGroup* group) + virtual void processGroup(LLviewerOctreeGroup* base_group) { - llassert(!group->isState(LLSpatialGroup::DIRTY) && !group->isEmpty()) + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + + llassert(!group->hasState(LLSpatialGroup::DIRTY) && !group->isEmpty()) if (mRes < 2) { - if (mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]) > 0) + if (AABBInFrustumObjectBounds(group) > 0) { mEmpty = FALSE; - update_min_max(mMin, mMax, group->mObjectExtents[0]); - update_min_max(mMin, mMax, group->mObjectExtents[1]); + const LLVector4a* exts = group->getObjectExtents(); + update_min_max(mMin, mMax, exts[0]); + update_min_max(mMin, mMax, exts[1]); } } else { mEmpty = FALSE; - update_min_max(mMin, mMax, group->mExtents[0]); - update_min_max(mMin, mMax, group->mExtents[1]); + const LLVector4a* exts = group->getExtents(); + update_min_max(mMin, mMax, exts[0]); + update_min_max(mMin, mMax, exts[1]); } } @@ -2130,10 +1227,12 @@ public: LLOctreeCullDetectVisible(LLCamera* camera) : LLOctreeCullShadow(camera), mResult(FALSE) { } - virtual bool earlyFail(LLSpatialGroup* group) + virtual bool earlyFail(LLviewerOctreeGroup* base_group) { + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + if (mResult || //already found a node, don't check any more - (group->mOctreeNode->getParent() && //never occlusion cull the root node + (group->getOctreeNode()->getParent() && //never occlusion cull the root node LLPipeline::sUseOcclusion && //ignore occlusion if disabled group->isOcclusionState(LLSpatialGroup::OCCLUDED))) { @@ -2143,9 +1242,9 @@ public: return false; } - virtual void processGroup(LLSpatialGroup* group) + virtual void processGroup(LLviewerOctreeGroup* base_group) { - if (group->isVisible()) + if (base_group->isVisible()) { mResult = TRUE; } @@ -2160,17 +1259,21 @@ public: LLOctreeSelect(LLCamera* camera, std::vector<LLDrawable*>* results) : LLOctreeCull(camera), mResults(results) { } - virtual bool earlyFail(LLSpatialGroup* group) { return false; } - virtual void preprocess(LLSpatialGroup* group) { } + virtual bool earlyFail(LLviewerOctreeGroup* group) { return false; } + virtual void preprocess(LLviewerOctreeGroup* group) { } - virtual void processGroup(LLSpatialGroup* group) + virtual void processGroup(LLviewerOctreeGroup* base_group) { - LLSpatialGroup::OctreeNode* branch = group->mOctreeNode; + LLSpatialGroup* group = (LLSpatialGroup*)base_group; + OctreeNode* branch = group->getOctreeNode(); - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { - LLDrawable* drawable = *i; - + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } if (!drawable->isDead()) { if (drawable->isSpatialBridge()) @@ -2283,18 +1386,22 @@ void drawBoxOutline(const LLVector4a& pos, const LLVector4a& size) drawBoxOutline(reinterpret_cast<const LLVector3&>(pos), reinterpret_cast<const LLVector3&>(size)); } -class LLOctreeDirty : public LLOctreeTraveler<LLDrawable> +class LLOctreeDirty : public OctreeTraveler { public: - virtual void visit(const LLOctreeNode<LLDrawable>* state) + virtual void visit(const OctreeNode* state) { LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); group->destroyGL(); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawable = *i; - if (drawable->getVObj().notNull() && !group->mSpatialPartition->mRenderByGroup) + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + if (drawable->getVObj().notNull() && !group->getSpatialPartition()->mRenderByGroup) { gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE); } @@ -2318,11 +1425,6 @@ void LLSpatialPartition::resetVertexBuffers() dirty.traverse(mOctree); } -BOOL LLSpatialPartition::isOcclusionEnabled() -{ - return mOcclusionEnabled || LLPipeline::sUseOcclusion > 2; -} - BOOL LLSpatialPartition::getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax) { LLVector4a visMina, visMaxa; @@ -2365,13 +1467,28 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result ((LLSpatialGroup*)mOctree->getListener(0))->validate(); #endif + LLOctreeSelect selecter(&camera, results); + selecter.traverse(mOctree); + + return 0; +} - if (for_select) +S32 LLSpatialPartition::cull(LLCamera &camera) +{ +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->checkStates(); +#endif { - LLOctreeSelect selecter(&camera, results); - selecter.traverse(mOctree); + LLFastTimer ftm(FTM_CULL_REBOUND); + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); } - else if (LLPipeline::sShadowRender) + +#if LL_OCTREE_PARANOIA_CHECK + ((LLSpatialGroup*)mOctree->getListener(0))->validate(); +#endif + + if (LLPipeline::sShadowRender) { LLFastTimer ftm(FTM_FRUSTUM_CULL); LLOctreeCullShadow culler(&camera); @@ -2393,50 +1510,6 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector<LLDrawable *>* result return 0; } -BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) -{ - if (camera->getOrigin().isExactlyZero()) - { - return FALSE; - } - - const F32 vel = SG_OCCLUSION_FUDGE*2.f; - LLVector4a fudge; - fudge.splat(vel); - - const LLVector4a& c = group->mBounds[0]; - LLVector4a r; - r.setAdd(group->mBounds[1], fudge); - - /*if (r.magVecSquared() > 1024.0*1024.0) - { - return TRUE; - }*/ - - LLVector4a e; - e.load3(camera->getOrigin().mV); - - LLVector4a min; - min.setSub(c,r); - LLVector4a max; - max.setAdd(c,r); - - S32 lt = e.lessThan(min).getGatheredBits() & 0x7; - if (lt) - { - return FALSE; - } - - S32 gt = e.greaterThan(max).getGatheredBits() & 0x7; - if (gt) - { - return FALSE; - } - - return TRUE; -} - - void pushVerts(LLDrawInfo* params, U32 mask) { LLRenderPass::applyModelMatrix(*params); @@ -2508,7 +1581,7 @@ void pushBufferVerts(LLVertexBuffer* buffer, U32 mask) void pushBufferVerts(LLSpatialGroup* group, U32 mask) { - if (group->mSpatialPartition->mRenderByGroup) + if (group->getSpatialPartition()->mRenderByGroup) { if (!group->mDrawMap.empty()) { @@ -2531,7 +1604,8 @@ void pushBufferVerts(LLSpatialGroup* group, U32 mask) } else { - drawBox(group->mBounds[0], group->mBounds[1]); + const LLVector4a* bounds = group->getBounds(); + drawBox(bounds[0], bounds[1]); } } @@ -2576,7 +1650,7 @@ void renderOctree(LLSpatialGroup* group) LLVector4 col; if (group->mBuilt > 0.f) { - group->mBuilt -= 2.f * gFrameIntervalSeconds; + group->mBuilt -= 2.f * gFrameIntervalSeconds.value(); if (group->mBufferUsage == GL_STATIC_DRAW_ARB) { col.setVec(1.0f, 0, 0, group->mBuilt*0.5f); @@ -2595,14 +1669,20 @@ void renderOctree(LLSpatialGroup* group) gGL.diffuseColor4f(1,0,0,group->mBuilt); gGL.flush(); glLineWidth(5.f); - drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]); + + const LLVector4a* bounds = group->getObjectBounds(); + drawBoxOutline(bounds[0], bounds[1]); gGL.flush(); glLineWidth(1.f); gGL.flush(); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawable = *i; - if (!group->mSpatialPartition->isBridge()) + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } + if (!group->getSpatialPartition()->isBridge()) { gGL.pushMatrix(); LLVector3 trans = drawable->getRegion()->getOriginAgent(); @@ -2634,7 +1714,7 @@ void renderOctree(LLSpatialGroup* group) } } - if (!group->mSpatialPartition->isBridge()) + if (!group->getSpatialPartition()->isBridge()) { gGL.popMatrix(); } @@ -2646,7 +1726,7 @@ void renderOctree(LLSpatialGroup* group) else { if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->isEmpty() - && group->mSpatialPartition->mRenderByGroup) + && group->getSpatialPartition()->mRenderByGroup) { col.setVec(0.8f, 0.4f, 0.1f, 0.1f); } @@ -2659,9 +1739,10 @@ void renderOctree(LLSpatialGroup* group) gGL.diffuseColor4fv(col.mV); LLVector4a fudge; fudge.splat(0.001f); - LLVector4a size = group->mObjectBounds[1]; - size.mul(1.01f); - size.add(fudge); + + //LLVector4a size = group->mObjectBounds[1]; + //size.mul(1.01f); + //size.add(fudge); //{ // LLGLDepthTest depth(GL_TRUE, GL_FALSE); @@ -2677,10 +1758,12 @@ void renderOctree(LLSpatialGroup* group) //drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]); gGL.diffuseColor4f(0,1,1,1); - drawBoxOutline(group->mBounds[0],group->mBounds[1]); + + const LLVector4a* bounds = group->getBounds(); + drawBoxOutline(bounds[0], bounds[1]); //draw bounding box for draw info - /*if (group->mSpatialPartition->mRenderByGroup) + /*if (group->getSpatialPartition()->mRenderByGroup) { gGL.diffuseColor4f(1.0f, 0.75f, 0.25f, 0.6f); for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) @@ -3444,13 +2527,17 @@ void renderPhysicsShape(LLDrawable* drawable, LLVOVolume* volume) void renderPhysicsShapes(LLSpatialGroup* group) { - for (LLSpatialGroup::OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + for (OctreeNode::const_element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawable = *i; + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) + { + continue; + } LLVOVolume* volume = drawable->getVOVolume(); if (volume && !volume->isAttachment() && volume->getPhysicsShapeType() != LLViewerObject::PHYSICS_SHAPE_NONE ) { - if (!group->mSpatialPartition->isBridge()) + if (!group->getSpatialPartition()->isBridge()) { gGL.pushMatrix(); LLVector3 trans = drawable->getRegion()->getOriginAgent(); @@ -4003,17 +3090,18 @@ void renderAgentTarget(LLVOAvatar* avatar) } } -class LLOctreeRenderNonOccluded : public LLOctreeTraveler<LLDrawable> +class LLOctreeRenderNonOccluded : public OctreeTraveler { public: LLCamera* mCamera; LLOctreeRenderNonOccluded(LLCamera* camera): mCamera(camera) {} - virtual void traverse(const LLSpatialGroup::OctreeNode* node) + virtual void traverse(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!mCamera || mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1])) + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) { node->accept(this); stop_glerror(); @@ -4053,11 +3141,11 @@ public: } } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) + virtual void visit(const OctreeNode* branch) { LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); - - if (group->isState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))) + const LLVector4a* bounds = group->getBounds(); + if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) { return; } @@ -4070,14 +3158,19 @@ public: if (!group->isEmpty()) { gGL.diffuseColor3f(0,0,1); - drawBoxOutline(group->mObjectBounds[0], - group->mObjectBounds[1]); + + const LLVector4a* obj_bounds = group->getObjectBounds(); + drawBoxOutline(obj_bounds[0], obj_bounds[1]); } } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) { - LLDrawable* drawable = *i; + continue; + } if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) { @@ -4200,17 +3293,18 @@ public: }; -class LLOctreeRenderPhysicsShapes : public LLOctreeTraveler<LLDrawable> +class LLOctreeRenderPhysicsShapes : public OctreeTraveler { public: LLCamera* mCamera; LLOctreeRenderPhysicsShapes(LLCamera* camera): mCamera(camera) {} - virtual void traverse(const LLSpatialGroup::OctreeNode* node) + virtual void traverse(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!mCamera || mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1])) + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1])) { node->accept(this); stop_glerror(); @@ -4228,23 +3322,24 @@ public: } } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) + virtual void visit(const OctreeNode* branch) { } }; -class LLOctreePushBBoxVerts : public LLOctreeTraveler<LLDrawable> +class LLOctreePushBBoxVerts : public OctreeTraveler { public: LLCamera* mCamera; LLOctreePushBBoxVerts(LLCamera* camera): mCamera(camera) {} - virtual void traverse(const LLSpatialGroup::OctreeNode* node) + virtual void traverse(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!mCamera || mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1])) + const LLVector4a* bounds = group->getBounds(); + if (!mCamera || mCamera->AABBInFrustum(bounds[0], bounds[1])) { node->accept(this); @@ -4255,19 +3350,23 @@ public: } } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) + virtual void visit(const OctreeNode* branch) { LLSpatialGroup* group = (LLSpatialGroup*) branch->getListener(0); - if (group->isState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]))) + const LLVector4a* bounds = group->getBounds(); + if (group->hasState(LLSpatialGroup::GEOM_DIRTY) || (mCamera && !mCamera->AABBInFrustumNoFarClip(bounds[0], bounds[1]))) { return; } - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + { + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(!drawable) { - LLDrawable* drawable = *i; - + continue; + } renderBoundingBox(drawable, FALSE); } } @@ -4279,7 +3378,7 @@ void LLSpatialPartition::renderIntersectingBBoxes(LLCamera* camera) pusher.traverse(mOctree); } -class LLOctreeStateCheck : public LLOctreeTraveler<LLDrawable> +class LLOctreeStateCheck : public OctreeTraveler { public: U32 mInheritedMask[LLViewerCamera::NUM_CAMERAS]; @@ -4292,7 +3391,7 @@ public: } } - virtual void traverse(const LLSpatialGroup::OctreeNode* node) + virtual void traverse(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); @@ -4319,7 +3418,7 @@ public: } - virtual void visit(const LLOctreeNode<LLDrawable>* state) + virtual void visit(const OctreeNode* state) { LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); @@ -4331,7 +3430,7 @@ public: } } - if (group->isState(LLSpatialGroup::DIRTY)) + if (group->hasState(LLSpatialGroup::DIRTY)) { assert_parent_state(group, LLSpatialGroup::DIRTY); } @@ -4342,7 +3441,7 @@ public: LLSpatialGroup* parent = group->getParent(); while (parent) { - if (!parent->isState(state)) + if (!parent->hasState(state)) { llerrs << "Spatial group failed parent state check." << llendl; } @@ -4457,7 +3556,7 @@ BOOL LLSpatialPartition::isVisible(const LLVector3& v) return TRUE; } -class LLOctreeIntersect : public LLSpatialGroup::OctreeTraveler +class LLOctreeIntersect : public OctreeTraveler { public: LLVector3 mStart; @@ -4484,21 +3583,21 @@ public: { } - virtual void visit(const LLSpatialGroup::OctreeNode* branch) + virtual void visit(const OctreeNode* branch) { - for (LLSpatialGroup::OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) + for (OctreeNode::const_element_iter i = branch->getDataBegin(); i != branch->getDataEnd(); ++i) { check(*i); } } - virtual LLDrawable* check(const LLSpatialGroup::OctreeNode* node) + virtual LLDrawable* check(const OctreeNode* node) { node->accept(this); for (U32 i = 0; i < node->getChildCount(); i++) { - const LLSpatialGroup::OctreeNode* child = node->getChild(i); + const OctreeNode* child = node->getChild(i); LLVector3 res; LLSpatialGroup* group = (LLSpatialGroup*) child->getListener(0); @@ -4506,15 +3605,16 @@ public: LLVector4a size; LLVector4a center; - size = group->mBounds[1]; - center = group->mBounds[0]; + const LLVector4a* bounds = group->getBounds(); + size = bounds[1]; + center = bounds[0]; LLVector3 local_start = mStart; LLVector3 local_end = mEnd; - if (group->mSpatialPartition->isBridge()) + if (group->getSpatialPartition()->isBridge()) { - LLMatrix4 local_matrix = group->mSpatialPartition->asBridge()->mDrawable->getRenderMatrix(); + LLMatrix4 local_matrix = group->getSpatialPartition()->asBridge()->mDrawable->getRenderMatrix(); local_matrix.invert(); local_start = mStart * local_matrix; @@ -4534,8 +3634,10 @@ public: return mHit; } - virtual bool check(LLDrawable* drawable) - { + virtual bool check(LLViewerOctreeEntry* entry) + { + LLDrawable* drawable = (LLDrawable*)entry->getDrawable(); + if (!drawable || !gPipeline.hasRenderType(drawable->getRenderType()) || !drawable->isVisible()) { return false; @@ -4926,5 +4028,3 @@ void LLCullResult::assertDrawMapsEmpty() } } - - diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h index b1706d9d35..406e796d4d 100755 --- a/indra/newview/llspatialpartition.h +++ b/indra/newview/llspatialpartition.h @@ -45,23 +45,16 @@ #define SG_STATE_INHERIT_MASK (OCCLUDED) #define SG_INITIAL_STATE_MASK (DIRTY | GEOM_DIRTY) +class LLViewerOctreePartition; class LLSpatialPartition; class LLSpatialBridge; class LLSpatialGroup; class LLTextureAtlas; class LLTextureAtlasSlot; +class LLViewerRegion; -S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad); -S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &radius_squared); - -S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad); -S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared); void pushVerts(LLFace* face, U32 mask); -// get index buffer for binary encoded axis vertex buffer given a box at center being viewed by given camera -U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center); -U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center); - class LLDrawInfo : public LLRefCount { protected: @@ -192,13 +185,13 @@ public: }; LL_ALIGN_PREFIX(16) -class LLSpatialGroup : public LLOctreeListener<LLDrawable> +class LLSpatialGroup : public LLOcclusionCullingGroup { friend class LLSpatialPartition; friend class LLOctreeStateCheck; public: - LLSpatialGroup(const LLSpatialGroup& rhs) + LLSpatialGroup(const LLSpatialGroup& rhs) : LLOcclusionCullingGroup(rhs) { *this = rhs; } @@ -219,7 +212,6 @@ public: return *this; } - static std::set<GLuint> sPendingQueries; //pending occlusion queries static U32 sNodeCount; static BOOL sNoDelete; //deletion of spatial groups and draw info not allowed if TRUE @@ -231,15 +223,6 @@ public: typedef std::map<LLFace*, buffer_list_t> buffer_texture_map_t; typedef std::map<U32, buffer_texture_map_t> buffer_map_t; - typedef LLOctreeListener<LLDrawable> BaseType; - typedef LLOctreeListener<LLDrawable> OctreeListener; - typedef LLTreeNode<LLDrawable> TreeNode; - typedef LLOctreeNode<LLDrawable> OctreeNode; - typedef LLOctreeRoot<LLDrawable> OctreeRoot; - typedef LLOctreeTraveler<LLDrawable> OctreeTraveler; - typedef LLOctreeNode<LLDrawable>::element_iter element_iter; - typedef LLOctreeNode<LLDrawable>::element_list element_list; - struct CompareDistanceGreater { bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs) @@ -266,104 +249,57 @@ public: typedef enum { - OCCLUDED = 0x00010000, - QUERY_PENDING = 0x00020000, - ACTIVE_OCCLUSION = 0x00040000, - DISCARD_QUERY = 0x00080000, - EARLY_FAIL = 0x00100000, - } eOcclusionState; - - typedef enum - { - DEAD = 0x00000001, - DIRTY = 0x00000002, - OBJECT_DIRTY = 0x00000004, - GEOM_DIRTY = 0x00000008, - ALPHA_DIRTY = 0x00000010, - SKIP_FRUSTUM_CHECK = 0x00000020, - IN_IMAGE_QUEUE = 0x00000040, - IMAGE_DIRTY = 0x00000080, - MESH_DIRTY = 0x00000100, - NEW_DRAWINFO = 0x00000200, - IN_BUILD_Q1 = 0x00000400, - IN_BUILD_Q2 = 0x00000800, + GEOM_DIRTY = LLviewerOctreeGroup::INVALID_STATE, + ALPHA_DIRTY = (GEOM_DIRTY << 1), + IN_IMAGE_QUEUE = (ALPHA_DIRTY << 1), + IMAGE_DIRTY = (IN_IMAGE_QUEUE << 1), + MESH_DIRTY = (IMAGE_DIRTY << 1), + NEW_DRAWINFO = (MESH_DIRTY << 1), + IN_BUILD_Q1 = (NEW_DRAWINFO << 1), + IN_BUILD_Q2 = (IN_BUILD_Q1 << 1), STATE_MASK = 0x0000FFFF, - } eSpatialState; - - typedef enum - { - STATE_MODE_SINGLE = 0, //set one node - STATE_MODE_BRANCH, //set entire branch - STATE_MODE_DIFF, //set entire branch as long as current state is different - STATE_MODE_ALL_CAMERAS, //used for occlusion state, set state for all cameras - } eSetStateMode; + } eSpatialState; LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part); - BOOL isHUDGroup() ; - BOOL isDead() { return isState(DEAD); } - BOOL isState(U32 state) const; - BOOL isOcclusionState(U32 state) const { return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; } - U32 getState() { return mState; } - void setState(U32 state); - void clearState(U32 state); + BOOL isHUDGroup() ; void clearDrawMap(); void validate(); - void checkStates(); void validateDrawMap(); void setState(U32 state, S32 mode); void clearState(U32 state, S32 mode); - - void setOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE); - void clearOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE); + void clearState(U32 state) {mState &= ~state;} LLSpatialGroup* getParent(); - - BOOL addObject(LLDrawable *drawablep, BOOL add_all = FALSE, BOOL from_octree = FALSE); + BOOL addObject(LLDrawable *drawablep); BOOL removeObject(LLDrawable *drawablep, BOOL from_octree = FALSE); BOOL updateInGroup(LLDrawable *drawablep, BOOL immediate = FALSE); // Update position if it's in the group - BOOL isVisible() const; BOOL isRecentlyVisible() const; - void setVisible(); - void shift(const LLVector4a &offset); - BOOL boundObjects(BOOL empty, LLVector4a& newMin, LLVector4a& newMax); - void unbound(); - BOOL rebound(); - void checkOcclusion(); //read back last occlusion query (if any) - void doOcclusion(LLCamera* camera); //issue occlusion query + void shift(const LLVector4a &offset); void destroyGL(bool keep_occlusion = false); void updateDistance(LLCamera& camera); - BOOL needsUpdate(); F32 getUpdateUrgency() const; BOOL changeLOD(); void rebuildGeom(); void rebuildMesh(); + void setState(U32 state) {mState |= state;} void dirtyGeom() { setState(GEOM_DIRTY); } void dirtyMesh() { setState(MESH_DIRTY); } - //octree wrappers to make code more readable - element_list& getData() { return mOctreeNode->getData(); } - element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } - element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } - bool hasElement(LLDrawable* drawablep) { return std::find(mOctreeNode->getDataBegin(), mOctreeNode->getDataEnd(), drawablep) != mOctreeNode->getDataEnd(); } - - U32 getElementCount() const { return mOctreeNode->getElementCount(); } - bool isEmpty() const { return mOctreeNode->isEmpty(); } - void drawObjectBox(LLColor4 col); + LLSpatialPartition* getSpatialPartition() {return (LLSpatialPartition*)mSpatialPartition;} + //LISTENER FUNCTIONS - virtual void handleInsertion(const TreeNode* node, LLDrawable* face); - virtual void handleRemoval(const TreeNode* node, LLDrawable* face); + virtual void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* face); + virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* face); virtual void handleDestruction(const TreeNode* node); - virtual void handleStateChange(const TreeNode* node); virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); - virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child); //------------------- //for atlas use @@ -386,21 +322,6 @@ public: public: - typedef enum - { - BOUNDS = 0, - EXTENTS = 2, - OBJECT_BOUNDS = 4, - OBJECT_EXTENTS = 6, - VIEW_ANGLE = 8, - LAST_VIEW_ANGLE = 9, - V4_COUNT = 10 - } eV4Index; - - LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) - 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 - LL_ALIGN_16(LLVector4a mObjectBounds[2]); // bounding box (center, size) of objects in this node LL_ALIGN_16(LLVector4a mViewAngle); LL_ALIGN_16(LLVector4a mLastUpdateViewAngle); @@ -419,13 +340,8 @@ private: //------------------- protected: - virtual ~LLSpatialGroup(); - - U32 mState; - U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS]; - U32 mOcclusionIssued[LLViewerCamera::NUM_CAMERAS]; - - S32 mLODHash; + virtual ~LLSpatialGroup(); + static S32 sLODSeed; public: @@ -435,17 +351,13 @@ public: U32 mGeometryBytes; //used by volumes to track how many bytes of geometry data are in this node F32 mSurfaceArea; //used by volumes to track estimated surface area of geometry in this node - F32 mBuilt; - OctreeNode* mOctreeNode; - LLSpatialPartition* mSpatialPartition; + F32 mBuilt; - LLPointer<LLVertexBuffer> mVertexBuffer; - GLuint mOcclusionQuery[LLViewerCamera::NUM_CAMERAS]; + LLPointer<LLVertexBuffer> mVertexBuffer; U32 mBufferUsage; draw_map_t mDrawMap; - S32 mVisible[LLViewerCamera::NUM_CAMERAS]; F32 mDistance; F32 mDepth; F32 mLastUpdateDistance; @@ -468,10 +380,10 @@ public: virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage); }; -class LLSpatialPartition: public LLGeometryManager +class LLSpatialPartition: public LLViewerOctreePartition, public LLGeometryManager { public: - 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); @@ -498,7 +410,8 @@ public: virtual void rebuildMesh(LLSpatialGroup* group); BOOL visibleObjectsInFrustum(LLCamera& camera); - S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum + /*virtual*/ S32 cull(LLCamera &camera); // Cull on arbitrary frustum + S32 cull(LLCamera &camera, std::vector<LLDrawable *>* results, BOOL for_select); // Cull on arbitrary frustum BOOL isVisible(const LLVector3& v); bool isHUDPartition() ; @@ -510,26 +423,21 @@ public: void renderDebug(); void renderIntersectingBBoxes(LLCamera* camera); void restoreGL(); - void resetVertexBuffers(); - BOOL isOcclusionEnabled(); + void resetVertexBuffers(); + BOOL getVisibleExtents(LLCamera& camera, LLVector3& visMin, LLVector3& visMax); public: - LLSpatialGroup::OctreeNode* mOctree; LLSpatialBridge* mBridge; // NULL for non-LLSpatialBridge instances, otherwise, mBridge == this // use a pointer instead of making "isBridge" and "asBridge" virtual so it's safe - // to call asBridge() from the destructor - BOOL mOcclusionEnabled; // if TRUE, occlusion culling is performed + // to call asBridge() from the destructor + BOOL mInfiniteFarClip; // if TRUE, frustum culling ignores far clip plane - U32 mBufferUsage; - const BOOL mRenderByGroup; - U32 mLODSeed; - U32 mLODPeriod; //number of frames between LOD updates for a given spatial group (staggered by mLODSeed) + U32 mBufferUsage; + const BOOL mRenderByGroup; U32 mVertexDataMask; F32 mSlopRatio; //percentage distance must change before drawables receive LOD update (default is 0.25); BOOL mDepthMask; //if TRUE, objects in this partition will be written to depth during alpha rendering - U32 mDrawableType; - U32 mPartitionType; }; // class for creating bridges between spatial partitions @@ -541,7 +449,7 @@ protected: public: typedef std::vector<LLPointer<LLSpatialBridge> > 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(); @@ -663,7 +571,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) { } }; @@ -672,14 +580,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); }; @@ -688,7 +596,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) { } @@ -698,7 +606,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); @@ -710,14 +618,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: @@ -747,7 +655,7 @@ class LLVolumeGeometryManager: public LLGeometryManager 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); } @@ -758,7 +666,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); } @@ -768,7 +676,7 @@ public: 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); }; @@ -777,7 +685,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) { } }; @@ -785,7 +693,7 @@ public: class LLHUDPartition : public LLBridgePartition { public: - LLHUDPartition(); + LLHUDPartition(LLViewerRegion* regionp); virtual void shift(const LLVector4a &offset); }; diff --git a/indra/newview/llspeakers.cpp b/indra/newview/llspeakers.cpp index a4582071e8..8177a50cc2 100755 --- a/indra/newview/llspeakers.cpp +++ b/indra/newview/llspeakers.cpp @@ -34,7 +34,9 @@ #include "llgroupmgr.h" #include "llsdutil.h" #include "lluicolortable.h" +#include "llhttpclient.h" #include "llviewerobjectlist.h" +#include "llviewerregion.h" #include "llvoavatar.h" #include "llworld.h" @@ -416,7 +418,7 @@ void LLSpeakerMgr::update(BOOL resort_ok) { LLUUID speaker_id = speaker_it->first; LLSpeaker* speakerp = speaker_it->second; - + if (voice_channel_active && LLVoiceClient::getInstance()->getVoiceEnabled(speaker_id)) { speakerp->mSpeechVolume = LLVoiceClient::getInstance()->getCurrentPower(speaker_id); diff --git a/indra/newview/llstartup.cpp b/indra/newview/llstartup.cpp index 82596a86b9..3c67216688 100755 --- a/indra/newview/llstartup.cpp +++ b/indra/newview/llstartup.cpp @@ -645,7 +645,7 @@ bool idle_startup() gAudiop = (LLAudioEngine *) new LLAudioEngine_OpenAL(); } #endif - + if (gAudiop) { #if LL_WINDOWS @@ -2052,7 +2052,7 @@ bool idle_startup() static LLFrameTimer wearables_timer; const F32 wearables_time = wearables_timer.getElapsedTimeF32(); - const F32 MAX_WEARABLES_TIME = 10.f; + static LLCachedControl<F32> max_wearables_time(gSavedSettings, "ClothingLoadingDelay"); if (!gAgent.isGenderChosen() && isAgentAvatarValid()) { @@ -2072,10 +2072,10 @@ bool idle_startup() display_startup(); - if (wearables_time > MAX_WEARABLES_TIME) + if (wearables_time > max_wearables_time()) { LLNotificationsUtil::add("ClothingLoading"); - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_WEARABLES_TOO_LONG); + record(LLStatViewer::LOADING_WEARABLES_LONG_DELAY, wearables_time); LLStartUp::setStartupState( STATE_CLEANUP ); return TRUE; } @@ -2106,7 +2106,7 @@ bool idle_startup() display_startup(); update_texture_fetch(); display_startup(); - set_startup_status(0.9f + 0.1f * wearables_time / MAX_WEARABLES_TIME, + set_startup_status(0.9f + 0.1f * wearables_time / max_wearables_time(), LLTrans::getString("LoginDownloadingClothing").c_str(), gAgent.mMOTD.c_str()); display_startup(); @@ -2186,9 +2186,6 @@ bool idle_startup() LLAppViewer::instance()->handleLoginComplete(); - // reset timers now that we are running "logged in" logic - LLFastTimer::reset(); - LLAgentPicksInfo::getInstance()->requestNumberOfPicks(); display_startup(); @@ -2296,7 +2293,7 @@ bool login_alert_status(const LLSD& notification, const LLSD& response) // break; case 2: // Teleport // Restart the login process, starting at our home locaton - LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME)); + LLStartUp::setStartSLURL(LLSLURL(LLSLURL::SIM_LOCATION_HOME)); LLStartUp::setStartupState( STATE_LOGIN_CLEANUP ); break; default: diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp index ff69c6e9fd..f3406d9f8d 100755 --- a/indra/newview/llstatusbar.cpp +++ b/indra/newview/llstatusbar.cpp @@ -37,7 +37,6 @@ #include "llviewercontrol.h" #include "llfloaterbuycurrency.h" #include "llbuycurrencyhtml.h" -#include "llfloaterlagmeter.h" #include "llpanelnearbymedia.h" #include "llpanelvolumepulldown.h" #include "llfloaterregioninfo.h" @@ -199,10 +198,10 @@ BOOL LLStatusBar::postBuild() sgp.rect(r); sgp.follows.flags(FOLLOWS_BOTTOM | FOLLOWS_RIGHT); sgp.mouse_opaque(false); + sgp.stat.count_stat_float(&LLStatViewer::KBIT); + sgp.units("Kbps"); + sgp.precision(0); mSGBandwidth = LLUICtrlFactory::create<LLStatGraph>(sgp); - mSGBandwidth->setStat(&LLViewerStats::getInstance()->mKBitStat); - mSGBandwidth->setUnits("Kbps"); - mSGBandwidth->setPrecision(0); addChild(mSGBandwidth); x -= SIM_STAT_WIDTH + 2; @@ -213,17 +212,20 @@ BOOL LLStatusBar::postBuild() pgp.rect(r); pgp.follows.flags(FOLLOWS_BOTTOM | FOLLOWS_RIGHT); pgp.mouse_opaque(false); + pgp.stat.sample_stat_float(&LLStatViewer::PACKETS_LOST_PERCENT); + pgp.units("%"); + pgp.min(0.f); + pgp.max(5.f); + pgp.precision(1); + pgp.per_sec(false); + LLStatGraph::Thresholds thresholds; + thresholds.threshold.add(LLStatGraph::ThresholdParams().value(0.1).color(LLColor4::green)) + .add(LLStatGraph::ThresholdParams().value(0.25f).color(LLColor4::yellow)) + .add(LLStatGraph::ThresholdParams().value(0.6f).color(LLColor4::red)); + + pgp.thresholds(thresholds); mSGPacketLoss = LLUICtrlFactory::create<LLStatGraph>(pgp); - mSGPacketLoss->setStat(&LLViewerStats::getInstance()->mPacketsLostPercentStat); - mSGPacketLoss->setUnits("%"); - mSGPacketLoss->setMin(0.f); - mSGPacketLoss->setMax(5.f); - mSGPacketLoss->setThreshold(0, 0.5f); - mSGPacketLoss->setThreshold(1, 1.f); - mSGPacketLoss->setThreshold(2, 3.f); - mSGPacketLoss->setPrecision(1); - mSGPacketLoss->mPerSec = FALSE; addChild(mSGPacketLoss); mPanelVolumePulldown = new LLPanelVolumePulldown(); @@ -253,9 +255,9 @@ void LLStatusBar::refresh() F32 bwtotal = gViewerThrottle.getMaxBandwidth() / 1000.f; mSGBandwidth->setMin(0.f); mSGBandwidth->setMax(bwtotal*1.25f); - mSGBandwidth->setThreshold(0, bwtotal*0.75f); - mSGBandwidth->setThreshold(1, bwtotal); - mSGBandwidth->setThreshold(2, bwtotal); + //mSGBandwidth->setThreshold(0, bwtotal*0.75f); + //mSGBandwidth->setThreshold(1, bwtotal); + //mSGBandwidth->setThreshold(2, bwtotal); } // update clock every 10 seconds diff --git a/indra/newview/llsurface.h b/indra/newview/llsurface.h index 9d24bf8771..33a64ae7d5 100755 --- a/indra/newview/llsurface.h +++ b/indra/newview/llsurface.h @@ -45,7 +45,6 @@ class LLTimer; class LLUUID; class LLAgent; -class LLStat; static const U8 NO_EDGE = 0x00; static const U8 EAST_EDGE = 0x01; diff --git a/indra/newview/lltexturecache.cpp b/indra/newview/lltexturecache.cpp index 305f6fca0f..f03cc22949 100755 --- a/indra/newview/lltexturecache.cpp +++ b/indra/newview/lltexturecache.cpp @@ -919,7 +919,7 @@ void LLTextureCache::setDirNames(ELLPath location) mFastCacheFileName = gDirUtilp->getExpandedFilename(location, textures_dirname, fast_cache_filename); } -void LLTextureCache::purgeCache(ELLPath location) +void LLTextureCache::purgeCache(ELLPath location, bool remove_dir) { LLMutexLock lock(&mHeaderMutex); @@ -945,7 +945,7 @@ void LLTextureCache::purgeCache(ELLPath location) } //remove the current texture cache. - purgeAllTextures(true); + purgeAllTextures(remove_dir); } //is called in the main thread before initCache(...) is called. diff --git a/indra/newview/lltexturecache.h b/indra/newview/lltexturecache.h index e3fc957fd2..5a68c31a6d 100755 --- a/indra/newview/lltexturecache.h +++ b/indra/newview/lltexturecache.h @@ -104,7 +104,7 @@ public: /*virtual*/ S32 update(F32 max_time_ms); - void purgeCache(ELLPath location); + void purgeCache(ELLPath location, bool remove_dir = true); void setReadOnly(BOOL read_only) ; S64 initCache(ELLPath location, S64 maxsize, BOOL texture_cache_mismatch); diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp index e2d0fdf357..a8038b7cf2 100755 --- a/indra/newview/lltexturectrl.cpp +++ b/indra/newview/lltexturectrl.cpp @@ -187,7 +187,7 @@ protected: F32 mContextConeOpacity; LLSaveFolderState mSavedFolderState; BOOL mSelectedItemPinned; - + LLRadioGroup* mModeSelector; LLScrollListCtrl* mLocalScrollCtrl; @@ -550,11 +550,11 @@ void LLFloaterTexturePicker::draw() if (gFocusMgr.childHasMouseCapture(getDragHandle())) { - mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, gSavedSettings.getF32("PickerContextOpacity"), LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME)); } else { - mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLCriticalDamp::getInterpolant(CONTEXT_FADE_TIME)); + mContextConeOpacity = lerp(mContextConeOpacity, 0.f, LLSmoothInterpolation::getInterpolant(CONTEXT_FADE_TIME)); } updateImageStats(); @@ -1311,7 +1311,7 @@ void LLTextureCtrl::onFloaterCommit(ETexturePickOp op, LLUUID id) // (i.e. op == TEXTURE_SELECT) or texture changes via DnD. else if (mCommitOnSelection || op == TEXTURE_SELECT) mViewModel->setDirty(); // *TODO: shouldn't we be using setValue() here? - + if(floaterp->isDirty() || id.notNull()) // mModelView->setDirty does not work. { setTentative( FALSE ); diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index be5fde9e2b..4b9a950b98 100755 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -53,6 +53,7 @@ #include "llviewerstatsrecorder.h" #include "llviewerassetstats.h" #include "llworld.h" +#include "llsdparam.h" #include "llsdutil.h" #include "llstartup.h" #include "llsdserialize.h" @@ -64,8 +65,8 @@ #include "bufferstream.h" bool LLTextureFetchDebugger::sDebuggerEnabled = false ; -LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128); -LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128); +LLTrace::SampleStatHandle<> LLTextureFetch::sCacheHitRate("texture_cache_hits"); +LLTrace::SampleStatHandle<> LLTextureFetch::sCacheReadLatency("texture_cache_read_latency"); ////////////////////////////////////////////////////////////////////////////// @@ -1246,7 +1247,7 @@ bool LLTextureFetchWorker::doWork(S32 param) LL_DEBUGS("Texture") << 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); + sample(LLTextureFetch::sCacheHitRate, 100.f); } else { @@ -1264,7 +1265,7 @@ bool LLTextureFetchWorker::doWork(S32 param) } // fall through - LLTextureFetch::sCacheHitRate.addValue(0.f); + sample(LLTextureFetch::sCacheHitRate, 0.f); } } @@ -1884,7 +1885,7 @@ void LLTextureFetchWorker::onCompleted(LLCore::HttpHandle handle, LLCore::HttpRe if (log_to_viewer_log || log_to_sim) { U64 timeNow = LLTimer::getTotalTime(); - mFetcher->mTextureInfo.setRequestStartTime(mID, mMetricsStartTime); + mFetcher->mTextureInfo.setRequestStartTime(mID, mMetricsStartTime.value()); mFetcher->mTextureInfo.setRequestType(mID, LLTextureInfoDetails::REQUEST_TYPE_HTTP); mFetcher->mTextureInfo.setRequestSize(mID, mRequestedSize); mFetcher->mTextureInfo.setRequestOffset(mID, mRequestedOffset); @@ -2329,11 +2330,11 @@ bool LLTextureFetchWorker::writeToCacheComplete() // Threads: Ttf void LLTextureFetchWorker::recordTextureStart(bool is_http) { - if (! mMetricsStartTime) + if (! mMetricsStartTime.value()) { mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); } - LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE, + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, is_http, LLImageBase::TYPE_AVATAR_BAKE == mType); } @@ -2342,15 +2343,15 @@ 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, + LLViewerAssetStatsFF::record_response(LLViewerAssetType::AT_TEXTURE, is_http, LLImageBase::TYPE_AVATAR_BAKE == mType, LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime); mMetricsStartTime = 0; } - LLViewerAssetStatsFF::record_dequeue_thread1(LLViewerAssetType::AT_TEXTURE, + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, is_http, LLImageBase::TYPE_AVATAR_BAKE == mType); } @@ -2411,6 +2412,10 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mHttpMetricsHeaders = new LLCore::HttpHeaders; mHttpMetricsHeaders->mHeaders.push_back("Content-Type: application/llsd+xml"); mHttpPolicyClass = LLAppViewer::instance()->getAppCoreHttp().getPolicyDefault(); + + //reset the texture timer. + gTextureTimer.reset(); + gTextureTimer.pause(); } LLTextureFetch::~LLTextureFetch() @@ -2756,7 +2761,7 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, F32 cache_read_time = worker->mCacheReadTime; if (cache_read_time != 0.f) { - sCacheReadLatency.addValue(cache_read_time * 1000.f); + sample(sCacheReadLatency, cache_read_time * 1000.f); } res = true; LL_DEBUGS("Texture") << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL; @@ -2882,7 +2887,7 @@ S32 LLTextureFetch::update(F32 max_time_ms) mNetworkQueueMutex.lock(); // +Mfnq mMaxBandwidth = band_width; - gTextureList.sTextureBits += mHTTPTextureBits; + add(LLStatViewer::TEXTURE_KBIT, mHTTPTextureBits); mHTTPTextureBits = 0; mNetworkQueueMutex.unlock(); // -Mfnq @@ -3789,7 +3794,7 @@ AssetReportHandler stats_handler; bool TFReqSetRegion::doWork(LLTextureFetch *) { - LLViewerAssetStatsFF::set_region_thread1(mRegionHandle); + LLViewerAssetStatsFF::set_region(mRegionHandle); return true; } @@ -3814,8 +3819,8 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) static const U32 report_priority(1); static LLCore::HttpHandler * const handler(fetcher->isQAMode() || true ? &stats_handler : NULL); - if (! gViewerAssetStatsThread1) - return true; + //if (! gViewerAssetStatsThread1) + // return true; static volatile bool reporting_started(false); static volatile S32 report_sequence(0); @@ -3825,17 +3830,21 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) // but leave it in 'this'. Destructor will rid us of it. LLViewerAssetStats & main_stats = *mMainStats; - // Merge existing stats into those from main, convert to LLSD - main_stats.merge(*gViewerAssetStatsThread1); - LLSD merged_llsd = main_stats.asLLSD(true); - - // Add some additional meta fields to the content - merged_llsd["session_id"] = mSessionID; - merged_llsd["agent_id"] = mAgentID; - merged_llsd["message"] = "ViewerAssetMetrics"; // Identifies the type of metrics - merged_llsd["sequence"] = report_sequence; // Sequence number - merged_llsd["initial"] = ! reporting_started; // Initial data from viewer - merged_llsd["break"] = LLTextureFetch::svMetricsDataBreak; // Break in data prior to this report + LLViewerAssetStats::AssetStats stats; + main_stats.getStats(stats, true); + //LLSD merged_llsd = main_stats.asLLSD(); + + bool initial_report = !reporting_started; + stats.session_id = mSessionID; + stats.agent_id = mAgentID; + stats.message = "ViewerAssetMetrics"; + stats.sequence = static_cast<bool>(report_sequence); + stats.initial = initial_report; + stats.break_ = static_cast<bool>(LLTextureFetch::svMetricsDataBreak); + + LLSD sd; + LLParamSDParser parser; + parser.writeSD(sd, stats); // Update sequence number if (S32_MAX == ++report_sequence) @@ -3843,13 +3852,14 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) reporting_started = true; // Limit the size of the stats report if necessary. - merged_llsd["truncated"] = truncate_viewer_metrics(10, merged_llsd); + + sd["truncated"] = truncate_viewer_metrics(10, sd); if (! mCapsURL.empty()) { LLCore::BufferArray * ba = new LLCore::BufferArray; LLCore::BufferArrayStream bas(ba); - LLSDSerialize::toXML(merged_llsd, bas); + LLSDSerialize::toXML(sd, bas); fetcher->getHttpRequest().requestPost(fetcher->getPolicyClass(), report_priority, @@ -3869,11 +3879,9 @@ TFReqSendMetrics::doWork(LLTextureFetch * fetcher) // In QA mode, Metrics submode, log the result for ease of testing if (fetcher->isQAMode()) { - LL_INFOS("Textures") << ll_pretty_print_sd(merged_llsd) << LL_ENDL; + LL_INFOS("Textures") << ll_pretty_print_sd(sd) << LL_ENDL; } - gViewerAssetStatsThread1->reset(); - return true; } diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index 902a3d7a25..2530beb722 100755 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -37,15 +37,15 @@ #include "lltextureinfo.h" #include "llapr.h" #include "llimageworker.h" -#include "llstat.h" #include "llcurl.h" -#include "llstat.h" #include "httprequest.h" #include "httpoptions.h" #include "httpheaders.h" #include "httphandler.h" +#include "lltrace.h" #include "llviewertexture.h" +class LLViewerTexture; class LLTextureFetchWorker; class LLImageDecodeThread; class LLHost; @@ -309,8 +309,8 @@ private: LLMutex mQueueMutex; //to protect mRequestMap and mCommands only LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue. - static LLStat sCacheHitRate; - static LLStat sCacheReadLatency; + static LLTrace::SampleStatHandle<> sCacheHitRate; + static LLTrace::SampleStatHandle<> sCacheReadLatency; LLTextureCache* mTextureCache; LLImageDecodeThread* mImageDecodeThread; @@ -330,7 +330,7 @@ private: LLTextureInfo mTextureInfo; // XXX possible delete - U32 mHTTPTextureBits; // Mfnq + LLUnit<LLUnits::Bits, U32> mHTTPTextureBits; // Mfnq // XXX possible delete //debug use diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp index e80136b286..c9ec5d9bf6 100755 --- a/indra/newview/lltextureview.cpp +++ b/indra/newview/lltextureview.cpp @@ -49,6 +49,8 @@ #include "llviewertexturelist.h" #include "llvovolume.h" #include "llviewerstats.h" +#include "llworld.h" +#include "llviewerobjectlist.h" // For avatar texture view #include "llvoavatarself.h" @@ -505,18 +507,21 @@ 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; + LLUnit<LLUnits::Mibibytes, S32> bound_mem = LLViewerTexture::sBoundTextureMemory; + LLUnit<LLUnits::Mibibytes, S32> max_bound_mem = LLViewerTexture::sMaxBoundTextureMem; + LLUnit<LLUnits::Mibibytes, S32> total_mem = LLViewerTexture::sTotalTextureMemory; + LLUnit<LLUnits::Mibibytes, S32> 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()) ; + F32 cache_usage = (F32)LLTrace::Mibibytes(LLAppViewer::getTextureCache()->getUsage()).value() ; + F32 cache_max_usage = (F32)LLTrace::Mibibytes(LLAppViewer::getTextureCache()->getMaxUsage()).value() ; S32 line_height = LLFontGL::getFontMonospace()->getLineHeight(); S32 v_offset = 0;//(S32)((texture_bar_height + 2.2f) * mTextureView->mNumTextureBars + 2.0f); - F32 total_texture_downloaded = (F32)gTotalTextureBytes / (1024 * 1024); - F32 total_object_downloaded = (F32)gTotalObjectBytes / (1024 * 1024); - U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests(); + LLUnit<LLUnits::Bytes, F32> total_texture_downloaded = gTotalTextureData; + LLUnit<LLUnits::Bytes, F32> total_object_downloaded = gTotalObjectData; + U32 total_http_requests = LLAppViewer::getTextureFetch()->getTotalNumHTTPRequests() ; + U32 total_active_cached_objects = LLWorld::getInstance()->getNumOfActiveCachedObjects(); + U32 total_objects = gObjectList.getNumObjects(); + //---------------------------------------------------------------------------- LLGLSUIDefault gls_ui; LLColor4 text_color(1.f, 1.f, 1.f, 0.75f); @@ -532,10 +537,10 @@ void LLGLTexMemBar::draw() text_color, LLFontGL::LEFT, LLFontGL::TOP); text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB FBO: %d MB Raw Tot: %d MB Bias: %.2f Cache: %.1f/%.1f MB", - 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), LLImageRaw::sGlobalRawMemory >> 20, discard_bias, @@ -549,9 +554,11 @@ void LLGLTexMemBar::draw() U32 cache_read(0U), cache_write(0U), res_wait(0U); LLAppViewer::getTextureFetch()->getStateStats(&cache_read, &cache_write, &res_wait); - text = llformat("Net Tot Tex: %.1f MB Tot Obj: %.1f MB Tot Htp: %d Cread: %u Cwrite: %u Rwait: %u", - total_texture_downloaded, - total_object_downloaded, + text = llformat("Net Tot Tex: %.1f MB Tot Obj: %.1f MB #Objs/#Cached: %d/%d Tot Htp: %d Cread: %u Cwrite: %u Rwait: %u", + total_texture_downloaded.value(), + total_object_downloaded.value(), + total_objects, + total_active_cached_objects, total_http_requests, cache_read, cache_write, @@ -679,7 +686,7 @@ void LLGLTexSizeBar::draw() if(LLImageGL::sCurTexSizeBar == mIndex) { - F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; + LLColor4 text_color(1.f, 1.f, 1.f, 0.75f); std::string text; text = llformat("%d", mTopLoaded) ; @@ -691,8 +698,8 @@ void LLGLTexSizeBar::draw() text_color, LLFontGL::LEFT, LLFontGL::TOP); } - F32 loaded_color[] = {1.0f, 0.0f, 0.0f, 0.75f}; - F32 bound_color[] = {1.0f, 1.0f, 0.0f, 0.75f}; + LLColor4 loaded_color(1.0f, 0.0f, 0.0f, 0.75f); + LLColor4 bound_color(1.0f, 1.0f, 0.0f, 0.75f); gl_rect_2d(mLeft, mBottom + (S32)(mTopLoaded * mScale), (mLeft + mRight) / 2, mBottom, loaded_color) ; gl_rect_2d((mLeft + mRight) / 2, mBottom + (S32)(mTopBound * mScale), mRight, mBottom, bound_color) ; } diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 3f75f8da5e..85232f4a0b 100755 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -42,7 +42,6 @@ #include "lllineeditor.h" #include "lluictrlfactory.h" #include "llnotifications.h" -#include "llfunctorregistry.h" #include "llrootview.h" #include "lltransientfloatermgr.h" #include "llviewercontrol.h" // for gSavedSettings diff --git a/indra/newview/lltoolbarview.cpp b/indra/newview/lltoolbarview.cpp index b2318f9158..ed0f22f16a 100755 --- a/indra/newview/lltoolbarview.cpp +++ b/indra/newview/lltoolbarview.cpp @@ -521,7 +521,7 @@ void LLToolBarView::draw() { if (mToolbars[i]) { - LLLayoutStack::ELayoutOrientation orientation = LLToolBarEnums::getOrientation(mToolbars[i]->getSideType()); + LLView::EOrientation orientation = LLToolBarEnums::getOrientation(mToolbars[i]->getSideType()); if (orientation == LLLayoutStack::HORIZONTAL) { diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index e085834326..a4dce9efe8 100755 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1094,7 +1094,7 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj, return; } LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); + add(LLStatViewer::EDIT_TEXTURE, 1); S32 num_faces = hit_obj->getNumTEs(); for( S32 face = 0; face < num_faces; face++ ) { @@ -1162,7 +1162,7 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, } // update viewer side image in anticipation of update from simulator LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture(asset_id); - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_EDIT_TEXTURE_COUNT ); + add(LLStatViewer::EDIT_TEXTURE, 1); hit_obj->setTEImage(hit_face, image); dialog_refresh_all(); @@ -1386,7 +1386,7 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, effectp->setDuration(LL_HUD_DUR_SHORT); effectp->setColor(LLColor4U(gAgent.getEffectColor())); - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_REZ_COUNT); + add(LLStatViewer::OBJECT_REZ, 1); } void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj, diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp index fc9a316759..c912d81a03 100755 --- a/indra/newview/lltoolpie.cpp +++ b/indra/newview/lltoolpie.cpp @@ -42,6 +42,7 @@ #include "llfloaterscriptdebug.h" #include "lltooltip.h" #include "llhudeffecttrail.h" +#include "llhudicon.h" #include "llhudmanager.h" #include "llkeyboard.h" #include "llmediaentry.h" diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp index 641fbc5042..b7718847ae 100755 --- a/indra/newview/lltoolplacer.cpp +++ b/indra/newview/lltoolplacer.cpp @@ -433,7 +433,7 @@ BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics ) effectp->setDuration(LL_HUD_DUR_SHORT); effectp->setColor(LLColor4U(gAgent.getEffectColor())); - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CREATE_COUNT); + add(LLStatViewer::OBJECT_CREATE, 1); return TRUE; } diff --git a/indra/newview/lltoolselect.cpp b/indra/newview/lltoolselect.cpp index 7c604a04bf..0a9153eecb 100755 --- a/indra/newview/lltoolselect.cpp +++ b/indra/newview/lltoolselect.cpp @@ -32,6 +32,7 @@ #include "llagentcamera.h" #include "llviewercontrol.h" #include "lldrawable.h" +#include "llhudicon.h" #include "llmanip.h" #include "llmenugl.h" #include "llselectmgr.h" diff --git a/indra/newview/lltoolselect.h b/indra/newview/lltoolselect.h index baa27f6071..74dababe8c 100755 --- a/indra/newview/lltoolselect.h +++ b/indra/newview/lltoolselect.h @@ -34,7 +34,7 @@ class LLObjectSelection; -class LLToolSelect : public LLTool, public LLSingleton<LLToolSelect> +class LLToolSelect : public LLTool { public: LLToolSelect( LLToolComposite* composite ); diff --git a/indra/newview/llviewerassetstats.cpp b/indra/newview/llviewerassetstats.cpp index aaa81c57d4..3a6ee636d4 100755 --- a/indra/newview/llviewerassetstats.cpp +++ b/indra/newview/llviewerassetstats.cpp @@ -31,6 +31,8 @@ #include "stdtypes.h" #include "llvoavatar.h" +#include "llsdparam.h" +#include "llsdutil.h" /* * Classes and utility functions for per-thread and per-region @@ -78,126 +80,258 @@ * */ +namespace LLViewerAssetStatsFF +{ + static EViewerAssetCategories asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp) + { + // For statistical purposes, we divide GETs into several + // populations of asset fetches: + // - textures which are de-prioritized in the asset system + // - wearables (clothing, bodyparts) which directly affect + // user experiences when they log in + // - sounds + // - gestures + // - everything else. + // + llassert_always(50 == LLViewerAssetType::AT_COUNT); + + // Multiple asset definitions are floating around so this requires some + // maintenance and attention. + static const EViewerAssetCategories asset_to_bin_map[LLViewerAssetType::AT_COUNT] = + { + EVACTextureTempHTTPGet, // (0) AT_TEXTURE + EVACSoundUDPGet, // AT_SOUND + EVACOtherGet, // AT_CALLINGCARD + EVACOtherGet, // AT_LANDMARK + EVACOtherGet, // AT_SCRIPT + EVACWearableUDPGet, // AT_CLOTHING + EVACOtherGet, // AT_OBJECT + EVACOtherGet, // AT_NOTECARD + EVACOtherGet, // AT_CATEGORY + EVACOtherGet, // AT_ROOT_CATEGORY + EVACOtherGet, // (10) AT_LSL_TEXT + EVACOtherGet, // AT_LSL_BYTECODE + EVACOtherGet, // AT_TEXTURE_TGA + EVACWearableUDPGet, // AT_BODYPART + EVACOtherGet, // AT_TRASH + EVACOtherGet, // AT_SNAPSHOT_CATEGORY + EVACOtherGet, // AT_LOST_AND_FOUND + EVACSoundUDPGet, // AT_SOUND_WAV + EVACOtherGet, // AT_IMAGE_TGA + EVACOtherGet, // AT_IMAGE_JPEG + EVACGestureUDPGet, // (20) AT_ANIMATION + EVACGestureUDPGet, // AT_GESTURE + EVACOtherGet, // AT_SIMSTATE + EVACOtherGet, // AT_FAVORITE + EVACOtherGet, // AT_LINK + EVACOtherGet, // AT_LINK_FOLDER + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // (30) + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // (40) + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // + EVACOtherGet, // AT_MESH + // (50) + }; -// ------------------------------------------------------ -// Global data definitions -// ------------------------------------------------------ -LLViewerAssetStats * gViewerAssetStatsMain(0); -LLViewerAssetStats * gViewerAssetStatsThread1(0); + if (at < 0 || at >= LLViewerAssetType::AT_COUNT) + { + return EVACOtherGet; + } + EViewerAssetCategories ret(asset_to_bin_map[at]); + if (EVACTextureTempHTTPGet == ret) + { + // Indexed with [is_temp][with_http] + static const EViewerAssetCategories texture_bin_map[2][2] = + { + { + EVACTextureNonTempUDPGet, + EVACTextureNonTempHTTPGet, + }, + { + EVACTextureTempUDPGet, + EVACTextureTempHTTPGet, + } + }; + ret = texture_bin_map[is_temp][with_http]; + } + return ret; + } + + static LLTrace::CountStatHandle<> sEnqueueAssetRequestsTempTextureHTTP ("enqueuedassetrequeststemptexturehttp", + "Number of temporary texture asset http requests enqueued"), + sEnqueueAssetRequestsTempTextureUDP ("enqueuedassetrequeststemptextureudp", + "Number of temporary texture asset udp requests enqueued"), + sEnqueueAssetRequestsNonTempTextureHTTP("enqueuedassetrequestsnontemptexturehttp", + "Number of texture asset http requests enqueued"), + sEnqueueAssetRequestsNonTempTextureUDP ("enqueuedassetrequestsnontemptextureudp", + "Number of texture asset udp requests enqueued"), + sEnqueuedAssetRequestsWearableUdp ("enqueuedassetrequestswearableudp", + "Number of wearable asset requests enqueued"), + sEnqueuedAssetRequestsSoundUdp ("enqueuedassetrequestssoundudp", + "Number of sound asset requests enqueued"), + sEnqueuedAssetRequestsGestureUdp ("enqueuedassetrequestsgestureudp", + "Number of gesture asset requests enqueued"), + sEnqueuedAssetRequestsOther ("enqueuedassetrequestsother", + "Number of other asset requests enqueued"); + + static LLTrace::CountStatHandle<>* sEnqueued[EVACCount] = { + &sEnqueueAssetRequestsTempTextureHTTP, + &sEnqueueAssetRequestsTempTextureUDP, + &sEnqueueAssetRequestsNonTempTextureHTTP, + &sEnqueueAssetRequestsNonTempTextureUDP, + &sEnqueuedAssetRequestsWearableUdp, + &sEnqueuedAssetRequestsSoundUdp, + &sEnqueuedAssetRequestsGestureUdp, + &sEnqueuedAssetRequestsOther + }; + + static LLTrace::CountStatHandle<> sDequeueAssetRequestsTempTextureHTTP ("dequeuedassetrequeststemptexturehttp", + "Number of temporary texture asset http requests dequeued"), + sDequeueAssetRequestsTempTextureUDP ("dequeuedassetrequeststemptextureudp", + "Number of temporary texture asset udp requests dequeued"), + sDequeueAssetRequestsNonTempTextureHTTP("dequeuedassetrequestsnontemptexturehttp", + "Number of texture asset http requests dequeued"), + sDequeueAssetRequestsNonTempTextureUDP ("dequeuedassetrequestsnontemptextureudp", + "Number of texture asset udp requests dequeued"), + sDequeuedAssetRequestsWearableUdp ("dequeuedassetrequestswearableudp", + "Number of wearable asset requests dequeued"), + sDequeuedAssetRequestsSoundUdp ("dequeuedassetrequestssoundudp", + "Number of sound asset requests dequeued"), + sDequeuedAssetRequestsGestureUdp ("dequeuedassetrequestsgestureudp", + "Number of gesture asset requests dequeued"), + sDequeuedAssetRequestsOther ("dequeuedassetrequestsother", + "Number of other asset requests dequeued"); + + static LLTrace::CountStatHandle<>* sDequeued[EVACCount] = { + &sDequeueAssetRequestsTempTextureHTTP, + &sDequeueAssetRequestsTempTextureUDP, + &sDequeueAssetRequestsNonTempTextureHTTP, + &sDequeueAssetRequestsNonTempTextureUDP, + &sDequeuedAssetRequestsWearableUdp, + &sDequeuedAssetRequestsSoundUdp, + &sDequeuedAssetRequestsGestureUdp, + &sDequeuedAssetRequestsOther + }; + + static LLTrace::EventStatHandle<LLTrace::Seconds> sResponseAssetRequestsTempTextureHTTP ("assetresponsetimestemptexturehttp", + "Time spent responding to temporary texture asset http requests"), + sResponseAssetRequestsTempTextureUDP ("assetresponsetimestemptextureudp", + "Time spent responding to temporary texture asset udp requests"), + sResponseAssetRequestsNonTempTextureHTTP("assetresponsetimesnontemptexturehttp", + "Time spent responding to texture asset http requests"), + sResponseAssetRequestsNonTempTextureUDP ("assetresponsetimesnontemptextureudp", + "Time spent responding to texture asset udp requests"), + sResponsedAssetRequestsWearableUdp ("assetresponsetimeswearableudp", + "Time spent responding to wearable asset requests"), + sResponsedAssetRequestsSoundUdp ("assetresponsetimessoundudp", + "Time spent responding to sound asset requests"), + sResponsedAssetRequestsGestureUdp ("assetresponsetimesgestureudp", + "Time spent responding to gesture asset requests"), + sResponsedAssetRequestsOther ("assetresponsetimesother", + "Time spent responding to other asset requests"); + + static LLTrace::EventStatHandle<LLTrace::Seconds>* sResponse[EVACCount] = { + &sResponseAssetRequestsTempTextureHTTP, + &sResponseAssetRequestsTempTextureUDP, + &sResponseAssetRequestsNonTempTextureHTTP, + &sResponseAssetRequestsNonTempTextureUDP, + &sResponsedAssetRequestsWearableUdp, + &sResponsedAssetRequestsSoundUdp, + &sResponsedAssetRequestsGestureUdp, + &sResponsedAssetRequestsOther + }; +} // ------------------------------------------------------ -// Local declarations +// Global data definitions // ------------------------------------------------------ -namespace -{ - -static LLViewerAssetStats::EViewerAssetCategories -asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp); - -} +LLViewerAssetStats * gViewerAssetStats(0); // ------------------------------------------------------ -// LLViewerAssetStats::PerRegionStats struct definition +// LLViewerAssetStats class definition // ------------------------------------------------------ -void -LLViewerAssetStats::PerRegionStats::reset() +LLViewerAssetStats::LLViewerAssetStats() +: mRegionHandle(U64(0)), + mCurRecording(NULL) { - for (int i(0); i < LL_ARRAY_SIZE(mRequests); ++i) - { - mRequests[i].mEnqueued.reset(); - mRequests[i].mDequeued.reset(); - mRequests[i].mResponse.reset(); - } - mFPS.reset(); - - mTotalTime = 0; - mStartTimestamp = LLViewerAssetStatsFF::get_timestamp(); + start(); } -void -LLViewerAssetStats::PerRegionStats::merge(const LLViewerAssetStats::PerRegionStats & src) +LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src) +: mRegionHandle(src.mRegionHandle) { - // mRegionHandle, mTotalTime, mStartTimestamp are left alone. + mRegionRecordings = src.mRegionRecordings; + + mCurRecording = &mRegionRecordings[mRegionHandle]; - // mFPS - if (src.mFPS.getCount() && mFPS.getCount()) + // assume this is being passed to another thread, so make sure we have unique copies of recording data + for (PerRegionRecordingContainer::iterator it = mRegionRecordings.begin(), end_it = mRegionRecordings.end(); + it != end_it; + ++it) { - mFPS.merge(src.mFPS); + it->second.stop(); + it->second.makeUnique(); } - // Avatar stats - data all comes from main thread, so leave alone. + LLStopWatchControlsMixin<LLViewerAssetStats>::setPlayState(src.getPlayState()); +} - // Requests - for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i) +void LLViewerAssetStats::handleStart() +{ + if (mCurRecording) { - mRequests[i].mEnqueued.merge(src.mRequests[i].mEnqueued); - mRequests[i].mDequeued.merge(src.mRequests[i].mDequeued); - mRequests[i].mResponse.merge(src.mRequests[i].mResponse); + mCurRecording->start(); } - } - -void -LLViewerAssetStats::PerRegionStats::accumulateTime(duration_t now) +void LLViewerAssetStats::handleStop() { - mTotalTime += (now - mStartTimestamp); - mStartTimestamp = now; + if (mCurRecording) + { + mCurRecording->stop(); + } } - -// ------------------------------------------------------ -// LLViewerAssetStats class definition -// ------------------------------------------------------ -LLViewerAssetStats::LLViewerAssetStats() - : mRegionHandle(U64(0)) +void LLViewerAssetStats::handleReset() { reset(); } -LLViewerAssetStats::LLViewerAssetStats(const LLViewerAssetStats & src) - : mRegionHandle(src.mRegionHandle), - mResetTimestamp(src.mResetTimestamp) -{ - const PerRegionContainer::const_iterator it_end(src.mRegionStats.end()); - for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it) - { - mRegionStats[it->first] = new PerRegionStats(*it->second); - } - mCurRegionStats = mRegionStats[mRegionHandle]; -} - - -void -LLViewerAssetStats::reset() +void LLViewerAssetStats::reset() { // Empty the map of all region stats - mRegionStats.clear(); + mRegionRecordings.clear(); - // If we have a current stats, reset it, otherwise, as at construction, - // create a new one as we must always have a current stats block. - if (mCurRegionStats) + // initialize new recording for current region + if (mRegionHandle) { - mCurRegionStats->reset(); + mCurRecording = &mRegionRecordings[mRegionHandle]; } - else - { - mCurRegionStats = new PerRegionStats(mRegionHandle); - } - - // And add reference to map - mRegionStats[mRegionHandle] = mCurRegionStats; - - // Start timestamp consistent with per-region collector - mResetTimestamp = mCurRegionStats->mStartTimestamp; } - -void -LLViewerAssetStats::setRegion(region_handle_t region_handle) +void LLViewerAssetStats::setRegion(region_handle_t region_handle) { if (region_handle == mRegionHandle) { @@ -205,410 +339,267 @@ LLViewerAssetStats::setRegion(region_handle_t region_handle) return; } - // Get duration for current set - const duration_t now = LLViewerAssetStatsFF::get_timestamp(); - mCurRegionStats->accumulateTime(now); - - // Prepare new set - PerRegionContainer::iterator new_stats = mRegionStats.find(region_handle); - if (mRegionStats.end() == new_stats) + if (mCurRecording) { - // Haven't seen this region_id before, create a new block and make it current. - mCurRegionStats = new PerRegionStats(region_handle); - mRegionStats[region_handle] = mCurRegionStats; + mCurRecording->pause(); } - else + if (region_handle) { - mCurRegionStats = new_stats->second; + mCurRecording = &mRegionRecordings[region_handle]; + mCurRecording->start(); } - mCurRegionStats->mStartTimestamp = now; + mRegionHandle = region_handle; } - -void -LLViewerAssetStats::recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp) +void LLViewerAssetStats::updateStats() { - const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); - - ++(mCurRegionStats->mRequests[int(eac)].mEnqueued); + if (mCurRecording && mCurRecording->isStarted()) + { + mCurRecording->update(); + } } - -void -LLViewerAssetStats::recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp) + +void LLViewerAssetStats::getStats(AssetStats& stats, bool compact_output) { - const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); + using namespace LLViewerAssetStatsFF; - ++(mCurRegionStats->mRequests[int(eac)].mDequeued); -} + stats.regions.setProvided(); -void -LLViewerAssetStats::recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, duration_t duration) -{ - const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); + for (PerRegionRecordingContainer::iterator it = mRegionRecordings.begin(), end_it = mRegionRecordings.end(); + it != end_it; + ++it) + { + RegionStats& r = stats.regions.add(); + LLTrace::Recording& rec = it->second; + if (!compact_output + || rec.getSum(*sEnqueued[EVACTextureTempHTTPGet]) + || rec.getSum(*sDequeued[EVACTextureTempHTTPGet]) + || rec.getSum(*sResponse[EVACTextureTempHTTPGet]).value()) + { + r.get_texture_temp_http .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureTempHTTPGet])) + .dequeued((S32)rec.getSum(*sDequeued[EVACTextureTempHTTPGet])) + .resp_count((S32)rec.getSum(*sResponse[EVACTextureTempHTTPGet]).value()) + .resp_min(rec.getMin(*sResponse[EVACTextureTempHTTPGet]).value()) + .resp_max(rec.getMax(*sResponse[EVACTextureTempHTTPGet]).value()) + .resp_mean(rec.getMean(*sResponse[EVACTextureTempHTTPGet]).value()); + } + if (!compact_output + || rec.getSum(*sEnqueued[EVACTextureTempUDPGet]) + || rec.getSum(*sDequeued[EVACTextureTempUDPGet]) + || rec.getSum(*sResponse[EVACTextureTempUDPGet]).value()) + { + r.get_texture_temp_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureTempUDPGet])) + .dequeued((S32)rec.getSum(*sDequeued[EVACTextureTempUDPGet])) + .resp_count((S32)rec.getSum(*sResponse[EVACTextureTempUDPGet]).value()) + .resp_min(rec.getMin(*sResponse[EVACTextureTempUDPGet]).value()) + .resp_max(rec.getMax(*sResponse[EVACTextureTempUDPGet]).value()) + .resp_mean(rec.getMean(*sResponse[EVACTextureTempUDPGet]).value()); + } + if (!compact_output + || rec.getSum(*sEnqueued[EVACTextureNonTempHTTPGet]) + || rec.getSum(*sDequeued[EVACTextureNonTempHTTPGet]) + || rec.getSum(*sResponse[EVACTextureNonTempHTTPGet]).value()) + { + r.get_texture_non_temp_http .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureNonTempHTTPGet])) + .dequeued((S32)rec.getSum(*sDequeued[EVACTextureNonTempHTTPGet])) + .resp_count((S32)rec.getSum(*sResponse[EVACTextureNonTempHTTPGet]).value()) + .resp_min(rec.getMin(*sResponse[EVACTextureNonTempHTTPGet]).value()) + .resp_max(rec.getMax(*sResponse[EVACTextureNonTempHTTPGet]).value()) + .resp_mean(rec.getMean(*sResponse[EVACTextureNonTempHTTPGet]).value()); + } - mCurRegionStats->mRequests[int(eac)].mResponse.record(duration); -} + if (!compact_output + || rec.getSum(*sEnqueued[EVACTextureNonTempUDPGet]) + || rec.getSum(*sDequeued[EVACTextureNonTempUDPGet]) + || rec.getSum(*sResponse[EVACTextureNonTempUDPGet]).value()) + { + r.get_texture_non_temp_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACTextureNonTempUDPGet])) + .dequeued((S32)rec.getSum(*sDequeued[EVACTextureNonTempUDPGet])) + .resp_count((S32)rec.getSum(*sResponse[EVACTextureNonTempUDPGet]).value()) + .resp_min(rec.getMin(*sResponse[EVACTextureNonTempUDPGet]).value()) + .resp_max(rec.getMax(*sResponse[EVACTextureNonTempUDPGet]).value()) + .resp_mean(rec.getMean(*sResponse[EVACTextureNonTempUDPGet]).value()); + } -void -LLViewerAssetStats::recordFPS(F32 fps) -{ - mCurRegionStats->mFPS.record(fps); -} + if (!compact_output + || rec.getSum(*sEnqueued[EVACWearableUDPGet]) + || rec.getSum(*sDequeued[EVACWearableUDPGet]) + || rec.getSum(*sResponse[EVACWearableUDPGet]).value()) + { + r.get_wearable_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACWearableUDPGet])) + .dequeued((S32)rec.getSum(*sDequeued[EVACWearableUDPGet])) + .resp_count((S32)rec.getSum(*sResponse[EVACWearableUDPGet]).value()) + .resp_min(rec.getMin(*sResponse[EVACWearableUDPGet]).value()) + .resp_max(rec.getMax(*sResponse[EVACWearableUDPGet]).value()) + .resp_mean(rec.getMean(*sResponse[EVACWearableUDPGet]).value()); + } -LLSD -LLViewerAssetStats::asLLSD(bool compact_output) -{ - // Top-level tags - static const LLSD::String tags[EVACCount] = + if (!compact_output + || rec.getSum(*sEnqueued[EVACSoundUDPGet]) + || rec.getSum(*sDequeued[EVACSoundUDPGet]) + || rec.getSum(*sResponse[EVACSoundUDPGet]).value()) { - LLSD::String("get_texture_temp_http"), - LLSD::String("get_texture_temp_udp"), - LLSD::String("get_texture_non_temp_http"), - LLSD::String("get_texture_non_temp_udp"), - LLSD::String("get_wearable_udp"), - LLSD::String("get_sound_udp"), - LLSD::String("get_gesture_udp"), - LLSD::String("get_other") - }; + r.get_sound_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACSoundUDPGet])) + .dequeued((S32)rec.getSum(*sDequeued[EVACSoundUDPGet])) + .resp_count((S32)rec.getSum(*sResponse[EVACSoundUDPGet]).value()) + .resp_min(rec.getMin(*sResponse[EVACSoundUDPGet]).value()) + .resp_max(rec.getMax(*sResponse[EVACSoundUDPGet]).value()) + .resp_mean(rec.getMean(*sResponse[EVACSoundUDPGet]).value()); + } - // Stats Group Sub-tags. - static const LLSD::String enq_tag("enqueued"); - static const LLSD::String deq_tag("dequeued"); - static const LLSD::String rcnt_tag("resp_count"); - static const LLSD::String rmin_tag("resp_min"); - static const LLSD::String rmax_tag("resp_max"); - static const LLSD::String rmean_tag("resp_mean"); - - // MMM Group Sub-tags. - static const LLSD::String cnt_tag("count"); - static const LLSD::String min_tag("min"); - static const LLSD::String max_tag("max"); - static const LLSD::String mean_tag("mean"); - - const duration_t now = LLViewerAssetStatsFF::get_timestamp(); - mCurRegionStats->accumulateTime(now); - - LLSD regions = LLSD::emptyArray(); - for (PerRegionContainer::iterator it = mRegionStats.begin(); - mRegionStats.end() != it; - ++it) - { - if (0 == it->first) + if (!compact_output + || rec.getSum(*sEnqueued[EVACGestureUDPGet]) + || rec.getSum(*sDequeued[EVACGestureUDPGet]) + || rec.getSum(*sResponse[EVACGestureUDPGet]).value()) { - // Never emit NULL UUID/handle in results. - continue; + r.get_gesture_udp .enqueued((S32)rec.getSum(*sEnqueued[EVACGestureUDPGet])) + .dequeued((S32)rec.getSum(*sDequeued[EVACGestureUDPGet])) + .resp_count((S32)rec.getSum(*sResponse[EVACGestureUDPGet]).value()) + .resp_min(rec.getMin(*sResponse[EVACGestureUDPGet]).value()) + .resp_max(rec.getMax(*sResponse[EVACGestureUDPGet]).value()) + .resp_mean(rec.getMean(*sResponse[EVACGestureUDPGet]).value()); } - PerRegionStats & stats = *it->second; - - LLSD reg_stat = LLSD::emptyMap(); - - for (int i = 0; i < LL_ARRAY_SIZE(tags); ++i) + if (!compact_output + || rec.getSum(*sEnqueued[EVACOtherGet]) + || rec.getSum(*sDequeued[EVACOtherGet]) + || rec.getSum(*sResponse[EVACOtherGet]).value()) { - PerRegionStats::prs_group & group(stats.mRequests[i]); - - if ((! compact_output) || - group.mEnqueued.getCount() || - group.mDequeued.getCount() || - group.mResponse.getCount()) - { - LLSD & slot = reg_stat[tags[i]]; - slot = LLSD::emptyMap(); - 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)); - } + r.get_other .enqueued((S32)rec.getSum(*sEnqueued[EVACOtherGet])) + .dequeued((S32)rec.getSum(*sDequeued[EVACOtherGet])) + .resp_count((S32)rec.getSum(*sResponse[EVACOtherGet]).value()) + .resp_min(rec.getMin(*sResponse[EVACOtherGet]).value()) + .resp_max(rec.getMax(*sResponse[EVACOtherGet]).value()) + .resp_mean(rec.getMean(*sResponse[EVACOtherGet]).value()); } - if ((! compact_output) || stats.mFPS.getCount()) + S32 fps = (S32)rec.getLastValue(LLStatViewer::FPS_SAMPLE); + if (!compact_output || fps != 0) { - LLSD & slot = reg_stat["fps"]; - slot = LLSD::emptyMap(); - slot[cnt_tag] = LLSD(S32(stats.mFPS.getCount())); - slot[min_tag] = LLSD(F64(stats.mFPS.getMin())); - slot[max_tag] = LLSD(F64(stats.mFPS.getMax())); - slot[mean_tag] = LLSD(F64(stats.mFPS.getMean())); + r.fps.count(fps); + r.fps.min(rec.getMin(LLStatViewer::FPS_SAMPLE)); + r.fps.max(rec.getMax(LLStatViewer::FPS_SAMPLE)); + r.fps.mean(rec.getMean(LLStatViewer::FPS_SAMPLE)); } U32 grid_x(0), grid_y(0); 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); - regions.append(reg_stat); + r.grid_x(grid_x); + r.grid_y(grid_y); + r.duration(LLUnit<LLUnits::Microseconds, F64>(rec.getDuration()).value()); } - LLSD ret = LLSD::emptyMap(); - ret["regions"] = regions; - ret["duration"] = LLSD::Real((now - mResetTimestamp) * 1.0e-6); - - return ret; + stats.duration(mCurRecording ? LLUnit<LLUnits::Microseconds, F64>(mCurRecording->getDuration()).value() : 0.0); } -void -LLViewerAssetStats::merge(const LLViewerAssetStats & src) +LLSD LLViewerAssetStats::asLLSD(bool compact_output) { - // mRegionHandle, mCurRegionStats and mResetTimestamp are left untouched. - // Just merge the stats bodies - - const PerRegionContainer::const_iterator it_end(src.mRegionStats.end()); - for (PerRegionContainer::const_iterator it(src.mRegionStats.begin()); it_end != it; ++it) + LLParamSDParser parser; + LLSD sd; + AssetStats stats; + getStats(stats, compact_output); + LLInitParam::predicate_rule_t rule = LLInitParam::default_parse_rules(); + if (!compact_output) { - PerRegionContainer::iterator dst(mRegionStats.find(it->first)); - if (mRegionStats.end() == dst) - { - // Destination is missing data, just make a private copy - mRegionStats[it->first] = new PerRegionStats(*it->second); - } - else - { - dst->second->merge(*it->second); - } + rule.allow(LLInitParam::EMPTY); } + parser.writeSD(sd, stats, rule); + return sd; } - // ------------------------------------------------------ // Global free-function definitions (LLViewerAssetStatsFF namespace) // ------------------------------------------------------ namespace LLViewerAssetStatsFF { - -// -// Target thread is elaborated in the function name. This could -// have been something 'templatey' like specializations iterated -// over a set of constants but with so few, this is clearer I think. -// -// As for the threads themselves... rather than do fine-grained -// locking as we gather statistics, this code creates a collector -// for each thread, allocated and run independently. Logging -// happens at relatively infrequent intervals and at that time -// the data is sent to a single thread to be aggregated into -// a single entity with locks, thread safety and other niceties. -// -// A particularly fussy implementation would distribute the -// per-thread pointers across separate cache lines. But that should -// be beyond current requirements. -// - -// 'main' thread - initial program thread - -void -set_region_main(LLViewerAssetStats::region_handle_t region_handle) -{ - if (! gViewerAssetStatsMain) - return; - - gViewerAssetStatsMain->setRegion(region_handle); -} - -void -record_enqueue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp) -{ - if (! gViewerAssetStatsMain) - return; - - gViewerAssetStatsMain->recordGetEnqueued(at, with_http, is_temp); -} - -void -record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp) -{ - if (! gViewerAssetStatsMain) - return; - - gViewerAssetStatsMain->recordGetDequeued(at, with_http, is_temp); -} - -void -record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration) -{ - if (! gViewerAssetStatsMain) - return; - - gViewerAssetStatsMain->recordGetServiced(at, with_http, is_temp, duration); -} - -void -record_fps_main(F32 fps) -{ - if (! gViewerAssetStatsMain) - return; - - gViewerAssetStatsMain->recordFPS(fps); -} - -// 'thread1' - should be for TextureFetch thread - -void -set_region_thread1(LLViewerAssetStats::region_handle_t region_handle) +void set_region(LLViewerAssetStats::region_handle_t region_handle) { - if (! gViewerAssetStatsThread1) + if (! gViewerAssetStats) return; - gViewerAssetStatsThread1->setRegion(region_handle); + gViewerAssetStats->setRegion(region_handle); } -void -record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp) +void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp) { - if (! gViewerAssetStatsThread1) - return; + const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); - gViewerAssetStatsThread1->recordGetEnqueued(at, with_http, is_temp); + add(*sEnqueued[int(eac)], 1); } -void -record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp) +void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp) { - if (! gViewerAssetStatsThread1) - return; + const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); - gViewerAssetStatsThread1->recordGetDequeued(at, with_http, is_temp); + add(*sDequeued[int(eac)], 1); } -void -record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration) +void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration) { - if (! gViewerAssetStatsThread1) - return; + const EViewerAssetCategories eac(asset_type_to_category(at, with_http, is_temp)); - gViewerAssetStatsThread1->recordGetServiced(at, with_http, is_temp, duration); + record(*sResponse[int(eac)], LLTrace::Microseconds(duration)); } - -void -init() +void init() { - if (! gViewerAssetStatsMain) - { - gViewerAssetStatsMain = new LLViewerAssetStats(); - } - if (! gViewerAssetStatsThread1) + if (! gViewerAssetStats) { - gViewerAssetStatsThread1 = new LLViewerAssetStats(); + gViewerAssetStats = new LLViewerAssetStats(); } } void cleanup() { - delete gViewerAssetStatsMain; - gViewerAssetStatsMain = 0; - - delete gViewerAssetStatsThread1; - gViewerAssetStatsThread1 = 0; + delete gViewerAssetStats; + gViewerAssetStats = 0; } } // namespace LLViewerAssetStatsFF -// ------------------------------------------------------ -// Local function definitions -// ------------------------------------------------------ - -namespace -{ - -LLViewerAssetStats::EViewerAssetCategories -asset_type_to_category(const LLViewerAssetType::EType at, bool with_http, bool is_temp) -{ - // For statistical purposes, we divide GETs into several - // populations of asset fetches: - // - textures which are de-prioritized in the asset system - // - wearables (clothing, bodyparts) which directly affect - // user experiences when they log in - // - sounds - // - gestures - // - everything else. - // - llassert_always(50 == LLViewerAssetType::AT_COUNT); - - // Multiple asset definitions are floating around so this requires some - // maintenance and attention. - static const LLViewerAssetStats::EViewerAssetCategories asset_to_bin_map[LLViewerAssetType::AT_COUNT] = - { - LLViewerAssetStats::EVACTextureTempHTTPGet, // (0) AT_TEXTURE - LLViewerAssetStats::EVACSoundUDPGet, // AT_SOUND - LLViewerAssetStats::EVACOtherGet, // AT_CALLINGCARD - LLViewerAssetStats::EVACOtherGet, // AT_LANDMARK - LLViewerAssetStats::EVACOtherGet, // AT_SCRIPT - LLViewerAssetStats::EVACWearableUDPGet, // AT_CLOTHING - LLViewerAssetStats::EVACOtherGet, // AT_OBJECT - LLViewerAssetStats::EVACOtherGet, // AT_NOTECARD - LLViewerAssetStats::EVACOtherGet, // AT_CATEGORY - LLViewerAssetStats::EVACOtherGet, // AT_ROOT_CATEGORY - LLViewerAssetStats::EVACOtherGet, // (10) AT_LSL_TEXT - LLViewerAssetStats::EVACOtherGet, // AT_LSL_BYTECODE - LLViewerAssetStats::EVACOtherGet, // AT_TEXTURE_TGA - LLViewerAssetStats::EVACWearableUDPGet, // AT_BODYPART - LLViewerAssetStats::EVACOtherGet, // AT_TRASH - LLViewerAssetStats::EVACOtherGet, // AT_SNAPSHOT_CATEGORY - LLViewerAssetStats::EVACOtherGet, // AT_LOST_AND_FOUND - LLViewerAssetStats::EVACSoundUDPGet, // AT_SOUND_WAV - LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_TGA - LLViewerAssetStats::EVACOtherGet, // AT_IMAGE_JPEG - LLViewerAssetStats::EVACGestureUDPGet, // (20) AT_ANIMATION - LLViewerAssetStats::EVACGestureUDPGet, // AT_GESTURE - LLViewerAssetStats::EVACOtherGet, // AT_SIMSTATE - LLViewerAssetStats::EVACOtherGet, // AT_FAVORITE - LLViewerAssetStats::EVACOtherGet, // AT_LINK - LLViewerAssetStats::EVACOtherGet, // AT_LINK_FOLDER - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // (30) - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // (40) - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // - LLViewerAssetStats::EVACOtherGet, // AT_MESH - // (50) - }; - - if (at < 0 || at >= LLViewerAssetType::AT_COUNT) - { - return LLViewerAssetStats::EVACOtherGet; - } - LLViewerAssetStats::EViewerAssetCategories ret(asset_to_bin_map[at]); - if (LLViewerAssetStats::EVACTextureTempHTTPGet == ret) - { - // Indexed with [is_temp][with_http] - static const LLViewerAssetStats::EViewerAssetCategories texture_bin_map[2][2] = - { - { - LLViewerAssetStats::EVACTextureNonTempUDPGet, - LLViewerAssetStats::EVACTextureNonTempHTTPGet, - }, - { - LLViewerAssetStats::EVACTextureTempUDPGet, - LLViewerAssetStats::EVACTextureTempHTTPGet, - } - }; - - ret = texture_bin_map[is_temp][with_http]; - } - return ret; -} -} // anonymous namespace +LLViewerAssetStats::AssetRequestType::AssetRequestType() +: enqueued("enqueued"), + dequeued("dequeued"), + resp_count("resp_count"), + resp_min("resp_min"), + resp_max("resp_max"), + resp_mean("resp_mean") +{} + +LLViewerAssetStats::FPSStats::FPSStats() +: count("count"), + min("min"), + max("max"), + mean("mean") +{} + +LLViewerAssetStats::RegionStats::RegionStats() +: get_texture_temp_http("get_texture_temp_http"), + get_texture_temp_udp("get_texture_temp_udp"), + get_texture_non_temp_http("get_texture_non_temp_http"), + get_texture_non_temp_udp("get_texture_non_temp_udp"), + get_wearable_udp("get_wearable_udp"), + get_sound_udp("get_sound_udp"), + get_gesture_udp("get_gesture_udp"), + get_other("get_other"), + fps("fps"), + grid_x("grid_x"), + grid_y("grid_y"), + duration("duration") +{} + +LLViewerAssetStats::AssetStats::AssetStats() +: regions("regions"), + duration("duration"), + session_id("session_id"), + agent_id("agent_id"), + message("message"), + sequence("sequence"), + initial("initial"), + break_("break") +{} diff --git a/indra/newview/llviewerassetstats.h b/indra/newview/llviewerassetstats.h index e4581d2120..1a8770f8a7 100755 --- a/indra/newview/llviewerassetstats.h +++ b/indra/newview/llviewerassetstats.h @@ -37,6 +37,8 @@ #include "llsimplestat.h" #include "llsd.h" #include "llvoavatar.h" +#include "lltrace.h" +#include "llinitparam.h" /** * @class LLViewerAssetStats @@ -73,29 +75,15 @@ * LLViewerAssetStatsFF is provided for conditional test-and-call * operations. */ -class LLViewerAssetStats +class LLViewerAssetStats : public LLStopWatchControlsMixin<LLViewerAssetStats> { public: - enum EViewerAssetCategories - { - EVACTextureTempHTTPGet, //< Texture GETs - temp/baked, HTTP - EVACTextureTempUDPGet, //< Texture GETs - temp/baked, UDP - EVACTextureNonTempHTTPGet, //< Texture GETs - perm, HTTP - EVACTextureNonTempUDPGet, //< Texture GETs - perm, UDP - EVACWearableUDPGet, //< Wearable GETs - EVACSoundUDPGet, //< Sound GETs - EVACGestureUDPGet, //< Gesture GETs - EVACOtherGet, //< Other GETs - - EVACCount // Must be last - }; - /** * Type for duration and other time values in the metrics. Selected * for compatibility with the pre-existing timestamp on the texture * fetcher class, LLTextureFetch. */ - typedef U64 duration_t; + typedef LLUnit<LLUnits::Microseconds, U64> duration_t; /** * Type for the region identifier used in stats. Currently uses @@ -104,64 +92,65 @@ public: */ typedef U64 region_handle_t; - /** - * @brief Collected data for a single region visited by the avatar. - * - * Fairly simple, for each asset bin enumerated above a count - * of enqueue and dequeue operations and simple stats on response - * times for completed requests. - */ - class PerRegionStats : public LLRefCount + struct AssetRequestType : public LLInitParam::Block<AssetRequestType> { - public: - PerRegionStats(const region_handle_t region_handle) - : LLRefCount(), - mRegionHandle(region_handle) - { - reset(); - } - - PerRegionStats(const PerRegionStats & src) - : LLRefCount(), - mRegionHandle(src.mRegionHandle), - mTotalTime(src.mTotalTime), - mStartTimestamp(src.mStartTimestamp), - mFPS(src.mFPS) - { - for (int i = 0; i < LL_ARRAY_SIZE(mRequests); ++i) - { - mRequests[i] = src.mRequests[i]; - } - } - - // Default assignment and destructor are correct. - - void reset(); + Mandatory<S32> enqueued, + dequeued, + resp_count; + Mandatory<F64> resp_min, + resp_max, + resp_mean; + + AssetRequestType(); + }; - void merge(const PerRegionStats & src); + struct FPSStats : public LLInitParam::Block<FPSStats> + { + Mandatory<S32> count; + Mandatory<F64> min, + max, + mean; + FPSStats(); + }; + + struct RegionStats : public LLInitParam::Block<RegionStats> + { + Optional<AssetRequestType> get_texture_temp_http, + get_texture_temp_udp, + get_texture_non_temp_http, + get_texture_non_temp_udp, + get_wearable_udp, + get_sound_udp, + get_gesture_udp, + get_other; + Optional<FPSStats> fps; + Optional<S32> grid_x, + grid_y; + Optional<F64> duration; + + RegionStats(); + }; + + struct AssetStats : public LLInitParam::Block<AssetStats> + { + Multiple<RegionStats> regions; + Mandatory<F64> duration; - // Apply current running time to total and reset start point. - // Return current timestamp as a convenience. - void accumulateTime(duration_t now); + Mandatory<LLUUID> session_id, + agent_id; - public: - region_handle_t mRegionHandle; - duration_t mTotalTime; - duration_t mStartTimestamp; - LLSimpleStatMMM<> mFPS; + Mandatory<std::string> message; + Mandatory<S32> sequence; + Mandatory<bool> initial, + break_; - struct prs_group - { - LLSimpleStatCounter mEnqueued; - LLSimpleStatCounter mDequeued; - LLSimpleStatMMM<duration_t> mResponse; - } - mRequests [EVACCount]; + AssetStats(); }; public: LLViewerAssetStats(); LLViewerAssetStats(const LLViewerAssetStats &); + // Default destructor is correct. LLViewerAssetStats & operator=(const LLViewerAssetStats &); // Not defined @@ -174,88 +163,32 @@ public: // collection calls. void setRegion(region_handle_t region_handle); - // Asset GET Requests - void recordGetEnqueued(LLViewerAssetType::EType at, bool with_http, bool is_temp); - void recordGetDequeued(LLViewerAssetType::EType at, bool with_http, bool is_temp); - void recordGetServiced(LLViewerAssetType::EType at, bool with_http, bool is_temp, duration_t duration); - - // Frames-Per-Second Samples - void recordFPS(F32 fps); - - // Avatar-related statistics - void recordAvatarStats(); - - // Merge a source instance into a destination instance. This is - // conceptually an 'operator+=()' method: - // - counts are added - // - minimums are min'd - // - maximums are max'd - // - other scalars are ignored ('this' wins) - // - void merge(const LLViewerAssetStats & src); + // gather latest metrics data + // call from main thread + void updateStats(); // Retrieve current metrics for all visited regions (NULL region UUID/handle excluded) - // Returned LLSD is structured as follows: - // - // &stats_group = { - // enqueued : int, - // dequeued : int, - // resp_count : int, - // resp_min : float, - // resp_max : float, - // resp_mean : float - // } - // - // &mmm_group = { - // count : int, - // min : float, - // max : float, - // mean : float - // } - // - // { - // duration: int - // regions: { - // $: { // Keys are strings of the region's handle in hex - // duration: : int, - // fps: : &mmm_group, - // get_texture_temp_http : &stats_group, - // get_texture_temp_udp : &stats_group, - // get_texture_non_temp_http : &stats_group, - // get_texture_non_temp_udp : &stats_group, - // get_wearable_udp : &stats_group, - // get_sound_udp : &stats_group, - // get_gesture_udp : &stats_group, - // get_other : &stats_group - // } - // } - // } - // - // @param compact_output If true, omits from conversion any mmm_block - // or stats_block that would contain all zero data. - // Useful for transmission when the receiver knows - // what is expected and will assume zero for missing - // blocks. + // Uses AssetStats structure seen above + void getStats(AssetStats& stats, bool compact_output); LLSD asLLSD(bool compact_output); protected: - typedef std::map<region_handle_t, LLPointer<PerRegionStats> > PerRegionContainer; + void handleStart(); + void handleStop(); + void handleReset(); + + typedef std::map<region_handle_t, LLTrace::Recording > PerRegionRecordingContainer; // Region of the currently-active region. Always valid but may // be zero after construction or when explicitly set. Unchanged // by a reset() call. region_handle_t mRegionHandle; - // Pointer to metrics collection for currently-active region. Always - // valid and unchanged after reset() though contents will be changed. - // Always points to a collection contained in mRegionStats. - LLPointer<PerRegionStats> mCurRegionStats; + // Pointer to metrics collection for currently-active region. + LLTrace::Recording* mCurRecording; // Metrics data for all regions during one collection cycle - PerRegionContainer mRegionStats; - - // Time of last reset - duration_t mResetTimestamp; + PerRegionRecordingContainer mRegionRecordings; }; @@ -273,12 +206,24 @@ protected: * - Main: main() program execution thread * - Thread1: TextureFetch worker thread */ -extern LLViewerAssetStats * gViewerAssetStatsMain; - -extern LLViewerAssetStats * gViewerAssetStatsThread1; +extern LLViewerAssetStats * gViewerAssetStats; namespace LLViewerAssetStatsFF { + enum EViewerAssetCategories + { + EVACTextureTempHTTPGet, //< Texture GETs - temp/baked, HTTP + EVACTextureTempUDPGet, //< Texture GETs - temp/baked, UDP + EVACTextureNonTempHTTPGet, //< Texture GETs - perm, HTTP + EVACTextureNonTempUDPGet, //< Texture GETs - perm, UDP + EVACWearableUDPGet, //< Wearable GETs + EVACSoundUDPGet, //< Sound GETs + EVACGestureUDPGet, //< Gesture GETs + EVACOtherGet, //< Other GETs + + EVACCount // Must be last + }; + /** * @brief Allocation and deallocation of globals. * @@ -303,28 +248,16 @@ inline LLViewerAssetStats::duration_t get_timestamp() /** * Region context, event and duration loggers for the Main thread. */ -void set_region_main(LLViewerAssetStats::region_handle_t region_handle); +void set_region(LLViewerAssetStats::region_handle_t region_handle); -void record_enqueue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp); +void record_enqueue(LLViewerAssetType::EType at, bool with_http, bool is_temp); -void record_dequeue_main(LLViewerAssetType::EType at, bool with_http, bool is_temp); +void record_dequeue(LLViewerAssetType::EType at, bool with_http, bool is_temp); -void record_response_main(LLViewerAssetType::EType at, bool with_http, bool is_temp, +void record_response(LLViewerAssetType::EType at, bool with_http, bool is_temp, LLViewerAssetStats::duration_t duration); -void record_fps_main(F32 fps); - -/** - * Region context, event and duration loggers for Thread 1. - */ -void set_region_thread1(LLViewerAssetStats::region_handle_t region_handle); - -void record_enqueue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp); - -void record_dequeue_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp); - -void record_response_thread1(LLViewerAssetType::EType at, bool with_http, bool is_temp, - LLViewerAssetStats::duration_t duration); +void record_avatar_stats(); } // namespace LLViewerAssetStatsFF diff --git a/indra/newview/llviewerassetstorage.cpp b/indra/newview/llviewerassetstorage.cpp index d042f62830..5c2dd20ec3 100755 --- a/indra/newview/llviewerassetstorage.cpp +++ b/indra/newview/llviewerassetstorage.cpp @@ -69,12 +69,12 @@ 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. - LLViewerAssetStatsFF::record_dequeue_main(mType, false, false); - LLViewerAssetStatsFF::record_response_main(mType, false, false, + LLViewerAssetStatsFF::record_dequeue(mType, false, false); + LLViewerAssetStatsFF::record_response(mType, false, false, (LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime)); mMetricsStartTime = 0; @@ -373,7 +373,7 @@ void LLViewerAssetStorage::_queueDataRequest( LLTransferTargetChannel *ttcp = gTransferManager.getTargetChannel(mUpstreamHost, LLTCT_ASSET); ttcp->requestTransfer(spa, tpvf, 100.f + (is_priority ? 1.f : 0.f)); - LLViewerAssetStatsFF::record_enqueue_main(atype, false, false); + LLViewerAssetStatsFF::record_enqueue(atype, false, false); } } else diff --git a/indra/newview/llvieweraudio.cpp b/indra/newview/llvieweraudio.cpp index 094694dc06..ffdaa21c84 100755 --- a/indra/newview/llvieweraudio.cpp +++ b/indra/newview/llvieweraudio.cpp @@ -37,6 +37,7 @@ #include "llviewerwindow.h" #include "llvoiceclient.h" #include "llviewermedia.h" +#include "llviewerregion.h" #include "llprogressview.h" #include "llcallbacklist.h" #include "llstartup.h" @@ -501,11 +502,11 @@ void audio_update_wind(bool force_update) // standing still. static LLUICachedControl<F32> wind_level("AudioLevelWind", 0.5f); LLVector3 scaled_wind_vec = gWindVec * wind_level; - + // Mix in the avatar's motion, subtract because when you walk north, // the apparent wind moves south. LLVector3 final_wind_vec = scaled_wind_vec - gAgent.getVelocity(); - + // rotate the wind vector to be listener (agent) relative gRelativeWindVec = gAgent.getFrameAgent().rotateToLocal( final_wind_vec ); diff --git a/indra/newview/llviewercamera.cpp b/indra/newview/llviewercamera.cpp index b5aa0ac92a..ebc4f09edb 100755 --- a/indra/newview/llviewercamera.cpp +++ b/indra/newview/llviewercamera.cpp @@ -49,11 +49,15 @@ #include "llglheaders.h" #include "llquaternion.h" #include "llwindow.h" // getPixelAspectRatio() +#include "lltracerecording.h" // System includes #include <iomanip> // for setprecision -U32 LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; +LLTrace::CountStatHandle<> LLViewerCamera::sVelocityStat("camera_velocity"); +LLTrace::CountStatHandle<> LLViewerCamera::sAngularVelocityStat("camera_angular_velocity"); + +LLViewerCamera::eCameraID LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; //glu pick matrix implementation borrowed from Mesa3D glh::matrix4f gl_pick_matrix(GLfloat x, GLfloat y, GLfloat width, GLfloat height, GLint* viewport) @@ -160,11 +164,11 @@ void LLViewerCamera::updateCameraLocation(const LLVector3 ¢er, F32 drot; rotation.getAngleAxis(&drot, &x, &y, &z); - mVelocityStat.addValue(dpos); - mAngularVelocityStat.addValue(drot); + add(sVelocityStat, dpos); + add(sAngularVelocityStat, drot); - mAverageSpeed = mVelocityStat.getMeanPerSec() ; - mAverageAngularSpeed = mAngularVelocityStat.getMeanPerSec() ; + mAverageSpeed = LLTrace::get_frame_recording().getPeriodMeanPerSec(sVelocityStat, 50); + mAverageAngularSpeed = LLTrace::get_frame_recording().getPeriodMeanPerSec(sAngularVelocityStat); mCosHalfCameraFOV = cosf(0.5f * getView() * llmax(1.0f, getAspect())); // update pixel meter ratio using default fov, not modified one diff --git a/indra/newview/llviewercamera.h b/indra/newview/llviewercamera.h index b857c7fe89..7b2887d725 100755 --- a/indra/newview/llviewercamera.h +++ b/indra/newview/llviewercamera.h @@ -29,10 +29,10 @@ #include "llcamera.h" #include "llsingleton.h" -#include "llstat.h" #include "lltimer.h" #include "m4math.h" #include "llcoord.h" +#include "lltrace.h" class LLViewerObject; @@ -80,7 +80,7 @@ public: NUM_CAMERAS } eCameraID; - static U32 sCurCameraID; + static eCameraID sCurCameraID; LLViewerCamera(); @@ -100,9 +100,9 @@ public: BOOL projectPosAgentToScreen(const LLVector3 &pos_agent, LLCoordGL &out_point, const BOOL clamp = TRUE) const; BOOL projectPosAgentToScreenEdge(const LLVector3 &pos_agent, LLCoordGL &out_point) const; - const LLVector3* getVelocityDir() const {return &mVelocityDir;} - LLStat *getVelocityStat() { return &mVelocityStat; } - LLStat *getAngularVelocityStat() { return &mAngularVelocityStat; } + LLVector3 getVelocityDir() const {return mVelocityDir;} + static LLTrace::CountStatHandle<>* getVelocityStat() {return &sVelocityStat; } + static LLTrace::CountStatHandle<>* getAngularVelocityStat() {return &sAngularVelocityStat; } F32 getCosHalfFov() {return mCosHalfCameraFOV;} F32 getAverageSpeed() {return mAverageSpeed ;} F32 getAverageAngularSpeed() {return mAverageAngularSpeed;} @@ -117,9 +117,9 @@ public: F32 getDefaultFOV() { return mCameraFOVDefault; } BOOL cameraUnderWater() const; + BOOL areVertsVisible(LLViewerObject* volumep, BOOL all_verts); const LLVector3 &getPointOfInterest() { return mLastPointOfInterest; } - BOOL areVertsVisible(LLViewerObject* volumep, BOOL all_verts); F32 getPixelMeterRatio() const { return mPixelMeterRatio; } S32 getScreenPixelArea() const { return mScreenPixelArea; } @@ -130,12 +130,12 @@ public: protected: void calcProjection(const F32 far_distance) const; - LLStat mVelocityStat; - LLStat mAngularVelocityStat; + static LLTrace::CountStatHandle<> sVelocityStat; + static LLTrace::CountStatHandle<> sAngularVelocityStat; + LLVector3 mVelocityDir ; F32 mAverageSpeed ; F32 mAverageAngularSpeed ; - mutable LLMatrix4 mProjectionMatrix; // Cache of perspective matrix mutable LLMatrix4 mModelviewMatrix; F32 mCameraFOVDefault; diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp index cf59e67955..7ad4743d82 100755 --- a/indra/newview/llviewerdisplay.cpp +++ b/indra/newview/llviewerdisplay.cpp @@ -77,6 +77,7 @@ #include "llwlparammanager.h" #include "llwaterparammanager.h" #include "llpostprocess.h" +#include "llscenemonitor.h" extern LLPointer<LLViewerTexture> gStartTexture; extern bool gShiftFrame; @@ -84,9 +85,6 @@ extern bool gShiftFrame; LLPointer<LLViewerTexture> gDisconnectedImagep = NULL; // used to toggle renderer back on after teleport -const F32 TELEPORT_RENDER_DELAY = 20.f; // Max time a teleport is allowed to take before we raise the curtain -const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. -const F32 TELEPORT_LOCAL_DELAY = 1.0f; // Delay to prevent teleports after starting an in-sim teleport. BOOL gTeleportDisplay = FALSE; LLFrameTimer gTeleportDisplayTimer; LLFrameTimer gTeleportArrivalTimer; @@ -372,7 +370,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLFastTimer t(FTM_TELEPORT_DISPLAY); LLAppViewer::instance()->pingMainloopTimeout("Display:Teleport"); - const F32 TELEPORT_ARRIVAL_DELAY = 2.f; // Time to preload the world before raising the curtain after we've actually already arrived. + static LLCachedControl<F32> teleport_arrival_delay(gSavedSettings, "TeleportArrivalDelay"); + static LLCachedControl<F32> teleport_local_delay(gSavedSettings, "TeleportLocalDelay"); S32 attach_count = 0; if (isAgentAvatarValid()) @@ -440,7 +439,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) case LLAgent::TELEPORT_ARRIVING: // Make the user wait while content "pre-caches" { - F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / TELEPORT_ARRIVAL_DELAY); + F32 arrival_fraction = (gTeleportArrivalTimer.getElapsedTimeF32() / teleport_arrival_delay()); if( arrival_fraction > 1.f ) { arrival_fraction = 1.f; @@ -457,7 +456,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) // Short delay when teleporting in the same sim (progress screen active but not shown - did not // fall-through from TELEPORT_START) { - if( gTeleportDisplayTimer.getElapsedTimeF32() > TELEPORT_LOCAL_DELAY ) + if( gTeleportDisplayTimer.getElapsedTimeF32() > teleport_local_delay() ) { //LLFirstUse::useTeleport(); gAgent.setTeleportState( LLAgent::TELEPORT_NONE ); @@ -607,7 +606,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLFastTimer t(FTM_DISPLAY_UPDATE_GEOM); - const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds; // 50 ms/second update time + const F32 max_geom_update_time = 0.005f*10.f*gFrameIntervalSeconds.value(); // 50 ms/second update time gPipeline.createObjects(max_geom_update_time); gPipeline.processPartitionQ(); gPipeline.updateGeom(max_geom_update_time); @@ -748,8 +747,10 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLFastTimer t(FTM_IMAGE_UPDATE_CLASS); - LLViewerTexture::updateClass(LLViewerCamera::getInstance()->getVelocityStat()->getMean(), - LLViewerCamera::getInstance()->getAngularVelocityStat()->getMean()); + LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat(); + LLTrace::CountStatHandle<>* angular_velocity_stat = LLViewerCamera::getAngularVelocityStat(); + LLViewerTexture::updateClass(LLTrace::get_frame_recording().getPeriodMeanPerSec(*velocity_stat), + LLTrace::get_frame_recording().getPeriodMeanPerSec(*angular_velocity_stat)); } @@ -760,7 +761,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) { LLFastTimer t(FTM_IMAGE_UPDATE_LIST); - F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds; // 50 ms/second decode time + F32 max_image_decode_time = 0.050f*gFrameIntervalSeconds.value(); // 50 ms/second decode time max_image_decode_time = llclamp(max_image_decode_time, 0.002f, 0.005f ); // min 2ms/frame, max 5ms/frame) gTextureList.updateImages(max_image_decode_time); } @@ -802,6 +803,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) } } + LLSceneMonitor::getInstance()->fetchQueryResult(); + LLGLState::checkStates(); LLGLState::checkClientArrays(); @@ -989,6 +992,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot) LLPipeline::sUnderWaterRender = FALSE; + { + //capture the frame buffer. + LLSceneMonitor::getInstance()->capture(); + } + LLAppViewer::instance()->pingMainloopTimeout("Display:RenderUI"); if (!for_snapshot) { @@ -1033,7 +1041,7 @@ void render_hud_attachments() // clamp target zoom level to reasonable values gAgentCamera.mHUDTargetZoom = llclamp(gAgentCamera.mHUDTargetZoom, 0.1f, 1.f); // smoothly interpolate current zoom level - gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f)); + gAgentCamera.mHUDCurZoom = lerp(gAgentCamera.mHUDCurZoom, gAgentCamera.mHUDTargetZoom, LLSmoothInterpolation::getInterpolant(0.03f)); if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices()) { @@ -1221,6 +1229,15 @@ void render_ui(F32 zoom_factor, int subfield) glh_set_current_modelview(glh_copy_matrix(gGLLastModelView)); } + if(LLSceneMonitor::getInstance()->needsUpdate()) + { + gGL.pushMatrix(); + gViewerWindow->setup2DRender(); + LLSceneMonitor::getInstance()->compare(); + gViewerWindow->setup3DRender(); + gGL.popMatrix(); + } + { BOOL to_texture = gPipeline.canUseVertexShaders() && LLPipeline::sRenderGlow; diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp index c6b28b9e5e..39f8249300 100755 --- a/indra/newview/llviewerfloaterreg.cpp +++ b/indra/newview/llviewerfloaterreg.cpp @@ -28,66 +28,65 @@ #include "llviewerprecompiledheaders.h" #include "llfloaterreg.h" - #include "llviewerfloaterreg.h" -#include "llfloaterautoreplacesettings.h" + +#include "llcommandhandler.h" #include "llcompilequeue.h" #include "llfasttimerview.h" #include "llfloaterabout.h" #include "llfloaterauction.h" +#include "llfloaterautoreplacesettings.h" #include "llfloateravatar.h" #include "llfloateravatarpicker.h" #include "llfloateravatartextures.h" #include "llfloaterbeacons.h" #include "llfloaterbuildoptions.h" +#include "llfloaterbulkpermission.h" +#include "llfloaterbump.h" #include "llfloaterbuy.h" #include "llfloaterbuycontents.h" #include "llfloaterbuycurrency.h" #include "llfloaterbuycurrencyhtml.h" #include "llfloaterbuyland.h" -#include "llfloaterbulkpermission.h" -#include "llfloaterbump.h" #include "llfloaterbvhpreview.h" #include "llfloatercamera.h" #include "llfloaterchatvoicevolume.h" #include "llfloaterconversationlog.h" #include "llfloaterconversationpreview.h" #include "llfloaterdeleteenvpreset.h" +#include "llfloaterdestinations.h" #include "llfloaterdisplayname.h" #include "llfloatereditdaycycle.h" #include "llfloatereditsky.h" #include "llfloatereditwater.h" #include "llfloaterenvironmentsettings.h" #include "llfloaterevent.h" -#include "llfloaterdestinations.h" #include "llfloaterfonttest.h" #include "llfloatergesture.h" #include "llfloatergodtools.h" #include "llfloatergroups.h" #include "llfloaterhardwaresettings.h" #include "llfloaterhelpbrowser.h" -#include "llfloaterwebcontent.h" -#include "llfloaterwebprofile.h" -#include "llfloatermediasettings.h" #include "llfloaterhud.h" #include "llfloaterimagepreview.h" #include "llfloaterimsession.h" #include "llfloaterinspect.h" #include "llfloaterinventory.h" #include "llfloaterjoystick.h" -#include "llfloaterlagmeter.h" #include "llfloaterland.h" #include "llfloaterlandholdings.h" #include "llfloatermap.h" +#include "llfloatermediasettings.h" #include "llfloatermemleak.h" +#include "llfloatermodelpreview.h" #include "llfloaternamedesc.h" #include "llfloaternotificationsconsole.h" #include "llfloaterobjectweights.h" #include "llfloateropenobject.h" #include "llfloateroutbox.h" #include "llfloaterpathfindingcharacters.h" -#include "llfloaterpathfindinglinksets.h" #include "llfloaterpathfindingconsole.h" +#include "llfloaterpathfindinglinksets.h" #include "llfloaterpay.h" #include "llfloaterperms.h" #include "llfloaterpostprocess.h" @@ -96,6 +95,7 @@ #include "llfloaterregiondebugconsole.h" #include "llfloaterregioninfo.h" #include "llfloaterreporter.h" +#include "llfloatersceneloadstats.h" #include "llfloaterscriptdebug.h" #include "llfloaterscriptlimits.h" #include "llfloatersearch.h" @@ -110,12 +110,14 @@ #include "llfloatertestlistview.h" #include "llfloatertexturefetchdebugger.h" #include "llfloatertools.h" -#include "llfloatertos.h" #include "llfloatertopobjects.h" +#include "llfloatertos.h" #include "llfloatertoybox.h" #include "llfloatertranslationsettings.h" #include "llfloateruipreview.h" #include "llfloatervoiceeffect.h" +#include "llfloaterwebcontent.h" +#include "llfloaterwebprofile.h" #include "llfloatervoicevolume.h" #include "llfloaterwhitelistentry.h" #include "llfloaterwindowsize.h" @@ -136,10 +138,8 @@ #include "llpreviewscript.h" #include "llpreviewsound.h" #include "llpreviewtexture.h" -#include "llsyswellwindow.h" #include "llscriptfloater.h" -#include "llfloatermodelpreview.h" -#include "llcommandhandler.h" +#include "llsyswellwindow.h" // *NOTE: Please add files in alphabetical order to keep merges easy. @@ -231,7 +231,6 @@ void LLViewerFloaterReg::registerFloaters() LLNotificationsUI::registerFloater(); LLFloaterDisplayNameUtil::registerFloater(); - LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>); LLFloaterReg::add("land_holdings", "floater_land_holdings.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLandHoldings>); LLFloaterReg::add("mem_leaking", "floater_mem_leaking.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterMemLeak>); @@ -305,6 +304,7 @@ void LLViewerFloaterReg::registerFloaters() LLFloaterReg::add("sound_devices", "floater_sound_devices.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundDevices>); LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>); LLFloaterReg::add("start_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterRunQueue>); + LLFloaterReg::add("scene_load_stats", "floater_scene_load_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSceneLoadStats>); LLFloaterReg::add("stop_queue", "floater_script_queue.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterNotRunQueue>); LLFloaterReg::add("snapshot", "floater_snapshot.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSnapshot>); LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>); diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index f6e840adcd..f4155df4d1 100755 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -501,7 +501,7 @@ void LLViewerJoystick::moveObjects(bool reset) }; F32 cur_delta[6]; - F32 time = gFrameIntervalSeconds; + F32 time = gFrameIntervalSeconds.value(); // avoid making ridicously big movements if there's a big drop in fps if (time > .2f) @@ -665,7 +665,7 @@ void LLViewerJoystick::moveAvatar(bool reset) }; // time interval in seconds between this frame and the previous - F32 time = gFrameIntervalSeconds; + F32 time = gFrameIntervalSeconds.value(); // avoid making ridicously big movements if there's a big drop in fps if (time > .2f) @@ -878,7 +878,7 @@ void LLViewerJoystick::moveFlycam(bool reset) gSavedSettings.getF32("FlycamAxisDeadZone6") }; - F32 time = gFrameIntervalSeconds; + F32 time = gFrameIntervalSeconds.value(); // avoid making ridiculously big movements if there's a big drop in fps if (time > .2f) diff --git a/indra/newview/llviewerkeyboard.cpp b/indra/newview/llviewerkeyboard.cpp index 4ecdc31e21..49ac2735ca 100755 --- a/indra/newview/llviewerkeyboard.cpp +++ b/indra/newview/llviewerkeyboard.cpp @@ -161,6 +161,11 @@ void agent_push_backward( EKeystate s ) camera_move_backward(s); return; } + else if (gAgentAvatarp->isSitting()) + { + gAgentCamera.changeCameraToThirdPerson(); + return; + } agent_push_forwardbackward(s, -1, LLAgent::DOUBLETAP_BACKWARD); } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index beca08203f..bb3f0fe932 100755 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -124,6 +124,7 @@ #include "llwindow.h" #include "llpathfindingmanager.h" #include "boost/unordered_map.hpp" +#include "llscenemonitor.h" using namespace LLAvatarAppearanceDefines; @@ -524,7 +525,10 @@ class LLAdvancedToggleConsole : public view_listener_t { toggle_visibility( (void*)gSceneView); } - + else if ("scene monitor" == console_type) + { + toggle_visibility( (void*)gSceneMonitorView); + } #if MEM_TRACK_MEM else if ("memory view" == console_type) { @@ -552,9 +556,9 @@ class LLAdvancedCheckConsole : public view_listener_t { new_value = LLFloaterReg::instanceVisible("fast_timers"); } - else if ("scene view" == console_type) + else if ("scene monitor" == console_type) { - new_value = get_visibility( (void*) gSceneView); + new_value = get_visibility( (void*) gSceneMonitorView); } #if MEM_TRACK_MEM else if ("memory view" == console_type) @@ -3963,24 +3967,24 @@ class LLViewToggleUI : public view_listener_t { if(gAgentCamera.getCameraMode() != CAMERA_MODE_MOUSELOOK) { - LLNotification::Params params("ConfirmHideUI"); - params.functor.function(boost::bind(&LLViewToggleUI::confirm, this, _1, _2)); - LLSD substitutions; + LLNotification::Params params("ConfirmHideUI"); + params.functor.function(boost::bind(&LLViewToggleUI::confirm, this, _1, _2)); + LLSD substitutions; #if LL_DARWIN - substitutions["SHORTCUT"] = "Cmd+Shift+U"; + substitutions["SHORTCUT"] = "Cmd+Shift+U"; #else - substitutions["SHORTCUT"] = "Ctrl+Shift+U"; + substitutions["SHORTCUT"] = "Ctrl+Shift+U"; #endif - params.substitutions = substitutions; + params.substitutions = substitutions; if (!gSavedSettings.getBOOL("HideUIControls")) - { - // hiding, so show notification - LLNotifications::instance().add(params); - } - else - { - LLNotifications::instance().forceResponse(params, 0); - } + { + // hiding, so show notification + LLNotifications::instance().add(params); + } + else + { + LLNotifications::instance().forceResponse(params, 0); + } } return true; } @@ -4027,72 +4031,6 @@ void handle_duplicate_in_place(void*) LLSelectMgr::getInstance()->selectDuplicate(offset, TRUE); } -/* dead code 30-apr-2008 -void handle_deed_object_to_group(void*) -{ - LLUUID group_id; - - LLSelectMgr::getInstance()->selectGetGroup(group_id); - LLSelectMgr::getInstance()->sendOwner(LLUUID::null, group_id, FALSE); - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_RELEASE_COUNT); -} - -BOOL enable_deed_object_to_group(void*) -{ - if(LLSelectMgr::getInstance()->getSelection()->isEmpty()) return FALSE; - LLPermissions perm; - LLUUID group_id; - - if (LLSelectMgr::getInstance()->selectGetGroup(group_id) && - gAgent.hasPowerInGroup(group_id, GP_OBJECT_DEED) && - LLSelectMgr::getInstance()->selectGetPermissions(perm) && - perm.deedToGroup(gAgent.getID(), group_id)) - { - return TRUE; - } - return FALSE; -} - -*/ - - -/* - * No longer able to support viewer side manipulations in this way - * -void god_force_inv_owner_permissive(LLViewerObject* object, - LLInventoryObject::object_list_t* inventory, - S32 serial_num, - void*) -{ - typedef std::vector<LLPointer<LLViewerInventoryItem> > item_array_t; - item_array_t items; - - LLInventoryObject::object_list_t::const_iterator inv_it = inventory->begin(); - LLInventoryObject::object_list_t::const_iterator inv_end = inventory->end(); - for ( ; inv_it != inv_end; ++inv_it) - { - if(((*inv_it)->getType() != LLAssetType::AT_CATEGORY)) - { - LLInventoryObject* obj = *inv_it; - LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem((LLViewerInventoryItem*)obj); - LLPermissions perm(new_item->getPermissions()); - perm.setMaskBase(PERM_ALL); - perm.setMaskOwner(PERM_ALL); - new_item->setPermissions(perm); - items.push_back(new_item); - } - } - item_array_t::iterator end = items.end(); - item_array_t::iterator it; - for(it = items.begin(); it != end; ++it) - { - // since we have the inventory item in the callback, it should not - // invalidate iteration through the selection manager. - object->updateInventory((*it), TASK_INVENTORY_ITEM_KEY, false); - } -} -*/ - void handle_object_owner_permissive(void*) { // only send this if they're a god. @@ -7370,7 +7308,7 @@ void handle_dump_avatar_local_textures(void*) void handle_dump_timers() { - LLFastTimer::dumpCurTimes(); + LLTrace::TimeBlock::dumpCurTimes(); } void handle_debug_avatar_textures(void*) @@ -7611,6 +7549,23 @@ void handle_web_browser_test(const LLSD& param) LLWeb::loadURLInternal(url); } +bool callback_clear_cache_immediately(const LLSD& notification, const LLSD& response) +{ + S32 option = LLNotificationsUtil::getSelectedOption(notification, response); + if ( option == 0 ) // YES + { + //clear cache + LLAppViewer::instance()->purgeCacheImmediate(); + } + + return false; +} + +void handle_cache_clear_immediately() +{ + LLNotificationsUtil::add("ConfirmClearCache", LLSD(), LLSD(), callback_clear_cache_immediately); +} + void handle_web_content_test(const LLSD& param) { std::string url = param.asString(); @@ -8340,10 +8295,10 @@ void initialize_menus() view_listener_t::addMenu(new LLViewStatusAway(), "View.Status.CheckAway"); view_listener_t::addMenu(new LLViewStatusDoNotDisturb(), "View.Status.CheckDoNotDisturb"); view_listener_t::addMenu(new LLViewCheckHUDAttachments(), "View.CheckHUDAttachments"); - + // Me > Movement view_listener_t::addMenu(new LLAdvancedAgentFlyingInfo(), "Agent.getFlying"); - + // Communicate > Voice morphing > Subscribe... commit.add("Communicate.VoiceMorphing.Subscribe", boost::bind(&handle_voice_morphing_subscribe)); LLVivoxVoiceClient * voice_clientp = LLVivoxVoiceClient::getInstance(); @@ -8351,7 +8306,7 @@ void initialize_menus() , boost::bind(&LLVivoxVoiceClient::onCheckVoiceEffect, voice_clientp, "NoVoiceMorphing")); commit.add("Communicate.VoiceMorphing.NoVoiceMorphing.Click" , boost::bind(&LLVivoxVoiceClient::onClickVoiceEffect, voice_clientp, "NoVoiceMorphing")); - + // World menu view_listener_t::addMenu(new LLWorldAlwaysRun(), "World.AlwaysRun"); view_listener_t::addMenu(new LLWorldCreateLandmark(), "World.CreateLandmark"); @@ -8577,6 +8532,8 @@ void initialize_menus() //Develop (Texture Fetch Debug Console) view_listener_t::addMenu(new LLDevelopTextureFetchDebugger(), "Develop.SetTexFetchDebugger"); + //Develop (clear cache immediately) + commit.add("Develop.ClearCache", boost::bind(&handle_cache_clear_immediately) ); // Admin >Object view_listener_t::addMenu(new LLAdminForceTakeCopy(), "Admin.ForceTakeCopy"); diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp index be78603e2d..b7282a8493 100755 --- a/indra/newview/llviewermenufile.cpp +++ b/indra/newview/llviewermenufile.cpp @@ -1096,17 +1096,17 @@ void upload_new_resource( if( LLAssetType::AT_SOUND == asset_type ) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_SOUND_COUNT ); + add(LLStatViewer::UPLOAD_SOUND, 1); } else if( LLAssetType::AT_TEXTURE == asset_type ) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_TEXTURE_COUNT ); + add(LLStatViewer::UPLOAD_TEXTURE, 1); } else if( LLAssetType::AT_ANIMATION == asset_type) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_ANIM_COUNT ); + add(LLStatViewer::ANIMATION_UPLOADS, 1); } if(LLInventoryType::IT_NONE == inv_type) @@ -1231,18 +1231,15 @@ void increase_new_upload_stats(LLAssetType::EType asset_type) { if ( LLAssetType::AT_SOUND == asset_type ) { - LLViewerStats::getInstance()->incStat( - LLViewerStats::ST_UPLOAD_SOUND_COUNT ); + add(LLStatViewer::UPLOAD_SOUND, 1); } else if ( LLAssetType::AT_TEXTURE == asset_type ) { - LLViewerStats::getInstance()->incStat( - LLViewerStats::ST_UPLOAD_TEXTURE_COUNT ); + add(LLStatViewer::UPLOAD_TEXTURE, 1); } else if ( LLAssetType::AT_ANIMATION == asset_type ) { - LLViewerStats::getInstance()->incStat( - LLViewerStats::ST_UPLOAD_ANIM_COUNT ); + add(LLStatViewer::ANIMATION_UPLOADS, 1); } } diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h index 3136358b83..3034d00b22 100755 --- a/indra/newview/llviewermenufile.h +++ b/indra/newview/llviewermenufile.h @@ -31,6 +31,8 @@ #include "llassetstorage.h" #include "llinventorytype.h" #include "llfilepicker.h" +#include "llthread.h" +#include <queue> class LLTransactionID; diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index ace16396db..f2a3ffc3dc 100755 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -1181,7 +1181,7 @@ bool check_offer_throttle(const std::string& from_name, bool check_only) } } } - + // Return "true" if we have a preview method for that asset type, "false" otherwise bool check_asset_previewable(const LLAssetType::EType asset_type) { @@ -1529,7 +1529,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& from_string = chatHistory_string = mFromName; LLNotificationFormPtr modified_form(notification_ptr ? new LLNotificationForm(*notification_ptr->getForm()) : new LLNotificationForm()); - + switch(button) { case IOR_SHOW: @@ -1627,7 +1627,7 @@ bool LLOfferInfo::inventory_offer_callback(const LLSD& notification, const LLSD& { opener = discard_agent_offer; } - + if (modified_form != NULL) { modified_form->setElementEnabled("Show", false); @@ -2376,7 +2376,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLNotification::Params params; switch(dialog) - { + { case IM_CONSOLE_AND_CHAT_HISTORY: args["MESSAGE"] = message; payload["from_id"] = from_id; @@ -2628,7 +2628,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLSD args; args["SUBJECT"] = subj; args["MESSAGE"] = mes; - LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).time_stamp(timestamp)); + LLNotifications::instance().add(LLNotification::Params("GroupNotice").substitutions(args).payload(payload).time_stamp(LLDate(timestamp))); } // Also send down the old path for now. @@ -3075,11 +3075,11 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else { - LLNotification::Params params("TeleportOffered"); - params.substitutions = args; - params.payload = payload; - LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); - } + LLNotification::Params params("TeleportOffered"); + params.substitutions = args; + params.payload = payload; + LLPostponedNotification::add<LLPostponedOfferNotification>( params, from_id, false); + } } } @@ -3170,10 +3170,10 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } else { - // do not show a message box, because you're about to be - // teleported. - LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0); - } + // do not show a message box, because you're about to be + // teleported. + LLNotifications::instance().forceResponse(LLNotification::Params("TeleportOffered").payload(payload), 0); + } } break; @@ -4129,7 +4129,7 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**) { LLTracker::stopTracking(NULL); } - else if ( is_teleport && !gAgent.getTeleportKeepsLookAt() ) + else if ( is_teleport && !gAgent.getTeleportKeepsLookAt() && look_at.isExactlyZero()) { //look at the beacon LLVector3 global_agent_pos = agent_pos; @@ -4340,7 +4340,7 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) msg_number += 1; if (head_rot_chg < THRESHOLD_HEAD_ROT_QDOT) { - //LL_INFOS("Messaging") << "head rot " << head_rotation << LL_ENDL; + //LL_INFOS("Messaging") << " head rot " << head_rotation << LL_ENDL; LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", head_rot_chg " << head_rot_chg << LL_ENDL; } if (cam_rot_chg.magVec() > ROTATION_THRESHOLD) @@ -4359,7 +4359,7 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) { LL_INFOS("Messaging") << "msg " << msg_number << ", frame " << LLFrameTimer::getFrameCount() << ", dcf = " << control_flag_change << LL_ENDL; } -*/ + */ duplicate_count = 0; } @@ -4480,18 +4480,18 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) // *TODO: Remove this dependency, or figure out a better way to handle // this hack. -extern U32 gObjectBits; +extern LLUnit<LLUnits::Bits, U32> gObjectData; void process_object_update(LLMessageSystem *mesgsys, void **user_data) { // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveCompressedSize(); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveSize(); } // Update the object... @@ -4503,11 +4503,11 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveCompressedSize(); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveSize(); } // Update the object... @@ -4519,11 +4519,11 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) // Update the data counters if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveCompressedSize(); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveSize(); } // Update the object... @@ -4535,11 +4535,11 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_ { if (mesgsys->getReceiveCompressedSize()) { - gObjectBits += mesgsys->getReceiveCompressedSize() * 8; + gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveCompressedSize(); } else { - gObjectBits += mesgsys->getReceiveSize() * 8; + gObjectData += (LLUnit<LLUnits::Bytes, U32>)mesgsys->getReceiveSize(); } gObjectList.processCompressedObjectUpdate(mesgsys, user_data, OUT_TERSE_IMPROVED); @@ -4547,30 +4547,42 @@ void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_ static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Kill Objects"); +const U32 KILLOBJECT_DELETE_OPCODE = 0; + void process_kill_object(LLMessageSystem *mesgsys, void **user_data) { LLFastTimer t(FTM_PROCESS_OBJECTS); LLUUID id; - U32 local_id; - S32 i; - S32 num_objects; - num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); + U32 ip = mesgsys->getSenderIP(); + U32 port = mesgsys->getSenderPort(); + LLViewerRegion* regionp = NULL; + { + LLHost host(ip, port); + regionp = LLWorld::getInstance()->getRegion(host); + } - for (i = 0; i < num_objects; i++) + bool delete_object = false; + S32 num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); + for (S32 i = 0; i < num_objects; ++i) { + U32 local_id; mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); + if (local_id == KILLOBJECT_DELETE_OPCODE) + { + // This local_id is invalid, but was sent by the server to flag + // all subsequent local_id's as objects that were actually deleted + // rather than unsubscribed from interestlist. + delete_object = true; + continue; + } - LLViewerObjectList::getUUIDFromLocal(id, - local_id, - gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); + LLViewerObjectList::getUUIDFromLocal(id, local_id, ip, port); if (id == LLUUID::null) { LL_DEBUGS("Messaging") << "Unknown kill for local " << local_id << LL_ENDL; - gObjectList.mNumUnknownKills++; continue; } else @@ -4578,9 +4590,12 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data) LL_DEBUGS("Messaging") << "Kill message for local " << local_id << LL_ENDL; } - // ...don't kill the avatar - if (!(id == gAgentID)) + if (id == gAgentID) { + // never kill our avatar + continue; + } + LLViewerObject *objectp = gObjectList.findObject(id); if (objectp) { @@ -4594,18 +4609,16 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data) // Do the kill gObjectList.killObject(objectp); } - else + + if(delete_object) { - LL_WARNS("Messaging") << "Object in UUID lookup, but not on object list in kill!" << LL_ENDL; - gObjectList.mNumUnknownKills++; - } + regionp->killCacheEntry(local_id); } // We should remove the object from selection after it is marked dead by gObjectList to make LLToolGrab, // which is using the object, release the mouse capture correctly when the object dies. // See LLToolGrab::handleHoverActive() and LLToolGrab::handleHoverNonPhysical(). LLSelectMgr::getInstance()->removeObjectFromSelections(id); - } } @@ -4817,145 +4830,18 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data) F32 stat_value; msg->getU32("Stat", "StatID", stat_id, i); msg->getF32("Stat", "StatValue", stat_value, i); - switch (stat_id) + LLStatViewer::SimMeasurementSampler* measurementp = LLStatViewer::SimMeasurementSampler::getInstance((ESimStatID)stat_id); + + if (measurementp ) { - case LL_SIM_STAT_TIME_DILATION: - LLViewerStats::getInstance()->mSimTimeDilation.addValue(stat_value); - break; - case LL_SIM_STAT_FPS: - LLViewerStats::getInstance()->mSimFPS.addValue(stat_value); - break; - case LL_SIM_STAT_PHYSFPS: - LLViewerStats::getInstance()->mSimPhysicsFPS.addValue(stat_value); - break; - case LL_SIM_STAT_AGENTUPS: - LLViewerStats::getInstance()->mSimAgentUPS.addValue(stat_value); - break; - case LL_SIM_STAT_FRAMEMS: - LLViewerStats::getInstance()->mSimFrameMsec.addValue(stat_value); - break; - case LL_SIM_STAT_NETMS: - LLViewerStats::getInstance()->mSimNetMsec.addValue(stat_value); - break; - case LL_SIM_STAT_SIMOTHERMS: - LLViewerStats::getInstance()->mSimSimOtherMsec.addValue(stat_value); - break; - case LL_SIM_STAT_SIMPHYSICSMS: - LLViewerStats::getInstance()->mSimSimPhysicsMsec.addValue(stat_value); - break; - case LL_SIM_STAT_AGENTMS: - LLViewerStats::getInstance()->mSimAgentMsec.addValue(stat_value); - break; - case LL_SIM_STAT_IMAGESMS: - LLViewerStats::getInstance()->mSimImagesMsec.addValue(stat_value); - break; - case LL_SIM_STAT_SCRIPTMS: - LLViewerStats::getInstance()->mSimScriptMsec.addValue(stat_value); - break; - case LL_SIM_STAT_NUMTASKS: - LLViewerStats::getInstance()->mSimObjects.addValue(stat_value); - break; - case LL_SIM_STAT_NUMTASKSACTIVE: - LLViewerStats::getInstance()->mSimActiveObjects.addValue(stat_value); - break; - case LL_SIM_STAT_NUMAGENTMAIN: - LLViewerStats::getInstance()->mSimMainAgents.addValue(stat_value); - break; - case LL_SIM_STAT_NUMAGENTCHILD: - LLViewerStats::getInstance()->mSimChildAgents.addValue(stat_value); - break; - case LL_SIM_STAT_NUMSCRIPTSACTIVE: - LLViewerStats::getInstance()->mSimActiveScripts.addValue(stat_value); - break; - case LL_SIM_STAT_SCRIPT_EPS: - LLViewerStats::getInstance()->mSimScriptEPS.addValue(stat_value); - break; - case LL_SIM_STAT_INPPS: - LLViewerStats::getInstance()->mSimInPPS.addValue(stat_value); - break; - case LL_SIM_STAT_OUTPPS: - LLViewerStats::getInstance()->mSimOutPPS.addValue(stat_value); - break; - case LL_SIM_STAT_PENDING_DOWNLOADS: - LLViewerStats::getInstance()->mSimPendingDownloads.addValue(stat_value); - break; - case LL_SIM_STAT_PENDING_UPLOADS: - LLViewerStats::getInstance()->mSimPendingUploads.addValue(stat_value); - break; - case LL_SIM_STAT_PENDING_LOCAL_UPLOADS: - LLViewerStats::getInstance()->mSimPendingLocalUploads.addValue(stat_value); - break; - case LL_SIM_STAT_TOTAL_UNACKED_BYTES: - LLViewerStats::getInstance()->mSimTotalUnackedBytes.addValue(stat_value / 1024.f); - break; - case LL_SIM_STAT_PHYSICS_PINNED_TASKS: - LLViewerStats::getInstance()->mPhysicsPinnedTasks.addValue(stat_value); - break; - case LL_SIM_STAT_PHYSICS_LOD_TASKS: - LLViewerStats::getInstance()->mPhysicsLODTasks.addValue(stat_value); - break; - case LL_SIM_STAT_SIMPHYSICSSTEPMS: - LLViewerStats::getInstance()->mSimSimPhysicsStepMsec.addValue(stat_value); - break; - case LL_SIM_STAT_SIMPHYSICSSHAPEMS: - LLViewerStats::getInstance()->mSimSimPhysicsShapeUpdateMsec.addValue(stat_value); - break; - case LL_SIM_STAT_SIMPHYSICSOTHERMS: - LLViewerStats::getInstance()->mSimSimPhysicsOtherMsec.addValue(stat_value); - break; - case LL_SIM_STAT_SIMPHYSICSMEMORY: - LLViewerStats::getInstance()->mPhysicsMemoryAllocated.addValue(stat_value); - break; - case LL_SIM_STAT_SIMSPARETIME: - LLViewerStats::getInstance()->mSimSpareMsec.addValue(stat_value); - break; - case LL_SIM_STAT_SIMSLEEPTIME: - LLViewerStats::getInstance()->mSimSleepMsec.addValue(stat_value); - break; - case LL_SIM_STAT_IOPUMPTIME: - LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value); - break; - case LL_SIM_STAT_PCTSCRIPTSRUN: - LLViewerStats::getInstance()->mSimPctScriptsRun.addValue(stat_value); - break; - case LL_SIM_STAT_SIMAISTEPTIMEMS: - LLViewerStats::getInstance()->mSimSimAIStepMsec.addValue(stat_value); - break; - case LL_SIM_STAT_SKIPPEDAISILSTEPS_PS: - LLViewerStats::getInstance()->mSimSimSkippedSilhouetteSteps.addValue(stat_value); - break; - case LL_SIM_STAT_PCTSTEPPEDCHARACTERS: - LLViewerStats::getInstance()->mSimSimPctSteppedCharacters.addValue(stat_value); - break; - default: - // Used to be a commented out warning. - LL_DEBUGS("Messaging") << "Unknown stat id" << stat_id << LL_ENDL; - break; + measurementp->sample(stat_value); + } + else + { + llwarns << "Unknown sim stat identifier: " << stat_id << llendl; } } - /* - msg->getF32Fast(_PREHASH_Statistics, _PREHASH_PhysicsTimeDilation, time_dilation); - LLViewerStats::getInstance()->mSimTDStat.addValue(time_dilation); - - // Process information - // { CpuUsage F32 } - // { SimMemTotal F32 } - // { SimMemRSS F32 } - // { ProcessUptime F32 } - F32 cpu_usage; - F32 sim_mem_total; - F32 sim_mem_rss; - F32 process_uptime; - msg->getF32Fast(_PREHASH_Statistics, _PREHASH_CpuUsage, cpu_usage); - msg->getF32Fast(_PREHASH_Statistics, _PREHASH_SimMemTotal, sim_mem_total); - msg->getF32Fast(_PREHASH_Statistics, _PREHASH_SimMemRSS, sim_mem_rss); - msg->getF32Fast(_PREHASH_Statistics, _PREHASH_ProcessUptime, process_uptime); - LLViewerStats::getInstance()->mSimCPUUsageStat.addValue(cpu_usage); - LLViewerStats::getInstance()->mSimMemTotalStat.addValue(sim_mem_total); - LLViewerStats::getInstance()->mSimMemRSSStat.addValue(sim_mem_rss); - */ - // // Various hacks that aren't statistics, but are being handled here. // @@ -5864,7 +5750,7 @@ bool handle_teleport_access_blocked(LLSD& llsdBlock) maturityLevelNotification = LLNotificationsUtil::add(notificationID+"_PreferencesOutOfSync", llsdBlock, llsdBlock, handle_prompt_for_maturity_level_change_callback); returnValue = true; } - } + } if ((maturityLevelNotification == NULL) || maturityLevelNotification->isIgnored()) { @@ -6010,7 +5896,7 @@ void process_alert_core(const std::string& message, BOOL modal) // HACK -- handle callbacks for specific alerts. It also is localized in notifications.xml if ( message == "You died and have been teleported to your home location") { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_KILLED_COUNT); + add(LLStatViewer::KILLED, 1); } else if( message == "Home position set." ) { @@ -6030,8 +5916,8 @@ void process_alert_core(const std::string& message, BOOL modal) std::string alert_name(message.substr(ALERT_PREFIX.length())); if (!handle_special_alerts(alert_name)) { - LLNotificationsUtil::add(alert_name); - } + LLNotificationsUtil::add(alert_name); + } } else if (message.find(NOTIFY_PREFIX) == 0) { @@ -6484,7 +6370,7 @@ void process_script_question(LLMessageSystem *msg, void **user_data) args["DOWNLOADURL"] = LLTrans::getString("ViewerDownloadURL"); LLNotificationsUtil::add("UnknownScriptQuestion",args,payload); } - + if (known_questions) { LLSD payload; @@ -7471,8 +7357,6 @@ void onCovenantLoadComplete(LLVFS *vfs, } else { - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); - if( LL_ERR_ASSET_REQUEST_NOT_IN_DATABASE == status || LL_ERR_FILE_EMPTY == status) { diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 064e96e394..9e6d8e78d1 100755 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -39,6 +39,7 @@ #include "llfloaterreg.h" #include "llfontgl.h" #include "llframetimer.h" +#include "llhudicon.h" #include "llinventory.h" #include "llinventorydefines.h" #include "llmaterialtable.h" @@ -100,6 +101,7 @@ #include "lltrans.h" #include "llsdutil.h" #include "llmediaentry.h" +#include "llvocache.h" //#define DEBUG_UPDATE_TYPE @@ -112,6 +114,9 @@ BOOL LLViewerObject::sMapDebug = TRUE; LLColor4 LLViewerObject::sEditSelectColor( 1.0f, 1.f, 0.f, 0.3f); // Edit OK LLColor4 LLViewerObject::sNoEditSelectColor( 1.0f, 0.f, 0.f, 0.3f); // Can't edit S32 LLViewerObject::sAxisArrowLength(50); +LLTrace::MemStatHandle LLViewerObject::sMemStat("LLViewerObject"); + + BOOL LLViewerObject::sPulseEnabled(FALSE); BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE @@ -119,6 +124,7 @@ BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE 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 +std::map<std::string, U32> LLViewerObject::sObjectDataMap; static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object"); @@ -481,6 +487,8 @@ void LLViewerObject::initVOClasses() LLVOGrass::initClass(); LLVOWater::initClass(); LLVOVolume::initClass(); + + initObjectDataMap(); } void LLViewerObject::cleanupVOClasses() @@ -490,6 +498,118 @@ void LLViewerObject::cleanupVOClasses() LLVOTree::cleanupClass(); LLVOAvatar::cleanupClass(); LLVOVolume::cleanupClass(); + + sObjectDataMap.clear(); +} + +//object data map for compressed && !OUT_TERSE_IMPROVED +//static +void LLViewerObject::initObjectDataMap() +{ + U32 count = 0; + + sObjectDataMap["ID"] = count; //full id //LLUUID + count += sizeof(LLUUID); + + sObjectDataMap["LocalID"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["PCode"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["State"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["CRC"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["Material"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["ClickAction"] = count; //U8 + count += sizeof(U8); + + sObjectDataMap["Scale"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["Pos"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["Rot"] = count; //LLVector3 + count += sizeof(LLVector3); + + sObjectDataMap["SpecialCode"] = count; //U32 + count += sizeof(U32); + + sObjectDataMap["Owner"] = count; //LLUUID + count += sizeof(LLUUID); + + sObjectDataMap["Omega"] = count; //LLVector3, when SpecialCode & 0x80 is set + count += sizeof(LLVector3); + + //ParentID is after Omega if there is Omega, otherwise is after Owner + sObjectDataMap["ParentID"] = count;//U32, when SpecialCode & 0x20 is set + count += sizeof(U32); + + //------- + //The rest items are not included here + //------- +} + +//static +void LLViewerObject::unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackVector3(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackUUID(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackU32(value, name.c_str()); + dp->reset(); +} + +//static +void LLViewerObject::unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name) +{ + dp->shift(sObjectDataMap[name]); + dp->unpackU8(value, name.c_str()); + dp->reset(); +} + +//static +U32 LLViewerObject::unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id) +{ + dp->shift(sObjectDataMap["SpecialCode"]); + U32 value; + dp->unpackU32(value, "SpecialCode"); + + parent_id = 0; + if(value & 0x20) + { + S32 offset = sObjectDataMap["ParentID"]; + if(!(value & 0x80)) + { + offset -= sizeof(LLVector3); + } + + dp->shift(offset); + dp->unpackU32(parent_id, "ParentID"); + } + dp->reset(); + + return parent_id; } // Replaces all name value pairs with data from \n delimited list @@ -870,6 +990,29 @@ U32 LLViewerObject::checkMediaURL(const std::string &media_url) return retval; } +//extract spatial information from object update message +//return parent_id +//static +U32 LLViewerObject::extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot) +{ + U32 parent_id = 0; + LLViewerObject::unpackParentID(dp, parent_id); + if(parent_id > 0) + { + //is a child, no need to decode further. + return parent_id; + } + + LLViewerObject::unpackVector3(dp, scale, "Scale"); + LLViewerObject::unpackVector3(dp, pos, "Pos"); + + LLVector3 vec; + LLViewerObject::unpackVector3(dp, vec, "Rot"); + rot.unpackFromVector3(vec); + + return parent_id; +} + U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -886,10 +1029,11 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, } // Coordinates of objects on simulators are region-local. - U64 region_handle; - mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); + U64 region_handle = 0; + if(mesgsys != NULL) { + mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); if(regionp != mRegionp && regionp && mRegionp)//region cross { @@ -915,11 +1059,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, return retval; } + 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; 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. @@ -1692,13 +1839,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Preload these five flags for every object. // Finer shades require the object to be selected, and the selection manager // stores the extended permission info. - U32 flags; - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); - // keep local flags and overwrite remote-controlled flags - mFlags = (mFlags & FLAGS_LOCAL) | flags; - - // ...new objects that should come in selected need to be added to the selected list - mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + if(mesgsys != NULL) + { + U32 flags; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); + loadFlags(flags); + } } break; @@ -1726,10 +1872,21 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, { // No parent now, new parent in message -> attach to that parent if possible LLUUID parent_uuid; + + if(mesgsys != NULL) + { LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, mesgsys->getSenderIP(), mesgsys->getSenderPort()); + } + else + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + mRegionp->getHost().getAddress(), + mRegionp->getHost().getPort()); + } LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid); @@ -1805,9 +1962,18 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // //parent_id - U32 ip = mesgsys->getSenderIP(); - U32 port = mesgsys->getSenderPort(); + U32 ip, port; + if(mesgsys != NULL) + { + ip = mesgsys->getSenderIP(); + port = mesgsys->getSenderPort(); + } + else + { + ip = mRegionp->getHost().getAddress(); + port = mRegionp->getHost().getPort(); + } gObjectList.orphanize(this, parent_id, ip, port); // Hide particles, icon and HUD @@ -1845,10 +2011,21 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, else { LLUUID parent_uuid; + + if(mesgsys != NULL) + { LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, gMessageSystem->getSenderIP(), gMessageSystem->getSenderPort()); + } + else + { + LLViewerObjectList::getUUIDFromLocal(parent_uuid, + parent_id, + mRegionp->getHost().getAddress(), + mRegionp->getHost().getPort()); + } sent_parentp = gObjectList.findObject(parent_uuid); if (isAvatar()) @@ -1869,8 +2046,18 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // // Switching parents, but we don't know the new parent. // - U32 ip = mesgsys->getSenderIP(); - U32 port = mesgsys->getSenderPort(); + U32 ip, port; + + if(mesgsys != NULL) + { + ip = mesgsys->getSenderIP(); + port = mesgsys->getSenderPort(); + } + else + { + ip = mRegionp->getHost().getAddress(); + port = mRegionp->getHost().getPort(); + } // We're an orphan, flag things appropriately. gObjectList.orphanize(this, parent_id, ip, port); @@ -1954,7 +2141,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, new_rot.normQuat(); - if (sPingInterpolate) + if (sPingInterpolate && mesgsys != NULL) { LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender()); if (cdp) @@ -1977,6 +2164,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // If we're going to skip this message, why are we // doing all the parenting, etc above? + if(mesgsys != NULL) + { U32 packet_id = mesgsys->getCurrentRecvPacketID(); if (packet_id < mLatestRecvPacketID && mLatestRecvPacketID - packet_id < 65536) @@ -1984,8 +2173,8 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, //skip application of this message, it's old return retval; } - mLatestRecvPacketID = packet_id; + } // Set the change flags for scale if (new_scale != getScale()) @@ -2033,7 +2222,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // If we're snapping the position by more than 0.5m, update LLViewerStats::mAgentPositionSnaps if ( asAvatar() && asAvatar()->isSelf() && (mag_sqr > 0.25f) ) { - LLViewerStats::getInstance()->mAgentPositionSnaps.push( diff.length() ); + record(LLStatViewer::AGENT_POSITION_SNAP, LLTrace::Meters(diff.length())); } } @@ -2156,7 +2345,21 @@ BOOL LLViewerObject::isActive() const return TRUE; } +//load flags from cache or from message +void LLViewerObject::loadFlags(U32 flags) +{ + if(flags == (U32)(-1)) + { + return; //invalid + } + // keep local flags and overwrite remote-controlled flags + mFlags = (mFlags & FLAGS_LOCAL) | flags; + + // ...new objects that should come in selected need to be added to the selected list + mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); + return; +} void LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 316dbce7d0..41a559c19d 100755 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -30,8 +30,7 @@ #include <map> #include "llassetstorage.h" -#include "lldarrayptr.h" -#include "llhudicon.h" +//#include "llhudicon.h" #include "llinventory.h" #include "llrefcount.h" #include "llprimitive.h" @@ -43,33 +42,30 @@ #include "v3math.h" #include "llvertexbuffer.h" #include "llbbox.h" -#include "llbbox.h" class LLAgent; // TODO: Get rid of this. class LLAudioSource; class LLAudioSourceVO; -class LLDataPacker; class LLColor4; -class LLFrameTimer; +class LLDataPacker; +class LLDataPackerBinaryBuffer; class LLDrawable; -class LLHost; class LLHUDText; -class LLWorld; -class LLNameValue; -class LLNetMap; +class LLHost; class LLMessageSystem; +class LLNameValue; class LLPartSysData; -class LLPrimitive; class LLPipeline; class LLTextureEntry; -class LLViewerTexture; +class LLVOAvatar; +class LLVOInventoryListener; class LLViewerInventoryItem; class LLViewerObject; +class LLViewerObjectMedia; class LLViewerPartSourceScript; class LLViewerRegion; -class LLViewerObjectMedia; -class LLVOInventoryListener; -class LLVOAvatar; +class LLViewerTexture; +class LLWorld; typedef enum e_object_update_type { @@ -107,7 +103,11 @@ struct PotentialReturnableObject //============================================================================ -class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate +class LLViewerObject +: public LLPrimitive, + public LLRefCount, + public LLGLUpdate, + public LLTrace::MemTrackable<LLViewerObject> { protected: ~LLViewerObject(); // use unref() @@ -157,6 +157,7 @@ public: INVALID_UPDATE = 0x80000000 }; + static U32 extractSpatialExtents(LLDataPackerBinaryBuffer *dp, LLVector3& pos, LLVector3& scale, LLQuaternion& rot); virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -505,6 +506,7 @@ public: virtual void updateRegion(LLViewerRegion *regionp); void updateFlags(BOOL physics_changed = FALSE); + void loadFlags(U32 flags); //load flags from cache or from message BOOL setFlags(U32 flag, BOOL state); BOOL setFlagsWithoutUpdate(U32 flag, BOOL state); void setPhysicsShapeType(U8 type); @@ -535,6 +537,13 @@ public: friend class LLViewerMediaList; public: + static void unpackVector3(LLDataPackerBinaryBuffer* dp, LLVector3& value, std::string name); + static void unpackUUID(LLDataPackerBinaryBuffer* dp, LLUUID& value, std::string name); + static void unpackU32(LLDataPackerBinaryBuffer* dp, U32& value, std::string name); + static void unpackU8(LLDataPackerBinaryBuffer* dp, U8& value, std::string name); + static U32 unpackParentID(LLDataPackerBinaryBuffer* dp, U32& parent_id); + +public: //counter-translation void resetChildrenPosition(const LLVector3& offset, BOOL simplified = FALSE) ; //counter-rotation @@ -557,6 +566,8 @@ private: // Motion prediction between updates void interpolateLinearMotion(const F64 & time, const F32 & dt); + static void initObjectDataMap(); + public: // // Viewer-side only types - use the LL_PCODE_APP mask. @@ -605,6 +616,7 @@ private: // Grabbed from UPDATE_FLAGS U32 mFlags; + static std::map<std::string, U32> sObjectDataMap; public: // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties U8 mPhysicsShapeType; @@ -628,9 +640,10 @@ public: // TODO: Make all this stuff private. JC LLPointer<LLHUDText> mText; - LLPointer<LLHUDIcon> mIcon; + LLPointer<class LLHUDIcon> mIcon; static BOOL sUseSharedDrawables; + static LLTrace::MemStatHandle sMemStat; protected: // delete an item in the inventory, but don't tell the @@ -666,8 +679,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 @@ -746,6 +757,7 @@ protected: static S32 sAxisArrowLength; + // These two caches are only correct for non-parented objects right now! mutable LLVector3 mPositionRegion; mutable LLVector3 mPositionAgent; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index caacf26cb3..546a7acfc6 100755 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -47,6 +47,7 @@ #include "lltooltip.h" #include "llworld.h" #include "llstring.h" +#include "llhudicon.h" #include "llhudnametag.h" #include "lldrawable.h" #include "llflexibleobject.h" @@ -76,6 +77,7 @@ #include "object_flags.h" #include "llappviewer.h" +#include "llvocache.h" extern F32 gMinObjectDistance; extern BOOL gAnimateTextures; @@ -93,7 +95,7 @@ extern LLPipeline gPipeline; U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check. std::map<U64, U32> LLViewerObjectList::sIPAndPortToIndex; std::map<U64, LLUUID> LLViewerObjectList::sIndexAndLocalIDToUUID; -LLStat LLViewerObjectList::sCacheHitRate("object_cache_hits", 128); +LLTrace::SampleStatHandle<> LLViewerObjectList::sCacheHitRate("object_cache_hits"); LLViewerObjectList::LLViewerObjectList() { @@ -106,7 +108,6 @@ LLViewerObjectList::LLViewerObjectList() mNumNewObjects = 0; mWasPaused = FALSE; mNumDeadObjectUpdates = 0; - mNumUnknownKills = 0; mNumUnknownUpdates = 0; } @@ -228,9 +229,15 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, U32 i, const EObjectUpdateType update_type, LLDataPacker* dpp, - BOOL just_created) + bool just_created, + bool from_cache) { - LLMessageSystem* msg = gMessageSystem; + LLMessageSystem* msg = NULL; + + if(!from_cache) + { + msg = gMessageSystem; + } // ignore returned flags objectp->processUpdateMessage(msg, user_data, i, update_type, dpp); @@ -254,7 +261,18 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, // RN: this must be called after we have a drawable // (from gPipeline.addObject) // so that the drawable parent is set properly - findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort()); + if(msg != NULL) + { + findOrphans(objectp, msg->getSenderIP(), msg->getSenderPort()); + } + else + { + LLViewerRegion* regionp = objectp->getRegion(); + if(regionp != NULL) + { + findOrphans(objectp, regionp->getHost().getAddress(), regionp->getHost().getPort()); + } + } // If we're just wandering around, don't create new objects selected. if (just_created @@ -277,10 +295,89 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, static LLFastTimer::DeclareTimer FTM_PROCESS_OBJECTS("Process Objects"); +LLViewerObject* LLViewerObjectList::processObjectUpdateFromCache(LLVOCacheEntry* entry, LLViewerRegion* regionp) +{ + LLDataPacker *cached_dpp = entry->getDP(); + + if (!cached_dpp) + { + return NULL; //nothing cached. + } + + LLViewerObject *objectp; + U32 local_id; + LLPCode pcode = 0; + LLUUID fullid; + LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance(); + + // Cache Hit. + cached_dpp->reset(); + cached_dpp->unpackUUID(fullid, "ID"); + cached_dpp->unpackU32(local_id, "LocalID"); + cached_dpp->unpackU8(pcode, "PCode"); + + objectp = findObject(fullid); + + if (objectp) + { + if(!objectp->isDead() && (objectp->mLocalID != entry->getLocalID() || + objectp->getRegion() != regionp)) + { + removeFromLocalIDTable(objectp); + setUUIDAndLocal(fullid, entry->getLocalID(), + regionp->getHost().getAddress(), + regionp->getHost().getPort()); + + if (objectp->mLocalID != entry->getLocalID()) + { // Update local ID in object with the one sent from the region + objectp->mLocalID = entry->getLocalID(); + } + + if (objectp->getRegion() != regionp) + { // Object changed region, so update it + objectp->updateRegion(regionp); // for LLVOAvatar + } + } + else + { + return objectp; //already loaded. + } + } + + bool justCreated = false; + if (!objectp) + { + objectp = createObjectFromCache(pcode, regionp, fullid, entry->getLocalID()); + + if (!objectp) + { + llinfos << "createObject failure for object: " << fullid << llendl; + recorder.objectUpdateFailure(entry->getLocalID(), OUT_FULL_CACHED, 0); + return NULL; + } + justCreated = true; + mNumNewObjects++; + sample(sCacheHitRate, 100.f); + } + + if (objectp->isDead()) + { + llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl; + } + + processUpdateCore(objectp, NULL, 0, OUT_FULL_CACHED, cached_dpp, justCreated, true); + objectp->loadFlags(entry->getUpdateFlags()); //just in case, reload update flags from cache. + + recorder.log(0.2f); + LLVOAvatar::cullAvatarsByPixelArea(); + + return objectp; +} + void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, void **user_data, const EObjectUpdateType update_type, - bool cached, bool compressed) + bool compressed) { LLFastTimer t(FTM_PROCESS_OBJECTS); @@ -298,7 +395,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); // I don't think this case is ever hit. TODO* Test this. - if (!cached && !compressed && update_type != OUT_FULL) + if (!compressed && update_type != OUT_FULL) { //llinfos << "TEST: !cached && !compressed && update_type != OUT_FULL" << llendl; gTerseObjectUpdates += num_objects; @@ -346,7 +443,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, U8 compressed_dpbuffer[2048]; LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048); - LLDataPacker *cached_dpp = NULL; LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance(); for (i = 0; i < num_objects; i++) @@ -355,57 +451,37 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, LLTimer update_timer; BOOL justCreated = FALSE; S32 msg_size = 0; + bool remove_from_cache = false; //remove from object cache if it is a full-update or terse update - if (cached) - { - U32 id; - U32 crc; - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i); - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i); - msg_size += sizeof(U32) * 2; - - // Lookup data packer and add this id to cache miss lists if necessary. - U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; - cached_dpp = regionp->getDP(id, crc, cache_miss_type); - if (cached_dpp) - { - // Cache Hit. - cached_dpp->reset(); - cached_dpp->unpackUUID(fullid, "ID"); - cached_dpp->unpackU32(local_id, "LocalID"); - cached_dpp->unpackU8(pcode, "PCode"); - } - else - { - // Cache Miss. - recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size); - - continue; // no data packer, skip this object - } - } - else if (compressed) + if (compressed) { - S32 uncompressed_length = 2048; + S32 uncompressed_length = 2048; compressed_dp.reset(); - U32 flags = 0; - if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? - { - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); - } - uncompressed_length = mesgsys->getSizeFast(_PREHASH_ObjectData, i, _PREHASH_Data); mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i); compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { - compressed_dp.unpackUUID(fullid, "ID"); - compressed_dp.unpackU32(local_id, "LocalID"); - compressed_dp.unpackU8(pcode, "PCode"); + U32 flags = 0; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); + + if(flags & FLAGS_TEMPORARY_ON_REZ) + { + compressed_dp.unpackUUID(fullid, "ID"); + compressed_dp.unpackU32(local_id, "LocalID"); + compressed_dp.unpackU8(pcode, "PCode"); + } + else //send to object cache + { + regionp->cacheFullUpdate(compressed_dp, flags); + continue; + } } else { + remove_from_cache = true; compressed_dp.unpackU32(local_id, "LocalID"); getUUIDFromLocal(fullid, local_id, @@ -435,6 +511,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } else // OUT_FULL only? { + remove_from_cache = true; mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); msg_size += sizeof(LLUUID); @@ -443,6 +520,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } objectp = findObject(fullid); + if(remove_from_cache) + { + objectp = regionp->forceToRemoveFromCache(local_id, objectp); + } + // This looks like it will break if the local_id of the object doesn't change // upon boundary crossing, but we check for region id matching later... // Reset object local id and region pointer if things have changed @@ -488,9 +570,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, continue; } } - else if (cached) // Cache hit only? - { - } else { if (update_type != OUT_FULL) @@ -521,13 +600,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, recorder.objectUpdateFailure(local_id, update_type, msg_size); continue; } + justCreated = TRUE; mNumNewObjects++; - sCacheHitRate.addValue(cached ? 100.f : 0.f); - } - if (objectp->isDead()) { llwarns << "Dead object " << objectp->mID << " in UUID map 1!" << llendl; @@ -541,17 +618,21 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, objectp->mLocalID = local_id; } processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); + +#if 0 if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { - bCached = true; - LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); - recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size); + U32 flags = 0; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); + + if(!(flags & FLAGS_TEMPORARY_ON_REZ)) + { + bCached = true; + LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp, flags); + recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size); + } } - } - else if (cached) // Cache hit only? - { - objectp->mLocalID = local_id; - processUpdateCore(objectp, user_data, i, update_type, cached_dpp, justCreated); +#endif } else { @@ -575,14 +656,53 @@ void LLViewerObjectList::processCompressedObjectUpdate(LLMessageSystem *mesgsys, void **user_data, const EObjectUpdateType update_type) { - processObjectUpdate(mesgsys, user_data, update_type, false, true); + processObjectUpdate(mesgsys, user_data, update_type, true); } void LLViewerObjectList::processCachedObjectUpdate(LLMessageSystem *mesgsys, void **user_data, const EObjectUpdateType update_type) { - processObjectUpdate(mesgsys, user_data, update_type, true, false); + //processObjectUpdate(mesgsys, user_data, update_type, true, false); + + S32 num_objects = mesgsys->getNumberOfBlocksFast(_PREHASH_ObjectData); + gFullObjectUpdates += num_objects; + + U64 region_handle; + mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); + LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); + if (!regionp) + { + llwarns << "Object update from unknown region! " << region_handle << llendl; + return; + } + + LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance(); + + for (S32 i = 0; i < num_objects; i++) + { + S32 msg_size = 0; + U32 id; + U32 crc; + U32 flags; + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i); + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i); + mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, i); + msg_size += sizeof(U32) * 2; + + // Lookup data packer and add this id to cache miss lists if necessary. + U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; + if(!regionp->probeCache(id, crc, flags, cache_miss_type)) + { + // Cache Miss. + recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size); + + continue; // no data packer, skip this object + } + sample(sCacheHitRate, 100.f); + } + + return; } void LLViewerObjectList::dirtyAllObjectInventory() @@ -853,6 +973,8 @@ private: LLSD mObjectIDs; }; +static LLFastTimer::DeclareTimer FTM_IDLE_COPY("Idle Copy"); + void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) { // Update globals @@ -903,10 +1025,8 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) U32 idle_count = 0; - static LLFastTimer::DeclareTimer idle_copy("Idle Copy"); - { - LLFastTimer t(idle_copy); + LLFastTimer t(FTM_IDLE_COPY); for (std::vector<LLPointer<LLViewerObject> >::iterator active_iter = mActiveObjects.begin(); active_iter != mActiveObjects.end(); active_iter++) @@ -916,9 +1036,9 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) { if (idle_count >= idle_list.size()) { - idle_list.push_back( objectp ); - } - else + idle_list.push_back( objectp ); + } + else { idle_list[idle_count] = objectp; } @@ -1032,10 +1152,10 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) } */ - LLViewerStats::getInstance()->mNumObjectsStat.addValue((S32) mObjects.size()); - LLViewerStats::getInstance()->mNumActiveObjectsStat.addValue(idle_count); - LLViewerStats::getInstance()->mNumSizeCulledStat.addValue(mNumSizeCulled); - LLViewerStats::getInstance()->mNumVisCulledStat.addValue(mNumVisCulled); + sample(LLStatViewer::NUM_OBJECTS, mObjects.size()); + sample(LLStatViewer::NUM_ACTIVE_OBJECTS, idle_count); + sample(LLStatViewer::NUM_SIZE_CULLED, mNumSizeCulled); + sample(LLStatViewer::NUM_VIS_CULLED, mNumVisCulled); } void LLViewerObjectList::fetchObjectCosts() @@ -1248,16 +1368,7 @@ BOOL LLViewerObjectList::killObject(LLViewerObject *objectp) if (objectp) { - if (objectp->isDead()) - { - // This object is already dead. Don't need to do more. - return TRUE; - } - else - { - objectp->markDead(); - } - + objectp->markDead(); // does the right thing if object already dead return TRUE; } @@ -1409,10 +1520,10 @@ void LLViewerObjectList::updateActive(LLViewerObject *objectp) { mActiveObjects.push_back(objectp); objectp->setListIndex(mActiveObjects.size()-1); - objectp->setOnActiveList(TRUE); - } - else - { + objectp->setOnActiveList(TRUE); + } + else + { llassert(idx < mActiveObjects.size()); llassert(mActiveObjects[idx] == objectp); @@ -1541,13 +1652,13 @@ void LLViewerObjectList::shiftObjects(const LLVector3 &offset) { LLFastTimer t(FTM_PIPELINE_SHIFT); - gPipeline.shiftObjects(offset); + gPipeline.shiftObjects(offset); } { LLFastTimer t(FTM_REGION_SHIFT); - LLWorld::getInstance()->shiftRegions(offset); -} + LLWorld::getInstance()->shiftRegions(offset); + } } void LLViewerObjectList::repartitionObjects() @@ -1893,6 +2004,29 @@ LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLVi return objectp; } +LLViewerObject *LLViewerObjectList::createObjectFromCache(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id) +{ + llassert_always(uuid.notNull()); + + LLViewerObject *objectp = LLViewerObject::createObject(uuid, pcode, regionp); + if (!objectp) + { +// llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << llendl; + return NULL; + } + + objectp->mLocalID = local_id; + mUUIDObjectMap[uuid] = objectp; + setUUIDAndLocal(uuid, + local_id, + regionp->getHost().getAddress(), + regionp->getHost().getPort()); + mObjects.push_back(objectp); + + updateActive(objectp); + + return objectp; +} LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id, const LLHost &sender) @@ -1960,9 +2094,7 @@ S32 LLViewerObjectList::findReferences(LLDrawable *drawablep) const void LLViewerObjectList::orphanize(LLViewerObject *childp, U32 parent_id, U32 ip, U32 port) { -#ifdef ORPHAN_SPAM - llinfos << "Orphaning object " << childp->getID() << " with parent " << parent_id << llendl; -#endif + LL_DEBUGS("ORPHANS") << "Orphaning object " << childp->getID() << " with parent " << parent_id << LL_ENDL; // We're an orphan, flag things appropriately. childp->mOrphaned = TRUE; @@ -2015,6 +2147,12 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) return; } + //search object cache to get orphans + if(objectp->getRegion()) + { + objectp->getRegion()->findOrphans(objectp->getLocalID()); + } + // See if we are a parent of an orphan. // Note: This code is fairly inefficient but it should happen very rarely. // It can be sped up if this is somehow a performance issue... @@ -2050,11 +2188,11 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) continue; } + LL_DEBUGS("ORPHANS") << "Reunited parent " << objectp->mID + << " with child " << childp->mID << LL_ENDL; + LL_DEBUGS("ORPHANS") << "Glob: " << objectp->getPositionGlobal() << LL_ENDL; + LL_DEBUGS("ORPHANS") << "Agent: " << objectp->getPositionAgent() << LL_ENDL; #ifdef ORPHAN_SPAM - llinfos << "Reunited parent " << objectp->mID - << " with child " << childp->mID << llendl; - llinfos << "Glob: " << objectp->getPositionGlobal() << llendl; - llinfos << "Agent: " << objectp->getPositionAgent() << llendl; addDebugBeacon(objectp->getPositionAgent(),""); #endif gPipeline.markMoved(objectp->mDrawable); @@ -2142,3 +2280,10 @@ bool LLViewerObjectList::OrphanInfo::operator!=(const OrphanInfo &rhs) const } +LLDebugBeacon::~LLDebugBeacon() +{ + if (mHUDObject.notNull()) + { + mHUDObject->markDead(); + } +} diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 449a4633ff..464554245e 100755 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -31,8 +31,8 @@ #include <set> // common includes -#include "llstat.h" #include "llstring.h" +#include "lltrace.h" // project includes #include "llviewerobject.h" @@ -40,6 +40,7 @@ class LLCamera; class LLNetMap; class LLDebugBeacon; +class LLVOCacheEntry; const U32 CLOSE_BIN_SIZE = 10; const U32 NUM_BINS = 128; @@ -65,6 +66,7 @@ public: inline LLViewerObject *findObject(const LLUUID &id); LLViewerObject *createObjectViewer(const LLPCode pcode, LLViewerRegion *regionp); // Create a viewer-side object + LLViewerObject *createObjectFromCache(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id); LLViewerObject *createObject(const LLPCode pcode, LLViewerRegion *regionp, const LLUUID &uuid, const U32 local_id, const LLHost &sender); @@ -78,8 +80,10 @@ public: void cleanDeadObjects(const BOOL use_timer = TRUE); // Clean up the dead object list. // Simulator and viewer side object updates... - void processUpdateCore(LLViewerObject* objectp, void** data, U32 block, const EObjectUpdateType update_type, LLDataPacker* dpp, BOOL justCreated); - void processObjectUpdate(LLMessageSystem *mesgsys, void **user_data, EObjectUpdateType update_type, bool cached=false, bool compressed=false); + void processUpdateCore(LLViewerObject* objectp, void** data, U32 block, const EObjectUpdateType update_type, + LLDataPacker* dpp, bool justCreated, bool from_cache = false); + LLViewerObject* processObjectUpdateFromCache(LLVOCacheEntry* entry, LLViewerRegion* regionp); + void processObjectUpdate(LLMessageSystem *mesgsys, void **user_data, EObjectUpdateType update_type, bool compressed=false); void processCompressedObjectUpdate(LLMessageSystem *mesgsys, void **user_data, EObjectUpdateType update_type); void processCachedObjectUpdate(LLMessageSystem *mesgsys, void **user_data, EObjectUpdateType update_type); void updateApparentAngles(LLAgent &agent); @@ -188,14 +192,13 @@ public: S32 mNumUnknownUpdates; S32 mNumDeadObjectUpdates; - S32 mNumUnknownKills; S32 mNumDeadObjects; protected: std::vector<U64> mOrphanParents; // LocalID/ip,port of orphaned objects std::vector<OrphanInfo> mOrphanChildren; // UUID's of orphaned objects S32 mNumOrphans; - static LLStat sCacheHitRate; + static LLTrace::SampleStatHandle<> sCacheHitRate; typedef std::vector<LLPointer<LLViewerObject> > vobj_list_t; @@ -234,20 +237,14 @@ protected: class LLDebugBeacon { public: - ~LLDebugBeacon() - { - if (mHUDObject.notNull()) - { - mHUDObject->markDead(); - } - } + ~LLDebugBeacon(); LLVector3 mPositionAgent; std::string mString; LLColor4 mColor; LLColor4 mTextColor; S32 mLineWidth; - LLPointer<LLHUDObject> mHUDObject; + LLPointer<class LLHUDObject> mHUDObject; }; diff --git a/indra/newview/llvieweroctree.cpp b/indra/newview/llvieweroctree.cpp new file mode 100644 index 0000000000..d631985e82 --- /dev/null +++ b/indra/newview/llvieweroctree.cpp @@ -0,0 +1,1459 @@ +/** + * @file llvieweroctree.cpp + * @brief LLViewerOctreeGroup class implementation and supporting functions + * + * $LicenseInfo:firstyear=2003&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 "llviewerprecompiledheaders.h" +#include "llvieweroctree.h" +#include "llviewerregion.h" +#include "pipeline.h" +#include "llviewercontrol.h" +#include "llappviewer.h" +#include "llglslshader.h" +#include "llviewershadermgr.h" + +//----------------------------------------------------------------------------------- +//static variables definitions +//----------------------------------------------------------------------------------- +U32 LLViewerOctreeEntryData::sCurVisible = 0; +BOOL LLViewerOctreeDebug::sInDebug = FALSE; + +//----------------------------------------------------------------------------------- +//some global functions definitions +//----------------------------------------------------------------------------------- +typedef enum +{ + b000 = 0x00, + b001 = 0x01, + b010 = 0x02, + b011 = 0x03, + b100 = 0x04, + b101 = 0x05, + b110 = 0x06, + b111 = 0x07, +} eLoveTheBits; + +//contact Runitai Linden for a copy of the SL object used to write this table +//basically, you give the table a bitmask of the look-at vector to a node and it +//gives you a triangle fan index array +static U16 sOcclusionIndices[] = +{ + //000 + b111, b110, b010, b011, b001, b101, b100, b110, + //001 + b011, b010, b000, b001, b101, b111, b110, b010, + //010 + b101, b100, b110, b111, b011, b001, b000, b100, + //011 + b001, b000, b100, b101, b111, b011, b010, b000, + //100 + b110, b000, b010, b011, b111, b101, b100, b000, + //101 + b010, b100, b000, b001, b011, b111, b110, b100, + //110 + b100, b010, b110, b111, b101, b001, b000, b010, + //111 + b000, b110, b100, b101, b001, b011, b010, b110, +}; + +U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center) +{ + LLVector4a origin; + origin.load3(camera->getOrigin().mV); + + S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7; + + return cypher*8; +} + +U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center) +{ + LLVector4a origin; + origin.load3(camera->getOrigin().mV); + + S32 cypher = center.greaterThan(origin).getGatheredBits() & 0x7; + + return (U8*) (sOcclusionIndices+cypher*8); +} + +//create a vertex buffer for efficiently rendering cubes +LLVertexBuffer* ll_create_cube_vb(U32 type_mask, U32 usage) +{ + LLVertexBuffer* ret = new LLVertexBuffer(type_mask, usage); + + ret->allocateBuffer(8, 64, true); + + LLStrider<LLVector3> pos; + LLStrider<U16> idx; + + ret->getVertexStrider(pos); + ret->getIndexStrider(idx); + + pos[0] = LLVector3(-1,-1,-1); + pos[1] = LLVector3(-1,-1, 1); + pos[2] = LLVector3(-1, 1,-1); + pos[3] = LLVector3(-1, 1, 1); + pos[4] = LLVector3( 1,-1,-1); + pos[5] = LLVector3( 1,-1, 1); + pos[6] = LLVector3( 1, 1,-1); + pos[7] = LLVector3( 1, 1, 1); + + for (U32 i = 0; i < 64; i++) + { + idx[i] = sOcclusionIndices[i]; + } + + ret->flush(); + + return ret; +} + + +#define LL_TRACK_PENDING_OCCLUSION_QUERIES 0 + +const F32 SG_OCCLUSION_FUDGE = 0.25f; +#define SG_DISCARD_TOLERANCE 0.01f + + +S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad) +{ + return AABBSphereIntersectR2(min, max, origin, rad*rad); +} + +S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &r) +{ + F32 d = 0.f; + F32 t; + + if ((min-origin).magVecSquared() < r && + (max-origin).magVecSquared() < r) + { + return 2; + } + + for (U32 i = 0; i < 3; i++) + { + if (origin.mV[i] < min.mV[i]) + { + t = min.mV[i] - origin.mV[i]; + d += t*t; + } + else if (origin.mV[i] > max.mV[i]) + { + t = origin.mV[i] - max.mV[i]; + d += t*t; + } + + if (d > r) + { + return 0; + } + } + + return 1; +} + + +S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad) +{ + return AABBSphereIntersectR2(min, max, origin, rad*rad); +} + +S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &r) +{ + F32 d = 0.f; + F32 t; + + LLVector4a origina; + origina.load3(origin.mV); + + LLVector4a v; + v.setSub(min, origina); + + if (v.dot3(v) < r) + { + v.setSub(max, origina); + if (v.dot3(v) < r) + { + return 2; + } + } + + + for (U32 i = 0; i < 3; i++) + { + if (origin.mV[i] < min[i]) + { + t = min[i] - origin.mV[i]; + d += t*t; + } + else if (origin.mV[i] > max[i]) + { + t = origin.mV[i] - max[i]; + d += t*t; + } + + if (d > r) + { + return 0; + } + } + + return 1; +} + +//----------------------------------------------------------------------------------- +//class LLViewerOctreeEntry definitions +//----------------------------------------------------------------------------------- +LLViewerOctreeEntry::LLViewerOctreeEntry() + : mGroup(NULL), + mBinRadius(0.f), + mBinIndex(-1) +{ + mPositionGroup.clear(); + mExtents[0].clear(); + mExtents[1].clear(); + + for(S32 i = 0; i < NUM_DATA_TYPE; i++) + { + mData[i] = NULL; + } +} + +LLViewerOctreeEntry::~LLViewerOctreeEntry() +{ + llassert(!mGroup); +} + +void LLViewerOctreeEntry::addData(LLViewerOctreeEntryData* data) +{ + //llassert(mData[data->getDataType()] == NULL); + llassert(data != NULL); + + mData[data->getDataType()] = data; +} + +void LLViewerOctreeEntry::removeData(LLViewerOctreeEntryData* data) +{ + //llassert(data->getDataType() != LLVOCACHEENTRY); //can not remove VOCache entry + + if(!mData[data->getDataType()]) + { + return; + } + + mData[data->getDataType()] = NULL; + + if(mGroup != NULL && !mData[LLDRAWABLE]) + { + LLviewerOctreeGroup* group = mGroup; + mGroup = NULL; + group->removeFromGroup(data); + + llassert(mBinIndex == -1); + } +} + +//called by group handleDestruction() ONLY when group is destroyed by octree. +void LLViewerOctreeEntry::nullGroup() +{ + mGroup = NULL; +} + +void LLViewerOctreeEntry::setGroup(LLviewerOctreeGroup* group) +{ + if(mGroup == group) + { + return; + } + + if(mGroup) + { + LLviewerOctreeGroup* group = mGroup; + mGroup = NULL; + group->removeFromGroup(this); + + llassert(mBinIndex == -1); + } + + mGroup = group; +} + +//----------------------------------------------------------------------------------- +//class LLViewerOctreeEntryData definitions +//----------------------------------------------------------------------------------- +LLViewerOctreeEntryData::~LLViewerOctreeEntryData() +{ + if(mEntry) + { + mEntry->removeData(this); + } +} + +LLViewerOctreeEntryData::LLViewerOctreeEntryData(LLViewerOctreeEntry::eEntryDataType_t data_type) + : mDataType(data_type), + mEntry(NULL) +{ +} + +//virtual +void LLViewerOctreeEntryData::setOctreeEntry(LLViewerOctreeEntry* entry) +{ + if(mEntry.notNull()) + { + return; + } + + if(!entry) + { + mEntry = new LLViewerOctreeEntry(); + } + else + { + mEntry = entry; + } + mEntry->addData(this); +} + +void LLViewerOctreeEntryData::setSpatialExtents(const LLVector3& min, const LLVector3& max) +{ + mEntry->mExtents[0].load3(min.mV); + mEntry->mExtents[1].load3(max.mV); +} + +void LLViewerOctreeEntryData::setSpatialExtents(const LLVector4a& min, const LLVector4a& max) +{ + mEntry->mExtents[0] = min; + mEntry->mExtents[1] = max; +} + +void LLViewerOctreeEntryData::setPositionGroup(const LLVector4a& pos) +{ + mEntry->mPositionGroup = pos; +} + +const LLVector4a* LLViewerOctreeEntryData::getSpatialExtents() const +{ + return mEntry->getSpatialExtents(); +} + +//virtual +void LLViewerOctreeEntryData::setGroup(LLviewerOctreeGroup* group) +{ + mEntry->setGroup(group); +} + +void LLViewerOctreeEntryData::shift(const LLVector4a &shift_vector) +{ + mEntry->mExtents[0].add(shift_vector); + mEntry->mExtents[1].add(shift_vector); + mEntry->mPositionGroup.add(shift_vector); +} + +LLviewerOctreeGroup* LLViewerOctreeEntryData::getGroup()const +{ + return mEntry.notNull() ? mEntry->mGroup : NULL; +} + +const LLVector4a& LLViewerOctreeEntryData::getPositionGroup() const +{ + return mEntry->getPositionGroup(); +} + +//virtual +bool LLViewerOctreeEntryData::isVisible() const +{ + if(mEntry) + { + return mEntry->mVisible == sCurVisible; + } + return false; +} + +//virtual +bool LLViewerOctreeEntryData::isRecentlyVisible() const +{ + if(!mEntry) + { + return false; + } + + if(isVisible()) + { + return true; + } + if(getGroup() && getGroup()->isRecentlyVisible()) + { + setVisible(); + return true; + } + + return (sCurVisible - mEntry->mVisible < getMinFrameRange()); +} + +void LLViewerOctreeEntryData::setVisible() const +{ + if(mEntry) + { + mEntry->mVisible = sCurVisible; + } +} + +//----------------------------------------------------------------------------------- +//class LLviewerOctreeGroup definitions +//----------------------------------------------------------------------------------- + +LLviewerOctreeGroup::~LLviewerOctreeGroup() +{ + //empty here +} + +LLviewerOctreeGroup::LLviewerOctreeGroup(OctreeNode* node) : + mOctreeNode(node), + mState(CLEAN) +{ + LLVector4a tmp; + tmp.splat(0.f); + mExtents[0] = mExtents[1] = mObjectBounds[0] = mObjectBounds[0] = mObjectBounds[1] = + mObjectExtents[0] = mObjectExtents[1] = tmp; + + mBounds[0] = node->getCenter(); + mBounds[1] = node->getSize(); + + mOctreeNode->addListener(this); +} + +bool LLviewerOctreeGroup::hasElement(LLViewerOctreeEntryData* data) +{ + if(!data->getEntry()) + { + return false; + } + return std::find(getDataBegin(), getDataEnd(), data->getEntry()) != getDataEnd(); +} + +bool LLviewerOctreeGroup::removeFromGroup(LLViewerOctreeEntryData* data) +{ + return removeFromGroup(data->getEntry()); +} + +bool LLviewerOctreeGroup::removeFromGroup(LLViewerOctreeEntry* entry) +{ + llassert(entry != NULL); + llassert(!entry->getGroup()); + + unbound(); + if (mOctreeNode) + { + if (!mOctreeNode->remove(entry)) + { + OCT_ERRS << "Could not remove LLVOCacheEntry from LLVOCacheOctreeGroup" << llendl; + return false; + } + } + setState(OBJECT_DIRTY); + + return true; +} + +//virtual +void LLviewerOctreeGroup::unbound() +{ + if (isDirty()) + { + return; + } + + setState(DIRTY); + + //all the parent nodes need to rebound this child + if (mOctreeNode) + { + OctreeNode* parent = (OctreeNode*) mOctreeNode->getParent(); + while (parent != NULL) + { + LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) parent->getListener(0); + if (!group || group->isDirty()) + { + return; + } + + group->setState(DIRTY); + parent = (OctreeNode*) parent->getParent(); + } + } +} + +//virtual +void LLviewerOctreeGroup::rebound() +{ + if (!isDirty()) + { + return; + } + + if (mOctreeNode->getChildCount() == 1 && mOctreeNode->getElementCount() == 0) + { + LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) mOctreeNode->getChild(0)->getListener(0); + group->rebound(); + + //copy single child's bounding box + mBounds[0] = group->mBounds[0]; + mBounds[1] = group->mBounds[1]; + mExtents[0] = group->mExtents[0]; + mExtents[1] = group->mExtents[1]; + + group->setState(SKIP_FRUSTUM_CHECK); + } + else if (mOctreeNode->isLeaf()) + { //copy object bounding box if this is a leaf + boundObjects(TRUE, mExtents[0], mExtents[1]); + mBounds[0] = mObjectBounds[0]; + mBounds[1] = mObjectBounds[1]; + } + else + { + LLVector4a& newMin = mExtents[0]; + LLVector4a& newMax = mExtents[1]; + LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) mOctreeNode->getChild(0)->getListener(0); + group->clearState(SKIP_FRUSTUM_CHECK); + group->rebound(); + //initialize to first child + newMin = group->mExtents[0]; + newMax = group->mExtents[1]; + + //first, rebound children + for (U32 i = 1; i < mOctreeNode->getChildCount(); i++) + { + group = (LLviewerOctreeGroup*) mOctreeNode->getChild(i)->getListener(0); + group->clearState(SKIP_FRUSTUM_CHECK); + group->rebound(); + const LLVector4a& max = group->mExtents[1]; + const LLVector4a& min = group->mExtents[0]; + + newMax.setMax(newMax, max); + newMin.setMin(newMin, min); + } + + boundObjects(FALSE, newMin, newMax); + + mBounds[0].setAdd(newMin, newMax); + mBounds[0].mul(0.5f); + mBounds[1].setSub(newMax, newMin); + mBounds[1].mul(0.5f); + } + + clearState(DIRTY); + + return; +} + +//virtual +void LLviewerOctreeGroup::handleInsertion(const TreeNode* node, LLViewerOctreeEntry* obj) +{ + obj->setGroup(this); + unbound(); + setState(OBJECT_DIRTY); +} + +//virtual +void LLviewerOctreeGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* obj) +{ + obj->setGroup(NULL); + unbound(); + setState(OBJECT_DIRTY); +} + +//virtual +void LLviewerOctreeGroup::handleDestruction(const TreeNode* node) +{ + for (OctreeNode::element_iter i = mOctreeNode->getDataBegin(); i != mOctreeNode->getDataEnd(); ++i) + { + LLViewerOctreeEntry* obj = *i; + if (obj && obj->getGroup() == this) + { + obj->nullGroup(); + //obj->setGroup(NULL); + } + } + mOctreeNode = NULL; +} + +//virtual +void LLviewerOctreeGroup::handleStateChange(const TreeNode* node) +{ + //drop bounding box upon state change + if (mOctreeNode != node) + { + mOctreeNode = (OctreeNode*) node; + } + unbound(); +} + +//virtual +void LLviewerOctreeGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) +{ + if (child->getListenerCount() == 0) + { + new LLviewerOctreeGroup(child); + } + else + { + OCT_ERRS << "LLviewerOctreeGroup redundancy detected." << llendl; + } + + unbound(); + + ((LLviewerOctreeGroup*)child->getListener(0))->unbound(); +} + +//virtual +void LLviewerOctreeGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNode* child) +{ + unbound(); +} + +LLviewerOctreeGroup* LLviewerOctreeGroup::getParent() +{ + if (isDead()) + { + return NULL; + } + + if(!mOctreeNode) + { + return NULL; + } + + OctreeNode* parent = mOctreeNode->getOctParent(); + + if (parent) + { + return (LLviewerOctreeGroup*) parent->getListener(0); + } + + return NULL; +} + +//virtual +bool LLviewerOctreeGroup::boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut) +{ + const OctreeNode* node = mOctreeNode; + + if (node->isEmpty()) + { //don't do anything if there are no objects + if (empty && mOctreeNode->getParent()) + { //only root is allowed to be empty + OCT_ERRS << "Empty leaf found in octree." << llendl; + } + return false; + } + + LLVector4a& newMin = mObjectExtents[0]; + LLVector4a& newMax = mObjectExtents[1]; + + if (hasState(OBJECT_DIRTY)) + { //calculate new bounding box + clearState(OBJECT_DIRTY); + + //initialize bounding box to first element + OctreeNode::const_element_iter i = node->getDataBegin(); + LLViewerOctreeEntry* entry = *i; + const LLVector4a* minMax = entry->getSpatialExtents(); + + newMin = minMax[0]; + newMax = minMax[1]; + + for (++i; i != node->getDataEnd(); ++i) + { + entry = *i; + minMax = entry->getSpatialExtents(); + + update_min_max(newMin, newMax, minMax[0]); + update_min_max(newMin, newMax, minMax[1]); + } + + mObjectBounds[0].setAdd(newMin, newMax); + mObjectBounds[0].mul(0.5f); + mObjectBounds[1].setSub(newMax, newMin); + mObjectBounds[1].mul(0.5f); + } + + if (empty) + { + minOut = newMin; + maxOut = newMax; + } + else + { + minOut.setMin(minOut, newMin); + maxOut.setMax(maxOut, newMax); + } + + return TRUE; +} + +//virtual +BOOL LLviewerOctreeGroup::isVisible() const +{ + return mVisible[LLViewerCamera::sCurCameraID] >= LLViewerOctreeEntryData::getCurrentFrame() ? TRUE : FALSE; +} + +//virtual +BOOL LLviewerOctreeGroup::isRecentlyVisible() const +{ + return FALSE; +} + +void LLviewerOctreeGroup::setVisible() +{ + mVisible[LLViewerCamera::sCurCameraID] = LLViewerOctreeEntryData::getCurrentFrame(); +} + +void LLviewerOctreeGroup::checkStates() +{ +#if LL_OCTREE_PARANOIA_CHECK + //LLOctreeStateCheck checker; + //checker.traverse(mOctreeNode); +#endif +} + +//------------------------------------------------------------------------------------------- +//occulsion culling functions and classes +//------------------------------------------------------------------------------------------- +std::set<U32> LLOcclusionCullingGroup::sPendingQueries; +class LLOcclusionQueryPool : public LLGLNamePool +{ +public: + LLOcclusionQueryPool() + { + mCurQuery = 1; + } + +protected: + + std::list<GLuint> mAvailableName; + GLuint mCurQuery; + + virtual GLuint allocateName() + { + GLuint ret = 0; + + if (!mAvailableName.empty()) + { + ret = mAvailableName.front(); + mAvailableName.pop_front(); + } + else + { + ret = mCurQuery++; + } + + return ret; + } + + virtual void releaseName(GLuint name) + { +#if LL_TRACK_PENDING_OCCLUSION_QUERIES + LLSpatialGroup::sPendingQueries.erase(name); +#endif + llassert(std::find(mAvailableName.begin(), mAvailableName.end(), name) == mAvailableName.end()); + mAvailableName.push_back(name); + } +}; + +static LLOcclusionQueryPool sQueryPool; +U32 LLOcclusionCullingGroup::getNewOcclusionQueryObjectName() +{ + return sQueryPool.allocate(); +} + +void LLOcclusionCullingGroup::releaseOcclusionQueryObjectName(GLuint name) +{ + sQueryPool.release(name); +} + +//===================================== +// Occlusion State Set/Clear +//===================================== +class LLSpatialSetOcclusionState : public OctreeTraveler +{ +public: + U32 mState; + LLSpatialSetOcclusionState(U32 state) : mState(state) { } + virtual void visit(const OctreeNode* branch) { ((LLOcclusionCullingGroup*) branch->getListener(0))->setOcclusionState(mState); } +}; + +class LLSpatialSetOcclusionStateDiff : public LLSpatialSetOcclusionState +{ +public: + LLSpatialSetOcclusionStateDiff(U32 state) : LLSpatialSetOcclusionState(state) { } + + virtual void traverse(const OctreeNode* n) + { + LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*) n->getListener(0); + + if (!group->isOcclusionState(mState)) + { + OctreeTraveler::traverse(n); + } + } +}; + + +LLOcclusionCullingGroup::LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctreePartition* part) : + LLviewerOctreeGroup(node), + mSpatialPartition(part) +{ + part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod; + mLODHash = part->mLODSeed; + + OctreeNode* oct_parent = node->getOctParent(); + LLOcclusionCullingGroup* parent = oct_parent ? (LLOcclusionCullingGroup*) oct_parent->getListener(0) : NULL; + + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mOcclusionQuery[i] = 0; + mOcclusionIssued[i] = 0; + mOcclusionState[i] = parent ? SG_STATE_INHERIT_MASK & parent->mOcclusionState[i] : 0; + mVisible[i] = 0; + } +} + +LLOcclusionCullingGroup::~LLOcclusionCullingGroup() +{ + releaseOcclusionQueryObjectNames(); +} + +BOOL LLOcclusionCullingGroup::needsUpdate() +{ + return (LLDrawable::getCurrentFrame() % mSpatialPartition->mLODPeriod == mLODHash) ? TRUE : FALSE; +} + +//virtual +void LLOcclusionCullingGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* child) +{ + if (child->getListenerCount() == 0) + { + new LLOcclusionCullingGroup(child, mSpatialPartition); + } + else + { + OCT_ERRS << "LLOcclusionCullingGroup redundancy detected." << llendl; + } + + unbound(); + + ((LLviewerOctreeGroup*)child->getListener(0))->unbound(); +} + +void LLOcclusionCullingGroup::releaseOcclusionQueryObjectNames() +{ + if (gGLManager.mHasOcclusionQuery) + { + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; ++i) + { + if (mOcclusionQuery[i]) + { + releaseOcclusionQueryObjectName(mOcclusionQuery[i]); + mOcclusionQuery[i] = 0; + } + } + } +} + +void LLOcclusionCullingGroup::setOcclusionState(U32 state, S32 mode) +{ + if (mode > STATE_MODE_SINGLE) + { + if (mode == STATE_MODE_DIFF) + { + LLSpatialSetOcclusionStateDiff setter(state); + setter.traverse(mOctreeNode); + } + else if (mode == STATE_MODE_BRANCH) + { + LLSpatialSetOcclusionState setter(state); + setter.traverse(mOctreeNode); + } + else + { + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mOcclusionState[i] |= state; + + if ((state & DISCARD_QUERY) && mOcclusionQuery[i]) + { + releaseOcclusionQueryObjectName(mOcclusionQuery[i]); + mOcclusionQuery[i] = 0; + } + } + } + } + else + { + mOcclusionState[LLViewerCamera::sCurCameraID] |= state; + if ((state & DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { + releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; + } + } +} + +class LLSpatialClearOcclusionState : public OctreeTraveler +{ +public: + U32 mState; + + LLSpatialClearOcclusionState(U32 state) : mState(state) { } + virtual void visit(const OctreeNode* branch) { ((LLOcclusionCullingGroup*) branch->getListener(0))->clearOcclusionState(mState); } +}; + +class LLSpatialClearOcclusionStateDiff : public LLSpatialClearOcclusionState +{ +public: + LLSpatialClearOcclusionStateDiff(U32 state) : LLSpatialClearOcclusionState(state) { } + + virtual void traverse(const OctreeNode* n) + { + LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*) n->getListener(0); + + if (group->isOcclusionState(mState)) + { + OctreeTraveler::traverse(n); + } + } +}; + +void LLOcclusionCullingGroup::clearOcclusionState(U32 state, S32 mode) +{ + if (mode > STATE_MODE_SINGLE) + { + if (mode == STATE_MODE_DIFF) + { + LLSpatialClearOcclusionStateDiff clearer(state); + clearer.traverse(mOctreeNode); + } + else if (mode == STATE_MODE_BRANCH) + { + LLSpatialClearOcclusionState clearer(state); + clearer.traverse(mOctreeNode); + } + else + { + for (U32 i = 0; i < LLViewerCamera::NUM_CAMERAS; i++) + { + mOcclusionState[i] &= ~state; + } + } + } + else + { + mOcclusionState[LLViewerCamera::sCurCameraID] &= ~state; + } +} + +static LLFastTimer::DeclareTimer FTM_OCCLUSION_READBACK("Readback Occlusion"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_WAIT("Occlusion Wait"); + +BOOL LLOcclusionCullingGroup::earlyFail(LLCamera* camera) +{ + if (camera->getOrigin().isExactlyZero()) + { + return FALSE; + } + + const F32 vel = SG_OCCLUSION_FUDGE*2.f; + LLVector4a fudge; + fudge.splat(vel); + + const LLVector4a* bounds = getBounds(); + const LLVector4a& c = bounds[0]; + LLVector4a r; + r.setAdd(bounds[1], fudge); + + /*if (r.magVecSquared() > 1024.0*1024.0) + { + return TRUE; + }*/ + + LLVector4a e; + e.load3(camera->getOrigin().mV); + + LLVector4a min; + min.setSub(c,r); + LLVector4a max; + max.setAdd(c,r); + + S32 lt = e.lessThan(min).getGatheredBits() & 0x7; + if (lt) + { + return FALSE; + } + + S32 gt = e.greaterThan(max).getGatheredBits() & 0x7; + if (gt) + { + return FALSE; + } + + return TRUE; +} + +void LLOcclusionCullingGroup::checkOcclusion() +{ + if (LLPipeline::sUseOcclusion > 1) + { + LLFastTimer t(FTM_OCCLUSION_READBACK); + LLOcclusionCullingGroup* parent = (LLOcclusionCullingGroup*)getParent(); + if (parent && parent->isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) + { //if the parent has been marked as occluded, the child is implicitly occluded + clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); + } + else if (isOcclusionState(QUERY_PENDING)) + { //otherwise, if a query is pending, read it back + + GLuint available = 0; + if (mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { + glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); + + static LLCachedControl<bool> wait_for_query(gSavedSettings, "RenderSynchronousOcclusion"); + + if (wait_for_query && mOcclusionIssued[LLViewerCamera::sCurCameraID] < gFrameCount) + { //query was issued last frame, wait until it's available + S32 max_loop = 1024; + LLFastTimer t(FTM_OCCLUSION_WAIT); + while (!available && max_loop-- > 0) + { + //do some usefu work while we wait + F32 max_time = llmin(gFrameIntervalSeconds.value()*10.f, 1.f); + LLAppViewer::instance()->updateTextureThreads(max_time); + + glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_AVAILABLE_ARB, &available); + } + } + } + else + { + available = 1; + } + + if (available) + { //result is available, read it back, otherwise wait until next frame + GLuint res = 1; + if (!isOcclusionState(DISCARD_QUERY) && mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { + glGetQueryObjectuivARB(mOcclusionQuery[LLViewerCamera::sCurCameraID], GL_QUERY_RESULT_ARB, &res); +#if LL_TRACK_PENDING_OCCLUSION_QUERIES + sPendingQueries.erase(mOcclusionQuery[LLViewerCamera::sCurCameraID]); +#endif + } + else if (mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { //delete the query to avoid holding onto hundreds of pending queries + releaseOcclusionQueryObjectName(mOcclusionQuery[LLViewerCamera::sCurCameraID]); + mOcclusionQuery[LLViewerCamera::sCurCameraID] = 0; + } + + if (isOcclusionState(DISCARD_QUERY)) + { + res = 2; + } + + if (res > 0) + { + assert_states_valid(this); + clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); + assert_states_valid(this); + } + else + { + assert_states_valid(this); + + setOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); + + assert_states_valid(this); + } + + clearOcclusionState(QUERY_PENDING | DISCARD_QUERY); + } + } + else if (mSpatialPartition->isOcclusionEnabled() && isOcclusionState(LLOcclusionCullingGroup::OCCLUDED)) + { //check occlusion has been issued for occluded node that has not had a query issued + assert_states_valid(this); + clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); + assert_states_valid(this); + } + } +} + +static LLFastTimer::DeclareTimer FTM_PUSH_OCCLUSION_VERTS("Push Occlusion"); +static LLFastTimer::DeclareTimer FTM_SET_OCCLUSION_STATE("Occlusion State"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_EARLY_FAIL("Occlusion Early Fail"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_ALLOCATE("Allocate"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_BUILD("Build"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_BEGIN_QUERY("Begin Query"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_END_QUERY("End Query"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_SET_BUFFER("Set Buffer"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW_WATER("Draw Water"); +static LLFastTimer::DeclareTimer FTM_OCCLUSION_DRAW("Draw"); + +void LLOcclusionCullingGroup::doOcclusion(LLCamera* camera) +{ + if (mSpatialPartition->isOcclusionEnabled() && LLPipeline::sUseOcclusion > 1) + { + // Don't cull hole/edge water, unless we have the GL_ARB_depth_clamp extension + if (earlyFail(camera)) + { + LLFastTimer t(FTM_OCCLUSION_EARLY_FAIL); + setOcclusionState(LLOcclusionCullingGroup::DISCARD_QUERY); + assert_states_valid(this); + clearOcclusionState(LLOcclusionCullingGroup::OCCLUDED, LLOcclusionCullingGroup::STATE_MODE_DIFF); + assert_states_valid(this); + } + else + { + if (!isOcclusionState(QUERY_PENDING) || isOcclusionState(DISCARD_QUERY)) + { + { //no query pending, or previous query to be discarded + LLFastTimer t(FTM_RENDER_OCCLUSION); + + if (!mOcclusionQuery[LLViewerCamera::sCurCameraID]) + { + LLFastTimer t(FTM_OCCLUSION_ALLOCATE); + mOcclusionQuery[LLViewerCamera::sCurCameraID] = getNewOcclusionQueryObjectName(); + } + + // Depth clamp all water to avoid it being culled as a result of being + // behind the far clip plane, and in the case of edge water to avoid + // it being culled while still visible. + bool const use_depth_clamp = gGLManager.mHasDepthClamp && + (mSpatialPartition->mDrawableType == LLDrawPool::POOL_WATER || + mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER); + + LLGLEnable clamp(use_depth_clamp ? GL_DEPTH_CLAMP : 0); + +#if !LL_DARWIN + U32 mode = gGLManager.mHasOcclusionQuery2 ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED_ARB; +#else + U32 mode = GL_SAMPLES_PASSED_ARB; +#endif + +#if LL_TRACK_PENDING_OCCLUSION_QUERIES + sPendingQueries.insert(mOcclusionQuery[LLViewerCamera::sCurCameraID]); +#endif + + { + LLFastTimer t(FTM_PUSH_OCCLUSION_VERTS); + + //store which frame this query was issued on + mOcclusionIssued[LLViewerCamera::sCurCameraID] = gFrameCount; + + { + LLFastTimer t(FTM_OCCLUSION_BEGIN_QUERY); + glBeginQueryARB(mode, mOcclusionQuery[LLViewerCamera::sCurCameraID]); + } + + LLGLSLShader* shader = LLGLSLShader::sCurBoundShaderPtr; + llassert(shader); + + shader->uniform3fv(LLShaderMgr::BOX_CENTER, 1, mBounds[0].getF32ptr()); + shader->uniform3f(LLShaderMgr::BOX_SIZE, mBounds[1][0]+SG_OCCLUSION_FUDGE, + mBounds[1][1]+SG_OCCLUSION_FUDGE, + mBounds[1][2]+SG_OCCLUSION_FUDGE); + + if (!use_depth_clamp && mSpatialPartition->mDrawableType == LLDrawPool::POOL_VOIDWATER) + { + LLFastTimer t(FTM_OCCLUSION_DRAW_WATER); + + LLGLSquashToFarClip squash(glh_get_current_projection(), 1); + if (camera->getOrigin().isExactlyZero()) + { //origin is invalid, draw entire box + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); + } + else + { + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); + } + } + else + { + LLFastTimer t(FTM_OCCLUSION_DRAW); + if (camera->getOrigin().isExactlyZero()) + { //origin is invalid, draw entire box + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, 0); + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, b111*8); + } + else + { + gPipeline.mCubeVB->drawRange(LLRender::TRIANGLE_FAN, 0, 7, 8, get_box_fan_indices(camera, mBounds[0])); + } + } + + + { + LLFastTimer t(FTM_OCCLUSION_END_QUERY); + glEndQueryARB(mode); + } + } + } + + { + LLFastTimer t(FTM_SET_OCCLUSION_STATE); + setOcclusionState(LLOcclusionCullingGroup::QUERY_PENDING); + clearOcclusionState(LLOcclusionCullingGroup::DISCARD_QUERY); + } + } + } + } +} +//------------------------------------------------------------------------------------------- +//end of occulsion culling functions and classes +//------------------------------------------------------------------------------------------- + +//----------------------------------------------------------------------------------- +//class LLViewerOctreePartition definitions +//----------------------------------------------------------------------------------- +LLViewerOctreePartition::LLViewerOctreePartition() : + mRegionp(NULL), + mOcclusionEnabled(TRUE), + mDrawableType(0), + mLODSeed(0), + mLODPeriod(1) +{ + LLVector4a center, size; + center.splat(0.f); + size.splat(1.f); + + mOctree = new OctreeRoot(center,size, NULL); +} + +LLViewerOctreePartition::~LLViewerOctreePartition() +{ + delete mOctree; + mOctree = NULL; +} + +BOOL LLViewerOctreePartition::isOcclusionEnabled() +{ + return mOcclusionEnabled || LLPipeline::sUseOcclusion > 2; +} + +//----------------------------------------------------------------------------------- +//class LLViewerOctreeCull definitions +//----------------------------------------------------------------------------------- + +//virtual +bool LLViewerOctreeCull::earlyFail(LLviewerOctreeGroup* group) +{ + return false; +} + +//virtual +void LLViewerOctreeCull::traverse(const OctreeNode* n) +{ + LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) n->getListener(0); + + if (earlyFail(group)) + { + return; + } + + if (mRes == 2 || + (mRes && group->hasState(LLviewerOctreeGroup::SKIP_FRUSTUM_CHECK))) + { //fully in, just add everything + OctreeTraveler::traverse(n); + } + else + { + mRes = frustumCheck(group); + + if (mRes) + { //at least partially in, run on down + OctreeTraveler::traverse(n); + } + + mRes = 0; + } +} + +//------------------------------------------ +//agent space group culling +S32 LLViewerOctreeCull::AABBInFrustumNoFarClipGroupBounds(const LLviewerOctreeGroup* group) +{ + return mCamera->AABBInFrustumNoFarClip(group->mBounds[0], group->mBounds[1]); +} + +S32 LLViewerOctreeCull::AABBSphereIntersectGroupExtents(const LLviewerOctreeGroup* group) +{ + return AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist); +} + +S32 LLViewerOctreeCull::AABBInFrustumGroupBounds(const LLviewerOctreeGroup* group) +{ + return mCamera->AABBInFrustum(group->mBounds[0], group->mBounds[1]); +} +//------------------------------------------ + +//------------------------------------------ +//agent space object set culling +S32 LLViewerOctreeCull::AABBInFrustumNoFarClipObjectBounds(const LLviewerOctreeGroup* group) +{ + return mCamera->AABBInFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]); +} + +S32 LLViewerOctreeCull::AABBSphereIntersectObjectExtents(const LLviewerOctreeGroup* group) +{ + return AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin(), mCamera->mFrustumCornerDist); +} + +S32 LLViewerOctreeCull::AABBInFrustumObjectBounds(const LLviewerOctreeGroup* group) +{ + return mCamera->AABBInFrustum(group->mObjectBounds[0], group->mObjectBounds[1]); +} +//------------------------------------------ + +//------------------------------------------ +//local regional space group culling +S32 LLViewerOctreeCull::AABBInRegionFrustumNoFarClipGroupBounds(const LLviewerOctreeGroup* group) +{ + return mCamera->AABBInRegionFrustumNoFarClip(group->mBounds[0], group->mBounds[1]); +} + +S32 LLViewerOctreeCull::AABBInRegionFrustumGroupBounds(const LLviewerOctreeGroup* group) +{ + return mCamera->AABBInRegionFrustum(group->mBounds[0], group->mBounds[1]); +} + +S32 LLViewerOctreeCull::AABBRegionSphereIntersectGroupExtents(const LLviewerOctreeGroup* group, const LLVector3& shift) +{ + return AABBSphereIntersect(group->mExtents[0], group->mExtents[1], mCamera->getOrigin() - shift, mCamera->mFrustumCornerDist); +} +//------------------------------------------ + +//------------------------------------------ +//local regional space object culling +S32 LLViewerOctreeCull::AABBInRegionFrustumObjectBounds(const LLviewerOctreeGroup* group) +{ + return mCamera->AABBInRegionFrustum(group->mObjectBounds[0], group->mObjectBounds[1]); +} + +S32 LLViewerOctreeCull::AABBInRegionFrustumNoFarClipObjectBounds(const LLviewerOctreeGroup* group) +{ + return mCamera->AABBInRegionFrustumNoFarClip(group->mObjectBounds[0], group->mObjectBounds[1]); +} + +S32 LLViewerOctreeCull::AABBRegionSphereIntersectObjectExtents(const LLviewerOctreeGroup* group, const LLVector3& shift) +{ + return AABBSphereIntersect(group->mObjectExtents[0], group->mObjectExtents[1], mCamera->getOrigin() - shift, mCamera->mFrustumCornerDist); +} +//------------------------------------------ + +//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; + } + + return true; +} + +//virtual +void LLViewerOctreeCull::preprocess(LLviewerOctreeGroup* group) +{ +} + +//virtual +void LLViewerOctreeCull::processGroup(LLviewerOctreeGroup* group) +{ +} + +//virtual +void LLViewerOctreeCull::visit(const OctreeNode* branch) +{ + LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) branch->getListener(0); + + preprocess(group); + + if (checkObjects(branch, group)) + { + processGroup(group); + } +} + +//-------------------------------------------------------------- +//class LLViewerOctreeDebug +//virtual +void LLViewerOctreeDebug::visit(const OctreeNode* branch) +{ +#if 0 + llinfos << "Node: " << (U32)branch << " # Elements: " << branch->getElementCount() << " # Children: " << branch->getChildCount() << llendl; + for (U32 i = 0; i < branch->getChildCount(); i++) + { + llinfos << "Child " << i << " : " << (U32)branch->getChild(i) << llendl; + } +#endif + LLviewerOctreeGroup* group = (LLviewerOctreeGroup*) branch->getListener(0); + processGroup(group); +} + +//virtual +void LLViewerOctreeDebug::processGroup(LLviewerOctreeGroup* group) +{ +#if 0 + const LLVector4a* vec4 = group->getBounds(); + LLVector3 vec[2]; + vec[0].set(vec4[0].getF32ptr()); + vec[1].set(vec4[1].getF32ptr()); + llinfos << "Bounds: " << vec[0] << " : " << vec[1] << llendl; + + vec4 = group->getExtents(); + vec[0].set(vec4[0].getF32ptr()); + vec[1].set(vec4[1].getF32ptr()); + llinfos << "Extents: " << vec[0] << " : " << vec[1] << llendl; + + vec4 = group->getObjectBounds(); + vec[0].set(vec4[0].getF32ptr()); + vec[1].set(vec4[1].getF32ptr()); + llinfos << "ObjectBounds: " << vec[0] << " : " << vec[1] << llendl; + + vec4 = group->getObjectExtents(); + vec[0].set(vec4[0].getF32ptr()); + vec[1].set(vec4[1].getF32ptr()); + llinfos << "ObjectExtents: " << vec[0] << " : " << vec[1] << llendl; +#endif +} +//-------------------------------------------------------------- diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h new file mode 100644 index 0000000000..0a96676be1 --- /dev/null +++ b/indra/newview/llvieweroctree.h @@ -0,0 +1,422 @@ +/** + * @file llvieweroctree.h + * @brief LLViewerObjectOctree.cpp header file, defining all supporting classes. + * + * $LicenseInfo:firstyear=2002&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_VIEWEROCTREE_H +#define LL_VIEWEROCTREE_H + +#include <vector> +#include <map> + +#include "v2math.h" +#include "v3math.h" +#include "v4math.h" +#include "m4math.h" +#include "llvector4a.h" +#include "llquaternion.h" +#include "lloctree.h" +#include "llviewercamera.h" + +class LLViewerRegion; +class LLViewerOctreeEntryData; +class LLviewerOctreeGroup; +class LLViewerOctreeEntry; +class LLViewerOctreePartition; + +typedef LLOctreeListener<LLViewerOctreeEntry> OctreeListener; +typedef LLTreeNode<LLViewerOctreeEntry> TreeNode; +typedef LLOctreeNode<LLViewerOctreeEntry> OctreeNode; +typedef LLOctreeRoot<LLViewerOctreeEntry> OctreeRoot; +typedef LLOctreeTraveler<LLViewerOctreeEntry> OctreeTraveler; + +#if LL_OCTREE_PARANOIA_CHECK +#define assert_octree_valid(x) x->validate() +#define assert_states_valid(x) ((LLviewerOctreeGroup*) x->mSpatialPartition->mOctree->getListener(0))->checkStates() +#else +#define assert_octree_valid(x) +#define assert_states_valid(x) +#endif + +// get index buffer for binary encoded axis vertex buffer given a box at center being viewed by given camera +U32 get_box_fan_indices(LLCamera* camera, const LLVector4a& center); +U8* get_box_fan_indices_ptr(LLCamera* camera, const LLVector4a& center); + +S32 AABBSphereIntersect(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &rad); +S32 AABBSphereIntersectR2(const LLVector4a& min, const LLVector4a& max, const LLVector3 &origin, const F32 &radius_squared); + +S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad); +S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared); + +//defines data needed for octree of an entry +LL_ALIGN_PREFIX(16) +class LLViewerOctreeEntry : public LLRefCount +{ + friend class LLViewerOctreeEntryData; + +public: + typedef enum + { + LLDRAWABLE = 0, + LLVOCACHEENTRY, + NUM_DATA_TYPE + }eEntryDataType_t; + + ~LLViewerOctreeEntry(); +public: + LLViewerOctreeEntry(); + + void nullGroup(); //called by group handleDestruction() only + void setGroup(LLviewerOctreeGroup* group); + void removeData(LLViewerOctreeEntryData* data); + + 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;} + + F32 getBinRadius() const {return mBinRadius;} + S32 getBinIndex() const {return mBinIndex; } + void setBinIndex(S32 index) const {mBinIndex = index; } + + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + +private: + void addData(LLViewerOctreeEntryData* data); + +private: + LLViewerOctreeEntryData* mData[NUM_DATA_TYPE]; //do not use LLPointer here. + LLviewerOctreeGroup* mGroup; + + //aligned members + LL_ALIGN_16(LLVector4a mExtents[2]); + LL_ALIGN_16(LLVector4a mPositionGroup); + F32 mBinRadius; + mutable S32 mBinIndex; + mutable U32 mVisible; + +} LL_ALIGN_POSTFIX(16); + +//defines an abstract class for entry data +LL_ALIGN_PREFIX(16) +class LLViewerOctreeEntryData : public LLRefCount +{ +protected: + ~LLViewerOctreeEntryData(); + +public: + LLViewerOctreeEntryData(const LLViewerOctreeEntryData& rhs) + { + *this = rhs; + } + LLViewerOctreeEntryData(LLViewerOctreeEntry::eEntryDataType_t data_type); + + LLViewerOctreeEntry::eEntryDataType_t getDataType() const {return mDataType;} + LLViewerOctreeEntry* getEntry() {return mEntry;} + + virtual void setOctreeEntry(LLViewerOctreeEntry* entry); + + virtual S32 getMinFrameRange()const = 0; + + F32 getBinRadius() const {return mEntry->getBinRadius();} + const LLVector4a* getSpatialExtents() const; + LLviewerOctreeGroup* getGroup()const; + const LLVector4a& getPositionGroup() const; + + void setBinRadius(F32 rad) {mEntry->mBinRadius = rad;} + void setSpatialExtents(const LLVector3& min, const LLVector3& max); + void setSpatialExtents(const LLVector4a& min, const LLVector4a& max); + void setPositionGroup(const LLVector4a& pos); + + virtual void setGroup(LLviewerOctreeGroup* group); + void shift(const LLVector4a &shift_vector); + + U32 getVisible() const {return mEntry ? mEntry->mVisible : 0;} + void setVisible() const; + virtual bool isVisible() const; + virtual bool isRecentlyVisible() const; + + static S32 getCurrentFrame() { return sCurVisible; } + +protected: + LLVector4a& getGroupPosition() {return mEntry->mPositionGroup;} + void initVisible(U32 visible) {mEntry->mVisible = visible;} + + static void incrementVisible() {sCurVisible++;} +protected: + LLPointer<LLViewerOctreeEntry> mEntry; + LLViewerOctreeEntry::eEntryDataType_t mDataType; + static U32 sCurVisible; // Counter for what value of mVisible means currently visible +}LL_ALIGN_POSTFIX(16); + + +//defines an octree group for an octree node, which contains multiple entries. +LL_ALIGN_PREFIX(16) +class LLviewerOctreeGroup : public LLOctreeListener<LLViewerOctreeEntry> +{ + friend class LLViewerOctreeCull; +protected: + ~LLviewerOctreeGroup(); + +public: + enum + { + CLEAN = 0x00000000, + DIRTY = 0x00000001, + OBJECT_DIRTY = 0x00000002, + SKIP_FRUSTUM_CHECK = 0x00000004, + DEAD = 0x00000008, + INVALID_STATE = 0x00000010, + }; + +public: + typedef LLOctreeNode<LLViewerOctreeEntry>::element_iter element_iter; + typedef LLOctreeNode<LLViewerOctreeEntry>::element_list element_list; + + LLviewerOctreeGroup(OctreeNode* node); + LLviewerOctreeGroup(const LLviewerOctreeGroup& rhs) + { + *this = rhs; + } + + void* operator new(size_t size) + { + return ll_aligned_malloc_16(size); + } + + void operator delete(void* ptr) + { + ll_aligned_free_16(ptr); + } + + bool removeFromGroup(LLViewerOctreeEntryData* data); + bool removeFromGroup(LLViewerOctreeEntry* entry); + + virtual void unbound(); + virtual void rebound(); + + BOOL isDead() { return hasState(DEAD); } + + void setVisible(); + BOOL isVisible() const; + virtual BOOL isRecentlyVisible() const; + bool isEmpty() const { return mOctreeNode->isEmpty(); } + + U32 getState() {return mState; } + bool isDirty() const {return mState & DIRTY;} + bool hasState(U32 state) const {return mState & state;} + void setState(U32 state) {mState |= state;} + void clearState(U32 state) {mState &= ~state;} + + //LISTENER FUNCTIONS + virtual void handleInsertion(const TreeNode* node, LLViewerOctreeEntry* obj); + virtual void handleRemoval(const TreeNode* node, LLViewerOctreeEntry* obj); + virtual void handleDestruction(const TreeNode* node); + virtual void handleStateChange(const TreeNode* node); + virtual void handleChildAddition(const OctreeNode* parent, OctreeNode* child); + virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child); + + OctreeNode* getOctreeNode() {return mOctreeNode;} + LLviewerOctreeGroup* getParent(); + + const LLVector4a* getBounds() const {return mBounds;} + const LLVector4a* getExtents() const {return mExtents;} + const LLVector4a* getObjectBounds() const {return mObjectBounds;} + const LLVector4a* getObjectExtents() const {return mObjectExtents;} + + //octree wrappers to make code more readable + element_list& getData() { return mOctreeNode->getData(); } + element_iter getDataBegin() { return mOctreeNode->getDataBegin(); } + element_iter getDataEnd() { return mOctreeNode->getDataEnd(); } + U32 getElementCount() const { return mOctreeNode->getElementCount(); } + bool hasElement(LLViewerOctreeEntryData* data); + +protected: + void checkStates(); +private: + virtual bool boundObjects(BOOL empty, LLVector4a& minOut, LLVector4a& maxOut); + +protected: + U32 mState; + OctreeNode* mOctreeNode; + + LL_ALIGN_16(LLVector4a mBounds[2]); // bounding box (center, size) of this node and all its children (tight fit to objects) + LL_ALIGN_16(LLVector4a mObjectBounds[2]); // bounding box (center, size) of objects in this node + 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 + +public: + S32 mVisible[LLViewerCamera::NUM_CAMERAS]; + +}LL_ALIGN_POSTFIX(16); + +//octree group which has capability to support occlusion culling +//LL_ALIGN_PREFIX(16) +class LLOcclusionCullingGroup : public LLviewerOctreeGroup +{ +public: + typedef enum + { + OCCLUDED = 0x00010000, + QUERY_PENDING = 0x00020000, + ACTIVE_OCCLUSION = 0x00040000, + DISCARD_QUERY = 0x00080000, + EARLY_FAIL = 0x00100000, + } eOcclusionState; + + typedef enum + { + STATE_MODE_SINGLE = 0, //set one node + STATE_MODE_BRANCH, //set entire branch + STATE_MODE_DIFF, //set entire branch as long as current state is different + STATE_MODE_ALL_CAMERAS, //used for occlusion state, set state for all cameras + } eSetStateMode; + +public: + LLOcclusionCullingGroup(OctreeNode* node, LLViewerOctreePartition* part); + LLOcclusionCullingGroup(const LLOcclusionCullingGroup& rhs) : LLviewerOctreeGroup(rhs) + { + *this = rhs; + } + ~LLOcclusionCullingGroup(); + + void setOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE); + void clearOcclusionState(U32 state, S32 mode = STATE_MODE_SINGLE); + void checkOcclusion(); //read back last occlusion query (if any) + void doOcclusion(LLCamera* camera); //issue occlusion query + BOOL isOcclusionState(U32 state) const { return mOcclusionState[LLViewerCamera::sCurCameraID] & state ? TRUE : FALSE; } + + BOOL needsUpdate(); + + //virtual + void handleChildAddition(const OctreeNode* parent, OctreeNode* child); + + static U32 getNewOcclusionQueryObjectName(); + static void releaseOcclusionQueryObjectName(U32 name); + +protected: + void releaseOcclusionQueryObjectNames(); + +private: + BOOL earlyFail(LLCamera* camera); + +protected: + U32 mOcclusionState[LLViewerCamera::NUM_CAMERAS]; + U32 mOcclusionIssued[LLViewerCamera::NUM_CAMERAS]; + + S32 mLODHash; + + LLViewerOctreePartition* mSpatialPartition; + U32 mOcclusionQuery[LLViewerCamera::NUM_CAMERAS]; + +public: + static std::set<U32> sPendingQueries; +};//LL_ALIGN_POSTFIX(16); + +class LLViewerOctreePartition +{ +public: + LLViewerOctreePartition(); + virtual ~LLViewerOctreePartition(); + + // Cull on arbitrary frustum + virtual S32 cull(LLCamera &camera) = 0; + BOOL isOcclusionEnabled(); + +public: + U32 mPartitionType; + 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 +{ +public: + LLViewerOctreeCull(LLCamera* camera) + : mCamera(camera), mRes(0) { } + + virtual bool earlyFail(LLviewerOctreeGroup* group); + virtual void traverse(const OctreeNode* n); + + //agent space group cull + S32 AABBInFrustumNoFarClipGroupBounds(const LLviewerOctreeGroup* group); + S32 AABBSphereIntersectGroupExtents(const LLviewerOctreeGroup* group); + S32 AABBInFrustumGroupBounds(const LLviewerOctreeGroup* group); + + //agent space object set cull + S32 AABBInFrustumNoFarClipObjectBounds(const LLviewerOctreeGroup* group); + S32 AABBSphereIntersectObjectExtents(const LLviewerOctreeGroup* group); + S32 AABBInFrustumObjectBounds(const LLviewerOctreeGroup* group); + + //local region space group cull + S32 AABBInRegionFrustumNoFarClipGroupBounds(const LLviewerOctreeGroup* group); + S32 AABBInRegionFrustumGroupBounds(const LLviewerOctreeGroup* group); + S32 AABBRegionSphereIntersectGroupExtents(const LLviewerOctreeGroup* group, const LLVector3& shift); + + //local region space object set cull + S32 AABBInRegionFrustumNoFarClipObjectBounds(const LLviewerOctreeGroup* group); + S32 AABBInRegionFrustumObjectBounds(const LLviewerOctreeGroup* group); + S32 AABBRegionSphereIntersectObjectExtents(const LLviewerOctreeGroup* group, const LLVector3& shift); + + virtual S32 frustumCheck(const LLviewerOctreeGroup* group) = 0; + virtual S32 frustumCheckObjects(const LLviewerOctreeGroup* group) = 0; + + virtual bool checkObjects(const OctreeNode* branch, const LLviewerOctreeGroup* group); + virtual void preprocess(LLviewerOctreeGroup* group); + virtual void processGroup(LLviewerOctreeGroup* group); + virtual void visit(const OctreeNode* branch); + +protected: + LLCamera *mCamera; + S32 mRes; +}; + +//scan the octree, output the info of each node for debug use. +class LLViewerOctreeDebug : public OctreeTraveler +{ +public: + virtual void processGroup(LLviewerOctreeGroup* group); + virtual void visit(const OctreeNode* branch); + +public: + static BOOL sInDebug; +}; + +#endif diff --git a/indra/newview/llviewerpartsim.cpp b/indra/newview/llviewerpartsim.cpp index 6bd9f66b9c..a23a15da32 100755 --- a/indra/newview/llviewerpartsim.cpp +++ b/indra/newview/llviewerpartsim.cpp @@ -151,8 +151,8 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 ¢er_agent, const F32 bo if (group != NULL) { - LLVector3 center(group->mOctreeNode->getCenter().getF32ptr()); - LLVector3 size(group->mOctreeNode->getSize().getF32ptr()); + LLVector3 center(group->getOctreeNode()->getCenter().getF32ptr()); + LLVector3 size(group->getOctreeNode()->getSize().getF32ptr()); size += LLVector3(0.01f, 0.01f, 0.01f); mMinObjPos = center - size; mMaxObjPos = center + size; @@ -467,6 +467,20 @@ LLViewerPartSim::LLViewerPartSim() mID = ++id_seed; } +//enable/disable particle system +void LLViewerPartSim::enable(bool enabled) +{ + if(!enabled && sMaxParticleCount > 0) + { + sMaxParticleCount = 0; //disable + } + else if(enabled && sMaxParticleCount < 1) + { + sMaxParticleCount = llmin(gSavedSettings.getS32("RenderMaxPartCount"), LL_MAX_PARTICLE_COUNT); + } + + return; +} void LLViewerPartSim::destroyClass() { diff --git a/indra/newview/llviewerpartsim.h b/indra/newview/llviewerpartsim.h index c91fcf0691..5c71b4c49e 100755 --- a/indra/newview/llviewerpartsim.h +++ b/indra/newview/llviewerpartsim.h @@ -27,7 +27,6 @@ #ifndef LL_LLVIEWERPARTSIM_H #define LL_LLVIEWERPARTSIM_H -#include "lldarrayptr.h" #include "llframetimer.h" #include "llpointer.h" #include "llpartdata.h" @@ -36,7 +35,6 @@ class LLViewerTexture; class LLViewerPart; class LLViewerRegion; -class LLViewerTexture; class LLVOPartGroup; #define LL_MAX_PARTICLE_COUNT 8192 @@ -134,6 +132,8 @@ public: typedef std::vector<LLViewerPartGroup *> group_list_t; typedef std::vector<LLPointer<LLViewerPartSource> > source_list_t; + void enable(bool enabled); + void shift(const LLVector3 &offset); void updateSimulation(); diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h index a565005f30..5df456dab6 100755 --- a/indra/newview/llviewerprecompiledheaders.h +++ b/indra/newview/llviewerprecompiledheaders.h @@ -52,11 +52,9 @@ // Library headers from llcommon project: #include "bitpack.h" -#include "lldeleteutils.h" #include "imageids.h" #include "indra_constants.h" #include "llinitparam.h" - #include "llallocator.h" #include "llapp.h" #include "llcriticaldamp.h" @@ -65,11 +63,7 @@ #include "llerror.h" #include "llfasttimer.h" #include "llframetimer.h" -#include "llhash.h" -#include "lllocalidhashmap.h" -#include "llnametable.h" #include "llpointer.h" -#include "llpriqueuemap.h" #include "llprocessor.h" #include "llrefcount.h" #include "llsafehandle.h" @@ -79,9 +73,7 @@ #include "llstrider.h" #include "llstring.h" #include "llsys.h" -#include "llthread.h" #include "lltimer.h" -#include "lluuidhashmap.h" #include "stdenums.h" #include "stdtypes.h" #include "timing.h" diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index b8b53aa6e4..781a754b7c 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -70,6 +70,7 @@ #include "stringize.h" #include "llviewercontrol.h" #include "llsdserialize.h" +#include "llvieweroctree.h" #ifdef LL_WINDOWS #pragma warning(disable:4355) @@ -85,31 +86,36 @@ const F32 CAP_REQUEST_TIMEOUT = 18; // Even though we gave up on login, keep trying for caps after we are logged in: const S32 MAX_CAP_REQUEST_ATTEMPTS = 30; +BOOL LLViewerRegion::sVOCacheCullingEnabled = FALSE; + typedef std::map<std::string, std::string> CapabilityMap; class LLViewerRegionImpl { public: LLViewerRegionImpl(LLViewerRegion * region, LLHost const & host) - : mHost(host), - mCompositionp(NULL), - mEventPoll(NULL), - mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS), - mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), - mSeedCapAttempts(0), - mHttpResponderID(0), - // I'd prefer to set the LLCapabilityListener name to match the region - // name -- it's disappointing that's not available at construction time. - // We could instead store an LLCapabilityListener*, making - // setRegionNameAndZone() replace the instance. Would that pose - // consistency problems? Can we even request a capability before calling - // setRegionNameAndZone()? - // For testability -- the new Michael Feathers paradigm -- - // LLCapabilityListener binds all the globals it expects to need at - // construction time. - mCapabilityListener(host.getString(), gMessageSystem, *region, - gAgent.getID(), gAgent.getSessionID()) - { - } + : mHost(host), + mCompositionp(NULL), + mEventPoll(NULL), + mSeedCapMaxAttempts(MAX_CAP_REQUEST_ATTEMPTS), + mSeedCapMaxAttemptsBeforeLogin(MAX_SEED_CAP_ATTEMPTS_BEFORE_LOGIN), + mSeedCapAttempts(0), + mHttpResponderID(0), + mLastCameraUpdate(0), + mLastCameraOrigin(), + mVOCachePartition(NULL), + mLandp(NULL), + // I'd prefer to set the LLCapabilityListener name to match the region + // name -- it's disappointing that's not available at construction time. + // We could instead store an LLCapabilityListener*, making + // setRegionNameAndZone() replace the instance. Would that pose + // consistency problems? Can we even request a capability before calling + // setRegionNameAndZone()? + // For testability -- the new Michael Feathers paradigm -- + // LLCapabilityListener binds all the globals it expects to need at + // construction time. + mCapabilityListener(host.getString(), gMessageSystem, *region, + gAgent.getID(), gAgent.getSessionID()) + {} void buildCapabilityNames(LLSD& capabilityNames); @@ -133,7 +139,14 @@ public: // Misc LLVLComposition *mCompositionp; // Composition layer for the surface - LLVOCacheEntry::vocache_entry_map_t mCacheMap; + LLVOCacheEntry::vocache_entry_map_t mCacheMap; //all cached entries + LLVOCacheEntry::vocache_entry_set_t mActiveSet; //all active entries; + LLVOCacheEntry::vocache_entry_set_t mWaitingSet; //entries waiting for LLDrawable to be generated. + std::set< LLPointer<LLviewerOctreeGroup> > mVisibleGroups; //visible groupa + LLVOCachePartition* mVOCachePartition; + LLVOCacheEntry::vocache_entry_set_t mVisibleEntries; //must-be-created visible entries wait for objects creation. + LLVOCacheEntry::vocache_entry_priority_list_t mWaitingList; //transient list storing sorted visible entries waiting for object creation. + // time? // LRU info? @@ -143,7 +156,7 @@ public: CapabilityMap mCapabilities; CapabilityMap mSecondCapabilitiesTracker; - + LLEventPoll* mEventPoll; S32 mSeedCapMaxAttempts; @@ -158,7 +171,10 @@ public: LLCapabilityListener mCapabilityListener; //spatial partitions for objects in this region - std::vector<LLSpatialPartition*> mObjectPartition; + std::vector<LLViewerOctreePartition*> mObjectPartition; + + LLVector3 mLastCameraOrigin; + U32 mLastCameraUpdate; }; // support for secondlife:///app/region/{REGION} SLapps @@ -350,7 +366,10 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, mCacheLoaded(FALSE), mCacheDirty(FALSE), mReleaseNotesRequested(FALSE), - mCapabilitiesReceived(false) + mCapabilitiesReceived(false), + mBitsReceived(0.f), + mPacketsReceived(0.f), + mDead(FALSE) { mWidth = region_width_meters; mImpl->mOriginGlobal = from_region_handle(handle); @@ -382,17 +401,20 @@ LLViewerRegion::LLViewerRegion(const U64 &handle, //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 LLGrassPartition()); //PARTITION_GRASS - mImpl->mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME - mImpl->mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE - mImpl->mObjectPartition.push_back(new LLHUDParticlePartition());//PARTITION_HUD_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 + 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 LLHUDParticlePartition(this));//PARTITION_HUD_PARTICLE + mImpl->mObjectPartition.push_back(new LLVOCachePartition(this)); //PARTITION_VO_CACHE mImpl->mObjectPartition.push_back(NULL); //PARTITION_NONE + + mImpl->mVOCachePartition = getVOCachePartition(); } @@ -413,6 +435,12 @@ void LLViewerRegion::initStats() LLViewerRegion::~LLViewerRegion() { + mDead = TRUE; + mImpl->mActiveSet.clear(); + mImpl->mVisibleEntries.clear(); + mImpl->mVisibleGroups.clear(); + mImpl->mWaitingSet.clear(); + gVLManager.cleanupData(this); // Can't do this on destruction, because the neighbor pointers might be invalid. // This should be reference counted... @@ -427,10 +455,10 @@ LLViewerRegion::~LLViewerRegion() delete mImpl->mEventPoll; LLHTTPSender::clearSender(mImpl->mHost); - saveObjectCache(); - std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer()); + saveObjectCache(); + delete mImpl; mImpl = NULL; } @@ -471,9 +499,13 @@ void LLViewerRegion::loadObjectCache() // Presume success. If it fails, we don't want to try again. mCacheLoaded = TRUE; - if(LLVOCache::hasInstance()) + if(LLVOCache::instanceExists()) { LLVOCache::getInstance()->readFromCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap) ; + if (mImpl->mCacheMap.empty()) + { + mCacheDirty = TRUE; + } } } @@ -490,16 +522,15 @@ void LLViewerRegion::saveObjectCache() return; } - if(LLVOCache::hasInstance()) + if(LLVOCache::instanceExists()) { - LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty) ; + const F32 start_time_threshold = 600.0f; //seconds + bool removal_enabled = sVOCacheCullingEnabled && (mRegionTimer.getElapsedTimeF32() > start_time_threshold); //allow to remove invalid objects from object cache file. + + LLVOCache::getInstance()->writeToCache(mHandle, mImpl->mCacheID, mImpl->mCacheMap, mCacheDirty, removal_enabled) ; mCacheDirty = FALSE; } - for(LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.begin(); iter != mImpl->mCacheMap.end(); ++iter) - { - delete iter->second; - } mImpl->mCacheMap.clear(); } @@ -765,8 +796,339 @@ void LLViewerRegion::dirtyHeights() } } +void LLViewerRegion::replaceCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry) +{ + U32 state = LLVOCacheEntry::INACTIVE; + bool in_vo_tree = false; + + if(old_entry) + { + old_entry->moveTo(new_entry); + state = old_entry->getState(); + in_vo_tree = (state == LLVOCacheEntry::INACTIVE && old_entry->getGroup() != NULL); + killCacheEntry(old_entry); + } + + mImpl->mCacheMap[new_entry->getLocalID()] = new_entry; + + if(state == LLVOCacheEntry::ACTIVE) + { + llassert(new_entry->getEntry()->hasDrawable()); + mImpl->mActiveSet.insert(new_entry); + } + else if(state == LLVOCacheEntry::WAITING) + { + mImpl->mWaitingSet.insert(new_entry); + } + else if(!old_entry || in_vo_tree) + { + addToVOCacheTree(new_entry); + } + new_entry->setState(state); +} + +//physically delete the cache entry +void LLViewerRegion::killCacheEntry(LLVOCacheEntry* entry) +{ + if(!entry) + { + return; + } + + //remove from active list and waiting list + if(entry->isState(LLVOCacheEntry::ACTIVE)) + { + mImpl->mActiveSet.erase(entry); + } + else + { + if(entry->isState(LLVOCacheEntry::WAITING)) + { + mImpl->mWaitingSet.erase(entry); + } + + //remove from mVOCachePartition + removeFromVOCacheTree(entry); + } + + //remove from the forced visible list + mImpl->mVisibleEntries.erase(entry); + + //kill LLViewerObject if exists + //this should be done by the rendering pipeline automatically. + + entry->setState(LLVOCacheEntry::INACTIVE); + + //remove from mCacheMap, real deletion + mImpl->mCacheMap.erase(entry->getLocalID()); +} + +//physically delete the cache entry +void LLViewerRegion::killCacheEntry(U32 local_id) +{ + killCacheEntry(getCacheEntry(local_id)); +} + +U32 LLViewerRegion::getNumOfActiveCachedObjects() const +{ + return mImpl->mActiveSet.size(); +} + +void LLViewerRegion::addActiveCacheEntry(LLVOCacheEntry* entry) +{ + if(!entry || mDead) + { + return; + } + + if(entry->isState(LLVOCacheEntry::WAITING)) + { + mImpl->mWaitingSet.erase(entry); + } + + entry->setState(LLVOCacheEntry::ACTIVE); + entry->setVisible(); + + llassert(entry->getEntry()->hasDrawable()); + mImpl->mActiveSet.insert(entry); +} + +void LLViewerRegion::removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep) +{ + if(mDead) + { + return; + } + + if(drawablep->getParent()) //child object + { + LLViewerOctreeEntry* parent_oct_entry = drawablep->getParent()->getEntry(); + if(parent_oct_entry && parent_oct_entry->hasVOCacheEntry()) + { + LLVOCacheEntry* parent = (LLVOCacheEntry*)parent_oct_entry->getVOCacheEntry(); + parent->addChild(entry); + } + } + else //insert to vo cache tree. + { + //shift to the local regional space from agent space + const LLVector3 pos = drawablep->getVObj()->getPositionRegion(); + LLVector4a vec(pos[0], pos[1], pos[2]); + LLVector4a shift; + shift.setSub(vec, entry->getPositionGroup()); + entry->shift(shift); + + addToVOCacheTree(entry); + } + + mImpl->mVisibleEntries.erase(entry); + mImpl->mActiveSet.erase(entry); + mImpl->mWaitingSet.erase(entry); + entry->setState(LLVOCacheEntry::INACTIVE); +} + +void LLViewerRegion::addVisibleGroup(LLviewerOctreeGroup* group) +{ + if(mDead || group->isEmpty()) + { + return; + } + group->setVisible(); + mImpl->mVisibleGroups.insert(group); +} + +void LLViewerRegion::addToVOCacheTree(LLVOCacheEntry* entry) +{ + if(!sVOCacheCullingEnabled) + { + return; + } + + if(mDead || !entry || !entry->getEntry()) + { + return; + } + if(entry->getGroup()) //already in octree. + { + return; + } + + mImpl->mVOCachePartition->addEntry(entry->getEntry()); +} + +void LLViewerRegion::removeFromVOCacheTree(LLVOCacheEntry* entry) +{ + if(mDead || !entry || !entry->getEntry()) + { + return; + } + if(!entry->getGroup()) + { + return; + } + + mImpl->mVOCachePartition->removeEntry(entry->getEntry()); +} + +//add the visible entries +void LLViewerRegion::addVisibleCacheEntry(LLVOCacheEntry* entry) +{ + if(mDead || !entry) + { + return; + } + + if(entry->isState(LLVOCacheEntry::IN_QUEUE)) + { + return; + } + + if(entry->isState(LLVOCacheEntry::INACTIVE)) + { + entry->setState(LLVOCacheEntry::IN_QUEUE); + } + mImpl->mVisibleEntries.insert(entry); +} + +F32 LLViewerRegion::updateVisibleEntries(F32 max_time) +{ + if(mImpl->mVisibleGroups.empty() && mImpl->mVisibleEntries.empty()) + { + return max_time; + } + + LLTimer update_timer; + + const LLVector3 camera_origin = LLViewerCamera::getInstance()->getOrigin(); + const U32 cur_frame = LLViewerOctreeEntryData::getCurrentFrame(); + bool needs_update = ((cur_frame - mImpl->mLastCameraUpdate) > 5) && ((camera_origin - mImpl->mLastCameraOrigin).lengthSquared() > 10.f); + + //process visible entries + max_time *= 0.5f; //only use up to half available time to update entries. + +#if 1 + for(LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mVisibleEntries.begin(); iter != mImpl->mVisibleEntries.end();) + { + LLVOCacheEntry* vo_entry = *iter; + vo_entry->calcSceneContribution(camera_origin, needs_update, mImpl->mLastCameraUpdate); + + if(vo_entry->getState() < LLVOCacheEntry::WAITING) + { + mImpl->mWaitingList.insert(vo_entry); + } + + LLVOCacheEntry* child; + S32 num_child = vo_entry->getNumOfChildren(); + S32 num_done = 0; + for(S32 i = 0; i < num_child; i++) + { + child = vo_entry->getChild(i); + if(child->getState() < LLVOCacheEntry::WAITING) + { + child->setSceneContribution(vo_entry->getSceneContribution()); + mImpl->mWaitingList.insert(child); + } + else + { + num_done++; + } + } + if(num_done == num_child) + { + vo_entry->clearChildrenList(); + } + + if(!vo_entry->getNumOfChildren()) + { + if(vo_entry->getState() >= LLVOCacheEntry::WAITING) + { + LLVOCacheEntry::vocache_entry_set_t::iterator next_iter = iter; + ++next_iter; + mImpl->mVisibleEntries.erase(iter); + iter = next_iter; + } + else + { + ++iter; + } + } + else + { + ++iter; + } + } +#endif + + //process visible groups + std::set< LLPointer<LLviewerOctreeGroup> >::iterator group_iter = mImpl->mVisibleGroups.begin(); + for(; group_iter != mImpl->mVisibleGroups.end(); ++group_iter) + { + LLPointer<LLviewerOctreeGroup> group = *group_iter; + if(group->getNumRefs() < 3 || //group to be deleted + !group->getOctreeNode() || group->isEmpty()) //group empty + { + continue; + } + + for (LLviewerOctreeGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) + { + if((*i)->hasVOCacheEntry()) + { + LLVOCacheEntry* vo_entry = (LLVOCacheEntry*)(*i)->getVOCacheEntry(); + + if(vo_entry->getParentID() > 0) //is a child + { + //child visibility depends on its parent. + continue; + } + + vo_entry->calcSceneContribution(camera_origin, needs_update, mImpl->mLastCameraUpdate); + mImpl->mWaitingList.insert(vo_entry); + } + } + } + + if(needs_update) + { + mImpl->mLastCameraOrigin = camera_origin; + mImpl->mLastCameraUpdate = cur_frame; + } + + return 2.0f * max_time - update_timer.getElapsedTimeF32(); +} + +F32 LLViewerRegion::createVisibleObjects(F32 max_time) +{ + if(mImpl->mWaitingList.empty()) + { + return max_time; + } + + LLTimer update_timer; + S32 max_num_objects = 64; //minimum number of new objects to be added + for(LLVOCacheEntry::vocache_entry_priority_list_t::iterator iter = mImpl->mWaitingList.begin(); + iter != mImpl->mWaitingList.end(); ++iter) + { + LLVOCacheEntry* vo_entry = *iter; + + if(vo_entry->getState() < LLVOCacheEntry::WAITING) + { + addNewObject(vo_entry); + if(max_num_objects-- < 0 && update_timer.getElapsedTimeF32() > max_time) + { + break; + } + } + } + mImpl->mWaitingList.clear(); + + return max_time - update_timer.getElapsedTimeF32(); +} + BOOL LLViewerRegion::idleUpdate(F32 max_update_time) { + LLTimer update_timer; + // did_update returns TRUE if we did at least one significant update BOOL did_update = mImpl->mLandp->idleUpdate(max_update_time); @@ -776,9 +1138,146 @@ BOOL LLViewerRegion::idleUpdate(F32 max_update_time) mParcelOverlay->idleUpdate(); } + max_update_time -= update_timer.getElapsedTimeF32(); + if(max_update_time < 0.f || mImpl->mCacheMap.empty()) + { + return did_update; + } + + if(!sVOCacheCullingEnabled) + { + return did_update; + } + + //kill invisible objects + max_update_time = killInvisibleObjects(max_update_time); + + max_update_time = updateVisibleEntries(max_update_time); + createVisibleObjects(max_update_time); + + mImpl->mVisibleGroups.clear(); + return did_update; } +F32 LLViewerRegion::killInvisibleObjects(F32 max_time) +{ +#if 1 + if(!sVOCacheCullingEnabled) + { + return max_time; + } + if(mImpl->mActiveSet.empty()) + { + return max_time; + } + + static LLVOCacheEntry* last_visited_entry = NULL; + + const size_t MAX_UPDATE = 32; + std::vector<LLDrawable*> delete_list; + S32 update_counter = llmin(MAX_UPDATE, mImpl->mActiveSet.size()); + LLVOCacheEntry::vocache_entry_set_t::iterator iter = mImpl->mActiveSet.upper_bound(last_visited_entry); + + for(; update_counter > 0; --update_counter, ++iter) + { + if(iter == mImpl->mActiveSet.end()) + { + iter = mImpl->mActiveSet.begin(); + } + + if(!(*iter)->isRecentlyVisible()) + { + killObject((*iter), delete_list); + } + } + + if(iter == mImpl->mActiveSet.end()) + { + last_visited_entry = NULL; + } + else + { + last_visited_entry = *iter; + } + + for(S32 i = 0; i < delete_list.size(); i++) + { + gObjectList.killObject(delete_list[i]->getVObj()); + } + delete_list.clear(); +#endif + return max_time; +} + +void LLViewerRegion::killObject(LLVOCacheEntry* entry, std::vector<LLDrawable*>& delete_list) +{ + //kill the object. + LLDrawable* drawablep = (LLDrawable*)entry->getEntry()->getDrawable(); + llassert(drawablep); + + if(!drawablep->getParent()) + { + LLViewerObject::const_child_list_t& child_list = drawablep->getVObj()->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); iter++) + { + LLViewerObject* child = *iter; + if(child->mDrawable->isRecentlyVisible()) + { + //set the parent group visible if any of its children visible. + ((LLViewerOctreeEntryData*)drawablep)->setVisible(); + return; + } + } + delete_list.push_back(drawablep); + } +} + +LLViewerObject* LLViewerRegion::addNewObject(LLVOCacheEntry* entry) +{ + LLViewerObject* obj = NULL; + if(!entry->getEntry()->hasDrawable()) //not added to the rendering pipeline yet + { + //add the object + obj = gObjectList.processObjectUpdateFromCache(entry, this); + if(obj) + { + if(!entry->isState(LLVOCacheEntry::ACTIVE)) + { + mImpl->mWaitingSet.insert(entry); + entry->setState(LLVOCacheEntry::WAITING); + } + } + } + else + { + llerrs << "Object is already created." << llendl; + } + return obj; +} + +//remove from object cache if the object receives a full-update or terse update +LLViewerObject* LLViewerRegion::forceToRemoveFromCache(U32 local_id, LLViewerObject* objectp) +{ + LLVOCacheEntry* entry = getCacheEntry(local_id); + if (!entry) + { + return objectp; //not in the cache, do nothing. + } + if(!objectp) //object not created + { + entry->setTouched(FALSE); //mark this entry invalid + + //create a new object before delete it from cache. + objectp = gObjectList.processObjectUpdateFromCache(entry, this); + } + + //remove from cache. + killCacheEntry(entry); + + return objectp; +} // As above, but forcibly do the update. void LLViewerRegion::forceUpdate() @@ -956,9 +1455,8 @@ void LLViewerRegion::updateNetStats() mPacketsLost = cdp->getPacketsLost(); mPingDelay = cdp->getPingDelay(); - mBitStat.addValue(mBitsIn - mLastBitsIn); - mPacketsStat.addValue(mPacketsIn - mLastPacketsIn); - mPacketsLostStat.addValue(mPacketsLost); + mBitsReceived += mBitsIn - mLastBitsIn; + mPacketsReceived += mPacketsIn - mLastPacketsIn; } @@ -1234,12 +1732,118 @@ void LLViewerRegion::setSimulatorFeatures(const LLSD& sim_features) mSimulatorFeatures = sim_features; } -LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp) +//this is called when the parent is not cacheable. +//move all orphan children out of cache and insert to rendering octree. +void LLViewerRegion::findOrphans(U32 parent_id) +{ + orphan_list_t::iterator iter = mOrphanMap.find(parent_id); + if(iter != mOrphanMap.end()) + { + std::vector<U32>* children = &mOrphanMap[parent_id]; + for(S32 i = 0; i < children->size(); i++) + { + forceToRemoveFromCache((*children)[i], NULL); + } + children->clear(); + mOrphanMap.erase(parent_id); + } +} + +void LLViewerRegion::decodeBoundingInfo(LLVOCacheEntry* entry) +{ + if(!sVOCacheCullingEnabled) + { + gObjectList.processObjectUpdateFromCache(entry, this); + return; + } + + if(entry != NULL && !entry->getEntry()) + { + entry->setOctreeEntry(NULL); + } + else if(entry->getGroup() != NULL) + { + return; //already in octree, no post processing. + } + + LLVector3 pos; + LLVector3 scale; + LLQuaternion rot; + + //decode spatial info and parent info + U32 parent_id = LLViewerObject::extractSpatialExtents(entry->getDP(), pos, scale, rot); + + if(parent_id > 0) //has parent + { + entry->setParentID(parent_id); + + //1, find the parent in cache + LLVOCacheEntry* parent = getCacheEntry(parent_id); + + //2, parent is not in the cache, put into the orphan list. + if(!parent) + { + mOrphanMap[parent_id].push_back(entry->getLocalID()); + } + else //parent in cache + { + if(!parent->isState(LLVOCacheEntry::INACTIVE)) + { + //parent is visible, so is the child. + addVisibleCacheEntry(entry); + } + else + { + parent->addChild(entry); + } + } + + return; + } + + // + //no parent + // + entry->setBoundingInfo(pos, scale); + if(!entry->getGroup() && entry->isState(LLVOCacheEntry::INACTIVE)) + { + addToVOCacheTree(entry); + } + + if(!parent_id) //a potential parent + { + //find all children and update their bounding info + orphan_list_t::iterator iter = mOrphanMap.find(entry->getLocalID()); + if(iter != mOrphanMap.end()) + { + std::vector<U32>* orphans = &mOrphanMap[entry->getLocalID()]; + S32 size = orphans->size(); + for(S32 i = 0; i < size; i++) + { + LLVOCacheEntry* child = getCacheEntry((*orphans)[i]); + if(child) + { + entry->addChild(child); + } + } + orphans->clear(); + mOrphanMap.erase(entry->getLocalID()); + } + } + + return ; +} + +LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags) { - U32 local_id = objectp->getLocalID(); - U32 crc = objectp->getCRC(); + eCacheUpdateResult result; + U32 crc; + U32 local_id; - LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL); + LLViewerObject::unpackU32(&dp, local_id, "LocalID"); + LLViewerObject::unpackU32(&dp, crc, "CRC"); + + LLVOCacheEntry* entry = getCacheEntry(local_id); if (entry) { @@ -1248,41 +1852,110 @@ LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObjec { // Record a hit entry->recordDupe(); - return CACHE_UPDATE_DUPE; + result = CACHE_UPDATE_DUPE; } + else + { + // Update the cache entry + LLPointer<LLVOCacheEntry> new_entry = new LLVOCacheEntry(local_id, crc, dp); - // Update the cache entry - mImpl->mCacheMap.erase(local_id); - delete entry; + //if visible, update it + if(!entry->isState(LLVOCacheEntry::INACTIVE)) + { + replaceCacheEntry(entry, new_entry); + } + else //invisible + { + //remove old entry + killCacheEntry(entry); + entry = new_entry; + + mImpl->mCacheMap[local_id] = entry; + decodeBoundingInfo(entry); + } + + result = CACHE_UPDATE_CHANGED; + } + } + else + { + // we haven't seen this object before + // Create new entry and add to map + result = CACHE_UPDATE_ADDED; entry = new LLVOCacheEntry(local_id, crc, dp); + mImpl->mCacheMap[local_id] = entry; - return CACHE_UPDATE_CHANGED; + + decodeBoundingInfo(entry); } + entry->setUpdateFlags(flags); + + return result; +} - // we haven't seen this object before +LLViewerRegion::eCacheUpdateResult LLViewerRegion::cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags) +{ + eCacheUpdateResult result = cacheFullUpdate(dp, flags); - // Create new entry and add to map - eCacheUpdateResult result = CACHE_UPDATE_ADDED; - if (mImpl->mCacheMap.size() > MAX_OBJECT_CACHE_ENTRIES) +#if 0 + LLVOCacheEntry* entry = mImpl->mCacheMap[objectp->getLocalID()]; + if(!entry) { - delete mImpl->mCacheMap.begin()->second ; - mImpl->mCacheMap.erase(mImpl->mCacheMap.begin()); - result = CACHE_UPDATE_REPLACED; + return result; + } + if(objectp->mDrawable.notNull() && !entry->getEntry()) + { + entry->setOctreeEntry(objectp->mDrawable->getEntry()); + } + if(entry->getEntry() && entry->getEntry()->hasDrawable() && entry->isState(LLVOCacheEntry::INACTIVE)) + { + addActiveCacheEntry(entry); } - entry = new LLVOCacheEntry(local_id, crc, dp); +#endif - mImpl->mCacheMap[local_id] = entry; return result; } +LLVOCacheEntry* LLViewerRegion::getCacheEntryForOctree(U32 local_id) +{ + if(!sVOCacheCullingEnabled) + { + return NULL; + } + + LLVOCacheEntry* entry = getCacheEntry(local_id); + removeFromVOCacheTree(entry); + + return entry; +} + +LLVOCacheEntry* LLViewerRegion::getCacheEntry(U32 local_id) +{ + LLVOCacheEntry::vocache_entry_map_t::iterator iter = mImpl->mCacheMap.find(local_id); + if(iter != mImpl->mCacheMap.end()) + { + return iter->second; + } + return NULL; +} + +void LLViewerRegion::addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type) +{ +#if 0 + mCacheMissList.insert(CacheMissItem(id, miss_type)); +#else + mCacheMissList.push_back(CacheMissItem(id, miss_type)); +#endif +} + // Get data packer for this object, if we have cached data // AND the CRC matches. JC -LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type) +bool LLViewerRegion::probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type) { //llassert(mCacheLoaded); This assert failes often, changing to early-out -- davep, 2010/10/18 - LLVOCacheEntry* entry = get_if_there(mImpl->mCacheMap, local_id, (LLVOCacheEntry*)NULL); + LLVOCacheEntry* entry = getCacheEntry(local_id); if (entry) { @@ -1291,45 +1964,57 @@ LLDataPacker *LLViewerRegion::getDP(U32 local_id, U32 crc, U8 &cache_miss_type) { // Record a hit entry->recordHit(); - cache_miss_type = CACHE_MISS_TYPE_NONE; - return entry->getDP(crc); + cache_miss_type = CACHE_MISS_TYPE_NONE; + entry->setUpdateFlags(flags); + + if(entry->isState(LLVOCacheEntry::ACTIVE)) + { + ((LLDrawable*)entry->getEntry()->getDrawable())->getVObj()->loadFlags(flags); + return true; + } + + if(entry->getGroup() || !entry->isState(LLVOCacheEntry::INACTIVE)) + { + return true; + } + + decodeBoundingInfo(entry); + return true; } else { // llinfos << "CRC miss for " << local_id << llendl; - cache_miss_type = CACHE_MISS_TYPE_CRC; - mCacheMissCRC.put(local_id); + + addCacheMiss(local_id, CACHE_MISS_TYPE_CRC); } } else { // llinfos << "Cache miss for " << local_id << llendl; - cache_miss_type = CACHE_MISS_TYPE_FULL; - mCacheMissFull.put(local_id); + addCacheMiss(local_id, CACHE_MISS_TYPE_FULL); } - return NULL; + return false; } void LLViewerRegion::addCacheMissFull(const U32 local_id) { - mCacheMissFull.put(local_id); + addCacheMiss(local_id, CACHE_MISS_TYPE_FULL); } void LLViewerRegion::requestCacheMisses() { - S32 full_count = mCacheMissFull.count(); - S32 crc_count = mCacheMissCRC.count(); - if (full_count == 0 && crc_count == 0) return; + if (!mCacheMissList.size()) + { + return; + } LLMessageSystem* msg = gMessageSystem; BOOL start_new_message = TRUE; S32 blocks = 0; - S32 i; - // Send full cache miss updates. For these, we KNOW we don't - // have a viewer object. - for (i = 0; i < full_count; i++) + //send requests for all cache-missed objects + for (CacheMissItem::cache_miss_list_t::iterator iter = mCacheMissList.begin(); iter != mCacheMissList.end(); ++iter) { if (start_new_message) { @@ -1341,34 +2026,8 @@ void LLViewerRegion::requestCacheMisses() } msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_FULL); - msg->addU32Fast(_PREHASH_ID, mCacheMissFull[i]); - blocks++; - - if (blocks >= 255) - { - sendReliableMessage(); - start_new_message = TRUE; - blocks = 0; - } - } - - // Send CRC miss updates. For these, we _might_ have a viewer object, - // but probably not. - for (i = 0; i < crc_count; i++) - { - if (start_new_message) - { - msg->newMessageFast(_PREHASH_RequestMultipleObjects); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - start_new_message = FALSE; - } - - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU8Fast(_PREHASH_CacheMissType, CACHE_MISS_TYPE_CRC); - msg->addU32Fast(_PREHASH_ID, mCacheMissCRC[i]); + msg->addU8Fast(_PREHASH_CacheMissType, (*iter).mType); + msg->addU32Fast(_PREHASH_ID, (*iter).mID); blocks++; if (blocks >= 255) @@ -1384,13 +2043,13 @@ void LLViewerRegion::requestCacheMisses() { sendReliableMessage(); } - mCacheMissFull.reset(); - mCacheMissCRC.reset(); mCacheDirty = TRUE ; // llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl; - LLViewerStatsRecorder::instance().requestCacheMissesEvent(full_count + crc_count); + LLViewerStatsRecorder::instance().requestCacheMissesEvent(mCacheMissList.size()); LLViewerStatsRecorder::instance().log(0.2f); + + mCacheMissList.clear(); } void LLViewerRegion::dumpCache() @@ -1568,8 +2227,20 @@ void LLViewerRegion::unpackRegionHandshake() msg->addUUID("AgentID", gAgent.getID()); msg->addUUID("SessionID", gAgent.getSessionID()); msg->nextBlock("RegionInfo"); - msg->addU32("Flags", 0x0 ); + + U32 flags = 0; + if(sVOCacheCullingEnabled) + { + flags = 0x00000001; //set the bit 0 to be 1 to ask sim to send all cacheable objects. + if(mImpl->mCacheMap.empty()) + { + flags |= 0x00000002; //set the bit 1 to be 1 to tell sim the cache file is empty, no need to send cache probes. + } + } + msg->addU32("Flags", flags ); msg->sendReliable(host); + + mRegionTimer.reset(); //reset region timer. } void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) @@ -1587,7 +2258,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("EventQueueGet"); if (gSavedSettings.getBOOL("UseHTTPInventory")) - { + { capabilityNames.append("FetchLib2"); capabilityNames.append("FetchLibDescendents2"); capabilityNames.append("FetchInventory2"); @@ -1606,7 +2277,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("LandResources"); capabilityNames.append("MapLayer"); capabilityNames.append("MapLayerGod"); - capabilityNames.append("MeshUploadFlag"); + capabilityNames.append("MeshUploadFlag"); capabilityNames.append("NavMeshGenerationStatus"); capabilityNames.append("NewFileAgentInventory"); capabilityNames.append("ObjectMedia"); @@ -1646,7 +2317,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("ViewerMetrics"); capabilityNames.append("ViewerStartAuction"); capabilityNames.append("ViewerStats"); - + // Please add new capabilities alphabetically to reduce // merge conflicts. } @@ -1654,7 +2325,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) void LLViewerRegion::setSeedCapability(const std::string& url) { if (getCapability("Seed") == url) - { + { //llwarns << "Ignoring duplicate seed capability" << llendl; //Instead of just returning we build up a second set of seed caps and compare them //to the "original" seed cap received and determine why there is problem! @@ -1864,9 +2535,18 @@ void LLViewerRegion::logActiveCapabilities() const LLSpatialPartition* LLViewerRegion::getSpatialPartition(U32 type) { - if (type < mImpl->mObjectPartition.size()) + if (type < mImpl->mObjectPartition.size() && type < PARTITION_VO_CACHE) + { + return (LLSpatialPartition*)mImpl->mObjectPartition[type]; + } + return NULL; +} + +LLVOCachePartition* LLViewerRegion::getVOCachePartition() +{ + if(PARTITION_VO_CACHE < mImpl->mObjectPartition.size()) { - return mImpl->mObjectPartition[type]; + return (LLVOCachePartition*)mImpl->mObjectPartition[PARTITION_VO_CACHE]; } return NULL; } diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h index b5fe4677b7..b39bac62bc 100755 --- a/indra/newview/llviewerregion.h +++ b/indra/newview/llviewerregion.h @@ -34,7 +34,6 @@ #include "lldarray.h" #include "llwind.h" -#include "llstat.h" #include "v3dmath.h" #include "llstring.h" #include "llregionflags.h" @@ -66,8 +65,11 @@ class LLDataPacker; class LLDataPackerBinaryBuffer; class LLHost; class LLBBox; - +class LLSpatialGroup; +class LLDrawable; class LLViewerRegionImpl; +class LLviewerOctreeGroup; +class LLVOCachePartition; class LLViewerRegion: public LLCapabilityProvider // implements this interface { @@ -85,6 +87,7 @@ public: PARTITION_VOLUME, PARTITION_BRIDGE, PARTITION_HUD_PARTICLE, + PARTITION_VO_CACHE, PARTITION_NONE, NUM_PARTITIONS } eObjectPartitions; @@ -223,6 +226,11 @@ public: F32 getWidth() const { return mWidth; } BOOL idleUpdate(F32 max_update_time); + void addVisibleGroup(LLviewerOctreeGroup* group); + void addVisibleCacheEntry(LLVOCacheEntry* entry); + void addActiveCacheEntry(LLVOCacheEntry* entry); + void removeActiveCacheEntry(LLVOCacheEntry* entry, LLDrawable* drawablep); + void killCacheEntry(U32 local_id); //physically delete the cache entry // Like idleUpdate, but forces everything to complete regardless of // how long it takes. @@ -315,10 +323,16 @@ public: } eCacheUpdateResult; // handle a full update message - eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp); - LLDataPacker *getDP(U32 local_id, U32 crc, U8 &cache_miss_type); + eCacheUpdateResult cacheFullUpdate(LLDataPackerBinaryBuffer &dp, U32 flags); + eCacheUpdateResult cacheFullUpdate(LLViewerObject* objectp, LLDataPackerBinaryBuffer &dp, U32 flags); + LLVOCacheEntry* getCacheEntryForOctree(U32 local_id); + LLVOCacheEntry* getCacheEntry(U32 local_id); + bool probeCache(U32 local_id, U32 crc, U32 flags, U8 &cache_miss_type); void requestCacheMisses(); void addCacheMissFull(const U32 local_id); + //remove from object cache if the object receives a full-update or terse update + LLViewerObject* forceToRemoveFromCache(U32 local_id, LLViewerObject* objectp); + void findOrphans(U32 parent_id); void dumpCache(); @@ -332,7 +346,9 @@ public: virtual std::string getDescription() const; std::string getHttpUrl() const { return mHttpUrl ;} + U32 getNumOfActiveCachedObjects() const; LLSpatialPartition* getSpatialPartition(U32 type); + LLVOCachePartition* getVOCachePartition(); bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const; bool childrenObjectReturnable( const std::vector<LLBBox>& boxes ) const; @@ -342,7 +358,21 @@ public: void getNeighboringRegionsStatus( std::vector<S32>& regions ); const LLViewerRegionImpl * getRegionImpl() const { return mImpl; } LLViewerRegionImpl * getRegionImplNC() { return mImpl; } - + +private: + void addToVOCacheTree(LLVOCacheEntry* entry); + LLViewerObject* addNewObject(LLVOCacheEntry* entry); + void killObject(LLVOCacheEntry* entry, std::vector<LLDrawable*>& delete_list); + void removeFromVOCacheTree(LLVOCacheEntry* entry); + void replaceCacheEntry(LLVOCacheEntry* old_entry, LLVOCacheEntry* new_entry); + void killCacheEntry(LLVOCacheEntry* entry); //physically delete the cache entry + + F32 killInvisibleObjects(F32 max_time); + F32 createVisibleObjects(F32 max_time); + F32 updateVisibleEntries(F32 max_time); //update visible entries + + void addCacheMiss(U32 id, LLViewerRegion::eCacheMissType miss_type); + void decodeBoundingInfo(LLVOCacheEntry* entry); public: struct CompareDistance { @@ -362,9 +392,8 @@ public: LLWind mWind; LLViewerParcelOverlay *mParcelOverlay; - LLStat mBitStat; - LLStat mPacketsStat; - LLStat mPacketsLostStat; + F32 mBitsReceived; + F32 mPacketsReceived; LLMatrix4 mRenderMatrix; @@ -376,8 +405,10 @@ public: LLDynamicArray<U32> mMapAvatars; LLDynamicArray<LLUUID> mMapAvatarIDs; + static BOOL sVOCacheCullingEnabled; //vo cache culling enabled or not. private: LLViewerRegionImpl * mImpl; + LLFrameTimer mRegionTimer; F32 mWidth; // Width of region on a side (meters) U64 mHandle; @@ -421,18 +452,29 @@ private: // Maps local ids to cache entries. // Regions can have order 10,000 objects, so assume // a structure of size 2^14 = 16,000 - BOOL mCacheLoaded; - BOOL mCacheDirty; + BOOL mCacheLoaded; + BOOL mCacheDirty; + BOOL mAlive; // can become false if circuit disconnects + BOOL mCapabilitiesReceived; + BOOL mReleaseNotesRequested; + BOOL mDead; //if true, this region is in the process of deleting. - LLDynamicArray<U32> mCacheMissFull; - LLDynamicArray<U32> mCacheMissCRC; + typedef std::map<U32, std::vector<U32> > orphan_list_t; + orphan_list_t mOrphanMap; - bool mAlive; // can become false if circuit disconnects - bool mCapabilitiesReceived; - caps_received_signal_t mCapabilitiesReceivedSignal; + class CacheMissItem + { + public: + CacheMissItem(U32 id, LLViewerRegion::eCacheMissType miss_type) : mID(id), mType(miss_type){} + + U32 mID; //local object id + LLViewerRegion::eCacheMissType mType; //cache miss type - BOOL mReleaseNotesRequested; + typedef std::list<CacheMissItem> cache_miss_list_t; + }; + CacheMissItem::cache_miss_list_t mCacheMissList; + caps_received_signal_t mCapabilitiesReceivedSignal; LLSD mSimulatorFeatures; }; diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index ba9818946c..78775c7205 100755 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -78,6 +78,8 @@ LLGLSLShader gGlowCombineProgram; LLGLSLShader gSplatTextureRectProgram; LLGLSLShader gGlowCombineFXAAProgram; LLGLSLShader gTwoTextureAddProgram; +LLGLSLShader gTwoTextureCompareProgram; +LLGLSLShader gOneTextureFilterProgram; LLGLSLShader gOneTextureNoColorProgram; LLGLSLShader gDebugProgram; LLGLSLShader gClipProgram; @@ -672,6 +674,8 @@ void LLViewerShaderMgr::unloadShaders() gSplatTextureRectProgram.unload(); gGlowCombineFXAAProgram.unload(); gTwoTextureAddProgram.unload(); + gTwoTextureCompareProgram.unload(); + gOneTextureFilterProgram.unload(); gOneTextureNoColorProgram.unload(); gSolidColorProgram.unload(); @@ -2709,6 +2713,38 @@ BOOL LLViewerShaderMgr::loadShadersInterface() if (success) { + gTwoTextureCompareProgram.mName = "Two Texture Compare Shader"; + gTwoTextureCompareProgram.mShaderFiles.clear(); + gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareV.glsl", GL_VERTEX_SHADER_ARB)); + gTwoTextureCompareProgram.mShaderFiles.push_back(make_pair("interface/twotexturecompareF.glsl", GL_FRAGMENT_SHADER_ARB)); + gTwoTextureCompareProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gTwoTextureCompareProgram.createShader(NULL, NULL); + if (success) + { + gTwoTextureCompareProgram.bind(); + gTwoTextureCompareProgram.uniform1i("tex0", 0); + gTwoTextureCompareProgram.uniform1i("tex1", 1); + gTwoTextureCompareProgram.uniform1i("dither_tex", 2); + } + } + + if (success) + { + gOneTextureFilterProgram.mName = "One Texture Filter Shader"; + gOneTextureFilterProgram.mShaderFiles.clear(); + gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterV.glsl", GL_VERTEX_SHADER_ARB)); + gOneTextureFilterProgram.mShaderFiles.push_back(make_pair("interface/onetexturefilterF.glsl", GL_FRAGMENT_SHADER_ARB)); + gOneTextureFilterProgram.mShaderLevel = mVertexShaderLevel[SHADER_INTERFACE]; + success = gOneTextureFilterProgram.createShader(NULL, NULL); + if (success) + { + gOneTextureFilterProgram.bind(); + gOneTextureFilterProgram.uniform1i("tex0", 0); + } + } + + if (success) + { gOneTextureNoColorProgram.mName = "One Texture No Color Shader"; gOneTextureNoColorProgram.mShaderFiles.clear(); gOneTextureNoColorProgram.mShaderFiles.push_back(make_pair("interface/onetexturenocolorV.glsl", GL_VERTEX_SHADER_ARB)); diff --git a/indra/newview/llviewershadermgr.h b/indra/newview/llviewershadermgr.h index e3d28f2f5c..24f9111d3d 100755 --- a/indra/newview/llviewershadermgr.h +++ b/indra/newview/llviewershadermgr.h @@ -232,6 +232,10 @@ extern LLGLSLShader gClipProgram; //output tex0[tc0] + tex1[tc1] extern LLGLSLShader gTwoTextureAddProgram; +//output tex0[tc0] - tex1[tc1] +extern LLGLSLShader gTwoTextureCompareProgram; +//discard some fragments based on user-set color tolerance +extern LLGLSLShader gOneTextureFilterProgram; extern LLGLSLShader gOneTextureNoColorProgram; diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index 35bba4184e..be477f7f9a 100755 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -61,363 +61,242 @@ #include "llviewernetwork.h" #include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived - -class StatAttributes +namespace LLStatViewer { -public: - StatAttributes(const char* name, - const BOOL enabled, - const BOOL is_timer) - : mName(name), - mEnabled(enabled), - mIsTimer(is_timer) - { - } + +LLTrace::CountStatHandle<> FPS("framesrendered"), + PACKETS_IN("packetsinstat"), + PACKETS_LOST("packetsloststat"), + PACKETS_OUT("packetsoutstat"), + TEXTURE_PACKETS("texturepacketsstat"), + TRIANGLES_DRAWN("trianglesdrawnstat"), + CHAT_COUNT("chatcount", "Chat messages sent"), + IM_COUNT("imcount", "IMs sent"), + OBJECT_CREATE("objectcreate"), + OBJECT_REZ("objectrez", "Object rez count"), + LOGIN_TIMEOUTS("logintimeouts", "Number of login attempts that timed out"), + LSL_SAVES("lslsaves", "Number of times user has saved a script"), + ANIMATION_UPLOADS("animationuploads", "Animations uploaded"), + FLY("fly", "Fly count"), + TELEPORT("teleport", "Teleport count"), + DELETE_OBJECT("deleteobject", "Objects deleted"), + SNAPSHOT("snapshot", "Snapshots taken"), + UPLOAD_SOUND("uploadsound", "Sounds uploaded"), + UPLOAD_TEXTURE("uploadtexture", "Textures uploaded"), + EDIT_TEXTURE("edittexture", "Changes to textures on objects"), + KILLED("killed", "Number of times killed"), + FRAMETIME_DOUBLED("frametimedoubled", "Ratio of frames 2x longer than previous"), + TEX_BAKES("texbakes"), + TEX_REBAKES("texrebakes"), + NUM_NEW_OBJECTS("numnewobjectsstat"); +LLTrace::CountStatHandle<LLTrace::Kibibits> KBIT("kbitstat"), + LAYERS_KBIT("layerskbitstat"), + OBJECT_KBIT("objectkbitstat"), + ASSET_KBIT("assetkbitstat"), + TEXTURE_KBIT("texturekbitstat"), + ACTUAL_IN_KBIT("actualinkbitstat"), + ACTUAL_OUT_KBIT("actualoutkbitstat"); + +LLTrace::CountStatHandle<LLTrace::Seconds> SIM_20_FPS_TIME("sim20fpstime", "Seconds with sim FPS below 20"), + SIM_PHYSICS_20_FPS_TIME("simphysics20fpstime", "Seconds with physics FPS below 20"), + LOSS_5_PERCENT_TIME("loss5percenttime", "Seconds with packet loss > 5%"); + +SimMeasurement<> SIM_TIME_DILATION("simtimedilation", "", LL_SIM_STAT_TIME_DILATION), + SIM_FPS("simfps", "", LL_SIM_STAT_FPS), + SIM_PHYSICS_FPS("simphysicsfps", "", LL_SIM_STAT_PHYSFPS), + SIM_AGENT_UPS("simagentups", "", LL_SIM_STAT_AGENTUPS), + SIM_SCRIPT_EPS("simscripteps", "", LL_SIM_STAT_SCRIPT_EPS), + SIM_SKIPPED_SILHOUETTE("simsimskippedsilhouettesteps", "", LL_SIM_STAT_SKIPPEDAISILSTEPS_PS), + SIM_SKIPPED_CHARACTERS_PERCENTAGE("simsimpctsteppedcharacters", "", LL_SIM_STAT_PCTSTEPPEDCHARACTERS), + SIM_MAIN_AGENTS("simmainagents", "", LL_SIM_STAT_NUMAGENTMAIN), + SIM_CHILD_AGENTS("simchildagents", "", LL_SIM_STAT_NUMAGENTCHILD), + SIM_OBJECTS("simobjects", "", LL_SIM_STAT_NUMTASKS), + SIM_ACTIVE_OBJECTS("simactiveobjects", "", LL_SIM_STAT_NUMTASKSACTIVE), + SIM_ACTIVE_SCRIPTS("simactivescripts", "", LL_SIM_STAT_NUMSCRIPTSACTIVE), + SIM_PERCENTAGE_SCRIPTS_RUN("simpctscriptsrun", "", LL_SIM_STAT_PCTSCRIPTSRUN), + SIM_IN_PACKETS_PER_SEC("siminpps", "", LL_SIM_STAT_INPPS), + SIM_OUT_PACKETS_PER_SEC("simoutpps", "", LL_SIM_STAT_OUTPPS), + SIM_PENDING_DOWNLOADS("simpendingdownloads", "", LL_SIM_STAT_PENDING_DOWNLOADS), + SIM_PENDING_UPLOADS("simpendinguploads", "", LL_SIM_STAT_PENDING_UPLOADS), + SIM_PENDING_LOCAL_UPLOADS("simpendinglocaluploads", "", LL_SIM_STAT_PENDING_LOCAL_UPLOADS), + SIM_PHYSICS_PINNED_TASKS("physicspinnedtasks", "", LL_SIM_STAT_PHYSICS_PINNED_TASKS), + SIM_PHYSICS_LOD_TASKS("physicslodtasks", "", LL_SIM_STAT_PHYSICS_LOD_TASKS); + +LLTrace::SampleStatHandle<> FPS_SAMPLE("fpssample"), + NUM_IMAGES("numimagesstat"), + NUM_RAW_IMAGES("numrawimagesstat"), + NUM_OBJECTS("numobjectsstat"), + NUM_ACTIVE_OBJECTS("numactiveobjectsstat"), + NUM_SIZE_CULLED("numsizeculledstat"), + NUM_VIS_CULLED("numvisculledstat"), + ENABLE_VBO("enablevbo", "Vertex Buffers Enabled"), + LIGHTING_DETAIL("lightingdetail", "Lighting Detail"), + VISIBLE_AVATARS("visibleavatars", "Visible Avatars"), + SHADER_OBJECTS("shaderobjects", "Object Shaders"), + DRAW_DISTANCE("drawdistance", "Draw Distance"), + PENDING_VFS_OPERATIONS("vfspendingoperations"), + PACKETS_LOST_PERCENT("packetslostpercentstat"), + WINDOW_WIDTH("windowwidth", "Window width"), + WINDOW_HEIGHT("windowheight", "Window height"); - std::string mName; - BOOL mEnabled; - BOOL mIsTimer; -}; +static LLTrace::SampleStatHandle<S64> CHAT_BUBBLES("chatbubbles", "Chat Bubbles Enabled"); -const StatAttributes STAT_INFO[LLViewerStats::ST_COUNT] = -{ - // ST_VERSION - StatAttributes("Version", TRUE, FALSE), - // ST_AVATAR_EDIT_SECONDS - StatAttributes("Seconds in Edit Appearence", FALSE, TRUE), - // ST_TOOLBOX_SECONDS - StatAttributes("Seconds using Toolbox", FALSE, TRUE), - // ST_CHAT_COUNT - StatAttributes("Chat messages sent", FALSE, FALSE), - // ST_IM_COUNT - StatAttributes("IMs sent", FALSE, FALSE), - // ST_FULLSCREEN_BOOL - StatAttributes("Fullscreen mode", FALSE, FALSE), - // ST_RELEASE_COUNT - StatAttributes("Object release count", FALSE, FALSE), - // ST_CREATE_COUNT - StatAttributes("Object create count", FALSE, FALSE), - // ST_REZ_COUNT - StatAttributes("Object rez count", FALSE, FALSE), - // ST_FPS_10_SECONDS - StatAttributes("Seconds below 10 FPS", FALSE, TRUE), - // ST_FPS_2_SECONDS - StatAttributes("Seconds below 2 FPS", FALSE, TRUE), - // ST_MOUSELOOK_SECONDS - StatAttributes("Seconds in Mouselook", FALSE, TRUE), - // ST_FLY_COUNT - StatAttributes("Fly count", FALSE, FALSE), - // ST_TELEPORT_COUNT - StatAttributes("Teleport count", FALSE, FALSE), - // ST_OBJECT_DELETE_COUNT - StatAttributes("Objects deleted", FALSE, FALSE), - // ST_SNAPSHOT_COUNT - StatAttributes("Snapshots taken", FALSE, FALSE), - // ST_UPLOAD_SOUND_COUNT - StatAttributes("Sounds uploaded", FALSE, FALSE), - // ST_UPLOAD_TEXTURE_COUNT - StatAttributes("Textures uploaded", FALSE, FALSE), - // ST_EDIT_TEXTURE_COUNT - StatAttributes("Changes to textures on objects", FALSE, FALSE), - // ST_KILLED_COUNT - StatAttributes("Number of times killed", FALSE, FALSE), - // ST_FRAMETIME_JITTER - StatAttributes("Average delta between sucessive frame times", FALSE, FALSE), - // ST_FRAMETIME_SLEW - StatAttributes("Average delta between frame time and mean", FALSE, FALSE), - // ST_INVENTORY_TOO_LONG - StatAttributes("Inventory took too long to load", FALSE, FALSE), - // ST_WEARABLES_TOO_LONG - StatAttributes("Wearables took too long to load", FALSE, FALSE), - // ST_LOGIN_SECONDS - StatAttributes("Time between LoginRequest and LoginReply", FALSE, FALSE), - // ST_LOGIN_TIMEOUT_COUNT - StatAttributes("Number of login attempts that timed out", FALSE, FALSE), - // ST_HAS_BAD_TIMER - StatAttributes("Known bad timer if != 0.0", FALSE, FALSE), - // ST_DOWNLOAD_FAILED - StatAttributes("Number of times LLAssetStorage::getAssetData() has failed", FALSE, FALSE), - // ST_LSL_SAVE_COUNT - StatAttributes("Number of times user has saved a script", FALSE, FALSE), - // ST_UPLOAD_ANIM_COUNT - StatAttributes("Animations uploaded", FALSE, FALSE), - // ST_FPS_8_SECONDS - StatAttributes("Seconds below 8 FPS", FALSE, TRUE), - // ST_SIM_FPS_20_SECONDS - StatAttributes("Seconds with sim FPS below 20", FALSE, TRUE), - // ST_PHYS_FPS_20_SECONDS - StatAttributes("Seconds with physics FPS below 20", FALSE, TRUE), - // ST_LOSS_05_SECONDS - StatAttributes("Seconds with packet loss > 5%", FALSE, TRUE), - // ST_FPS_DROP_50_RATIO - StatAttributes("Ratio of frames 2x longer than previous", FALSE, FALSE), - // ST_ENABLE_VBO - StatAttributes("Vertex Buffers Enabled", TRUE, FALSE), - // ST_DELTA_BANDWIDTH - StatAttributes("Increase/Decrease in bandwidth based on packet loss", FALSE, FALSE), - // ST_MAX_BANDWIDTH - StatAttributes("Max bandwidth setting", FALSE, FALSE), - // ST_LIGHTING_DETAIL - StatAttributes("Lighting Detail", FALSE, FALSE), - // ST_VISIBLE_AVATARS - StatAttributes("Visible Avatars", FALSE, FALSE), - // ST_SHADER_OJECTS - StatAttributes("Object Shaders", FALSE, FALSE), - // ST_SHADER_ENVIRONMENT - StatAttributes("Environment Shaders", FALSE, FALSE), - // ST_VISIBLE_DRAW_DIST - StatAttributes("Draw Distance", FALSE, FALSE), - // ST_VISIBLE_CHAT_BUBBLES - StatAttributes("Chat Bubbles Enabled", FALSE, FALSE), - // ST_SHADER_AVATAR - StatAttributes("Avatar Shaders", FALSE, FALSE), - // ST_FRAME_SECS - StatAttributes("FRAME_SECS", FALSE, FALSE), - // ST_UPDATE_SECS - StatAttributes("UPDATE_SECS", FALSE, FALSE), - // ST_NETWORK_SECS - StatAttributes("NETWORK_SECS", FALSE, FALSE), - // ST_IMAGE_SECS - StatAttributes("IMAGE_SECS", FALSE, FALSE), - // ST_REBUILD_SECS - StatAttributes("REBUILD_SECS", FALSE, FALSE), - // ST_RENDER_SECS - StatAttributes("RENDER_SECS", FALSE, FALSE), - // ST_CROSSING_AVG - StatAttributes("CROSSING_AVG", FALSE, FALSE), - // ST_CROSSING_MAX - StatAttributes("CROSSING_MAX", FALSE, FALSE), - // ST_LIBXUL_WIDGET_USED - StatAttributes("LibXUL Widget used", FALSE, FALSE), // Unused - // ST_WINDOW_WIDTH - StatAttributes("Window width", FALSE, FALSE), - // ST_WINDOW_HEIGHT - StatAttributes("Window height", FALSE, FALSE), - // ST_TEX_BAKES - StatAttributes("Texture Bakes", FALSE, FALSE), - // ST_TEX_REBAKES - StatAttributes("Texture Rebakes", FALSE, FALSE) +LLTrace::SampleStatHandle<LLTrace::Bytes> GL_TEX_MEM("gltexmemstat"), + GL_BOUND_MEM("glboundmemstat"), + RAW_MEM("rawmemstat"), + FORMATTED_MEM("formattedmemstat"), + DELTA_BANDWIDTH("deltabandwidth", "Increase/Decrease in bandwidth based on packet loss"), + MAX_BANDWIDTH("maxbandwidth", "Max bandwidth setting"); -}; + +SimMeasurement<LLTrace::Milliseconds> SIM_FRAME_TIME("simframemsec", "", LL_SIM_STAT_FRAMEMS), + SIM_NET_TIME("simnetmsec", "", LL_SIM_STAT_NETMS), + SIM_OTHER_TIME("simsimothermsec", "", LL_SIM_STAT_SIMOTHERMS), + SIM_PHYSICS_TIME("simsimphysicsmsec", "", LL_SIM_STAT_SIMPHYSICSMS), + SIM_PHYSICS_STEP_TIME("simsimphysicsstepmsec", "", LL_SIM_STAT_SIMPHYSICSSTEPMS), + SIM_PHYSICS_SHAPE_UPDATE_TIME("simsimphysicsshapeupdatemsec", "", LL_SIM_STAT_SIMPHYSICSSHAPEMS), + SIM_PHYSICS_OTHER_TIME("simsimphysicsothermsec", "", LL_SIM_STAT_SIMPHYSICSOTHERMS), + SIM_AI_TIME("simsimaistepmsec", "", LL_SIM_STAT_SIMAISTEPTIMEMS), + SIM_AGENTS_TIME("simagentmsec", "", LL_SIM_STAT_AGENTMS), + SIM_IMAGES_TIME("simimagesmsec", "", LL_SIM_STAT_IMAGESMS), + SIM_SCRIPTS_TIME("simscriptmsec", "", LL_SIM_STAT_SCRIPTMS), + SIM_SPARE_TIME("simsparemsec", "", LL_SIM_STAT_SIMSPARETIME), + SIM_SLEEP_TIME("simsleepmsec", "", LL_SIM_STAT_SIMSLEEPTIME), + SIM_PUMP_IO_TIME("simpumpiomsec", "", LL_SIM_STAT_IOPUMPTIME); + +SimMeasurement<LLTrace::Bytes> SIM_UNACKED_BYTES("simtotalunackedbytes", "", LL_SIM_STAT_TOTAL_UNACKED_BYTES), + SIM_PHYSICS_MEM("physicsmemoryallocated", "", LL_SIM_STAT_SIMPHYSICSMEMORY); -LLViewerStats::LLViewerStats() : - mKBitStat("kbitstat"), - mLayersKBitStat("layerskbitstat"), - mObjectKBitStat("objectkbitstat"), - mAssetKBitStat("assetkbitstat"), - mTextureKBitStat("texturekbitstat"), - mVFSPendingOperations("vfspendingoperations"), - mObjectsDrawnStat("objectsdrawnstat"), - mObjectsCulledStat("objectsculledstat"), - mObjectsTestedStat("objectstestedstat"), - mObjectsComparedStat("objectscomparedstat"), - mObjectsOccludedStat("objectsoccludedstat"), - mFPSStat("fpsstat"), - mPacketsInStat("packetsinstat"), - mPacketsLostStat("packetsloststat"), - mPacketsOutStat("packetsoutstat"), - mPacketsLostPercentStat("packetslostpercentstat", 64), - mTexturePacketsStat("texturepacketsstat"), - mActualInKBitStat("actualinkbitstat"), - mActualOutKBitStat("actualoutkbitstat"), - mTrianglesDrawnStat("trianglesdrawnstat"), - mSimTimeDilation("simtimedilation"), - mSimFPS("simfps"), - mSimPhysicsFPS("simphysicsfps"), - mSimAgentUPS("simagentups"), - mSimScriptEPS("simscripteps"), - mSimFrameMsec("simframemsec"), - mSimNetMsec("simnetmsec"), - mSimSimOtherMsec("simsimothermsec"), - mSimSimPhysicsMsec("simsimphysicsmsec"), - mSimSimPhysicsStepMsec("simsimphysicsstepmsec"), - mSimSimPhysicsShapeUpdateMsec("simsimphysicsshapeupdatemsec"), - mSimSimPhysicsOtherMsec("simsimphysicsothermsec"), - mSimSimAIStepMsec("simsimaistepmsec"), - mSimSimSkippedSilhouetteSteps("simsimskippedsilhouettesteps"), - mSimSimPctSteppedCharacters("simsimpctsteppedcharacters"), - mSimAgentMsec("simagentmsec"), - mSimImagesMsec("simimagesmsec"), - mSimScriptMsec("simscriptmsec"), - mSimSpareMsec("simsparemsec"), - mSimSleepMsec("simsleepmsec"), - mSimPumpIOMsec("simpumpiomsec"), - mSimMainAgents("simmainagents"), - mSimChildAgents("simchildagents"), - mSimObjects("simobjects"), - mSimActiveObjects("simactiveobjects"), - mSimActiveScripts("simactivescripts"), - mSimPctScriptsRun("simpctscriptsrun"), - mSimInPPS("siminpps"), - mSimOutPPS("simoutpps"), - mSimPendingDownloads("simpendingdownloads"), - mSimPendingUploads("simpendinguploads"), - mSimPendingLocalUploads("simpendinglocaluploads"), - mSimTotalUnackedBytes("simtotalunackedbytes"), - mPhysicsPinnedTasks("physicspinnedtasks"), - mPhysicsLODTasks("physicslodtasks"), - mPhysicsMemoryAllocated("physicsmemoryallocated"), - mSimPingStat("simpingstat"), - mNumImagesStat("numimagesstat", 32, TRUE), - mNumRawImagesStat("numrawimagesstat", 32, TRUE), - mGLTexMemStat("gltexmemstat", 32, TRUE), - mGLBoundMemStat("glboundmemstat", 32, TRUE), - mRawMemStat("rawmemstat", 32, TRUE), - mFormattedMemStat("formattedmemstat", 32, TRUE), - mNumObjectsStat("numobjectsstat"), - mNumActiveObjectsStat("numactiveobjectsstat"), - mNumNewObjectsStat("numnewobjectsstat"), - mNumSizeCulledStat("numsizeculledstat"), - mNumVisCulledStat("numvisculledstat"), - mLastTimeDiff(0.0) -{ - for (S32 i = 0; i < ST_COUNT; i++) - { - mStats[i] = 0.0; - } +LLTrace::SampleStatHandle<LLTrace::Milliseconds> FRAMETIME_JITTER("frametimejitter", "Average delta between successive frame times"), + FRAMETIME_SLEW("frametimeslew", "Average delta between frame time and mean"), + SIM_PING("simpingstat"); + +LLTrace::EventStatHandle<LLTrace::Meters> AGENT_POSITION_SNAP("agentpositionsnap", "agent position corrections"); + +LLTrace::EventStatHandle<> LOADING_WEARABLES_LONG_DELAY("loadingwearableslongdelay", "Wearables took too long to load"); - if (LLTimer::knownBadTimer()) - { - mStats[ST_HAS_BAD_TIMER] = 1.0; - } +LLTrace::EventStatHandle<LLTrace::Milliseconds> REGION_CROSSING_TIME("regioncrossingtime", "CROSSING_AVG"), + FRAME_STACKTIME("framestacktime", "FRAME_SECS"), + UPDATE_STACKTIME("updatestacktime", "UPDATE_SECS"), + NETWORK_STACKTIME("networkstacktime", "NETWORK_SECS"), + IMAGE_STACKTIME("imagestacktime", "IMAGE_SECS"), + REBUILD_STACKTIME("rebuildstacktime", "REBUILD_SECS"), + RENDER_STACKTIME("renderstacktime", "RENDER_SECS"); - mAgentPositionSnaps.reset(); -} +LLTrace::EventStatHandle<LLTrace::Seconds> AVATAR_EDIT_TIME("avataredittime", "Seconds in Edit Appearance"), + TOOLBOX_TIME("toolboxtime", "Seconds using Toolbox"), + MOUSELOOK_TIME("mouselooktime", "Seconds in Mouselook"), + FPS_10_TIME("fps10time", "Seconds below 10 FPS"), + FPS_8_TIME("fps8time", "Seconds below 8 FPS"), + FPS_2_TIME("fps2time", "Seconds below 2 FPS"); -LLViewerStats::~LLViewerStats() -{ -} -void LLViewerStats::resetStats() -{ - LLViewerStats& stats = LLViewerStats::instance(); - stats.mKBitStat.reset(); - stats.mLayersKBitStat.reset(); - stats.mObjectKBitStat.reset(); - stats.mTextureKBitStat.reset(); - stats.mVFSPendingOperations.reset(); - stats.mAssetKBitStat.reset(); - stats.mPacketsInStat.reset(); - stats.mPacketsLostStat.reset(); - stats.mPacketsOutStat.reset(); - stats.mFPSStat.reset(); - stats.mTexturePacketsStat.reset(); - stats.mAgentPositionSnaps.reset(); } - -F64 LLViewerStats::getStat(EStatType type) const +LLViewerStats::LLViewerStats() +: mLastTimeDiff(0.0) { - return mStats[type]; + mRecording.start(); + LLTrace::get_frame_recording().start(); } -F64 LLViewerStats::setStat(EStatType type, F64 value) +LLViewerStats::~LLViewerStats() { - mStats[type] = value; - return mStats[type]; } -F64 LLViewerStats::incStat(EStatType type, F64 value) +void LLViewerStats::resetStats() { - mStats[type] += value; - return mStats[type]; + LLViewerStats::instance().mRecording.reset(); } void LLViewerStats::updateFrameStats(const F64 time_diff) { - if (mPacketsLostPercentStat.getCurrent() > 5.0) + LLTrace::Seconds time_diff_seconds(time_diff); + if (getRecording().getLastValue(LLStatViewer::PACKETS_LOST_PERCENT) > 5.0) { - incStat(ST_LOSS_05_SECONDS, time_diff); + add(LLStatViewer::LOSS_5_PERCENT_TIME, time_diff_seconds); } - if (mSimFPS.getCurrent() < 20.f && mSimFPS.getCurrent() > 0.f) + F32 sim_fps = getRecording().getLastValue(LLStatViewer::SIM_FPS); + if (0.f < sim_fps && sim_fps < 20.f) { - incStat(ST_SIM_FPS_20_SECONDS, time_diff); + add(LLStatViewer::SIM_20_FPS_TIME, time_diff_seconds); } - if (mSimPhysicsFPS.getCurrent() < 20.f && mSimPhysicsFPS.getCurrent() > 0.f) + F32 sim_physics_fps = getRecording().getLastValue(LLStatViewer::SIM_PHYSICS_FPS); + + if (0.f < sim_physics_fps && sim_physics_fps < 20.f) { - incStat(ST_PHYS_FPS_20_SECONDS, time_diff); + add(LLStatViewer::SIM_PHYSICS_20_FPS_TIME, time_diff_seconds); } if (time_diff >= 0.5) { - incStat(ST_FPS_2_SECONDS, time_diff); + record(LLStatViewer::FPS_2_TIME, time_diff_seconds); } if (time_diff >= 0.125) { - incStat(ST_FPS_8_SECONDS, time_diff); + record(LLStatViewer::FPS_8_TIME, time_diff_seconds); } if (time_diff >= 0.1) { - incStat(ST_FPS_10_SECONDS, time_diff); + record(LLStatViewer::FPS_10_TIME, time_diff_seconds); } if (gFrameCount && mLastTimeDiff > 0.0) { // new "stutter" meter - setStat(ST_FPS_DROP_50_RATIO, - (getStat(ST_FPS_DROP_50_RATIO) * (F64)(gFrameCount - 1) + - (time_diff >= 2.0 * mLastTimeDiff ? 1.0 : 0.0)) / gFrameCount); - + add(LLStatViewer::FRAMETIME_DOUBLED, time_diff >= 2.0 * mLastTimeDiff ? 1 : 0); // old stats that were never really used - setStat(ST_FRAMETIME_JITTER, - (getStat(ST_FRAMETIME_JITTER) * (gFrameCount - 1) + - fabs(mLastTimeDiff - time_diff) / mLastTimeDiff) / gFrameCount); + sample(LLStatViewer::FRAMETIME_JITTER, LLTrace::Milliseconds(mLastTimeDiff - time_diff)); F32 average_frametime = gRenderStartTime.getElapsedTimeF32() / (F32)gFrameCount; - setStat(ST_FRAMETIME_SLEW, - (getStat(ST_FRAMETIME_SLEW) * (gFrameCount - 1) + - fabs(average_frametime - time_diff) / average_frametime) / gFrameCount); + sample(LLStatViewer::FRAMETIME_SLEW, LLTrace::Milliseconds(average_frametime - time_diff)); F32 max_bandwidth = gViewerThrottle.getMaxBandwidth(); F32 delta_bandwidth = gViewerThrottle.getCurrentBandwidth() - max_bandwidth; - setStat(ST_DELTA_BANDWIDTH, delta_bandwidth / 1024.f); - - setStat(ST_MAX_BANDWIDTH, max_bandwidth / 1024.f); - + sample(LLStatViewer::DELTA_BANDWIDTH, LLTrace::Bits(delta_bandwidth)); + sample(LLStatViewer::MAX_BANDWIDTH, LLTrace::Bits(max_bandwidth)); } mLastTimeDiff = time_diff; - } -void LLViewerStats::addToMessage(LLSD &body) const +void LLViewerStats::addToMessage(LLSD &body) { LLSD &misc = body["misc"]; - for (S32 i = 0; i < ST_COUNT; i++) - { - if (STAT_INFO[i].mEnabled) - { - // TODO: send timer value so dataserver can normalize - misc[STAT_INFO[i].mName] = mStats[i]; - llinfos << "STAT: " << STAT_INFO[i].mName << ": " << mStats[i] - << llendl; - } - } + misc["Version"] = TRUE; + //TODO RN: get last value, not mean + misc["Vertex Buffers Enabled"] = getRecording().getMean(LLStatViewer::ENABLE_VBO); - body["AgentPositionSnaps"] = mAgentPositionSnaps.getData(); - llinfos << "STAT: AgentPositionSnaps: Mean = " << mAgentPositionSnaps.getMean() << "; StdDev = " << mAgentPositionSnaps.getStdDev() - << "; Count = " << mAgentPositionSnaps.getCount() << llendl; + body["AgentPositionSnaps"] = getRecording().getSum(LLStatViewer::AGENT_POSITION_SNAP).value(); //mAgentPositionSnaps.asLLSD(); + llinfos << "STAT: AgentPositionSnaps: Mean = " << getRecording().getMean(LLStatViewer::AGENT_POSITION_SNAP).value() << "; StdDev = " << getRecording().getStandardDeviation(LLStatViewer::AGENT_POSITION_SNAP).value() + << "; Count = " << getRecording().getSampleCount(LLStatViewer::AGENT_POSITION_SNAP) << llendl; } // *NOTE:Mani The following methods used to exist in viewer.cpp // Moving them here, but not merging them into LLViewerStats yet. -U32 gTotalLandIn = 0, gTotalLandOut = 0; -U32 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; - - - -U32 gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0; -U32 gObjectBits = 0; +U32 gTotalLandIn = 0, + gTotalLandOut = 0, + gTotalWaterIn = 0, + gTotalWaterOut = 0; + +F32 gAveLandCompression = 0.f, + gAveWaterCompression = 0.f, + gBestLandCompression = 1.f, + gBestWaterCompression = 1.f, + gWorstLandCompression = 0.f, + gWorstWaterCompression = 0.f; + +LLUnit<LLUnits::Bytes, U32> gTotalWorldData = 0, + gTotalObjectData = 0, + gTotalTextureData = 0; +U32 gSimPingCount = 0; +LLUnit<LLUnits::Bits, U32> gObjectData = 0; F32 gAvgSimPing = 0.f; -U32 gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0}; +LLUnit<LLUnits::Bytes, U32> gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0}; extern U32 gVisCompared; extern U32 gVisTested; @@ -426,59 +305,68 @@ LLFrameTimer gTextureTimer; void update_statistics() { - gTotalWorldBytes += gVLManager.getTotalBytes(); - gTotalObjectBytes += gObjectBits / 8; - - LLViewerStats& stats = LLViewerStats::instance(); + gTotalWorldData += gVLManager.getTotalBytes(); + gTotalObjectData += gObjectData; // make sure we have a valid time delta for this frame if (gFrameIntervalSeconds > 0.f) { if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_MOUSELOOK_SECONDS, gFrameIntervalSeconds); + record(LLStatViewer::MOUSELOOK_TIME, gFrameIntervalSeconds); } else if (gAgentCamera.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_AVATAR_EDIT_SECONDS, gFrameIntervalSeconds); + record(LLStatViewer::AVATAR_EDIT_TIME, gFrameIntervalSeconds); } else if (LLFloaterReg::instanceVisible("build")) { - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TOOLBOX_SECONDS, gFrameIntervalSeconds); + record(LLStatViewer::TOOLBOX_TIME, gFrameIntervalSeconds); } } - stats.setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); - stats.setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail()); - stats.setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip")); - stats.setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles")); - - stats.setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime("Frame")); - F64 idle_secs = gDebugView->mFastTimerView->getTime("Idle"); - F64 network_secs = gDebugView->mFastTimerView->getTime("Network"); - stats.setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs); - stats.setStat(LLViewerStats::ST_NETWORK_SECS, network_secs); - stats.setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime("Update Images")); - stats.setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime("Sort Draw State")); - stats.setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime("Geometry")); + + LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording(); + + sample(LLStatViewer::ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); + sample(LLStatViewer::LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail()); + sample(LLStatViewer::DRAW_DISTANCE, (F64)gSavedSettings.getF32("RenderFarClip")); + sample(LLStatViewer::CHAT_BUBBLES, gSavedSettings.getBOOL("UseChatBubbles")); + + typedef LLInstanceTracker<LLTrace::TraceType<LLTrace::TimeBlockAccumulator>, std::string> trace_type_t; + + LLUnit<LLUnits::Seconds, F64> idle_secs = last_frame_recording.getSum(*trace_type_t::getInstance("Idle")); + LLUnit<LLUnits::Seconds, F64> network_secs = last_frame_recording.getSum(*trace_type_t::getInstance("Network")); + + record(LLStatViewer::FRAME_STACKTIME, last_frame_recording.getSum(*trace_type_t::getInstance("Frame"))); + record(LLStatViewer::UPDATE_STACKTIME, idle_secs - network_secs); + record(LLStatViewer::NETWORK_STACKTIME, network_secs); + record(LLStatViewer::IMAGE_STACKTIME, last_frame_recording.getSum(*trace_type_t::getInstance("Update Images"))); + record(LLStatViewer::REBUILD_STACKTIME, last_frame_recording.getSum(*trace_type_t::getInstance("Sort Draw State"))); + record(LLStatViewer::RENDER_STACKTIME, last_frame_recording.getSum(*trace_type_t::getInstance("Render Geometry"))); LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost()); if (cdp) { - stats.mSimPingStat.addValue(cdp->getPingDelay()); + sample(LLStatViewer::SIM_PING, LLTrace::Milliseconds(cdp->getPingDelay())); gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1); gSimPingCount++; } else { - stats.mSimPingStat.addValue(10000); + sample(LLStatViewer::SIM_PING, LLTrace::Seconds(10)); + } + + if (LLViewerStats::instance().getRecording().getSum(LLStatViewer::FPS)) + { + sample(LLStatViewer::FPS_SAMPLE, LLTrace::get_frame_recording().getPeriodMeanPerSec(LLStatViewer::FPS)); } + add(LLStatViewer::FPS, 1); - 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); - stats.mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending()); - stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f); + add(LLStatViewer::LAYERS_KBIT, LLTrace::Bits(layer_bits)); + add(LLStatViewer::OBJECT_KBIT, gObjectData); + sample(LLStatViewer::PENDING_VFS_OPERATIONS, LLVFile::getVFSThread()->getPending()); + add(LLStatViewer::ASSET_KBIT, LLTrace::Bits(gTransferManager.getTransferBitsIn(LLTCT_ASSET))); gTransferManager.resetTransferBitsIn(LLTCT_ASSET); if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) @@ -499,14 +387,14 @@ void update_statistics() visible_avatar_frames = 1.f; avg_visible_avatars = (avg_visible_avatars * (F32)(visible_avatar_frames - 1.f) + visible_avatars) / visible_avatar_frames; } - stats.setStat(LLViewerStats::ST_VISIBLE_AVATARS, (F64)avg_visible_avatars); + sample(LLStatViewer::VISIBLE_AVATARS, (F64)avg_visible_avatars); } LLWorld::getInstance()->updateNetStats(); LLWorld::getInstance()->requestCacheMisses(); // Reset all of these values. gVLManager.resetBitCounts(); - gObjectBits = 0; + gObjectData = 0; // gDecodedBits = 0; // Only update texture stats periodically so that they are less noisy @@ -515,11 +403,7 @@ void update_statistics() static LLFrameTimer texture_stats_timer; if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) { - stats.mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f); - stats.mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets); - gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8; - LLViewerTextureList::sTextureBits = 0; - LLViewerTextureList::sTexturePackets = 0; + gTotalTextureData = LLTrace::Bytes(LLViewerStats::instance().getRecording().getSum(LLStatViewer::TEXTURE_KBIT)); texture_stats_timer.reset(); } } @@ -668,9 +552,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"] = LLTrace::Kibibytes(gTotalWorldData).value(); + download["object_kbytes"] = LLTrace::Kibibytes(gTotalObjectData).value(); + download["texture_kbytes"] = LLTrace::Kibibytes(gTotalTextureData).value(); download["mesh_kbytes"] = LLMeshRepository::sBytesReceived/1024.0; LLSD &in = body["stats"]["net"]["in"]; @@ -775,7 +659,7 @@ void LLViewerStats::PhaseMap::clearPhases() mPhaseMap.clear(); } -LLSD LLViewerStats::PhaseMap::dumpPhases() +LLSD LLViewerStats::PhaseMap::asLLSD() { LLSD result; for (phase_map_t::iterator iter = mPhaseMap.begin(); iter != mPhaseMap.end(); ++iter) diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 6b2461be41..bfba7bca9a 100755 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -1,5 +1,5 @@ /** - * @file llviewerstats.h + * @file llviewerim_peningtats.h * @brief LLViewerStats class header file * * $LicenseInfo:firstyear=2002&license=viewerlgpl$ @@ -27,171 +27,187 @@ #ifndef LL_LLVIEWERSTATS_H #define LL_LLVIEWERSTATS_H -#include "llstat.h" +#include "llstatenums.h" #include "lltextureinfo.h" +#include "lltracerecording.h" +#include "lltrace.h" + +namespace LLStatViewer +{ + +struct SimMeasurementSampler : public LLInstanceTracker<SimMeasurementSampler, ESimStatID> +{ + SimMeasurementSampler(ESimStatID id) + : LLInstanceTracker<SimMeasurementSampler, ESimStatID>(id) + {} + virtual ~SimMeasurementSampler() {} + + virtual void sample(F64 value) = 0; +}; + +template<typename T = F64> +struct SimMeasurement : public LLTrace::SampleStatHandle<T>, public SimMeasurementSampler +{ + SimMeasurement(const char* name, const char* description, ESimStatID stat_id) + : LLTrace::SampleStatHandle<T>(name, description), + SimMeasurementSampler(stat_id) + {} + + using SimMeasurementSampler::getInstance; + + /*virtual*/ void sample(F64 value) + { + LLTrace::sample(*this, value); + } +}; + +template<typename T, typename VALUE_T> +void sample(SimMeasurement<T>& measurement, VALUE_T value) +{ + LLTrace::sample(measurement, value); +} + +extern LLTrace::CountStatHandle<> FPS, + PACKETS_IN, + PACKETS_LOST, + PACKETS_OUT, + TEXTURE_PACKETS, + TRIANGLES_DRAWN, + CHAT_COUNT, + IM_COUNT, + OBJECT_CREATE, + OBJECT_REZ, + LOGIN_TIMEOUTS, + LSL_SAVES, + ANIMATION_UPLOADS, + FLY, + TELEPORT, + DELETE_OBJECT, + SNAPSHOT, + UPLOAD_SOUND, + UPLOAD_TEXTURE, + EDIT_TEXTURE, + KILLED, + FRAMETIME_DOUBLED, + TEX_BAKES, + TEX_REBAKES, + NUM_NEW_OBJECTS; + + +extern LLTrace::CountStatHandle<LLTrace::Kibibits> KBIT, + LAYERS_KBIT, + OBJECT_KBIT, + ASSET_KBIT, + TEXTURE_KBIT, + ACTUAL_IN_KBIT, + ACTUAL_OUT_KBIT; + +extern LLTrace::CountStatHandle<LLTrace::Seconds> SIM_20_FPS_TIME, + SIM_PHYSICS_20_FPS_TIME, + LOSS_5_PERCENT_TIME; + +extern SimMeasurement<> SIM_TIME_DILATION, + SIM_FPS, + SIM_PHYSICS_FPS, + SIM_AGENT_UPS, + SIM_SCRIPT_EPS, + SIM_SKIPPED_SILHOUETTE, + SIM_SKIPPED_CHARACTERS_PERCENTAGE, + SIM_MAIN_AGENTS, + SIM_CHILD_AGENTS, + SIM_OBJECTS, + SIM_ACTIVE_OBJECTS, + SIM_ACTIVE_SCRIPTS, + SIM_PERCENTAGE_SCRIPTS_RUN, + SIM_IN_PACKETS_PER_SEC, + SIM_OUT_PACKETS_PER_SEC, + SIM_PENDING_DOWNLOADS, + SIM_PENDING_UPLOADS, + SIM_PENDING_LOCAL_UPLOADS, + SIM_PHYSICS_PINNED_TASKS, + SIM_PHYSICS_LOD_TASKS; + +extern LLTrace::SampleStatHandle<> FPS_SAMPLE, + NUM_IMAGES, + NUM_RAW_IMAGES, + NUM_OBJECTS, + NUM_ACTIVE_OBJECTS, + NUM_SIZE_CULLED, + NUM_VIS_CULLED, + ENABLE_VBO, + LIGHTING_DETAIL, + VISIBLE_AVATARS, + SHADER_OBJECTS, + DRAW_DISTANCE, + PENDING_VFS_OPERATIONS, + PACKETS_LOST_PERCENT, + WINDOW_WIDTH, + WINDOW_HEIGHT; + +extern LLTrace::SampleStatHandle<LLTrace::Bytes> DELTA_BANDWIDTH, + MAX_BANDWIDTH, + GL_TEX_MEM, + GL_BOUND_MEM, + RAW_MEM, + FORMATTED_MEM; + +extern SimMeasurement<LLTrace::Milliseconds> SIM_FRAME_TIME, + SIM_NET_TIME, + SIM_OTHER_TIME, + SIM_PHYSICS_TIME, + SIM_PHYSICS_STEP_TIME, + SIM_PHYSICS_SHAPE_UPDATE_TIME, + SIM_PHYSICS_OTHER_TIME, + SIM_AI_TIME, + SIM_AGENTS_TIME, + SIM_IMAGES_TIME, + SIM_SCRIPTS_TIME, + SIM_SPARE_TIME, + SIM_SLEEP_TIME, + SIM_PUMP_IO_TIME; + +extern SimMeasurement<LLTrace::Bytes> SIM_UNACKED_BYTES, + SIM_PHYSICS_MEM; + + +extern LLTrace::SampleStatHandle<LLTrace::Milliseconds> FRAMETIME_JITTER, + FRAMETIME_SLEW, + SIM_PING; + +extern LLTrace::EventStatHandle<LLTrace::Meters> AGENT_POSITION_SNAP; + +extern LLTrace::EventStatHandle<> LOADING_WEARABLES_LONG_DELAY; + +extern LLTrace::EventStatHandle<LLTrace::Milliseconds> REGION_CROSSING_TIME, + FRAME_STACKTIME, + UPDATE_STACKTIME, + NETWORK_STACKTIME, + IMAGE_STACKTIME, + REBUILD_STACKTIME, + RENDER_STACKTIME; + +extern LLTrace::EventStatHandle<LLTrace::Seconds> AVATAR_EDIT_TIME, + TOOLBOX_TIME, + MOUSELOOK_TIME, + FPS_10_TIME, + FPS_8_TIME, + FPS_2_TIME; + +} class LLViewerStats : public LLSingleton<LLViewerStats> { public: - LLStat mKBitStat, - mLayersKBitStat, - mObjectKBitStat, - mAssetKBitStat, - mTextureKBitStat, - mVFSPendingOperations, - mObjectsDrawnStat, - mObjectsCulledStat, - mObjectsTestedStat, - mObjectsComparedStat, - mObjectsOccludedStat, - mFPSStat, - mPacketsInStat, - mPacketsLostStat, - mPacketsOutStat, - mPacketsLostPercentStat, - mTexturePacketsStat, - mActualInKBitStat, // From the packet ring (when faking a bad connection) - mActualOutKBitStat, // From the packet ring (when faking a bad connection) - mTrianglesDrawnStat; - - // Simulator stats - LLStat mSimTimeDilation, - - mSimFPS, - mSimPhysicsFPS, - mSimAgentUPS, - mSimScriptEPS, - - mSimFrameMsec, - mSimNetMsec, - mSimSimOtherMsec, - mSimSimPhysicsMsec, - - mSimSimPhysicsStepMsec, - mSimSimPhysicsShapeUpdateMsec, - mSimSimPhysicsOtherMsec, - mSimSimAIStepMsec, - mSimSimSkippedSilhouetteSteps, - mSimSimPctSteppedCharacters, - - mSimAgentMsec, - mSimImagesMsec, - mSimScriptMsec, - mSimSpareMsec, - mSimSleepMsec, - mSimPumpIOMsec, - - mSimMainAgents, - mSimChildAgents, - mSimObjects, - mSimActiveObjects, - mSimActiveScripts, - mSimPctScriptsRun, - - mSimInPPS, - mSimOutPPS, - mSimPendingDownloads, - mSimPendingUploads, - mSimPendingLocalUploads, - mSimTotalUnackedBytes, - - mPhysicsPinnedTasks, - mPhysicsLODTasks, - mPhysicsMemoryAllocated, - - mSimPingStat, - - mNumImagesStat, - mNumRawImagesStat, - mGLTexMemStat, - mGLBoundMemStat, - mRawMemStat, - mFormattedMemStat, - - mNumObjectsStat, - mNumActiveObjectsStat, - mNumNewObjectsStat, - mNumSizeCulledStat, - mNumVisCulledStat; - void resetStats(); + public: - // If you change this, please also add a corresponding text label in llviewerstats.cpp - enum EStatType - { - ST_VERSION = 0, - ST_AVATAR_EDIT_SECONDS = 1, - ST_TOOLBOX_SECONDS = 2, - ST_CHAT_COUNT = 3, - ST_IM_COUNT = 4, - ST_FULLSCREEN_BOOL = 5, - ST_RELEASE_COUNT= 6, - ST_CREATE_COUNT = 7, - ST_REZ_COUNT = 8, - ST_FPS_10_SECONDS = 9, - ST_FPS_2_SECONDS = 10, - ST_MOUSELOOK_SECONDS = 11, - ST_FLY_COUNT = 12, - ST_TELEPORT_COUNT = 13, - ST_OBJECT_DELETE_COUNT = 14, - ST_SNAPSHOT_COUNT = 15, - ST_UPLOAD_SOUND_COUNT = 16, - ST_UPLOAD_TEXTURE_COUNT = 17, - ST_EDIT_TEXTURE_COUNT = 18, - ST_KILLED_COUNT = 19, - ST_FRAMETIME_JITTER = 20, - ST_FRAMETIME_SLEW = 21, - ST_INVENTORY_TOO_LONG = 22, - ST_WEARABLES_TOO_LONG = 23, - ST_LOGIN_SECONDS = 24, - ST_LOGIN_TIMEOUT_COUNT = 25, - ST_HAS_BAD_TIMER = 26, - ST_DOWNLOAD_FAILED = 27, - ST_LSL_SAVE_COUNT = 28, - ST_UPLOAD_ANIM_COUNT = 29, - ST_FPS_8_SECONDS = 30, - ST_SIM_FPS_20_SECONDS = 31, - ST_PHYS_FPS_20_SECONDS = 32, - ST_LOSS_05_SECONDS = 33, - ST_FPS_DROP_50_RATIO = 34, - ST_ENABLE_VBO = 35, - ST_DELTA_BANDWIDTH = 36, - ST_MAX_BANDWIDTH = 37, - ST_LIGHTING_DETAIL = 38, - ST_VISIBLE_AVATARS = 39, - ST_SHADER_OBJECTS = 40, - ST_SHADER_ENVIRONMENT = 41, - ST_DRAW_DIST = 42, - ST_CHAT_BUBBLES = 43, - ST_SHADER_AVATAR = 44, - ST_FRAME_SECS = 45, - ST_UPDATE_SECS = 46, - ST_NETWORK_SECS = 47, - ST_IMAGE_SECS = 48, - ST_REBUILD_SECS = 49, - ST_RENDER_SECS = 50, - ST_CROSSING_AVG = 51, - ST_CROSSING_MAX = 52, - ST_LIBXUL_WIDGET_USED = 53, // Unused - ST_WINDOW_WIDTH = 54, - ST_WINDOW_HEIGHT = 55, - ST_TEX_BAKES = 56, - ST_TEX_REBAKES = 57, - - ST_COUNT = 58 - }; LLViewerStats(); ~LLViewerStats(); - // all return latest value of given stat - F64 getStat(EStatType type) const; - F64 setStat(EStatType type, F64 value); // set the stat to value - F64 incStat(EStatType type, F64 value = 1.f); // add value to the stat - void updateFrameStats(const F64 time_diff); - void addToMessage(LLSD &body) const; + void addToMessage(LLSD &body); struct StatsAccumulator { @@ -263,7 +279,7 @@ public: mCountOfNextUpdatesToIgnore = 0; } - inline LLSD getData() const + inline LLSD asLLSD() const { LLSD data; data["mean"] = getMean(); @@ -275,8 +291,6 @@ public: } }; - StatsAccumulator mAgentPositionSnaps; - // Phase tracking (originally put in for avatar rezzing), tracking // progress of active/completed phases for activities like outfit changing. typedef std::map<std::string,LLFrameTimer> phase_map_t; @@ -294,16 +308,18 @@ public: void stopPhase(const std::string& phase_name); void stopAllPhases(); void clearPhases(); - LLSD dumpPhases(); + LLSD asLLSD(); static StatsAccumulator& getPhaseStats(const std::string& phase_name); static void recordPhaseStat(const std::string& phase_name, F32 value); phase_map_t::iterator begin() { return mPhaseMap.begin(); } phase_map_t::iterator end() { return mPhaseMap.end(); } }; + LLTrace::Recording& getRecording() { return mRecording; } + const LLTrace::Recording& getRecording() const { return mRecording; } private: - F64 mStats[ST_COUNT]; + LLTrace::Recording mRecording; F64 mLastTimeDiff; // used for time stat updates }; @@ -315,7 +331,7 @@ void update_statistics(); void send_stats(); extern LLFrameTimer gTextureTimer; -extern U32 gTotalTextureBytes; -extern U32 gTotalObjectBytes; -extern U32 gTotalTextureBytesPerBoostLevel[] ; +extern LLUnit<LLUnits::Bytes, U32> gTotalTextureData; +extern LLUnit<LLUnits::Bytes, U32> gTotalObjectData; +extern LLUnit<LLUnits::Bytes, U32> gTotalTextureBytesPerBoostLevel[] ; #endif // LL_LLVIEWERSTATS_H diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp index f9a725547f..acd8f6a29c 100755 --- a/indra/newview/llviewerstatsrecorder.cpp +++ b/indra/newview/llviewerstatsrecorder.cpp @@ -224,15 +224,15 @@ void LLViewerStatsRecorder::writeToLog( F32 interval ) } } else - { - llwarns << "Couldn't open " << STATS_FILE_NAME << " for logging." << llendl; + { + //llwarns << "Couldn't open " << STATS_FILE_NAME << " for logging." << llendl; return; } } - std::ostringstream data_msg; + std::ostringstream data_msg; - data_msg << getTimeSinceStart() + data_msg << getTimeSinceStart() << "\t " << mObjectCacheHitCount << "\t" << mObjectCacheMissFullCount << "\t" << mObjectCacheMissCrcCount diff --git a/indra/newview/llviewertexlayer.cpp b/indra/newview/llviewertexlayer.cpp index 777e1f9c76..4cd4375146 100755 --- a/indra/newview/llviewertexlayer.cpp +++ b/indra/newview/llviewertexlayer.cpp @@ -364,7 +364,7 @@ void LLViewerTexLayerSetBuffer::doUpload() { LLViewerTexLayerSet* layer_set = getViewerTexLayerSet(); LL_DEBUGS("Avatar") << "Uploading baked " << layer_set->getBodyRegionName() << llendl; - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_BAKES); + add(LLStatViewer::TEX_BAKES, 1); // Don't need caches since we're baked now. (note: we won't *really* be baked // until this image is sent to the server and the Avatar Appearance message is received.) diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp index eb6c453e76..e0a88bfad6 100755 --- a/indra/newview/llviewertexture.cpp +++ b/indra/newview/llviewertexture.cpp @@ -65,6 +65,11 @@ #include "lltexturecache.h" /////////////////////////////////////////////////////////////////////////////// +// extern +const LLUnit<LLUnits::Mibibytes, S32> gMinVideoRam = 32; +const LLUnit<LLUnits::Mibibytes, S32> gMaxVideoRam = 512; + + // statics LLPointer<LLViewerTexture> LLViewerTexture::sNullImagep = NULL; LLPointer<LLViewerTexture> LLViewerTexture::sBlackImagep = NULL; @@ -83,11 +88,11 @@ S32 LLViewerTexture::sAuxCount = 0; LLFrameTimer LLViewerTexture::sEvaluationTimer; F32 LLViewerTexture::sDesiredDiscardBias = 0.f; F32 LLViewerTexture::sDesiredDiscardScale = 1.1f; -S32 LLViewerTexture::sBoundTextureMemoryInBytes = 0; -S32 LLViewerTexture::sTotalTextureMemoryInBytes = 0; -S32 LLViewerTexture::sMaxBoundTextureMemInMegaBytes = 0; -S32 LLViewerTexture::sMaxTotalTextureMemInMegaBytes = 0; -S32 LLViewerTexture::sMaxDesiredTextureMemInBytes = 0 ; +LLUnit<LLUnits::Bytes, S32> LLViewerTexture::sBoundTextureMemory = 0; +LLUnit<LLUnits::Bytes, S32> LLViewerTexture::sTotalTextureMemory = 0; +LLUnit<LLUnits::Mibibytes, S32> LLViewerTexture::sMaxBoundTextureMem = 0; +LLUnit<LLUnits::Mibibytes, S32> LLViewerTexture::sMaxTotalTextureMem = 0; +LLUnit<LLUnits::Bytes, S32> LLViewerTexture::sMaxDesiredTextureMem = 0 ; S8 LLViewerTexture::sCameraMovingDiscardBias = 0 ; F32 LLViewerTexture::sCameraMovingBias = 0.0f ; S32 LLViewerTexture::sMaxSculptRez = 128 ; //max sculpt image size @@ -277,7 +282,7 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture( } LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( - const std::string& filename, + const std::string& filename, FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, @@ -290,7 +295,7 @@ LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromFile( } //static -LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url, +LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromUrl(const std::string& url, FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, @@ -397,7 +402,7 @@ void LLViewerTextureManager::init() LLViewerTexture::sCheckerBoardImagep = LLViewerTextureManager::getLocalTexture(image_raw.get(), TRUE); LLViewerTexture::initClass() ; - + // Create a texture manager bridge. gTextureManagerBridgep = new LLViewerTextureManagerBridge; @@ -527,17 +532,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;//in bytes + sTotalTextureMemory = LLImageGL::sGlobalTextureMemory;//in bytes + sMaxBoundTextureMem = gTextureList.getMaxResidentTexMem();//in MB + sMaxTotalTextureMem = gTextureList.getMaxTotalTextureMem() ;//in MB + 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 >= sMaxBoundTextureMem || + 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, LLUnit<LLUnits::Bytes, S32>(gMaxVideoRam)); // If we are using more texture memory than we should, // scale up the desired discard level @@ -553,8 +558,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 < sMaxBoundTextureMem * 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 @@ -572,8 +577,8 @@ void LLViewerTexture::updateClass(const F32 velocity, const F32 angular_velocity 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 * sMaxBoundTextureMem * texmem_middle_bound_scale) && + (sTotalTextureMemory < 0.75f * sMaxTotalTextureMem * texmem_middle_bound_scale) ; } //end of static functions @@ -676,6 +681,30 @@ void LLViewerTexture::setBoostLevel(S32 level) { mSelectedTime = gFrameTimeSeconds; } + +} + +bool LLViewerTexture::isActiveFetching() +{ + return false; +} + +bool LLViewerTexture::bindDebugImage(const S32 stage) +{ + if (stage < 0) return false; + + bool res = true; + if (LLViewerTexture::sCheckerBoardImagep.notNull() && (this != LLViewerTexture::sCheckerBoardImagep.get())) + { + res = gGL.getTexUnit(stage)->bind(LLViewerTexture::sCheckerBoardImagep); + } + + if(!res) + { + return bindDefaultImage(stage); + } + + return res; } bool LLViewerTexture::bindDefaultImage(S32 stage) @@ -1177,7 +1206,7 @@ void LLViewerFetchedTexture::destroyTexture() { return ; } - + //LL_DEBUGS("Avatar") << mID << llendl; destroyGLTexture() ; mFullyLoaded = FALSE ; @@ -1704,6 +1733,13 @@ bool LLViewerFetchedTexture::setDebugFetching(S32 debug_level) return true; } +bool LLViewerFetchedTexture::isActiveFetching() +{ + static LLCachedControl<bool> 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<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); @@ -3064,13 +3100,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 > sMaxBoundTextureMem * 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() ; diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h index f2e1a90713..e939731cf2 100755 --- a/indra/newview/llviewertexture.h +++ b/indra/newview/llviewertexture.h @@ -34,12 +34,13 @@ #include "llgltypes.h" #include "llrender.h" #include "llmetricperformancetester.h" +#include "llunit.h" #include <map> #include <list> -#define MIN_VIDEO_RAM_IN_MEGA_BYTES 32 -#define MAX_VIDEO_RAM_IN_MEGA_BYTES 512 // 512MB max for performance reasons. +extern const LLUnit<LLUnits::Mibibytes, S32> gMinVideoRam; +extern const LLUnit<LLUnits::Mibibytes, S32> gMaxVideoRam; class LLFace; class LLImageGL ; @@ -124,7 +125,9 @@ public: virtual void dump(); // debug info to llinfos /*virtual*/ bool bindDefaultImage(const S32 stage = 0) ; + /*virtual*/ bool bindDebugImage(const S32 stage = 0) ; /*virtual*/ void forceImmediateUpdate() ; + /*virtual*/ bool isActiveFetching(); /*virtual*/ const LLUUID& getID() const { return mID; } void setBoostLevel(S32 level); @@ -202,11 +205,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 LLUnit<LLUnits::Bytes, S32> sBoundTextureMemory; + static LLUnit<LLUnits::Bytes, S32> sTotalTextureMemory; + static LLUnit<LLUnits::Mibibytes, S32> sMaxBoundTextureMem; + static LLUnit<LLUnits::Mibibytes, S32> sMaxTotalTextureMem; + static LLUnit<LLUnits::Bytes, S32> sMaxDesiredTextureMem ; static S8 sCameraMovingDiscardBias; static F32 sCameraMovingBias; static S32 sMaxSculptRez ; @@ -395,12 +398,15 @@ public: void loadFromFastCache(); void setInFastCacheList(bool in_list) { mInFastCacheList = in_list; } bool isInFastCacheList() { return mInFastCacheList; } + + /*virtual*/bool isActiveFetching(); //is actively in fetching by the fetching pipeline. + protected: /*virtual*/ void switchToCachedImage(); S32 getCurrentDiscardLevelForFetching() ; private: - void init(bool firstinit) ; + void init(bool firstinit) ; void cleanup() ; void saveRawImage() ; @@ -447,7 +453,7 @@ protected: 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. diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index d2af48f528..f3b3a6086d 100755 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -58,21 +58,14 @@ #include "pipeline.h" #include "llappviewer.h" #include "llxuiparser.h" +#include "lltracerecording.h" #include "llviewerdisplay.h" - +#include "llstartup.h" //////////////////////////////////////////////////////////////////////////// void (*LLViewerTextureList::sUUIDCallback)(void **, const LLUUID&) = NULL; -U32 LLViewerTextureList::sTextureBits = 0; -U32 LLViewerTextureList::sTexturePackets = 0; S32 LLViewerTextureList::sNumImages = 0; -LLStat LLViewerTextureList::sNumImagesStat("Num Images", 32, TRUE); -LLStat LLViewerTextureList::sNumRawImagesStat("Num Raw Images", 32, TRUE); -LLStat LLViewerTextureList::sGLTexMemStat("GL Texture Mem", 32, TRUE); -LLStat LLViewerTextureList::sGLBoundMemStat("GL Bound Mem", 32, TRUE); -LLStat LLViewerTextureList::sRawMemStat("Raw Image Mem", 32, TRUE); -LLStat LLViewerTextureList::sFormattedMemStat("Formatted Image Mem", 32, TRUE); LLViewerTextureList gTextureList; static LLFastTimer::DeclareTimer FTM_PROCESS_IMAGES("Process Images"); @@ -324,7 +317,7 @@ void LLViewerTextureList::restoreGL() /////////////////////////////////////////////////////////////////////////////// -LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename, +LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename, FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, @@ -376,7 +369,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromUrl(const std::string& } LLPointer<LLViewerFetchedTexture> imagep = findImage(new_id); - + if (!imagep.isNull()) { LLViewerFetchedTexture *texture = imagep.get(); @@ -432,7 +425,7 @@ 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, @@ -475,7 +468,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id, { llwarns << "FTType mismatch: requested " << f_type << " image has " << imagep->getFTType() << llendl; } - + } if (imagep.isNull()) { @@ -488,7 +481,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, +LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id, FTType f_type, BOOL usemipmaps, LLViewerTexture::EBoostLevel boost_priority, @@ -649,9 +642,11 @@ static LLFastTimer::DeclareTimer FTM_IMAGE_FETCH("Fetch"); static LLFastTimer::DeclareTimer FTM_FAST_CACHE_IMAGE_FETCH("Fast Cache Fetch"); static LLFastTimer::DeclareTimer FTM_IMAGE_CREATE("Create"); static LLFastTimer::DeclareTimer FTM_IMAGE_STATS("Stats"); +static LLFastTimer::DeclareTimer FTM_UPDATE_IMAGES("Update Images"); void LLViewerTextureList::updateImages(F32 max_time) { + LLFastTimer _(FTM_UPDATE_IMAGES); static BOOL cleared = FALSE; if(gTeleportDisplay) { @@ -665,14 +660,17 @@ void LLViewerTextureList::updateImages(F32 max_time) } cleared = FALSE; - LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerStats::getInstance()->mTextureKBitStat.getMeanPerSec()); + LLAppViewer::getTextureFetch()->setTextureBandwidth(LLTrace::get_frame_recording().getPeriodMeanPerSec(LLStatViewer::TEXTURE_KBIT)); - 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()->mRawMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageRaw::sGlobalRawMemory)); - LLViewerStats::getInstance()->mFormattedMemStat.addValue((F32)BYTES_TO_MEGA_BYTES(LLImageFormatted::sGlobalFormattedMemory)); + { + using namespace LLStatViewer; + sample(NUM_IMAGES, sNumImages); + sample(NUM_RAW_IMAGES, LLImageRaw::sRawImageCount); + sample(GL_TEX_MEM, LLImageGL::sGlobalTextureMemory); + sample(GL_BOUND_MEM, LLImageGL::sBoundTextureMemory); + sample(RAW_MEM, LLTrace::Bytes(LLImageRaw::sGlobalRawMemory)); + sample(FORMATTED_MEM, LLTrace::Bytes(LLImageFormatted::sGlobalFormattedMemory)); + } { //loading from fast cache @@ -753,8 +751,18 @@ void LLViewerTextureList::updateImagesDecodePriorities() { // Update the decode priority for N images each frame { - 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); + 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 + if(LLStartUp::getStartupState() < STATE_STARTED) + { + //do not remove pre-fetched images if viewer does not finish logging in. + lazy_flush_timeout = 30000.f; + max_inactive_time = 20000.f; + } + + 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.value()) + 1, MAX_PRIO_UPDATES); S32 update_counter = llmin(max_update_count, mUUIDMap.size()); uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID); while ((update_counter-- > 0) && !mUUIDMap.empty()) @@ -776,14 +784,10 @@ void LLViewerTextureList::updateImagesDecodePriorities() // // Flush formatted images using a lazy flush // - const F32 LAZY_FLUSH_TIMEOUT = 30.f; // stop decoding - const F32 MAX_INACTIVE_TIME = 20.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 (imagep->getLastReferencedTimer()->getElapsedTimeF32() > lazy_flush_timeout) { // Remove the unused image from the image list deleteImage(imagep); @@ -795,7 +799,7 @@ void LLViewerTextureList::updateImagesDecodePriorities() { if(imagep->hasSavedRawImage()) { - if(imagep->getElapsedLastReferencedSavedRawImageTime() > MAX_INACTIVE_TIME) + if(imagep->getElapsedLastReferencedSavedRawImageTime() > max_inactive_time) { imagep->destroySavedRawImage() ; } @@ -812,7 +816,7 @@ void LLViewerTextureList::updateImagesDecodePriorities() } else if(imagep->isInactive()) { - if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) + if (imagep->getLastReferencedTimer()->getElapsedTimeF32() > max_inactive_time) { imagep->setDeletionCandidate() ; } @@ -988,11 +992,11 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) static const F32 MIN_PRIORITY_THRESHOLD = gSavedSettings.getF32("TextureFetchUpdatePriorityThreshold"); // default: 0.0 static const bool SKIP_LOW_PRIO = gSavedSettings.getBOOL("TextureFetchUpdateSkipLowPriority"); // default: false - size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*MAX_HIGH_PRIO_COUNT*gFrameIntervalSeconds)+1, MAX_HIGH_PRIO_COUNT); + size_t max_priority_count = llmin((S32) (MAX_HIGH_PRIO_COUNT*MAX_HIGH_PRIO_COUNT*gFrameIntervalSeconds.value())+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); + size_t max_update_count = llmin((S32) (MAX_UPDATE_COUNT*MAX_UPDATE_COUNT*gFrameIntervalSeconds.value())+1, MAX_UPDATE_COUNT); max_update_count = llmin(max_update_count, total_update_count); // MAX_HIGH_PRIO_COUNT high priority entries @@ -1229,7 +1233,7 @@ S32 LLViewerTextureList::getMinVideoRamSetting() { S32 system_ram = (S32)BYTES_TO_MEGA_BYTES(gSysMemory.getPhysicalMemoryClamped()); //min texture mem sets to 64M if total physical mem is more than 1.5GB - return (system_ram > 1500) ? 64 : MIN_VIDEO_RAM_IN_MEGA_BYTES ; + return (system_ram > 1500) ? 64 : gMinVideoRam.value() ; } //static @@ -1279,7 +1283,7 @@ S32 LLViewerTextureList::getMaxVideoRamSetting(bool get_recommended) else max_texmem = llmin(max_texmem, (S32)(system_ram)); - max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), MAX_VIDEO_RAM_IN_MEGA_BYTES); + max_texmem = llclamp(max_texmem, getMinVideoRamSetting(), gMaxVideoRam.value()); return max_texmem; } @@ -1367,8 +1371,8 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d { received_size = msg->getReceiveSize() ; } - gTextureList.sTextureBits += received_size * 8; - gTextureList.sTexturePackets++; + add(LLStatViewer::TEXTURE_KBIT, LLTrace::Bytes(received_size)); + add(LLStatViewer::TEXTURE_PACKETS, 1); U8 codec; U16 packets; @@ -1440,8 +1444,9 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d { received_size = msg->getReceiveSize() ; } - gTextureList.sTextureBits += received_size * 8; - gTextureList.sTexturePackets++; + + add(LLStatViewer::TEXTURE_KBIT, LLTrace::Bytes(received_size)); + add(LLStatViewer::TEXTURE_PACKETS, 1); //llprintline("Start decode, image header..."); msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h index 136042620d..5b6e927e32 100755 --- a/indra/newview/llviewertexturelist.h +++ b/indra/newview/llviewertexturelist.h @@ -1,5 +1,5 @@ /** - * @file llviewertexturelist.h + * @file llviewertexturelinumimagest.h * @brief Object for managing the list of images within a region * * $LicenseInfo:firstyear=2000&license=viewerlgpl$ @@ -30,11 +30,11 @@ #include "lluuid.h" //#include "message.h" #include "llgl.h" -#include "llstat.h" #include "llviewertexture.h" #include "llui.h" #include <list> #include <set> +#include "lluiimage.h" const U32 LL_IMAGE_REZ_LOSSLESS_CUTOFF = 128; @@ -204,17 +204,6 @@ private: S32 mMaxTotalTextureMemInMegaBytes; LLFrameTimer mForceDecodeTimer; -public: - static U32 sTextureBits; - static U32 sTexturePackets; - - static LLStat sNumImagesStat; - static LLStat sNumRawImagesStat; - static LLStat sGLTexMemStat; - static LLStat sGLBoundMemStat; - static LLStat sRawMemStat; - static LLStat sFormattedMemStat; - private: static S32 sNumImages; static void (*sUUIDCallback)(void**, const LLUUID &); diff --git a/indra/newview/llviewerthrottle.cpp b/indra/newview/llviewerthrottle.cpp index 5147272122..34f2c8f6e6 100755 --- a/indra/newview/llviewerthrottle.cpp +++ b/indra/newview/llviewerthrottle.cpp @@ -304,7 +304,8 @@ void LLViewerThrottle::updateDynamicThrottle() } mUpdateTimer.reset(); - if (LLViewerStats::getInstance()->mPacketsLostPercentStat.getMean() > TIGHTEN_THROTTLE_THRESHOLD) + F32 mean_packets_lost = LLViewerStats::instance().getRecording().getMean(LLStatViewer::PACKETS_LOST_PERCENT); + if (mean_packets_lost > TIGHTEN_THROTTLE_THRESHOLD) { if (mThrottleFrac <= MIN_FRACTIONAL || mCurrentBandwidth / 1024.0f <= MIN_BANDWIDTH) { @@ -317,7 +318,7 @@ void LLViewerThrottle::updateDynamicThrottle() mCurrent.sendToSim(); llinfos << "Tightening network throttle to " << mCurrentBandwidth << llendl; } - else if (LLViewerStats::getInstance()->mPacketsLostPercentStat.getMean() <= EASE_THROTTLE_THRESHOLD) + else if (mean_packets_lost <= EASE_THROTTLE_THRESHOLD) { if (mThrottleFrac >= MAX_FRACTIONAL || mCurrentBandwidth / 1024.0f >= MAX_BANDWIDTH) { diff --git a/indra/newview/llviewerwearable.cpp b/indra/newview/llviewerwearable.cpp index e8425dc76a..c7e97cfe94 100644 --- a/indra/newview/llviewerwearable.cpp +++ b/indra/newview/llviewerwearable.cpp @@ -30,6 +30,7 @@ #include "llagentcamera.h" #include "llagentwearables.h" #include "llfloatersidepanelcontainer.h" +#include "lllocaltextureobject.h" #include "llnotificationsutil.h" #include "llsidepanelappearance.h" #include "lltextureentry.h" diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index fe4d5b3e4d..349849a267 100755 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -40,6 +40,7 @@ #include "llagentcamera.h" #include "llcommunicationchannel.h" #include "llfloaterreg.h" +#include "llhudicon.h" #include "llmeshrepository.h" #include "llnotificationhandler.h" #include "llpanellogin.h" @@ -81,7 +82,6 @@ #include "llmediaentry.h" #include "llurldispatcher.h" #include "raytrace.h" -#include "llstat.h" // newview includes #include "llagent.h" @@ -253,6 +253,9 @@ std::string LLViewerWindow::sSnapshotDir; std::string LLViewerWindow::sMovieBaseName; +LLTrace::SampleStatHandle<> LLViewerWindow::sMouseVelocityStat("Mouse Velocity"); + + class RecordToChatConsole : public LLError::Recorder, public LLSingleton<RecordToChatConsole> { public: @@ -457,6 +460,8 @@ public: if (gSavedSettings.getBOOL("DebugShowRenderInfo")) { + LLTrace::Recording& last_frame_recording = LLTrace::get_frame_recording().getLastRecording(); + if (gPipeline.getUseVertexShaders() == 0) { addText(xpos, ypos, "Shaders Disabled"); @@ -562,7 +567,7 @@ public: addText(xpos, ypos, llformat("%d Unique Textures", LLImageGL::sUniqueCount)); ypos += y_inc; - addText(xpos, ypos, llformat("%d Render Calls", gPipeline.mBatchCount)); + addText(xpos, ypos, llformat("%d Render Calls", last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize))); ypos += y_inc; addText(xpos, ypos, llformat("%d/%d Objects Active", gObjectList.getNumActiveObjects(), gObjectList.getNumObjects())); @@ -577,15 +582,10 @@ public: gPipeline.mTextureMatrixOps = 0; gPipeline.mMatrixOpCount = 0; - if (gPipeline.mBatchCount > 0) - { - addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", gPipeline.mMinBatchSize, gPipeline.mMaxBatchSize, - gPipeline.mTrianglesDrawn/gPipeline.mBatchCount)); - - gPipeline.mMinBatchSize = gPipeline.mMaxBatchSize; - gPipeline.mMaxBatchSize = 0; - gPipeline.mBatchCount = 0; - } + if (last_frame_recording.getSampleCount(LLPipeline::sStatBatchSize) > 0) + { + addText(xpos, ypos, llformat("Batch min/max/mean: %d/%d/%d", last_frame_recording.getMin(LLPipeline::sStatBatchSize), last_frame_recording.getMax(LLPipeline::sStatBatchSize), last_frame_recording.getMean(LLPipeline::sStatBatchSize))); + } ypos += y_inc; addText(xpos, ypos, llformat("UI Verts/Calls: %d/%d", LLRender::sUIVerts, LLRender::sUICalls)); @@ -596,9 +596,9 @@ public: ypos += y_inc; - if (!LLSpatialGroup::sPendingQueries.empty()) + if (!LLOcclusionCullingGroup::sPendingQueries.empty()) { - addText(xpos,ypos, llformat("%d Queries pending", LLSpatialGroup::sPendingQueries.size())); + addText(xpos,ypos, llformat("%d Queries pending", LLOcclusionCullingGroup::sPendingQueries.size())); ypos += y_inc; } @@ -738,7 +738,7 @@ public: { if(gTotalTextureBytesPerBoostLevel[i] > 0) { - addText(xpos, ypos, llformat("Boost_Level %d: %.3f MB", i, (F32)gTotalTextureBytesPerBoostLevel[i] / (1024 * 1024))); + addText(xpos, ypos, llformat("Boost_Level %d: %.3f MB", i, LLUnit<LLUnits::Mibibytes, F32>(gTotalTextureBytesPerBoostLevel[i]).value())); ypos += y_inc; } } @@ -1409,10 +1409,11 @@ BOOL LLViewerWindow::handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S FillRect(hdc, &wnd_rect, CreateSolidBrush(RGB(255, 255, 255))); std::string temp_str; + LLTrace::Recording& recording = LLViewerStats::instance().getRecording(); temp_str = llformat( "FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */ - LLViewerStats::getInstance()->mFPSStat.getMeanPerSec(), - LLViewerStats::getInstance()->mSimPhysicsFPS.getPrev(0), - LLViewerStats::getInstance()->mSimTimeDilation.getPrev(0)); + recording.getPerSec(LLStatViewer::FPS), //mFPSStat.getMeanPerSec(), + recording.getLastValue(LLStatViewer::SIM_PHYSICS_FPS), + recording.getLastValue(LLStatViewer::SIM_TIME_DILATION)); S32 len = temp_str.length(); TextOutA(hdc, 0, 0, temp_str.c_str(), len); @@ -1547,8 +1548,7 @@ LLViewerWindow::LLViewerWindow(const Params& p) mResDirty(false), mStatesDirty(false), mCurrResolutionIndex(0), - mProgressView(NULL), - mMouseVelocityStat(new LLStat("Mouse Velocity")) + mProgressView(NULL) { // gKeyboard is still NULL, so it doesn't do LLWindowListener any good to // pass its value right now. Instead, pass it a nullary function that @@ -2089,8 +2089,6 @@ LLViewerWindow::~LLViewerWindow() delete mDebugText; mDebugText = NULL; - - delete mMouseVelocityStat; } @@ -2201,8 +2199,8 @@ void LLViewerWindow::reshape(S32 width, S32 height) } } - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_WIDTH, (F64)width); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_WINDOW_HEIGHT, (F64)height); + sample(LLStatViewer::WINDOW_WIDTH, width); + sample(LLStatViewer::WINDOW_HEIGHT, height); LLLayoutStack::updateClass(); } @@ -2796,11 +2794,12 @@ void append_xui_tooltip(LLView* viewp, LLToolTip::Params& params) } } +static LLFastTimer::DeclareTimer ftm("Update UI"); + // Update UI based on stored mouse position from mouse-move // event processing. void LLViewerWindow::updateUI() { - static LLFastTimer::DeclareTimer ftm("Update UI"); LLFastTimer t(ftm); static std::string last_handle_msg; @@ -3268,8 +3267,8 @@ void LLViewerWindow::updateMouseDelta() static F32 fdy = 0.f; F32 amount = 16.f; - fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f); - fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f); + fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds.value()*amount,1.f); + fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds.value()*amount,1.f); mCurrentMouseDelta.set(llround(fdx), llround(fdy)); mouse_vel.setVec(fdx,fdy); @@ -3280,7 +3279,7 @@ void LLViewerWindow::updateMouseDelta() mouse_vel.setVec((F32) dx, (F32) dy); } - mMouseVelocityStat->addValue(mouse_vel.magVec()); + sample(sMouseVelocityStat, mouse_vel.magVec()); } void LLViewerWindow::updateKeyboardFocus() @@ -4771,7 +4770,7 @@ void LLViewerWindow::stopGL(BOOL save_state) gGLManager.mIsDisabled = TRUE; stop_glerror(); - llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemoryInBytes << " bytes" << llendl; + llinfos << "Remaining allocated texture memory: " << LLImageGL::sGlobalTextureMemory.value() << " bytes" << llendl; } } @@ -5272,8 +5271,8 @@ void LLPickInfo::getSurfaceInfo() LLFace* facep = objectp->mDrawable->getFace(mObjectFace); if (facep) { - mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal); - } + mUVCoords = facep->surfaceToTexture(mSTCoords, mIntersection, mNormal); + } } // and XY coords: diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h index b33488fd78..e0943d9825 100755 --- a/indra/newview/llviewerwindow.h +++ b/indra/newview/llviewerwindow.h @@ -45,12 +45,12 @@ #include "llnotifications.h" #include "llhandle.h" #include "llinitparam.h" +#include "lltrace.h" #include <boost/function.hpp> #include <boost/signals2.hpp> #include <boost/scoped_ptr.hpp> -class LLStat; class LLView; class LLViewerObject; class LLUUID; @@ -251,7 +251,7 @@ public: S32 getCurrentMouseDX() const { return mCurrentMouseDelta.mX; } S32 getCurrentMouseDY() const { return mCurrentMouseDelta.mY; } LLCoordGL getCurrentMouseDelta() const { return mCurrentMouseDelta; } - LLStat* getMouseVelocityStat() { return mMouseVelocityStat; } + static LLTrace::SampleStatHandle<>* getMouseVelocityStat() { return &sMouseVelocityStat; } BOOL getLeftMouseDown() const { return mLeftMouseDown; } BOOL getMiddleMouseDown() const { return mMiddleMouseDown; } BOOL getRightMouseDown() const { return mRightMouseDown; } @@ -432,7 +432,6 @@ private: LLCoordGL mCurrentMousePoint; // last mouse position in GL coords LLCoordGL mLastMousePoint; // Mouse point at last frame. LLCoordGL mCurrentMouseDelta; //amount mouse moved this frame - LLStat* mMouseVelocityStat; BOOL mLeftMouseDown; BOOL mMiddleMouseDown; BOOL mRightMouseDown; @@ -487,6 +486,8 @@ private: // Object temporarily hovered over while dragging LLPointer<LLViewerObject> mDragHoveredObject; + + static LLTrace::SampleStatHandle<> sMouseVelocityStat; }; // diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 06fb23b84b..d4c31fd4b0 100755 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -51,7 +51,6 @@ #include "llpolyskeletaldistortion.h" #include "lleditingmotion.h" #include "llemote.h" -//#include "llfirstuse.h" #include "llfloatertools.h" #include "llheadrotmotion.h" #include "llhudeffecttrail.h" @@ -81,6 +80,7 @@ #include "llviewermenu.h" #include "llviewerobjectlist.h" #include "llviewerparcelmgr.h" +#include "llviewerregion.h" #include "llviewershadermgr.h" #include "llviewerstats.h" #include "llviewerwearable.h" @@ -100,6 +100,7 @@ #include "lldebugmessagebox.h" #include "llsdutil.h" +#include "llscenemonitor.h" #include "llsdserialize.h" extern F32 SPEED_ADJUST_MAX; @@ -250,7 +251,7 @@ struct LLAppearanceMessageContents std::vector<F32> mParamWeights; std::vector<LLVisualParam*> mParams; }; - + struct LLVOAvatarChildJoint : public LLInitParam::ChoiceBlock<LLVOAvatarChildJoint> { Alternative<Lazy<struct LLVOAvatarBoneInfo, IS_A_BLOCK> > bone; @@ -769,6 +770,11 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mLastPelvisToFoot = 0.0f; mPelvisFixup = 0.0f; mLastPelvisFixup = 0.0f; + + if(LLSceneMonitor::getInstance()->isEnabled()) + { + LLSceneMonitor::getInstance()->freezeAvatar((LLCharacter*)this); + } } std::string LLVOAvatar::avString() const @@ -1196,7 +1202,7 @@ void LLVOAvatar::initInstance(void) registerMotion( ANIM_AGENT_TARGET, LLTargetingMotion::create ); registerMotion( ANIM_AGENT_WALK_ADJUST, LLWalkAdjustMotion::create ); } - + LLAvatarAppearance::initInstance(); // preload specific motions here @@ -1542,7 +1548,7 @@ LLViewerObject* LLVOAvatar::lineSegmentIntersectRiggedAttachments(const LLVector return hit; } - + LLVOAvatar* LLVOAvatar::asAvatar() { return this; @@ -2446,7 +2452,7 @@ void LLVOAvatar::idleUpdateWindEffect() LLVector3 velocity = getVelocity(); F32 speed = velocity.length(); //RN: velocity varies too much frame to frame for this to work - mRippleAccel.clearVec();//lerp(mRippleAccel, (velocity - mLastVel) * time_delta, LLCriticalDamp::getInterpolant(0.02f)); + mRippleAccel.clearVec();//lerp(mRippleAccel, (velocity - mLastVel) * time_delta, LLSmoothInterpolation::getInterpolant(0.02f)); mLastVel = velocity; LLVector4 wind; wind.setVec(getRegion()->mWind.getVelocityNoisy(getPositionAgent(), 4.f) - velocity); @@ -2469,11 +2475,11 @@ void LLVOAvatar::idleUpdateWindEffect() F32 interp; if (wind.mV[VW] > mWindVec.mV[VW]) { - interp = LLCriticalDamp::getInterpolant(0.2f); + interp = LLSmoothInterpolation::getInterpolant(0.2f); } else { - interp = LLCriticalDamp::getInterpolant(0.4f); + interp = LLSmoothInterpolation::getInterpolant(0.4f); } mWindVec = lerp(mWindVec, wind, interp); @@ -2541,7 +2547,7 @@ void LLVOAvatar::idleUpdateNameTag(const LLVector3& root_pos_last) mVisibleChat = visible_chat; new_name = TRUE; } - + if (sRenderGroupTitles != mRenderGroupTitles) { mRenderGroupTitles = sRenderGroupTitles; @@ -2746,7 +2752,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) mNameText->setFont(LLFontGL::getFontSansSerif()); mNameText->setTextAlignment(LLHUDNameTag::ALIGN_TEXT_LEFT); mNameText->setFadeDistance(CHAT_NORMAL_RADIUS * 2.f, 5.f); - + std::deque<LLChat>::iterator chat_iter = mChats.begin(); mNameText->clearString(); @@ -2899,7 +2905,7 @@ void LLVOAvatar::idleUpdateNameTagPosition(const LLVector3& root_pos_last) mTargetRootToHeadOffset = head_offset; } - mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLCriticalDamp::getInterpolant(0.2f)); + mCurRootToHeadOffset = lerp(mCurRootToHeadOffset, mTargetRootToHeadOffset, LLSmoothInterpolation::getInterpolant(0.2f)); LLVector3 name_position = mRoot->getLastWorldPosition() + (mCurRootToHeadOffset * root_rot); name_position += (local_camera_up * root_rot) - (projected_vec(local_camera_at * root_rot, camera_to_av)); @@ -3364,7 +3370,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // Set the root rotation, but do so incrementally so that it // lags in time by some fixed amount. - //F32 u = LLCriticalDamp::getInterpolant(PELVIS_LAG); + //F32 u = LLSmoothInterpolation::getInterpolant(PELVIS_LAG); F32 pelvis_lag_time = 0.f; if (self_in_mouselook) { @@ -3707,7 +3713,7 @@ bool LLVOAvatar::shouldAlphaMask() //----------------------------------------------------------------------------- // renderSkinned() //----------------------------------------------------------------------------- -U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) +U32 LLVOAvatar::renderSkinned() { U32 num_indices = 0; @@ -3868,75 +3874,62 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) //-------------------------------------------------------------------- // render all geometry attached to the skeleton //-------------------------------------------------------------------- - static LLStat render_stat; - LLViewerJointMesh::sRenderPass = pass; - - if (pass == AVATAR_RENDER_PASS_SINGLE) + bool should_alpha_mask = shouldAlphaMask(); + LLGLState test(GL_ALPHA_TEST, should_alpha_mask); + + if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) { - - bool should_alpha_mask = shouldAlphaMask(); - LLGLState test(GL_ALPHA_TEST, should_alpha_mask); - - if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) - { - gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); - } - - BOOL first_pass = TRUE; - if (!LLDrawPoolAvatar::sSkipOpaque) + gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); + } + + BOOL first_pass = TRUE; + if (!LLDrawPoolAvatar::sSkipOpaque) + { + if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { - if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) + if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy) { - if (isTextureVisible(TEX_HEAD_BAKED) || mIsDummy) + LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); + if (head_mesh) { - LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); - if (head_mesh) - { - num_indices += head_mesh->render(mAdjustedPixelArea, TRUE, mIsDummy); - } - first_pass = FALSE; - } - } - if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy) - { - LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); - if (upper_mesh) - { - num_indices += upper_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); - } - first_pass = FALSE; - } - - if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy) - { - LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); - if (lower_mesh) - { - num_indices += lower_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + num_indices += head_mesh->render(mAdjustedPixelArea, TRUE, mIsDummy); } first_pass = FALSE; } } - - if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) + if (isTextureVisible(TEX_UPPER_BAKED) || mIsDummy) { - gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); + if (upper_mesh) + { + num_indices += upper_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } + first_pass = FALSE; } - - if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) + + if (isTextureVisible(TEX_LOWER_BAKED) || mIsDummy) { - LLGLState blend(GL_BLEND, !mIsDummy); - LLGLState test(GL_ALPHA_TEST, !mIsDummy); - num_indices += renderTransparent(first_pass); + LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); + if (lower_mesh) + { + num_indices += lower_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } + first_pass = FALSE; } } - LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE; + if (should_alpha_mask && !LLGLSLShader::sNoFixedFunction) + { + gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); + } - //llinfos << "Avatar render: " << render_timer.getElapsedTimeF32() << llendl; - - //render_stat.addValue(render_timer.getElapsedTimeF32()*1000.f); + if (!LLDrawPoolAvatar::sSkipTransparent || LLPipeline::sImpostorRender) + { + LLGLState blend(GL_BLEND, !mIsDummy); + LLGLState test(GL_ALPHA_TEST, !mIsDummy); + num_indices += renderTransparent(first_pass); + } return num_indices; } @@ -5108,7 +5101,7 @@ BOOL LLVOAvatar::loadSkeletonNode () { return FALSE; } - + // ATTACHMENTS { LLAvatarXmlInfo::attachment_info_list_t::iterator iter; @@ -6082,7 +6075,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 (isAgentAvatarValid()) { gAgentAvatarp->addMetricsTimerRecord(record); @@ -6290,11 +6283,11 @@ void LLVOAvatar::updateMeshTextures() use_lkg_baked_layer[i], last_id_string.c_str()); } - + for (U32 i=0; i < mBakedTextureDatas.size(); i++) { debugColorizeSubMeshes(i, LLColor4::white); - + LLViewerTexLayerSet* layerset = getTexLayerSet(i); if (use_lkg_baked_layer[i] && !isUsingLocalAppearance() ) { @@ -6754,7 +6747,7 @@ void dump_visual_param(apr_file_t* file, LLVisualParam* viewer_param, F32 value) // param_location_name(vparam->getParamLocation()).c_str() ); } - + void LLVOAvatar::dumpAppearanceMsgParams( const std::string& dump_prefix, const LLAppearanceMessageContents& contents) @@ -6821,7 +6814,7 @@ void LLVOAvatar::parseAppearanceMessage(LLMessageSystem* mesgsys, LLAppearanceMe // For future use: //mesgsys->getU32Fast(_PREHASH_AppearanceData, _PREHASH_Flags, appearance_flags, 0); } - + // Parse visual params, if any. S32 num_blocks = mesgsys->getNumberOfBlocksFast(_PREHASH_VisualParam); bool drop_visual_params_debug = gSavedSettings.getBOOL("BlockSomeAvatarAppearanceVisualParams") && (ll_rand(2) == 0); // pretend that ~12% of AvatarAppearance messages arrived without a VisualParam block, for testing @@ -7245,7 +7238,7 @@ void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTextu LLUUID *avatar_idp = (LLUUID *)userdata; LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); - + if (selfp) { LL_DEBUGS("Avatar") << selfp->avString() << "discard_level " << discard_level << " success " << success << " final " << final << LL_ENDL; @@ -7559,14 +7552,14 @@ void LLVOAvatar::cullAvatarsByPixelArea() if (gFrameTimeSeconds != sUnbakedUpdateTime) // only update once per frame { sUnbakedUpdateTime = gFrameTimeSeconds; - sUnbakedTime += gFrameIntervalSeconds; + sUnbakedTime += gFrameIntervalSeconds.value(); } if (grey_avatars > 0) { if (gFrameTimeSeconds != sGreyUpdateTime) // only update once per frame { sGreyUpdateTime = gFrameTimeSeconds; - sGreyTime += gFrameIntervalSeconds; + sGreyTime += gFrameIntervalSeconds.value(); } } } @@ -7619,7 +7612,7 @@ void LLVOAvatar::setIsUsingServerBakes(BOOL newval) // virtual void LLVOAvatar::removeMissingBakedTextures() -{ +{ } //virtual diff --git a/indra/newview/llvoavatar.h b/indra/newview/llvoavatar.h index 85f6f25009..c814d4c129 100755 --- a/indra/newview/llvoavatar.h +++ b/indra/newview/llvoavatar.h @@ -33,7 +33,7 @@ #include <string> #include <vector> -#include <boost/signals2.hpp> +#include <boost/signals2/trackable.hpp> #include "imageids.h" // IMG_INVISIBLE #include "llavatarappearance.h" @@ -74,6 +74,7 @@ struct LLVOAvatarChildJoint; //class LLViewerJoint; struct LLAppearanceMessageContents; struct LLVOAvatarSkeletonInfo; +class LLViewerJointMesh; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // LLVOAvatar @@ -372,7 +373,7 @@ public: bool isVisuallyMuted() const; U32 renderRigid(); - U32 renderSkinned(EAvatarRenderPass pass); + U32 renderSkinned(); F32 getLastSkinTime() { return mLastSkinTime; } U32 renderTransparent(BOOL first_pass); void renderCollisionVolumes(); diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index d54eb5f040..9ab910f7fd 100755 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -43,6 +43,7 @@ #include "llhudeffecttrail.h" #include "llhudmanager.h" #include "llinventoryfunctions.h" +#include "lllocaltextureobject.h" #include "llnotificationsutil.h" #include "llselectmgr.h" #include "lltoolgrab.h" // for needsRenderBeam @@ -789,7 +790,10 @@ U32 LLVOAvatarSelf::processUpdateMessage(LLMessageSystem *mesgsys, updateMeshTextures(); // unpack the texture UUIDs to the texture slots - retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); + if(mesgsys != NULL) + { + retval = unpackTEMessage(mesgsys, _PREHASH_ObjectData, (S32) block_num); + } // need to trigger a few operations to get the avatar to use the new bakes for (U32 i = 0; i < mBakedTextureDatas.size(); i++) @@ -896,17 +900,11 @@ void LLVOAvatarSelf::updateRegion(LLViewerRegion *regionp) if (mLastRegionHandle != 0) { ++mRegionCrossingCount; - F64 delta = (F64)mRegionCrossingTimer.getElapsedTimeF32(); - F64 avg = (mRegionCrossingCount == 1) ? 0 : LLViewerStats::getInstance()->getStat(LLViewerStats::ST_CROSSING_AVG); - F64 delta_avg = (delta + avg*(mRegionCrossingCount-1)) / mRegionCrossingCount; - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CROSSING_AVG, delta_avg); - - F64 max = (mRegionCrossingCount == 1) ? 0 : LLViewerStats::getInstance()->getStat(LLViewerStats::ST_CROSSING_MAX); - max = llmax(delta, max); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CROSSING_MAX, max); + LLTrace::Seconds delta = mRegionCrossingTimer.getElapsedTimeF32(); + record(LLStatViewer::REGION_CROSSING_TIME, delta); // Diagnostics - llinfos << "Region crossing took " << (F32)(delta * 1000.0) << " ms " << llendl; + llinfos << "Region crossing took " << (F32)(delta * 1000.0).value() << " ms " << llendl; } if (regionp) { @@ -2233,7 +2231,7 @@ LLSD LLVOAvatarSelf::metricsData() result["timers"]["ruth"] = mRuthTimer.getElapsedTimeF32(); result["timers"]["invisible"] = mInvisibleTimer.getElapsedTimeF32(); result["timers"]["fully_loaded"] = mFullyLoadedTimer.getElapsedTimeF32(); - result["startup"] = LLStartUp::getPhases().dumpPhases(); + result["startup"] = LLStartUp::getPhases().asLLSD(); return result; } @@ -2351,7 +2349,7 @@ LLSD summarize_by_buckets(std::vector<LLSD> in_records, accum_it != accum.end(); ++accum_it) { LLSD out_record = accum_it->first; - out_record["stats"] = accum_it->second.getData(); + out_record["stats"] = accum_it->second.asLLSD(); result.append(out_record); } return result; @@ -2586,7 +2584,7 @@ void LLVOAvatarSelf::addLocalTextureStats( ETextureIndex type, LLViewerFetchedTe { F32 desired_pixels; desired_pixels = llmin(mPixelArea, (F32)getTexImageArea()); - + imagep->setBoostLevel(getAvatarBoostLevel()); imagep->setAdditionalDecodePriority(SELF_ADDITIONAL_PRI) ; imagep->resetTextureStats(); @@ -2851,7 +2849,7 @@ void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**) llinfos << "TAT: rebake - matched entry " << (S32)index << llendl; gAgentAvatarp->invalidateComposite(layer_set, TRUE); found = TRUE; - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES); + add(LLStatViewer::TEX_REBAKES, 1); } } } @@ -2887,7 +2885,7 @@ void LLVOAvatarSelf::forceBakeAllTextures(bool slam_for_debug) } invalidateComposite(layer_set, TRUE); - LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TEX_REBAKES); + add(LLStatViewer::TEX_REBAKES, 1); } else { @@ -3076,7 +3074,7 @@ void LLVOAvatarSelf::deleteScratchTextures() sScratchTexNames.deleteAllData(); sScratchTexLastBindTime.deleteAllData(); - LLImageGL::sGlobalTextureMemoryInBytes -= sScratchTexBytes; + LLImageGL::sGlobalTextureMemory -= sScratchTexBytes; sScratchTexBytes = 0; } } diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp index 7db19c5c1b..5e2d2efc5e 100755 --- a/indra/newview/llvocache.cpp +++ b/indra/newview/llvocache.cpp @@ -29,6 +29,12 @@ #include "llerror.h" #include "llregionhandle.h" #include "llviewercontrol.h" +#include "llviewerobjectlist.h" +#include "lldrawable.h" +#include "llviewerregion.h" +#include "pipeline.h" + +LLTrace::MemStatHandle LLVOCachePartition::sMemStat("LLVOCachePartition"); BOOL check_read(LLAPRFile* apr_file, void* src, S32 n_bytes) { @@ -46,12 +52,18 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes) //--------------------------------------------------------------------------- LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp) - : + : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mLocalID(local_id), mCRC(crc), + mUpdateFlags(-1), mHitCount(0), mDupeCount(0), - mCRCChangeCount(0) + mCRCChangeCount(0), + mState(INACTIVE), + mMinFrameRange(64), + mSceneContrib(0.f), + mTouched(TRUE), + mParentID(0) { mBuffer = new U8[dp.getBufferSize()]; mDP.assignBuffer(mBuffer, dp.getBufferSize()); @@ -59,24 +71,39 @@ LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer & } LLVOCacheEntry::LLVOCacheEntry() - : + : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), mLocalID(0), mCRC(0), + mUpdateFlags(-1), mHitCount(0), mDupeCount(0), mCRCChangeCount(0), - mBuffer(NULL) + mBuffer(NULL), + mState(INACTIVE), + mMinFrameRange(64), + mSceneContrib(0.f), + mTouched(TRUE), + mParentID(0) { mDP.assignBuffer(mBuffer, 0); } LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) - : mBuffer(NULL) + : LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY), + mBuffer(NULL), + mUpdateFlags(-1), + mState(INACTIVE), + mMinFrameRange(64), + mSceneContrib(0.f), + mTouched(FALSE), + mParentID(0) { S32 size = -1; BOOL success; mDP.assignBuffer(mBuffer, 0); + setOctreeEntry(NULL); + success = check_read(apr_file, &mLocalID, sizeof(U32)); if(success) { @@ -132,32 +159,88 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file) mDupeCount = 0; mCRCChangeCount = 0; mBuffer = NULL; + mEntry = NULL; + mState = 0; } } LLVOCacheEntry::~LLVOCacheEntry() { mDP.freeBuffer(); + //llassert(mState == INACTIVE); } +//virtual +void LLVOCacheEntry::setOctreeEntry(LLViewerOctreeEntry* entry) +{ + if(!entry && mDP.getBufferSize() > 0) + { + LLUUID fullid; + LLViewerObject::unpackUUID(&mDP, fullid, "ID"); + + LLViewerObject* obj = gObjectList.findObject(fullid); + if(obj && obj->mDrawable) + { + entry = obj->mDrawable->getEntry(); + } + } -// New CRC means the object has changed. -void LLVOCacheEntry::assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp) + LLViewerOctreeEntryData::setOctreeEntry(entry); +} + +void LLVOCacheEntry::moveTo(LLVOCacheEntry* new_entry) { - if ( (mCRC != crc) - ||(mDP.getBufferSize() == 0)) + //copy LLViewerOctreeEntry + if(mEntry.notNull()) { - mCRC = crc; - mHitCount = 0; - mCRCChangeCount++; + new_entry->setOctreeEntry(mEntry); + mEntry = NULL; + } + + //copy children + S32 num_children = getNumOfChildren(); + for(S32 i = 0; i < num_children; i++) + { + new_entry->addChild(getChild(i)); + } + mChildrenList.clear(); +} - mDP.freeBuffer(); - mBuffer = new U8[dp.getBufferSize()]; - mDP.assignBuffer(mBuffer, dp.getBufferSize()); - mDP = dp; +void LLVOCacheEntry::setState(U32 state) +{ + mState = state; + + if(getState() == ACTIVE) + { + const S32 MIN_REAVTIVE_INTERVAL = 32; + U32 last_visible = getVisible(); + + setVisible(); + + if(getVisible() - last_visible < MIN_REAVTIVE_INTERVAL + mMinFrameRange) + { + mMinFrameRange = llmin(mMinFrameRange * 2, 2048); + } + else + { + mMinFrameRange = 64; //reset + } } } +//virtual +S32 LLVOCacheEntry::getMinFrameRange()const +{ + return mMinFrameRange; +} + +void LLVOCacheEntry::addChild(LLVOCacheEntry* entry) +{ + llassert(entry != NULL); + + mChildrenList.push_back(entry); +} + LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc) { if ( (mCRC != crc) @@ -170,9 +253,20 @@ LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP(U32 crc) return &mDP; } +LLDataPackerBinaryBuffer *LLVOCacheEntry::getDP() +{ + if (mDP.getBufferSize() == 0) + { + //llinfos << "Not getting cache entry, invalid!" << llendl; + return NULL; + } + + return &mDP; +} void LLVOCacheEntry::recordHit() { + setTouched(); mHitCount++; } @@ -189,6 +283,11 @@ void LLVOCacheEntry::dump() const BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const { + if(!mEntry) + { + return FALSE; + } + BOOL success; success = check_write(apr_file, (void*)&mLocalID, sizeof(U32)); if(success) @@ -221,49 +320,183 @@ BOOL LLVOCacheEntry::writeToFile(LLAPRFile* apr_file) const return success ; } +void LLVOCacheEntry::calcSceneContribution(const LLVector3& camera_origin, bool needs_update, U32 last_update) +{ + if(!needs_update && getVisible() >= last_update) + { + return; //no need to update + } + + const LLVector4a& center = getPositionGroup(); + + LLVector4a origin; + origin.load3(camera_origin.mV); + + LLVector4a lookAt; + lookAt.setSub(center, origin); + F32 squared_dist = lookAt.dot3(lookAt).getF32(); + + F32 rad = getBinRadius(); + mSceneContrib = rad * rad / squared_dist; + + setVisible(); +} + +void LLVOCacheEntry::setBoundingInfo(const LLVector3& pos, const LLVector3& scale) +{ + LLVector4a center, newMin, newMax; + center.load3(pos.mV); + LLVector4a size; + size.load3(scale.mV); + newMin.setSub(center, size); + newMax.setAdd(center, size); + + setPositionGroup(center); + setSpatialExtents(newMin, newMax); + setBinRadius(llmin(size.getLength3().getF32() * 4.f, 256.f)); +} + //------------------------------------------------------------------- -//LLVOCache +//LLVOCachePartition //------------------------------------------------------------------- -// Format string used to construct filename for the object cache -static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; +LLVOCachePartition::LLVOCachePartition(LLViewerRegion* regionp) +{ + mLODPeriod = 16; + mRegionp = regionp; + mPartitionType = LLViewerRegion::PARTITION_VO_CACHE; + + new LLOcclusionCullingGroup(mOctree, this); +} -const U32 MAX_NUM_OBJECT_ENTRIES = 128 ; -const U32 MIN_ENTRIES_TO_PURGE = 16 ; -const U32 INVALID_TIME = 0 ; -const char* object_cache_dirname = "objectcache"; -const char* header_filename = "object.cache"; +void LLVOCachePartition::addEntry(LLViewerOctreeEntry* entry) +{ + llassert(entry->hasVOCacheEntry()); -LLVOCache* LLVOCache::sInstance = NULL; + mOctree->insert(entry); +} + +void LLVOCachePartition::removeEntry(LLViewerOctreeEntry* entry) +{ + entry->getVOCacheEntry()->setGroup(NULL); -//static -LLVOCache* LLVOCache::getInstance() -{ - if(!sInstance) + llassert(!entry->getGroup()); +} + +class LLVOCacheOctreeCull : public LLViewerOctreeCull +{ +public: + LLVOCacheOctreeCull(LLCamera* camera, LLViewerRegion* regionp, const LLVector3& shift, bool use_object_cache_occlusion) + : LLViewerOctreeCull(camera), + mRegionp(regionp) { - sInstance = new LLVOCache() ; + mLocalShift = shift; + mUseObjectCacheOcclusion = (use_object_cache_occlusion && LLPipeline::sUseOcclusion); } - return sInstance ; -} -//static -BOOL LLVOCache::hasInstance() -{ - return sInstance != NULL ; -} + virtual bool earlyFail(LLviewerOctreeGroup* base_group) + { + if( mUseObjectCacheOcclusion && + base_group->getOctreeNode()->getParent()) //never occlusion cull the root node + { + LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; + if(group->needsUpdate()) + { + return false; //needs to issue new occlusion culling check. + } + + group->checkOcclusion(); + + if (group->isOcclusionState(LLSpatialGroup::OCCLUDED)) + { + return true; + } + } + + return false; + } + + virtual S32 frustumCheck(const LLviewerOctreeGroup* group) + { + S32 res = AABBInRegionFrustumGroupBounds(group); + + //S32 res = AABBInRegionFrustumNoFarClipGroupBounds(group); + if (res != 0) + { + res = llmin(res, AABBRegionSphereIntersectGroupExtents(group, mLocalShift)); + } + return res; + } + + virtual S32 frustumCheckObjects(const LLviewerOctreeGroup* group) + { + S32 res = AABBInRegionFrustumObjectBounds(group); + + //S32 res = AABBInRegionFrustumNoFarClipObjectBounds(group); + if (res != 0) + { + res = llmin(res, AABBRegionSphereIntersectObjectExtents(group, mLocalShift)); + } + return res; + } -//static -void LLVOCache::destroyClass() + virtual void processGroup(LLviewerOctreeGroup* base_group) + { + if(mUseObjectCacheOcclusion && base_group->getOctreeNode()->getParent()) + { + LLOcclusionCullingGroup* group = (LLOcclusionCullingGroup*)base_group; + if (group->needsUpdate() || group->mVisible[LLViewerCamera::sCurCameraID] < LLDrawable::getCurrentFrame() - 1) + { + ((LLOcclusionCullingGroup*)group)->doOcclusion(mCamera); + group->setVisible(); + return; //wait for occlusion culling results + } + } + mRegionp->addVisibleGroup(base_group); + } + +private: + LLViewerRegion* mRegionp; + LLVector3 mLocalShift; //shift vector from agent space to local region space. + bool mUseObjectCacheOcclusion; +}; + +S32 LLVOCachePartition::cull(LLCamera &camera) { - if(sInstance) + static LLCachedControl<bool> use_object_cache_occlusion(gSavedSettings,"UseObjectCacheOcclusion"); + + if(!LLViewerRegion::sVOCacheCullingEnabled) { - delete sInstance ; - sInstance = NULL ; + return 0; } + + ((LLviewerOctreeGroup*)mOctree->getListener(0))->rebound(); + + //localize the camera + LLVector3 region_agent = mRegionp->getOriginAgent(); + camera.calcRegionFrustumPlanes(region_agent); + + LLVOCacheOctreeCull culler(&camera, mRegionp, region_agent, use_object_cache_occlusion); + culler.traverse(mOctree); + + return 0; } +//------------------------------------------------------------------- +//LLVOCache +//------------------------------------------------------------------- +// Format string used to construct filename for the object cache +static const char OBJECT_CACHE_FILENAME[] = "objects_%d_%d.slc"; + +const U32 MAX_NUM_OBJECT_ENTRIES = 128 ; +const U32 MIN_ENTRIES_TO_PURGE = 16 ; +const U32 INVALID_TIME = 0 ; +const char* object_cache_dirname = "objectcache"; +const char* header_filename = "object.cache"; + + LLVOCache::LLVOCache(): - mInitialized(FALSE), - mReadOnly(TRUE), + mInitialized(false), + mReadOnly(true), mNumEntries(0), mCacheSize(1) { @@ -300,7 +533,7 @@ void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) llwarns << "Cache already initialized." << llendl; return ; } - mInitialized = TRUE ; + mInitialized = true; setDirNames(location); if (!mReadOnly) @@ -325,13 +558,19 @@ void LLVOCache::initCache(ELLPath location, U32 size, U32 cache_version) } } -void LLVOCache::removeCache(ELLPath location) +void LLVOCache::removeCache(ELLPath location, bool started) { + if(started) + { + removeCache(); + return; + } + if(mReadOnly) { llwarns << "Not removing cache at " << location << ": Cache is currently in read-only mode." << llendl; return ; - } + } llinfos << "about to remove the object cache due to settings." << llendl ; @@ -342,22 +581,25 @@ void LLVOCache::removeCache(ELLPath location) LLFile::rmdir(cache_dir); clearCacheInMemory(); - mInitialized = FALSE ; + mInitialized = false; } void LLVOCache::removeCache() { - llassert_always(mInitialized) ; + if(!mInitialized) + { + //OK to remove cache even it is not initialized. + llwarns << "Object cache is not initialized yet." << llendl; + } + if(mReadOnly) { llwarns << "Not clearing object cache: Cache is currently in read-only mode." << llendl; return ; } - llinfos << "about to remove the object cache due to some error." << llendl ; - std::string mask = "*"; - llinfos << "Removing cache at " << mObjectCacheDirName << llendl; + llinfos << "Removing object cache at " << mObjectCacheDirName << llendl; gDirUtilp->deleteFilesInDir(mObjectCacheDirName, mask); clearCacheInMemory() ; @@ -366,23 +608,23 @@ void LLVOCache::removeCache() void LLVOCache::removeEntry(HeaderEntryInfo* entry) { - llassert_always(mInitialized) ; + llassert_always(mInitialized); if(mReadOnly) { - return ; + return; } if(!entry) { - return ; + return; } - header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry) ; + header_entry_queue_t::iterator iter = mHeaderEntryQueue.find(entry); if(iter != mHeaderEntryQueue.end()) { - mHandleEntryMap.erase(entry->mHandle) ; - mHeaderEntryQueue.erase(iter) ; - removeFromCache(entry) ; - delete entry ; + mHandleEntryMap.erase(entry->mHandle); + mHeaderEntryQueue.erase(iter); + removeFromCache(entry); + delete entry; mNumEntries = mHandleEntryMap.size() ; } @@ -625,11 +867,10 @@ void LLVOCache::readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::voca { for (S32 i = 0; i < num_entries; i++) { - LLVOCacheEntry* entry = new LLVOCacheEntry(&apr_file); + LLPointer<LLVOCacheEntry> entry = new LLVOCacheEntry(&apr_file); if (!entry->getLocalID()) { llwarns << "Aborting cache file load for " << filename << ", cache file corruption!" << llendl; - delete entry ; success = false ; break ; } @@ -665,7 +906,7 @@ void LLVOCache::purgeEntries(U32 size) mNumEntries = mHandleEntryMap.size() ; } -void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) +void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled) { if(!mEnabled) { @@ -738,7 +979,10 @@ void LLVOCache::writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry: for (LLVOCacheEntry::vocache_entry_map_t::const_iterator iter = cache_entry_map.begin(); success && iter != cache_entry_map.end(); ++iter) { - success = iter->second->writeToFile(&apr_file) ; + if(!removal_enabled || iter->second->isTouched()) + { + success = iter->second->writeToFile(&apr_file) ; + } } } } diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h index 14e3b4c793..e46fec9dc3 100755 --- a/indra/newview/llvocache.h +++ b/indra/newview/llvocache.h @@ -29,51 +29,138 @@ #include "lluuid.h" #include "lldatapacker.h" -#include "lldlinked.h" #include "lldir.h" - +#include "llvieweroctree.h" +#include "llapr.h" //--------------------------------------------------------------------------- // Cache entries class LLVOCacheEntry; +class LLCamera; -class LLVOCacheEntry +class LLVOCacheEntry : public LLViewerOctreeEntryData { public: + enum //low 16-bit state + { + INACTIVE = 0x00000000, //not visible + IN_QUEUE = 0x00000001, //in visible queue, object to be created + WAITING = 0x00000002, //object creation request sent + ACTIVE = 0x00000004 //object created, and in rendering pipeline. + }; + + struct CompareVOCacheEntry + { + bool operator()(const LLVOCacheEntry* const& lhs, const LLVOCacheEntry* const& rhs) + { + F32 lpa = lhs->getSceneContribution(); + F32 rpa = rhs->getSceneContribution(); + + //larger pixel area first + if(lpa > rpa) + { + return true; + } + else if(lpa < rpa) + { + return false; + } + else + { + return lhs < rhs; + } + } + }; +protected: + ~LLVOCacheEntry(); +public: LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp); LLVOCacheEntry(LLAPRFile* apr_file); - LLVOCacheEntry(); - ~LLVOCacheEntry(); + LLVOCacheEntry(); + void setState(U32 state); + //void clearState(U32 state) {mState &= ~state;} + bool isState(U32 state) {return mState == state;} + bool hasState(U32 state) {return mState & state;} + U32 getState() const {return mState;} + U32 getLocalID() const { return mLocalID; } U32 getCRC() const { return mCRC; } S32 getHitCount() const { return mHitCount; } S32 getCRCChangeCount() const { return mCRCChangeCount; } + S32 getMinFrameRange()const; + + void calcSceneContribution(const LLVector3& camera_origin, bool needs_update, U32 last_update); + void setSceneContribution(F32 scene_contrib) {mSceneContrib = scene_contrib;} + F32 getSceneContribution() const { return mSceneContrib;} void dump() const; BOOL writeToFile(LLAPRFile* apr_file) const; - void assignCRC(U32 crc, LLDataPackerBinaryBuffer &dp); LLDataPackerBinaryBuffer *getDP(U32 crc); + LLDataPackerBinaryBuffer *getDP(); void recordHit(); void recordDupe() { mDupeCount++; } + + void moveTo(LLVOCacheEntry* new_entry); //copy variables + /*virtual*/ void setOctreeEntry(LLViewerOctreeEntry* entry); + + void setParentID(U32 id) {mParentID = id;} + U32 getParentID() const {return mParentID;} + + void addChild(LLVOCacheEntry* entry); + LLVOCacheEntry* getChild(S32 i) {return mChildrenList[i];} + S32 getNumOfChildren() {return mChildrenList.size();} + void clearChildrenList() {mChildrenList.clear();} + + //called from processing object update message + void setBoundingInfo(const LLVector3& pos, const LLVector3& scale); + + void setTouched(BOOL touched = TRUE) {mTouched = touched;} + BOOL isTouched() const {return mTouched;} + + void setUpdateFlags(U32 flags) {mUpdateFlags = flags;} + U32 getUpdateFlags() const {return mUpdateFlags;} public: - typedef std::map<U32, LLVOCacheEntry*> vocache_entry_map_t; + typedef std::map<U32, LLPointer<LLVOCacheEntry> > vocache_entry_map_t; + typedef std::set<LLVOCacheEntry*> vocache_entry_set_t; + typedef std::set<LLVOCacheEntry*, CompareVOCacheEntry> vocache_entry_priority_list_t; protected: U32 mLocalID; + U32 mParentID; U32 mCRC; + U32 mUpdateFlags; //receive from sim S32 mHitCount; S32 mDupeCount; S32 mCRCChangeCount; LLDataPackerBinaryBuffer mDP; U8 *mBuffer; + + F32 mSceneContrib; //projected scene contributuion of this object. + S32 mMinFrameRange; + U32 mState; //high 16 bits reserved for special use. + std::vector<LLVOCacheEntry*> mChildrenList; //children entries in a linked set. + + BOOL mTouched; //if set, this entry is valid, otherwise it is invalid. +}; + +class LLVOCachePartition : public LLViewerOctreePartition, public LLTrace::MemTrackable<LLVOCachePartition> +{ +public: + LLVOCachePartition(LLViewerRegion* regionp); + + void addEntry(LLViewerOctreeEntry* entry); + void removeEntry(LLViewerOctreeEntry* entry); + /*virtual*/ S32 cull(LLCamera &camera); + + static LLTrace::MemStatHandle sMemStat; }; // //Note: LLVOCache is not thread-safe // -class LLVOCache +class LLVOCache : public LLSingleton<LLVOCache> { private: struct HeaderEntryInfo @@ -106,19 +193,20 @@ private: typedef std::set<HeaderEntryInfo*, header_entry_less> header_entry_queue_t; typedef std::map<U64, HeaderEntryInfo*> handle_entry_map_t; private: + friend class LLSingleton<LLVOCache>; LLVOCache() ; public: ~LLVOCache() ; void initCache(ELLPath location, U32 size, U32 cache_version) ; - void removeCache(ELLPath location) ; + void removeCache(ELLPath location, bool started = false) ; void readFromCache(U64 handle, const LLUUID& id, LLVOCacheEntry::vocache_entry_map_t& cache_entry_map) ; - void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache) ; + void writeToCache(U64 handle, const LLUUID& id, const LLVOCacheEntry::vocache_entry_map_t& cache_entry_map, BOOL dirty_cache, bool removal_enabled); void removeEntry(U64 handle) ; - void setReadOnly(BOOL read_only) {mReadOnly = read_only;} + void setReadOnly(bool read_only) {mReadOnly = read_only;} private: void setDirNames(ELLPath location); @@ -134,9 +222,9 @@ private: BOOL updateEntry(const HeaderEntryInfo* entry); private: - BOOL mEnabled; - BOOL mInitialized ; - BOOL mReadOnly ; + bool mEnabled; + bool mInitialized ; + bool mReadOnly ; HeaderMetaInfo mMetaInfo; U32 mCacheSize; U32 mNumEntries; @@ -145,12 +233,6 @@ private: LLVolatileAPRPool* mLocalAPRFilePoolp ; header_entry_queue_t mHeaderEntryQueue; handle_entry_map_t mHandleEntryMap; - - static LLVOCache* sInstance ; -public: - static LLVOCache* getInstance() ; - static BOOL hasInstance() ; - static void destroyClass() ; }; #endif diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index 6a25b765cf..e9efc7db9a 100755 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -603,8 +603,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; @@ -624,9 +624,9 @@ void LLGrassPartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count LLViewerCamera* camera = LLViewerCamera::getInstance(); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawablep = *i; + LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable(); - if (drawablep->isDead()) + if (!drawablep || drawablep->isDead()) { continue; } @@ -738,8 +738,10 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group) LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), //facep->getTexture(), buffer, fullbright); - info->mExtents[0] = group->mObjectExtents[0]; - info->mExtents[1] = group->mObjectExtents[1]; + + const LLVector4a* exts = group->getObjectExtents(); + info->mExtents[0] = exts[0]; + info->mExtents[1] = exts[1]; info->mVSize = vsize; draw_vec.push_back(info); //for alpha sorting diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp index ac2a34ba1e..312842a70f 100755 --- a/indra/newview/llvoicechannel.cpp +++ b/indra/newview/llvoicechannel.cpp @@ -28,12 +28,14 @@ #include "llagent.h" #include "llfloaterreg.h" +#include "llhttpclient.h" #include "llimview.h" #include "llnotifications.h" #include "llnotificationsutil.h" #include "llpanel.h" #include "llrecentpeople.h" #include "llviewercontrol.h" +#include "llviewerregion.h" #include "llvoicechannel.h" diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h index 714dd6a9f2..bd9ea029a9 100755 --- a/indra/newview/llvoiceclient.h +++ b/indra/newview/llvoiceclient.h @@ -34,7 +34,6 @@ class LLVOAvatar; #include "lliosocket.h" #include "v3math.h" #include "llframetimer.h" -#include "llviewerregion.h" #include "llcallingcard.h" // for LLFriendObserver #include "llsecapi.h" #include "llcontrol.h" diff --git a/indra/newview/llvoinventorylistener.h b/indra/newview/llvoinventorylistener.h index bf14d19b01..c50c475478 100755 --- a/indra/newview/llvoinventorylistener.h +++ b/indra/newview/llvoinventorylistener.h @@ -30,7 +30,9 @@ #ifndef LL_LLVOINVENTORYLISTENER_H #define LL_LLVOINVENTORYLISTENER_H -#include "llviewerobject.h" +#include "llinventory.h" + +class LLViewerObject; class LLVOInventoryListener { diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp index 0b34bbb90f..41b306007d 100755 --- a/indra/newview/llvopartgroup.cpp +++ b/indra/newview/llvopartgroup.cpp @@ -489,8 +489,8 @@ U32 LLVOPartGroup::getPartitionType() const return LLViewerRegion::PARTITION_PARTICLE; } -LLParticlePartition::LLParticlePartition() -: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB) +LLParticlePartition::LLParticlePartition(LLViewerRegion* regionp) +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK | LLVertexBuffer::MAP_TEXTURE_INDEX, TRUE, GL_STREAM_DRAW_ARB, regionp) { mRenderPass = LLRenderPass::PASS_ALPHA; mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES; @@ -499,8 +499,8 @@ LLParticlePartition::LLParticlePartition() mLODPeriod = 1; } -LLHUDParticlePartition::LLHUDParticlePartition() : - LLParticlePartition() +LLHUDParticlePartition::LLHUDParticlePartition(LLViewerRegion* regionp) : + LLParticlePartition(regionp) { mDrawableType = LLPipeline::RENDER_TYPE_HUD_PARTICLES; mPartitionType = LLViewerRegion::PARTITION_HUD_PARTICLE; @@ -510,7 +510,7 @@ static LLFastTimer::DeclareTimer FTM_REBUILD_PARTICLE_VBO("Particle VBO"); void LLParticlePartition::rebuildGeom(LLSpatialGroup* group) { - if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) + if (group->isDead() || !group->hasState(LLSpatialGroup::GEOM_DIRTY)) { return; } @@ -558,9 +558,9 @@ void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_co LLViewerCamera* camera = LLViewerCamera::getInstance(); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawablep = *i; + LLDrawable* drawablep = (LLDrawable*)(*i)->getDrawable(); - if (drawablep->isDead()) + if (!drawablep || drawablep->isDead()) { continue; } @@ -699,8 +699,10 @@ void LLParticlePartition::getGeometry(LLSpatialGroup* group) LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), //facep->getTexture(), buffer, fullbright); - info->mExtents[0] = group->mObjectExtents[0]; - info->mExtents[1] = group->mObjectExtents[1]; + + const LLVector4a* exts = group->getObjectExtents(); + info->mExtents[0] = exts[0]; + info->mExtents[1] = exts[1]; info->mVSize = vsize; draw_vec.push_back(info); //for alpha sorting diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp index 36793017ed..0a119e853a 100755 --- a/indra/newview/llvosky.cpp +++ b/indra/newview/llvosky.cpp @@ -2146,7 +2146,7 @@ void LLVOSky::updateFog(const F32 distance) // get the water param manager variables float water_fog_density = LLWaterParamManager::getInstance()->getFogDensity(); - LLColor4 water_fog_color = LLDrawPoolWater::sWaterFogColor.mV; + LLColor4 water_fog_color(LLDrawPoolWater::sWaterFogColor.mV); // adjust the color based on depth. We're doing linear approximations float depth_scale = gSavedSettings.getF32("WaterGLFogDepthScale"); diff --git a/indra/newview/llvosurfacepatch.cpp b/indra/newview/llvosurfacepatch.cpp index de15f0ef43..5b7aee2427 100755 --- a/indra/newview/llvosurfacepatch.cpp +++ b/indra/newview/llvosurfacepatch.cpp @@ -1052,8 +1052,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/llvosurfacepatch.h b/indra/newview/llvosurfacepatch.h index a15878368e..21693e85e1 100755 --- a/indra/newview/llvosurfacepatch.h +++ b/indra/newview/llvosurfacepatch.h @@ -33,6 +33,8 @@ class LLSurfacePatch; class LLDrawPool; class LLVector2; +class LLFacePool; +class LLFace; class LLVOSurfacePatch : public LLStaticViewerObject { diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp index 145a0380d6..9a044968d2 100755 --- a/indra/newview/llvotree.cpp +++ b/indra/newview/llvotree.cpp @@ -1290,8 +1290,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 8730ef66bb..126055c8fb 100755 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -406,7 +406,7 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, dp->dumpBufferToLog(); llwarns << "Flushing cache files" << llendl; - if(LLVOCache::hasInstance() && getRegion()) + if(LLVOCache::instanceExists() && getRegion()) { LLVOCache::getInstance()->removeEntry(getRegion()->getHandle()) ; } @@ -1143,7 +1143,7 @@ void LLVOVolume::sculpt() { // Log first time, then every 100 afterwards otherwise this can flood the logs llwarns << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() << " at " << current_discard - << " is less than -2." << llendl; + << " is less than -2." << llendl; low_sculpty_discard_warning_count = 0; } @@ -1157,7 +1157,7 @@ void LLVOVolume::sculpt() { // Log first time, then every 100 afterwards otherwise this can flood the logs llwarns << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() << " at " << current_discard - << " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl; + << " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl; high_sculpty_discard_warning_count = 0; } @@ -3945,8 +3945,8 @@ 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) { mLODPeriod = 32; mDepthMask = FALSE; @@ -3956,8 +3956,8 @@ 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) { mDepthMask = FALSE; mLODPeriod = 32; @@ -4175,9 +4175,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) group->mLastUpdateViewAngle = group->mViewAngle; - if (!group->isState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) + if (!group->hasState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::ALPHA_DIRTY)) { - if (group->isState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) + if (group->hasState(LLSpatialGroup::MESH_DIRTY) && !LLPipeline::sDelayVBUpdate) { rebuildMesh(group); } @@ -4190,7 +4190,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) LLVOAvatar* pAvatarVO = NULL; - LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); if (bridge) { if (bridge->mAvatar.isNull()) @@ -4215,7 +4215,8 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) group->mSurfaceArea = 0; //cache object box size since it might be used for determining visibility - group->mObjectBoxSize = group->mObjectBounds[1].getLength3().getF32(); + const LLVector4a* bounds = group->getObjectBounds(); + group->mObjectBoxSize = bounds[1].getLength3().getF32(); group->clearDrawMap(); @@ -4226,10 +4227,10 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) std::vector<LLFace*> simple_faces; std::vector<LLFace*> alpha_faces; - U32 useage = group->mSpatialPartition->mBufferUsage; + U32 useage = group->getSpatialPartition()->mBufferUsage; - U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); - U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); + U32 max_total = (gSavedSettings.getS32("RenderMaxNodeSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); U32 cur_total = 0; @@ -4242,9 +4243,9 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //get all the faces into a list for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { - LLDrawable* drawablep = *drawable_iter; + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if (drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) + if (!drawablep || drawablep->isDead() || drawablep->isState(LLDrawable::FORCE_INVISIBLE) ) { continue; } @@ -4648,10 +4649,13 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) //drawables have been rebuilt, clear rebuild status for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { - LLDrawable* drawablep = *drawable_iter; + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if(drawablep) + { drawablep->clearState(LLDrawable::REBUILD_ALL); } } + } group->mLastUpdateTime = gFrameTimeSeconds; group->mBuilt = 1.f; @@ -4675,7 +4679,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) { llassert(group); - if (group && group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY)) + if (group && group->hasState(LLSpatialGroup::MESH_DIRTY) && !group->hasState(LLSpatialGroup::GEOM_DIRTY)) { LLFastTimer ftm(FTM_REBUILD_VOLUME_VB); LLFastTimer t(FTM_REBUILD_VOLUME_GEN_DRAW_INFO); //make sure getgeometryvolume shows up in the right place in timers @@ -4688,9 +4692,9 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { - LLDrawable* drawablep = *drawable_iter; + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if (!drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) + if (drawablep && !drawablep->isDead() && drawablep->isState(LLDrawable::REBUILD_ALL) && !drawablep->isState(LLDrawable::RIGGED) ) { LLVOVolume* vobj = drawablep->getVOVolume(); vobj->preRebuild(); @@ -4756,7 +4760,11 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group) llwarns << "Not all mapped vertex buffers are unmapped!" << llendl ; for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { - LLDrawable* drawablep = *drawable_iter; + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); + if(!drawablep) + { + continue; + } for (S32 i = 0; i < drawablep->getNumFaces(); ++i) { LLFace* face = drawablep->getFace(i); @@ -4829,7 +4837,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: #endif //calculate maximum number of vertices to store in a single buffer - U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->mSpatialPartition->mVertexDataMask); + U32 max_vertices = (gSavedSettings.getS32("RenderMaxVBOSize")*1024)/LLVertexBuffer::calcVertexSize(group->getSpatialPartition()->mVertexDataMask); max_vertices = llmin(max_vertices, (U32) 65535); { @@ -5220,7 +5228,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std:: void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) { //initialize to default usage for this partition - U32 usage = group->mSpatialPartition->mBufferUsage; + U32 usage = group->getSpatialPartition()->mBufferUsage; //clear off any old faces mFaceList.clear(); @@ -5229,9 +5237,9 @@ void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_coun for (LLSpatialGroup::element_iter drawable_iter = group->getDataBegin(); drawable_iter != group->getDataEnd(); ++drawable_iter) { - LLDrawable* drawablep = *drawable_iter; + LLDrawable* drawablep = (LLDrawable*)(*drawable_iter)->getDrawable(); - if (drawablep->isDead()) + if (!drawablep || drawablep->isDead()) { continue; } @@ -5269,7 +5277,7 @@ 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/llvowater.cpp b/indra/newview/llvowater.cpp index e8a1c3d1d6..50e7ed7bb5 100755 --- a/indra/newview/llvowater.cpp +++ b/indra/newview/llvowater.cpp @@ -298,15 +298,15 @@ 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/llvowlsky.cpp b/indra/newview/llvowlsky.cpp index 4e26587184..0f2f49a975 100755 --- a/indra/newview/llvowlsky.cpp +++ b/indra/newview/llvowlsky.cpp @@ -394,7 +394,7 @@ BOOL LLVOWLSky::updateGeometry(LLDrawable * drawable) segment->flush(); } - llinfos << "completed in " << llformat("%.2f", timer.getElapsedTimeF32()) << "seconds" << llendl; + llinfos << "completed in " << llformat("%.2f", timer.getElapsedTimeF32().value()) << "seconds" << llendl; } #else mStripsVerts = new LLVertexBuffer(LLDrawPoolWLSky::SKY_VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); diff --git a/indra/newview/llwatchdog.cpp b/indra/newview/llwatchdog.cpp index 4f582fc2db..c852f1869b 100755 --- a/indra/newview/llwatchdog.cpp +++ b/indra/newview/llwatchdog.cpp @@ -27,6 +27,7 @@ #include "llviewerprecompiledheaders.h" #include "llwatchdog.h" +#include "llthread.h" const U32 WATCHDOG_SLEEP_TIME_USEC = 1000000; diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp index ef1a953f59..79c2778253 100755 --- a/indra/newview/llwearablelist.cpp +++ b/indra/newview/llwearablelist.cpp @@ -148,7 +148,6 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID { LLFile::remove(std::string(filename)); } - LLViewerStats::getInstance()->incStat( LLViewerStats::ST_DOWNLOAD_FAILED ); LL_WARNS("Wearable") << "Wearable download failed: " << LLAssetStorage::getErrorString( status ) << " " << uuid << LL_ENDL; switch( status ) diff --git a/indra/newview/llwindebug.h b/indra/newview/llwindebug.h index 3837825d31..6f274c6f16 100755 --- a/indra/newview/llwindebug.h +++ b/indra/newview/llwindebug.h @@ -28,6 +28,7 @@ #define LL_LLWINDEBUG_H #include "stdtypes.h" +#include "llwin32headerslean.h" #include <dbghelp.h> class LLWinDebug: diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp index 793becf0c8..42a0be9e2f 100755 --- a/indra/newview/llworld.cpp +++ b/indra/newview/llworld.cpp @@ -55,7 +55,7 @@ #include "message.h" #include "pipeline.h" #include "llappviewer.h" // for do_disconnect() - +#include "llscenemonitor.h" #include <deque> #include <queue> #include <map> @@ -110,6 +110,7 @@ LLWorld::LLWorld() : gGL.getTexUnit(0)->bind(mDefaultWaterTexturep); mDefaultWaterTexturep->setAddressMode(LLTexUnit::TAM_CLAMP); + LLViewerRegion::sVOCacheCullingEnabled = gSavedSettings.getBOOL("ObjectCacheViewCullingEnabled") && gSavedSettings.getBOOL("ObjectCacheEnabled"); } @@ -122,10 +123,7 @@ void LLWorld::destroyClass() LLViewerRegion* region_to_delete = *region_it++; removeRegion(region_to_delete->getHost()); } - if(LLVOCache::hasInstance()) - { - LLVOCache::getInstance()->destroyClass() ; - } + LLViewerPartSim::getInstance()->destroyClass(); mDefaultWaterTexturep = NULL ; @@ -133,6 +131,11 @@ void LLWorld::destroyClass() { mEdgeWaterObjects[i] = NULL; } + + //make all visible drawbles invisible. + LLDrawable::incrementVisible(); + + LLSceneMonitor::deleteSingleton(); } @@ -599,7 +602,8 @@ void LLWorld::updateVisibilities() if (part) { LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); - if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1])) + const LLVector4a* bounds = group->getBounds(); + if (LLViewerCamera::getInstance()->AABBInFrustum(bounds[0], bounds[1])) { mCulledRegionList.erase(curiter); mVisibleRegionList.push_back(regionp); @@ -622,7 +626,8 @@ void LLWorld::updateVisibilities() if (part) { LLSpatialGroup* group = (LLSpatialGroup*) part->mOctree->getListener(0); - if (LLViewerCamera::getInstance()->AABBInFrustum(group->mBounds[0], group->mBounds[1])) + const LLVector4a* bounds = group->getBounds(); + if (LLViewerCamera::getInstance()->AABBInFrustum(bounds[0], bounds[1])) { regionp->calculateCameraDistance(); regionp->getLand().updatePatchVisibilities(gAgent); @@ -660,6 +665,13 @@ void LLWorld::updateRegions(F32 max_update_time) did_one = TRUE; } } + + mNumOfActiveCachedObjects = 0; + for (region_list_t::iterator iter = mRegionList.begin(); + iter != mRegionList.end(); ++iter) + { + mNumOfActiveCachedObjects += (*iter)->getNumOfActiveCachedObjects(); + } } void LLWorld::updateParticles() @@ -692,8 +704,10 @@ void LLWorld::updateNetStats() { LLViewerRegion* regionp = *iter; regionp->updateNetStats(); - bits += regionp->mBitStat.getCurrent(); - packets += llfloor( regionp->mPacketsStat.getCurrent() ); + bits += regionp->mBitsReceived; + packets += llfloor( regionp->mPacketsReceived ); + regionp->mBitsReceived = 0.f; + regionp->mPacketsReceived = 0.f; } S32 packets_in = gMessageSystem->mPacketsIn - mLastPacketsIn; @@ -702,19 +716,17 @@ void LLWorld::updateNetStats() S32 actual_in_bits = gMessageSystem->mPacketRing.getAndResetActualInBits(); S32 actual_out_bits = gMessageSystem->mPacketRing.getAndResetActualOutBits(); - LLViewerStats::getInstance()->mActualInKBitStat.addValue(actual_in_bits/1024.f); - LLViewerStats::getInstance()->mActualOutKBitStat.addValue(actual_out_bits/1024.f); - LLViewerStats::getInstance()->mKBitStat.addValue(bits/1024.f); - LLViewerStats::getInstance()->mPacketsInStat.addValue(packets_in); - LLViewerStats::getInstance()->mPacketsOutStat.addValue(packets_out); - LLViewerStats::getInstance()->mPacketsLostStat.addValue(gMessageSystem->mDroppedPackets); + + add(LLStatViewer::ACTUAL_IN_KBIT, LLTrace::Bits(actual_in_bits)); + add(LLStatViewer::ACTUAL_OUT_KBIT, LLTrace::Bits(actual_out_bits)); + add(LLStatViewer::KBIT, LLTrace::Bits(bits)); + add(LLStatViewer::PACKETS_IN, packets_in); + add(LLStatViewer::PACKETS_OUT, packets_out); + add(LLStatViewer::PACKETS_LOST, packets_lost); if (packets_in) { - LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(100.f*((F32)packets_lost/(F32)packets_in)); - } - else - { - LLViewerStats::getInstance()->mPacketsLostPercentStat.addValue(0.f); + F32 packet_loss = 100.f * ((F32)packets_lost/(F32)packets_in); + sample(LLStatViewer::PACKETS_LOST_PERCENT, packet_loss); } mLastPacketsIn = gMessageSystem->mPacketsIn; @@ -1127,6 +1139,7 @@ void send_agent_pause() } gObjectList.mWasPaused = TRUE; + LLViewerStats::instance().getRecording().stop(); } @@ -1156,8 +1169,8 @@ void send_agent_resume() gMessageSystem->sendReliable(regionp->getHost()); } - // Reset the FPS counter to avoid an invalid fps - LLViewerStats::getInstance()->mFPSStat.start(); + // Resume data collection to ignore invalid rates + LLViewerStats::instance().getRecording().resume(); LLAppViewer::instance()->resumeMainloopTimeout(); } diff --git a/indra/newview/llworld.h b/indra/newview/llworld.h index f350009d10..8187142b2b 100755 --- a/indra/newview/llworld.h +++ b/indra/newview/llworld.h @@ -144,6 +144,7 @@ public: U64 getSpaceTimeUSec() const; void getInfo(LLSD& info); + U32 getNumOfActiveCachedObjects() const {return mNumOfActiveCachedObjects;} public: typedef std::list<LLViewerRegion*> region_list_t; @@ -181,7 +182,7 @@ private: S32 mLastPacketsIn; S32 mLastPacketsOut; S32 mLastPacketsLost; - + U32 mNumOfActiveCachedObjects; U64 mSpaceTimeUSec; BOOL mClassicCloudsEnabled; diff --git a/indra/newview/llworldmapmessage.h b/indra/newview/llworldmapmessage.h index 12b6ef4792..ac1ea1607c 100755 --- a/indra/newview/llworldmapmessage.h +++ b/indra/newview/llworldmapmessage.h @@ -27,6 +27,8 @@ #ifndef LL_LLWORLDMAPMESSAGE_H #define LL_LLWORLDMAPMESSAGE_H +#include "boost/function.hpp" + // Handling of messages (send and process) as well as SLURL callback if necessary class LLMessageSystem; diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp index 1940cf541e..6759328b84 100755 --- a/indra/newview/llworldmapview.cpp +++ b/indra/newview/llworldmapview.cpp @@ -302,8 +302,8 @@ void LLWorldMapView::draw() mVisibleRegions.clear(); // animate pan if necessary - sPanX = lerp(sPanX, sTargetPanX, LLCriticalDamp::getInterpolant(0.1f)); - sPanY = lerp(sPanY, sTargetPanY, LLCriticalDamp::getInterpolant(0.1f)); + sPanX = lerp(sPanX, sTargetPanX, LLSmoothInterpolation::getInterpolant(0.1f)); + sPanY = lerp(sPanY, sTargetPanY, LLSmoothInterpolation::getInterpolant(0.1f)); const S32 width = getRect().getWidth(); const S32 height = getRect().getHeight(); diff --git a/indra/newview/llxmlrpctransaction.cpp b/indra/newview/llxmlrpctransaction.cpp index 0da70d398b..583196fb7a 100755 --- a/indra/newview/llxmlrpctransaction.cpp +++ b/indra/newview/llxmlrpctransaction.cpp @@ -25,6 +25,8 @@ */ #include "llviewerprecompiledheaders.h" +// include this to get winsock2 because openssl attempts to include winsock1 +#include "llwin32headerslean.h" #include <openssl/x509_vfy.h> #include <openssl/ssl.h> #include "llsecapi.h" diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 7eed9acb4b..dd5c153d55 100755 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -87,6 +87,7 @@ #include "llviewerregion.h" // for audio debugging. #include "llviewerwindow.h" // For getSpinAxis #include "llvoavatarself.h" +#include "llvocache.h" #include "llvoground.h" #include "llvosky.h" #include "llvotree.h" @@ -112,6 +113,7 @@ #include "llfloaterpathfindingconsole.h" #include "llfloaterpathfindingcharacters.h" #include "llpathfindingpathtool.h" +#include "llscenemonitor.h" #ifdef _DEBUG // Debug indices is disabled for now for debug performance - djs 4/24/02 @@ -197,6 +199,7 @@ BOOL LLPipeline::CameraOffset; F32 LLPipeline::CameraMaxCoF; F32 LLPipeline::CameraDoFResScale; F32 LLPipeline::RenderAutoHideSurfaceAreaLimit; +LLTrace::EventStatHandle<S64> LLPipeline::sStatBatchSize("renderbatchsize"); const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f; const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f; @@ -404,17 +407,9 @@ bool addDeferredAttachments(LLRenderTarget& target) LLPipeline::LLPipeline() : mBackfaceCull(FALSE), - mBatchCount(0), mMatrixOpCount(0), mTextureMatrixOps(0), - mMaxBatchSize(0), - mMinBatchSize(0), - mMeanBatchSize(0), - mTrianglesDrawn(0), mNumVisibleNodes(0), - mVerticesRelit(0), - mLightingChanges(0), - mGeometryChanges(0), mNumVisibleFaces(0), mInitialized(FALSE), @@ -491,7 +486,6 @@ void LLPipeline::init() getPool(LLDrawPool::POOL_BUMP); getPool(LLDrawPool::POOL_GLOW); - LLViewerStats::getInstance()->mTrianglesDrawnStat.reset(); resetFrameStats(); if (gSavedSettings.getBOOL("DisableAllRenderFeatures")) @@ -1433,18 +1427,18 @@ S32 LLPipeline::setLightingDetail(S32 level) return mLightingDetail; } -class LLOctreeDirtyTexture : public LLOctreeTraveler<LLDrawable> +class LLOctreeDirtyTexture : public OctreeTraveler { public: const std::set<LLViewerFetchedTexture*>& mTextures; LLOctreeDirtyTexture(const std::set<LLViewerFetchedTexture*>& textures) : mTextures(textures) { } - virtual void visit(const LLOctreeNode<LLDrawable>* node) + virtual void visit(const OctreeNode* node) { LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) + if (!group->hasState(LLSpatialGroup::GEOM_DIRTY) && !group->isEmpty()) { for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) { @@ -1633,11 +1627,9 @@ void LLPipeline::addPool(LLDrawPool *new_poolp) void LLPipeline::allocDrawable(LLViewerObject *vobj) { - LLDrawable *drawable = new LLDrawable(); + LLDrawable *drawable = new LLDrawable(vobj); vobj->mDrawable = drawable; - drawable->mVObjp = vobj; - //encompass completely sheared objects by taking //the most extreme point possible (<1,1,0.5>) drawable->setRadius(LLVector3(1,1,0.5f).scaleVec(vobj->getScale()).length()); @@ -1677,7 +1669,7 @@ void LLPipeline::unlinkDrawable(LLDrawable *drawable) if (drawablep->getSpatialGroup()) { LLFastTimer t(FTM_REMOVE_FROM_SPATIAL_PARTITION); - if (!drawablep->getSpatialGroup()->mSpatialPartition->remove(drawablep, drawablep->getSpatialGroup())) + if (!drawablep->getSpatialGroup()->getSpatialPartition()->remove(drawablep, drawablep->getSpatialGroup())) { #ifdef LL_RELEASE_FOR_DOWNLOAD llwarns << "Couldn't remove object from spatial group!" << llendl; @@ -1823,17 +1815,7 @@ void LLPipeline::resetFrameStats() { assertInitialized(); - LLViewerStats::getInstance()->mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f); - - if (mBatchCount > 0) - { - mMeanBatchSize = gPipeline.mTrianglesDrawn/gPipeline.mBatchCount; - } - mTrianglesDrawn = 0; sCompiles = 0; - mVerticesRelit = 0; - mLightingChanges = 0; - mGeometryChanges = 0; mNumVisibleFaces = 0; if (mOldRenderDebugMask != mRenderDebugMask) @@ -1841,7 +1823,6 @@ void LLPipeline::resetFrameStats() gObjectList.clearDebugText(); mOldRenderDebugMask = mRenderDebugMask; } - } //external functions for asynchronous updating @@ -1942,6 +1923,8 @@ void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) static LLFastTimer::DeclareTimer FTM_OCTREE_BALANCE("Balance Octree"); static LLFastTimer::DeclareTimer FTM_UPDATE_MOVE("Update Move"); +static LLFastTimer::DeclareTimer FTM_RETEXTURE("Retexture"); +static LLFastTimer::DeclareTimer FTM_MOVED_LIST("Moved List"); void LLPipeline::updateMove() { @@ -1955,8 +1938,7 @@ void LLPipeline::updateMove() assertInitialized(); { - static LLFastTimer::DeclareTimer ftm("Retexture"); - LLFastTimer t(ftm); + LLFastTimer t(FTM_RETEXTURE); for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); iter != mRetexturedList.end(); ++iter) @@ -1971,8 +1953,7 @@ void LLPipeline::updateMove() } { - static LLFastTimer::DeclareTimer ftm("Moved List"); - LLFastTimer t(ftm); + LLFastTimer t(FTM_MOVED_LIST); updateMovedList(mMovedList); } @@ -2061,7 +2042,7 @@ void check_references(LLSpatialGroup* group, LLDrawable* drawable) { for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - if (drawable == *i) + if (drawable == (LLDrawable*)(*i)->getDrawable()) { llerrs << "LLDrawable deleted while actively reference by LLPipeline." << llendl; } @@ -2083,10 +2064,13 @@ void check_references(LLSpatialGroup* group, LLFace* face) { for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawable = *i; + LLDrawable* drawable = (LLDrawable*)(*i)->getDrawable(); + if(drawable) + { check_references(drawable, face); } } +} void LLPipeline::checkReferences(LLFace* face) { @@ -2263,7 +2247,7 @@ BOOL LLPipeline::getVisibleExtents(LLCamera& camera, LLVector3& min, LLVector3& min = LLVector3(X,X,X); max = LLVector3(-X,-X,-X); - U32 saved_camera_id = LLViewerCamera::sCurCameraID; + LLViewerCamera::eCameraID saved_camera_id = LLViewerCamera::sCurCameraID; LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_WORLD; BOOL res = TRUE; @@ -2408,6 +2392,13 @@ void LLPipeline::updateCull(LLCamera& camera, LLCullResult& result, S32 water_cl } } } + + //scan the VO Cache tree + LLVOCachePartition* vo_part = region->getVOCachePartition(); + if(vo_part) + { + vo_part->cull(camera); + } } if (bound_shader) @@ -2475,15 +2466,16 @@ void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera) return; } + const LLVector4a* bounds = group->getBounds(); if (sMinRenderSize > 0.f && - llmax(llmax(group->mBounds[1][0], group->mBounds[1][1]), group->mBounds[1][2]) < sMinRenderSize) + llmax(llmax(bounds[1][0], bounds[1][1]), bounds[1][2]) < sMinRenderSize) { return; } assertInitialized(); - if (!group->mSpatialPartition->mRenderByGroup) + if (!group->getSpatialPartition()->mRenderByGroup) { //render by drawable sCull->pushDrawableGroup(group); } @@ -2588,7 +2580,6 @@ BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) if (update_complete && assertInitialized()) { drawablep->setState(LLDrawable::BUILT); - mGeometryChanges++; } return update_complete; } @@ -2732,7 +2723,7 @@ void LLPipeline::rebuildGroups() { group->rebuildGeom(); - if (group->mSpatialPartition->mRenderByGroup) + if (group->getSpatialPartition()->mRenderByGroup) { count++; } @@ -2801,7 +2792,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, LLUnitImplicit<LLUnits::Seconds, F32>(max_dtime)); LLSpatialGroup* last_group = NULL; LLSpatialBridge* last_bridge = NULL; @@ -3055,23 +3046,23 @@ void LLPipeline::markMeshDirty(LLSpatialGroup* group) void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) { - if (group && !group->isDead() && group->mSpatialPartition) + if (group && !group->isDead() && group->getSpatialPartition()) { - if (group->mSpatialPartition->mPartitionType == LLViewerRegion::PARTITION_HUD) + if (group->getSpatialPartition()->mPartitionType == LLViewerRegion::PARTITION_HUD) { priority = TRUE; } if (priority) { - if (!group->isState(LLSpatialGroup::IN_BUILD_Q1)) + if (!group->hasState(LLSpatialGroup::IN_BUILD_Q1)) { llassert_always(!mGroupQ1Locked); mGroupQ1.push_back(group); group->setState(LLSpatialGroup::IN_BUILD_Q1); - if (group->isState(LLSpatialGroup::IN_BUILD_Q2)) + if (group->hasState(LLSpatialGroup::IN_BUILD_Q2)) { LLSpatialGroup::sg_vector_t::iterator iter = std::find(mGroupQ2.begin(), mGroupQ2.end(), group); if (iter != mGroupQ2.end()) @@ -3082,7 +3073,7 @@ void LLPipeline::markRebuild(LLSpatialGroup* group, BOOL priority) } } } - else if (!group->isState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1)) + else if (!group->hasState(LLSpatialGroup::IN_BUILD_Q2 | LLSpatialGroup::IN_BUILD_Q1)) { llassert_always(!mGroupQ2Locked); mGroupQ2.push_back(group); @@ -3157,7 +3148,7 @@ void LLPipeline::stateSort(LLCamera& camera, LLCullResult &result) group->setVisible(); for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - markVisible(*i, camera); + markVisible((LLDrawable*)(*i)->getDrawable(), camera); } if (!sDelayVBUpdate) @@ -3244,8 +3235,7 @@ void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) { for (LLSpatialGroup::element_iter i = group->getDataBegin(); i != group->getDataEnd(); ++i) { - LLDrawable* drawablep = *i; - stateSort(drawablep, camera); + stateSort((LLDrawable*)(*i)->getDrawable(), camera); } if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) @@ -3346,7 +3336,6 @@ void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) } } - mNumVisibleFaces += drawablep->getNumFaces(); } @@ -3359,7 +3348,10 @@ void forAllDrawables(LLCullResult::sg_iterator begin, { for (LLSpatialGroup::element_iter j = (*i)->getDataBegin(); j != (*i)->getDataEnd(); ++j) { - func(*j); + if((*j)->hasDrawable()) + { + func((LLDrawable*)(*j)->getDrawable()); + } } } } @@ -3587,7 +3579,7 @@ void LLPipeline::postSort(LLCamera& camera) continue; } - if (group->isState(LLSpatialGroup::NEW_DRAWINFO) && group->isState(LLSpatialGroup::GEOM_DIRTY)) + if (group->hasState(LLSpatialGroup::NEW_DRAWINFO) && group->hasState(LLSpatialGroup::GEOM_DIRTY)) { //no way this group is going to be drawable without a rebuild group->rebuildGeom(); } @@ -3625,7 +3617,7 @@ void LLPipeline::postSort(LLCamera& camera) if (alpha != group->mDrawMap.end()) { //store alpha groups for sorting - LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); if (LLViewerCamera::sCurCameraID == LLViewerCamera::CAMERA_WORLD) { if (bridge) @@ -3769,33 +3761,6 @@ void LLPipeline::postSort(LLCamera& camera) } } - /*static LLFastTimer::DeclareTimer FTM_TRANSFORM_WAIT("Transform Fence"); - static LLFastTimer::DeclareTimer FTM_TRANSFORM_DO_WORK("Transform Work"); - if (use_transform_feedback) - { //using transform feedback, wait for transform feedback to complete - LLFastTimer t(FTM_TRANSFORM_WAIT); - - S32 done = 0; - //glGetQueryivARB(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_CURRENT_QUERY, &count); - - glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); - - while (!done) - { - { - LLFastTimer t(FTM_TRANSFORM_DO_WORK); - F32 max_time = llmin(gFrameIntervalSeconds*10.f, 1.f); - //do some useful work while we wait - LLAppViewer::getTextureCache()->update(max_time); // unpauses the texture cache thread - LLAppViewer::getImageDecodeThread()->update(max_time); // unpauses the image thread - LLAppViewer::getTextureFetch()->update(max_time); // unpauses the texture fetch thread - } - glGetQueryObjectivARB(mMeshDirtyQueryObject, GL_QUERY_RESULT_AVAILABLE, &done); - } - - mTransformFeedbackPrimitives = 0; - }*/ - //LLSpatialGroup::sNoDelete = FALSE; llpushcallstacks ; } @@ -4539,10 +4504,8 @@ void LLPipeline::addTrianglesDrawn(S32 index_count, U32 render_type) count = index_count/3; } - mTrianglesDrawn += count; - mBatchCount++; - mMaxBatchSize = llmax(mMaxBatchSize, count); - mMinBatchSize = llmin(mMinBatchSize, count); + record(sStatBatchSize, count); + add(LLStatViewer::TRIANGLES_DRAWN, count); if (LLPipeline::sRenderFrameTest) { @@ -4971,7 +4934,7 @@ void LLPipeline::renderDebug() { DebugBlip& blip = *iter; - blip.mAge += gFrameIntervalSeconds; + blip.mAge += gFrameIntervalSeconds.value(); if (blip.mAge > 2.f) { mDebugBlips.erase(iter++); @@ -4981,7 +4944,7 @@ void LLPipeline::renderDebug() iter++; } - blip.mPosition.mV[2] += gFrameIntervalSeconds*2.f; + blip.mPosition.mV[2] += gFrameIntervalSeconds.value()*2.f; gGL.color4fv(blip.mColor.mV); gGL.vertex3fv(blip.mPosition.mV); @@ -5223,7 +5186,7 @@ void LLPipeline::renderDebug() continue; } - LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); + LLSpatialBridge* bridge = group->getSpatialPartition()->asBridge(); if (bridge && (!bridge->mDrawable || bridge->mDrawable->isDead())) { @@ -5787,7 +5750,7 @@ void LLPipeline::calcNearbyLights(LLCamera& camera) { if (farthest_light->fade >= 0.f) { - farthest_light->fade = -gFrameIntervalSeconds; + farthest_light->fade = -(gFrameIntervalSeconds.value()); } } else @@ -5883,12 +5846,12 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) if (fade >= 0.f) { fade = fade / LIGHT_FADE_TIME; - ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds; + ((Light*) (&(*iter)))->fade += gFrameIntervalSeconds.value(); } else { fade = 1.f + fade / LIGHT_FADE_TIME; - ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds; + ((Light*) (&(*iter)))->fade -= gFrameIntervalSeconds.value(); } fade = llclamp(fade,0.f,1.f); light_color *= fade; @@ -6828,7 +6791,7 @@ void LLPipeline::resetVertexBuffers(LLDrawable* drawable) } void LLPipeline::resetVertexBuffers() -{ +{ mResetVertexBuffers = true; } @@ -7218,7 +7181,7 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield) } else if (transition_time < 1.f) { //currently in a transition, continue interpolating - transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds; + transition_time += 1.f/CameraFocusTransitionTime*gFrameIntervalSeconds.value(); transition_time = llmin(transition_time, 1.f); F32 t = cosf(transition_time*F_PI+F_PI)*0.5f+0.5f; @@ -9207,7 +9170,7 @@ void LLPipeline::generateHighlight(LLCamera& camera) if (!mHighlightSet.empty()) { - F32 transition = gFrameIntervalSeconds/RenderHighlightFadeTime; + F32 transition = gFrameIntervalSeconds.value()/RenderHighlightFadeTime; LLGLDisable test(GL_ALPHA_TEST); LLGLDepthTest depth(GL_FALSE); @@ -9465,7 +9428,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) mShadowFrustPoints[j].clear(); } - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+j; + LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0+j); //restore render matrices glh_set_current_modelview(saved_view); @@ -9842,12 +9805,14 @@ void LLPipeline::generateSunShadow(LLCamera& camera) if (gen_shadow) { - F32 fade_amt = gFrameIntervalSeconds * llmax(LLViewerCamera::getInstance()->getVelocityStat()->getCurrentPerSec(), 1.f); + LLTrace::CountStatHandle<>* velocity_stat = LLViewerCamera::getVelocityStat(); + F32 fade_amt = gFrameIntervalSeconds.value() + * llmax(LLTrace::get_frame_recording().getLastRecording().getSum(*velocity_stat) / LLTrace::get_frame_recording().getLastRecording().getDuration().value(), 1.0); //update shadow targets for (U32 i = 0; i < 2; i++) { //for each current shadow - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW4+i; + LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW4+i); if (mShadowSpotLight[i].notNull() && (mShadowSpotLight[i] == mTargetShadowSpotLight[0] || @@ -9966,7 +9931,7 @@ void LLPipeline::generateSunShadow(LLCamera& camera) static LLCullResult result[2]; - LLViewerCamera::sCurCameraID = LLViewerCamera::CAMERA_SHADOW0+i+4; + LLViewerCamera::sCurCameraID = (LLViewerCamera::eCameraID)(LLViewerCamera::CAMERA_SHADOW0 + i + 4); renderShadow(view[i+4], proj[i+4], shadow_cam, result[i], FALSE, FALSE, target_width); @@ -10016,7 +9981,7 @@ void LLPipeline::renderGroups(LLRenderPass* pass, U32 type, U32 mask, BOOL textu LLSpatialGroup* group = *i; if (!group->isDead() && (!sUseOcclusion || !group->isOcclusionState(LLSpatialGroup::OCCLUDED)) && - gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) && + gPipeline.hasRenderType(group->getSpatialPartition()->mDrawableType) && group->mDrawMap.find(type) != group->mDrawMap.end()) { pass->renderGroup(group,type,mask,texture); diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h index a8db93585e..530d484dbd 100755 --- a/indra/newview/pipeline.h +++ b/indra/newview/pipeline.h @@ -29,8 +29,6 @@ #include "llcamera.h" #include "llerror.h" -#include "lldarrayptr.h" -#include "lldqueueptr.h" #include "lldrawpool.h" #include "llspatialpartition.h" #include "m4math.h" @@ -42,25 +40,13 @@ #include <stack> -#include <stack> - -#include <stack> - class LLViewerTexture; -class LLEdge; class LLFace; class LLViewerObject; -class LLAgent; -class LLDisplayPrimitive; class LLTextureEntry; -class LLRenderFunc; -class LLCubeMap; class LLCullResult; class LLVOAvatar; class LLGLSLShader; -class LLCurlRequest; - -class LLMeshResponder; typedef enum e_avatar_skinning_method { @@ -514,23 +500,14 @@ public: LLQuaternion mFlyCamRotation; BOOL mBackfaceCull; - S32 mBatchCount; S32 mMatrixOpCount; S32 mTextureMatrixOps; - S32 mMaxBatchSize; - S32 mMinBatchSize; - S32 mMeanBatchSize; - S32 mTrianglesDrawn; S32 mNumVisibleNodes; - S32 mVerticesRelit; S32 mDebugTextureUploadCost; S32 mDebugSculptUploadCost; S32 mDebugMeshUploadCost; - S32 mLightingChanges; - S32 mGeometryChanges; - S32 mNumVisibleFaces; static S32 sCompiles; @@ -564,6 +541,8 @@ public: static S32 sVisibleLightCount; static F32 sMinRenderSize; + static LLTrace::EventStatHandle<S64> sStatBatchSize; + //screen texture U32 mScreenWidth; U32 mScreenHeight; diff --git a/indra/newview/skins/default/xui/da/floater_lagmeter.xml b/indra/newview/skins/default/xui/da/floater_lagmeter.xml deleted file mode 100755 index 149d174c34..0000000000 --- a/indra/newview/skins/default/xui/da/floater_lagmeter.xml +++ /dev/null @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="LAG METER"> - <floater.string name="max_title_msg"> - Lag måler - </floater.string> - <floater.string name="max_width_px"> - 360 - </floater.string> - <floater.string name="min_title_msg"> - Lag - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - Klient - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - Normal, vindue i baggrund - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - Klients billeder/sek under [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - Klients billeder/sek mellem [CLIENT_FRAME_RATE_CRITICAL] og [CLIENT_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - Mulig årsag: 'Vis afstand' sat for højt i grafik indstillinger - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - Mulig årsag: Billeder hentes - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - Mulig årsag: For mange billeder i hukommelse - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - Mulig årsag: For mange komplekse objekter i scenariet - </floater.string> - <floater.string name="network_text_msg"> - Netværk - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - Forbindelsen mister over [NETWORK_PACKET_LOSS_CRITICAL]% pakker - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - Forbindelsen mister [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]% pakker - </floater.string> - <floater.string name="network_performance_normal_msg"> - Normal - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - Forbindelsens ping tider er over [NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_ping_warning_msg"> - Forbindelsens ping tider er [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - Muligvis dårlig forbindelse eller 'båndbredde' sat for højt i netværksopsætning. - </floater.string> - <floater.string name="network_ping_cause_msg"> - Muligvis dårlig forbindelse eller fil delings program. - </floater.string> - <floater.string name="server_text_msg"> - Server - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - Simulator framerate er under [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - Simulator framerate er mellem [SERVER_FRAME_RATE_CRITICAL] og [SERVER_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="server_physics_cause_msg"> - Mulig årsag: For mange fysiske objekter - </floater.string> - <floater.string name="server_scripts_cause_msg"> - Mulig årsag: For mange objekter med script - </floater.string> - <floater.string name="server_net_cause_msg"> - Mulig årsag: For meget netværks trafik - </floater.string> - <floater.string name="server_agent_cause_msg"> - Mulig årsag: For mange avatarer i bevægelse i regionen - </floater.string> - <floater.string name="server_images_cause_msg"> - Mulig årsag: For mange billed udregninger - </floater.string> - <floater.string name="server_generic_cause_msg"> - Mulig årsag: Simulator belastning for stor - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button label="" label_selected="" name="client_lagmeter" tool_tip="Status for klient lag"/> - <text name="client"> - Klient - </text> - <text name="client_text"> - Normal - </text> - <button label="" label_selected="" name="network_lagmeter" tool_tip="Network lag status"/> - <text name="network"> - Netværk - </text> - <text name="network_text"> - Normal - </text> - <button label="" label_selected="" name="server_lagmeter" tool_tip="Status for server lag"/> - <text name="server"> - Server - </text> - <text name="server_text"> - Normal - </text> - <button label=">>" name="minimize" tool_tip="Ændre størrelse"/> -</floater> diff --git a/indra/newview/skins/default/xui/de/floater_lagmeter.xml b/indra/newview/skins/default/xui/de/floater_lagmeter.xml deleted file mode 100755 index 45ff37c147..0000000000 --- a/indra/newview/skins/default/xui/de/floater_lagmeter.xml +++ /dev/null @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="LAG METER"> - <floater.string name="max_title_msg"> - Lag-Anzeige - </floater.string> - <floater.string name="max_width_px"> - 350 - </floater.string> - <floater.string name="min_title_msg"> - Lag - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - Client - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - Normal, Fenster im Hintergrund - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - Client-Frame-Rate unter [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - Client-Frame-Rate zwischen [CLIENT_FRAME_RATE_CRITICAL] und [CLIENT_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - Mögliche Ursache: Sichtweite zu groß - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - Mögliche Ursache: Bilder werden geladen - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - Mögliche Ursache: Zu viele Bilder im Speicher - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - Mögliche Ursache: Zu viele komplexe Objekte in der Szene - </floater.string> - <floater.string name="network_text_msg"> - Netzwerk - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - Paketverlust der Verbindung übersteigt [NETWORK_PACKET_LOSS_CRITICAL]% - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - Paketverlust der Verbindung liegt bei [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]% - </floater.string> - <floater.string name="network_performance_normal_msg"> - Normal - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - Ping-Zeit der Verbindung übersteigt [NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_ping_warning_msg"> - Ping-Zeit der Verbindung liegt bei [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - Möglicherweise schlechte Verbindung oder zu hoher Wert für „Bandbreite“. - </floater.string> - <floater.string name="network_ping_cause_msg"> - Möglicherweise schlechte Verbindung oder File-Sharing-Anwendung. - </floater.string> - <floater.string name="server_text_msg"> - Server - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - Simulator-Frame-Rate liegt unter [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - Simulator-Frame-Rate liegt zwischen [SERVER_FRAME_RATE_CRITICAL] und [SERVER_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="server_physics_cause_msg"> - Mögliche Ursache: Zu viele physische Objekte - </floater.string> - <floater.string name="server_scripts_cause_msg"> - Mögliche Ursache: Zu viele geskriptete Objekte - </floater.string> - <floater.string name="server_net_cause_msg"> - Mögliche Ursache: Zu viel Netzwerktraffic - </floater.string> - <floater.string name="server_agent_cause_msg"> - Mögliche Ursache: Zu viele Personen in Bewegung in der Region - </floater.string> - <floater.string name="server_images_cause_msg"> - Mögliche Ursache: Zu viele Bildberechnungen - </floater.string> - <floater.string name="server_generic_cause_msg"> - Mögliche Ursache: Zu hohe Simulator-Last - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button name="client_lagmeter" tool_tip="Client-Lag-Status"/> - <text name="client"> - Client - </text> - <text name="client_text"> - Normal - </text> - <button name="network_lagmeter" tool_tip="Netzwerk-Lag-Status"/> - <text name="network"> - Netzwerk - </text> - <text name="network_text"> - Normal - </text> - <button name="server_lagmeter" tool_tip="Server-Lag-Status"/> - <text name="server"> - Server - </text> - <text name="server_text"> - Normal - </text> - <button label=">> " name="minimize" tool_tip="Fenstergröße ändern"/> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_lagmeter.xml b/indra/newview/skins/default/xui/en/floater_lagmeter.xml deleted file mode 100755 index b24c745bdd..0000000000 --- a/indra/newview/skins/default/xui/en/floater_lagmeter.xml +++ /dev/null @@ -1,336 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - legacy_header_height="18" - height="170" - layout="topleft" - name="floater_lagmeter" - help_topic="floater_lagmeter" - save_rect="true" - title="LAG METER" - width="350"> - <floater.string - name="max_title_msg"> - Lag Meter - </floater.string> - <floater.string - name="max_width_px"> - 360 - </floater.string> - <floater.string - name="min_title_msg"> - Lag - </floater.string> - <floater.string - name="min_width_px"> - 90 - </floater.string> - <floater.string - name="client_text_msg"> - Client - </floater.string> - <floater.string - name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string - name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string - name="client_frame_time_window_bg_msg"> - Normal, window in background - </floater.string> - <floater.string - name="client_frame_time_critical_msg"> - Client frame rate below [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string - name="client_frame_time_warning_msg"> - Client frame rate between [CLIENT_FRAME_RATE_CRITICAL] and [CLIENT_FRAME_RATE_WARNING] - </floater.string> - <floater.string - name="client_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string - name="client_draw_distance_cause_msg"> - Possible cause: Draw distance set too high - </floater.string> - <floater.string - name="client_texture_loading_cause_msg"> - Possible cause: Images loading - </floater.string> - <floater.string - name="client_texture_memory_cause_msg"> - Possible cause: Too many images in memory - </floater.string> - <floater.string - name="client_complex_objects_cause_msg"> - Possible cause: Too many complex objects in scene - </floater.string> - <floater.string - name="network_text_msg"> - Network - </floater.string> - <floater.string - name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string - name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string - name="network_packet_loss_critical_msg"> - Connection is dropping over [NETWORK_PACKET_LOSS_CRITICAL]% of packets - </floater.string> - <floater.string - name="network_packet_loss_warning_msg"> - Connection is dropping [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]% of packets - </floater.string> - <floater.string - name="network_performance_normal_msg"> - Normal - </floater.string> - <floater.string - name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string - name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string - name="network_ping_critical_msg"> - Connection ping time is over [NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string - name="network_ping_warning_msg"> - Connection ping time is [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string - name="network_packet_loss_cause_msg"> - Possible bad connection or 'Bandwidth' pref too high. - </floater.string> - <floater.string - name="network_ping_cause_msg"> - Possible bad connection or file-sharing app. - </floater.string> - <floater.string - name="server_text_msg"> - Server - </floater.string> - <floater.string - name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string - name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string - name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string - name="server_frame_time_critical_msg"> - Simulator framerate below [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string - name="server_frame_time_warning_msg"> - Simulator framerate between [SERVER_FRAME_RATE_CRITICAL] and [SERVER_FRAME_RATE_WARNING] - </floater.string> - <floater.string - name="server_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string - name="server_physics_cause_msg"> - Possible Cause: Too many physical objects - </floater.string> - <floater.string - name="server_scripts_cause_msg"> - Possible Cause: Too many scripted objects - </floater.string> - <floater.string - name="server_net_cause_msg"> - Possible Cause: Too much network traffic - </floater.string> - <floater.string - name="server_agent_cause_msg"> - Possible Cause: Too many moving people in region - </floater.string> - <floater.string - name="server_images_cause_msg"> - Possible Cause: Too many image calculations - </floater.string> - <floater.string - name="server_generic_cause_msg"> - Possible Cause: Simulator load too heavy - </floater.string> - <floater.string - name="smaller_label"> - >> - </floater.string> - <floater.string - name="bigger_label"> - << - </floater.string> - <button - follows="top|left" - height="16" - image_selected="lag_status_good.tga" - image_unselected="lag_status_good.tga" - layout="topleft" - left="8" - name="client_lagmeter" - tab_stop="false" - tool_tip="Client lag status" - top="24" - width="16" /> - <text - type="string" - length="1" - follows="left|top" - font="SansSerif" - height="16" - layout="topleft" - left_pad="3" - name="client" - top_delta="0" - width="128"> - Client - </text> - <text - invisiblity_control="LagMeterShrunk" - type="string" - length="1" - bottom="40" - follows="left|top" - font="SansSerif" - height="16" - layout="topleft" - left="110" - name="client_text" - right="-10"> - Normal - </text> - <text - invisiblity_control="LagMeterShrunk" - bottom="56" - follows="left|top" - height="16" - layout="topleft" - left="40" - name="client_lag_cause" - right="-32" /> - <button - follows="top|left" - height="16" - image_selected="lag_status_good.tga" - image_unselected="lag_status_good.tga" - layout="topleft" - left="8" - name="network_lagmeter" - tab_stop="false" - tool_tip="Network lag status" - top="64" - width="16" /> - <text - type="string" - length="1" - follows="left|top" - font="SansSerif" - height="16" - layout="topleft" - left_pad="3" - name="network" - top_delta="0" - width="128"> - Network - </text> - <text - invisiblity_control="LagMeterShrunk" - type="string" - length="1" - bottom="80" - follows="left|top" - font="SansSerif" - height="16" - layout="topleft" - left="110" - name="network_text" - right="-10"> - Normal - </text> - <text - invisiblity_control="LagMeterShrunk" - bottom="96" - follows="left|top" - height="16" - layout="topleft" - left="40" - name="network_lag_cause" - right="-32" /> - <button - follows="top|left" - height="16" - image_selected="lag_status_good.tga" - image_unselected="lag_status_good.tga" - layout="topleft" - left="8" - name="server_lagmeter" - tab_stop="false" - tool_tip="Server lag status" - top="104" - width="16" /> - <text - type="string" - length="1" - follows="left|top" - font="SansSerif" - height="16" - layout="topleft" - left_pad="3" - name="server" - top_delta="0" - width="60"> - Server - </text> - <text - invisiblity_control="LagMeterShrunk" - type="string" - length="1" - bottom="120" - follows="left|top" - font="SansSerif" - height="16" - layout="topleft" - left="110" - name="server_text" - right="-10"> - Normal - </text> - <text - invisiblity_control="LagMeterShrunk" - bottom="136" - follows="left|top" - height="16" - layout="topleft" - left="40" - name="server_lag_cause" - right="-32" /> - <button - follows="left|top" - height="20" - label=">>" - layout="topleft" - left="10" - name="minimize" - tool_tip="Toggle floater size" - top_delta="24" - width="40"> - <button.commit_callback - function="LagMeter.ClickShrink" /> - </button> -</floater> diff --git a/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml b/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml new file mode 100644 index 0000000000..246e8bb256 --- /dev/null +++ b/indra/newview/skins/default/xui/en/floater_scene_load_stats.xml @@ -0,0 +1,446 @@ +<?xml version="1.0" encoding="utf-8" standalone="yes" ?> +<floater legacy_header_height="18" + can_resize="true" + height="400" + layout="topleft" + name="Scene Load Statistics" + save_rect="true" + save_visibility="true" + title="SCENE LOAD STATISTICS" + width="260"> + <button follows="top|left" + top="20" + bottom="60" + left="10" + width="100" + label="Pause" + name="playpause"/> + <scroll_container follows="top|left|bottom|right" + bottom="400" + layout="topleft" + left="0" + name="statistics_scroll" + reserve_scroll_corner="true" + top="60" + width="260"> + <container_view follows="top|left|bottom|right" + height="378" + layout="topleft" + left="2" + name="statistics_view" + top="20" + width="245" > +<!--Basic Section--> + <stat_view name="basic" + label="Basic" + show_label="true" + setting="OpenDebugStatBasic"> + <stat_bar name="frame difference" + label="Frame Pixel Difference" + orientation="horizontal" + unit_label="%" + stat="FramePixelDifference" + bar_max="100" + tick_spacing="10" + unit_scale="100" + precision="0"/> + <stat_bar name="bandwidth" + label="Bandwidth" + orientation="horizontal" + unit_label="kbps" + stat="kbitstat" + bar_max="5000" + tick_spacing="500" + precision="0"/> + <stat_bar name="packet_loss" + label="Packet Loss" + orientation="horizontal" + unit_label=" %" + stat="packetslostpercentstat" + bar_max="5" + tick_spacing="0.5" + precision="3" + show_bar="false" + show_mean="true"/> + </stat_view> +<!--Advanced Section--> + <stat_view name="advanced" + label="Advanced" + show_label="true" + setting="OpenDebugStatAdvanced"> + <stat_view name="render" + label="Render" + show_label="true" + setting="OpenDebugStatRender"> + <stat_bar name="objs" + label="Total Objects" + orientation="horizontal" + unit_label="" + stat="numobjectsstat" + bar_max="50000" + tick_spacing="5000" + precision="0" + show_bar="false"/> + <stat_bar name="newobjs" + label="New Objects" + orientation="horizontal" + unit_label="/sec" + stat="numnewobjectsstat" + bar_max="2000" + tick_spacing="200" + show_bar="false"/> + <stat_bar name="object_cache_hits" + label="Object Cache Hit Rate" + orientation="horizontal" + stat="object_cache_hits" + bar_max="100" + unit_label="%" + tick_spacing="20" + show_history="true" + show_bar="false"/> + </stat_view> +<!--Texture Stats--> + <stat_view name="texture" + label="Texture" + show_label="true"> + <stat_bar name="texture_cache_hits" + label="Cache Hit Rate" + orientation="horizontal" + stat="texture_cache_hits" + bar_max="100.f" + unit_label="%" + tick_spacing="20" + show_history="true" + show_bar="false"/> + <stat_bar name="texture_cache_read_latency" + label="Cache Read Latency" + orientation="horizontal" + unit_label="msec" + stat="texture_cache_read_latency" + bar_max="1000.f" + tick_spacing="100" + show_history="true" + show_bar="false"/> + <stat_bar name="numimagesstat" + label="Count" + orientation="horizontal" + stat="numimagesstat" + bar_max="8000.f" + tick_spacing="2000.f" + show_bar="false"/> + <stat_bar name="numrawimagesstat" + label="Raw Count" + orientation="horizontal" + stat="numrawimagesstat" + bar_max="8000.f" + tick_spacing="2000.f" + show_bar="false"/> + </stat_view> +<!--Network Stats--> + <stat_view name="network" + label="Network" + show_label="true" + setting="OpenDebugStatNet"> + <stat_bar name="packetsinstat" + label="Packets In" + orientation="horizontal" + stat="packetsinstat" + unit_label="/sec" + bar_max="1024.f" + tick_spacing="128.f" + precision="1" + show_bar="false"/> + <stat_bar name="packetsoutstat" + label="Packets Out" + orientation="horizontal" + stat="packetsoutstat" + unit_label="/sec" + bar_max="1024.f" + tick_spacing="128.f" + precision="1" + show_bar="false"/> + <stat_bar name="objectkbitstat" + label="Objects" + orientation="horizontal" + stat="objectkbitstat" + unit_label="kbps" + bar_max="1024.f" + tick_spacing="128.f" + precision="1" + show_bar="false"/> + <stat_bar name="texturekbitstat" + label="Texture" + orientation="horizontal" + stat="texturekbitstat" + unit_label="kbps" + bar_max="1024.f" + tick_spacing="128.f" + precision="1" + show_bar="false"/> + <stat_bar name="assetkbitstat" + label="Asset" + orientation="horizontal" + stat="assetkbitstat" + unit_label="kbps" + bar_max="1024.f" + tick_spacing="128.f" + precision="1" + show_bar="false"/> + <stat_bar name="layerskbitstat" + label="Layers" + orientation="horizontal" + stat="layerskbitstat" + unit_label="kbps" + bar_max="1024.f" + tick_spacing="128.f" + precision="1" + show_bar="false"/> + <stat_bar name="actualinkbitstat" + label="Actual In" + orientation="horizontal" + stat="actualinkbitstat" + unit_label="kbps" + bar_max="1024.f" + tick_spacing="128.f" + precision="1" + show_bar="false"/> + <stat_bar name="actualoutkbitstat" + label="Actual Out" + orientation="horizontal" + stat="actualoutkbitstat" + unit_label="kbps" + bar_max="1024.f" + tick_spacing="128.f" + precision="1" + show_bar="false"/> + <stat_bar name="vfspendingoperations" + label="VFS Pending Operations" + orientation="horizontal" + stat="vfspendingoperations" + unit_label=" Ops." + show_bar="false"/> + </stat_view> + </stat_view> +<!--Sim Stats--> + <stat_view name="sim" + label="Simulator" + show_label="true" + setting="OpenDebugStatSim"> + <stat_bar name="simobjects" + label="Objects" + orientation="horizontal" + stat="simobjects" + precision="0" + bar_max="30000.f" + tick_spacing="5000.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simactiveobjects" + label="Active Objects" + orientation="horizontal" + stat="simactiveobjects" + precision="0" + bar_max="5000.f" + tick_spacing="750.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simactivescripts" + label="Active Scripts" + orientation="horizontal" + stat="simactivescripts" + precision="0" + bar_max="15000.f" + tick_spacing="1875.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="siminpps" + label="Packets In" + orientation="horizontal" + stat="siminpps" + unit_label="pps" + precision="0" + bar_max="2000.f" + tick_spacing="250.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simoutpps" + label="Packets Out" + orientation="horizontal" + stat="simoutpps" + unit_label="pps" + precision="0" + bar_max="2000.f" + tick_spacing="250.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simpendingdownloads" + label="Pending Downloads" + orientation="horizontal" + stat="simpendingdownloads" + precision="0" + bar_max="800.f" + tick_spacing="100.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simpendinguploads" + label="Pending Uploads" + orientation="horizontal" + stat="simpendinguploads" + precision="0" + bar_max="100.f" + tick_spacing="25.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simtotalunackedbytes" + label="Total Unacked Bytes" + orientation="horizontal" + stat="simtotalunackedbytes" + unit_label="kb" + precision="1" + bar_max="100000.f" + tick_spacing="25000.f" + show_bar="false" + show_mean="false"/> + <stat_view name="simperf" + label="Time (ms)" + show_label="true"> + <stat_bar name="simframemsec" + label="Total Frame Time" + orientation="horizontal" + stat="simframemsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simnetmsec" + label="Net Time" + orientation="horizontal" + stat="simnetmsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simsimphysicsmsec" + label="Physics Time" + orientation="horizontal" + stat="simsimphysicsmsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simsimothermsec" + label="Simulation Time" + orientation="horizontal" + stat="simsimothermsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simagentmsec" + label="Agent Time" + orientation="horizontal" + stat="simagentmsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simimagesmsec" + label="Images Time" + orientation="horizontal" + stat="simimagesmsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simscriptmsec" + label="Script Time" + orientation="horizontal" + stat="simscriptmsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simsparemsec" + label="Spare Time" + orientation="horizontal" + stat="simsparemsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> +<!--2nd level time blocks under 'Details' second--> + <stat_view name="timedetails" + label="Time Details (ms)" + show_label="true"> + <stat_bar name="simsimphysicsstepmsec" + label=" Physics Step" + orientation="horizontal" + stat="simsimphysicsstepmsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simsimphysicsshapeupdatemsec" + label=" Update Phys Shapes" + orientation="horizontal" + stat="simsimphysicsshapeupdatemsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simsimphysicsothermsec" + label=" Physics Other" + orientation="horizontal" + stat="simsimphysicsothermsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simsleepmsec" + label=" Sleep Time" + orientation="horizontal" + stat="simsleepmsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + <stat_bar name="simpumpiomsec" + label=" Pump IO" + orientation="horizontal" + stat="simpumpiomsec" + unit_label="ms" + precision="3" + bar_max="40.f" + tick_spacing="10.f" + show_bar="false" + show_mean="false"/> + </stat_view> + </stat_view> + </stat_view> + </container_view> + </scroll_container> +</floater> diff --git a/indra/newview/skins/default/xui/en/floater_stats.xml b/indra/newview/skins/default/xui/en/floater_stats.xml index f9eb16d224..0493f487d4 100755 --- a/indra/newview/skins/default/xui/en/floater_stats.xml +++ b/indra/newview/skins/default/xui/en/floater_stats.xml @@ -31,17 +31,17 @@ <stat_view name="basic" label="Basic" + follows="left|top|right" show_label="true" setting="OpenDebugStatBasic"> <stat_bar name="fps" label="FPS" unit_label="fps" - stat="fpsstat" + stat="framesrendered" bar_min="0" bar_max="60" tick_spacing="6" - label_spacing="12" precision="1" show_bar="true" show_history="true"> @@ -54,7 +54,6 @@ bar_min="0" bar_max="5000" tick_spacing="500" - label_spacing="1000" precision="0" show_bar="true" show_history="false"> @@ -67,9 +66,7 @@ bar_min="0" bar_max="5" tick_spacing="0.5" - label_spacing="1" precision="3" - show_per_sec="false" show_bar="false" show_mean="true"> </stat_bar> @@ -81,10 +78,8 @@ bar_min="0" bar_max="5000" tick_spacing="500" - label_spacing="1000" precision="0" show_bar="false" - show_per_sec="false" show_mean="false"> </stat_bar> </stat_view> @@ -92,11 +87,13 @@ <stat_view name="advanced" label="Advanced" + follows="left|top|right" show_label="true" setting="OpenDebugStatAdvanced"> <stat_view name="render" label="Render" + follows="left|top|right" show_label="true" setting="OpenDebugStatRender"> <stat_bar @@ -104,10 +101,10 @@ label="KTris Drawn per Frame" unit_label="/fr" stat="trianglesdrawnstat" + unit_scale="0.001" bar_min="0" bar_max="10000" tick_spacing="1000" - label_spacing="2000" precision="0" show_per_sec="false" show_bar="false"> @@ -116,11 +113,11 @@ name="ktrissec" label="KTris Drawn per Sec" unit_label="/sec" + unit_scale="0.001" stat="trianglesdrawnstat" bar_min="0" bar_max="200000" tick_spacing="25000" - label_spacing="50000" precision="0" show_bar="false"> </stat_bar> @@ -132,9 +129,7 @@ bar_min="0" bar_max="50000" tick_spacing="5000" - label_spacing="10000" precision="0" - show_per_sec="false" show_bar="false"> </stat_bar> <stat_bar @@ -145,8 +140,6 @@ bar_min="0" bar_max="2000" tick_spacing="200" - label_spacing="400" - show_per_sec="true" show_bar="false"> </stat_bar> <stat_bar @@ -157,9 +150,7 @@ bar_max="100" unit_label="%" tick_spacing="20" - label_spacing="20" show_history="true" - show_per_sec="false" show_bar="false"> </stat_bar> </stat_view> @@ -167,6 +158,7 @@ <stat_view name="texture" label="Texture" + follows="left|top|right" show_label="true"> <stat_bar name="texture_cache_hits" @@ -176,9 +168,7 @@ bar_max="100.f" unit_label="%" tick_spacing="20" - label_spacing="20" show_history="true" - show_per_sec="false" show_bar="false"> </stat_bar> <stat_bar @@ -189,9 +179,7 @@ bar_min="0.f" bar_max="1000.f" tick_spacing="100" - label_spacing="200" show_history="true" - show_per_sec="false" show_bar="false"> </stat_bar> <stat_bar @@ -201,8 +189,6 @@ bar_min="0.f" bar_max="8000.f" tick_spacing="2000.f" - label_spacing="4000.f" - show_per_sec="false" show_bar="false"> </stat_bar> @@ -213,8 +199,6 @@ bar_min="0.f" bar_max="8000.f" tick_spacing="2000.f" - label_spacing="4000.f" - show_per_sec="false" show_bar="false"> </stat_bar> @@ -222,12 +206,12 @@ name="gltexmemstat" label="GL Mem" stat="gltexmemstat" + unit_label="MB" + unit_scale="0.000001" bar_min="0.f" bar_max="400.f" tick_spacing="100.f" - label_spacing="200.f" precision="1" - show_per_sec="false" show_bar="false"> </stat_bar> @@ -235,25 +219,25 @@ name="formattedmemstat" label="Formatted Mem" stat="formattedmemstat" + unit_label="MB" + unit_scale="0.000001" bar_min="0.f" bar_max="400.f" tick_spacing="100.f" - label_spacing="200.f" - precision="1" - show_per_sec="false" + precision="3" show_bar="false"> </stat_bar> <stat_bar name="rawmemstat" label="Raw Mem" + unit_label="MB" + unit_scale="0.000001" stat="rawmemstat" bar_min="0.f" bar_max="400.f" tick_spacing="100.f" - label_spacing="200.f" - precision="1" - show_per_sec="false" + precision="3" show_bar="false"> </stat_bar> @@ -261,12 +245,12 @@ name="glboundmemstat" label="Bound Mem" stat="glboundmemstat" + unit_label="MB" + unit_scale="0.000001" bar_min="0.f" bar_max="400.f" tick_spacing="100.f" - label_spacing="200.f" - precision="1" - show_per_sec="false" + precision="3" show_bar="false"> </stat_bar> </stat_view> @@ -274,6 +258,7 @@ <stat_view name="network" label="Network" + follows="left|top|right" show_label="true" setting="OpenDebugStatNet"> <stat_bar @@ -284,7 +269,6 @@ bar_min="0.f" bar_max="1024.f" tick_spacing="128.f" - label_spacing="256.f" precision="1" show_bar="false"> </stat_bar> @@ -297,7 +281,6 @@ bar_min="0.f" bar_max="1024.f" tick_spacing="128.f" - label_spacing="256.f" precision="1" show_bar="false" > </stat_bar> @@ -310,7 +293,6 @@ bar_min="0.f" bar_max="1024.f" tick_spacing="128.f" - label_spacing="256.f" precision="1" show_bar="false" > </stat_bar> @@ -323,7 +305,6 @@ bar_min="0.f" bar_max="1024.f" tick_spacing="128.f" - label_spacing="256.f" precision="1" show_bar="false" > </stat_bar> @@ -336,7 +317,6 @@ bar_min="0.f" bar_max="1024.f" tick_spacing="128.f" - label_spacing="256.f" precision="1" show_bar="false" > </stat_bar> @@ -349,7 +329,6 @@ bar_min="0.f" bar_max="1024.f" tick_spacing="128.f" - label_spacing="256.f" precision="1" show_bar="false" > </stat_bar> @@ -362,7 +341,6 @@ bar_min="0.f" bar_max="1024.f" tick_spacing="128.f" - label_spacing="256.f" precision="1" show_bar="false" show_history="false" > @@ -376,7 +354,6 @@ bar_min="0.f" bar_max="1024.f" tick_spacing="128.f" - label_spacing="256.f" precision="1" show_bar="false" show_history="false"> @@ -387,7 +364,6 @@ label="VFS Pending Operations" stat="vfspendingoperations" unit_label=" Ops." - show_per_sec="false" show_bar="false" > </stat_bar> </stat_view> @@ -396,6 +372,7 @@ <stat_view name="sim" label="Simulator" + follows="left|top|right" show_label="true" setting="OpenDebugStatSim"> <stat_bar @@ -406,8 +383,6 @@ bar_min="0.f" bar_max="1.f" tick_spacing="0.16666f" - label_spacing="0.33333f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -420,8 +395,6 @@ bar_min="0.f" bar_max="45.f" tick_spacing="7.5f" - label_spacing="15.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -434,8 +407,6 @@ bar_min="0.f" bar_max="45.f" tick_spacing="7.5.f" - label_spacing="15.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -443,6 +414,7 @@ <stat_view name="physicsdetail" label="Physics Details" + follows="left|top|right" show_label="true"> <stat_bar name="physicspinnedtasks" @@ -452,8 +424,6 @@ bar_min="0.f" bar_max="500.f" tick_spacing="50.f" - label_spacing="100.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -466,8 +436,6 @@ bar_min="0.f" bar_max="500.f" tick_spacing="50.f" - label_spacing="100.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -481,8 +449,6 @@ bar_min="0.f" bar_max="1024.f" tick_spacing="128.f" - label_spacing="256.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -496,8 +462,6 @@ bar_min="0.f" bar_max="100.f" tick_spacing="25.f" - label_spacing="50.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -510,8 +474,6 @@ bar_min="0.f" bar_max="80.f" tick_spacing="10.f" - label_spacing="40.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -524,8 +486,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="5.f" - label_spacing="10.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -538,8 +498,6 @@ bar_min="0.f" bar_max="30000.f" tick_spacing="5000.f" - label_spacing="10000.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -552,8 +510,6 @@ bar_min="0.f" bar_max="5000.f" tick_spacing="750.f" - label_spacing="1250.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -566,8 +522,6 @@ bar_min="0.f" bar_max="15000.f" tick_spacing="1875.f" - label_spacing="3750.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -579,9 +533,7 @@ bar_min="0" bar_max="100" tick_spacing="10" - label_spacing="20" precision="3" - show_per_sec="false" show_bar="false" show_mean="true"> </stat_bar> @@ -595,8 +547,6 @@ bar_min="0.f" bar_max="5000.f" tick_spacing="750.f" - label_spacing="1250.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -604,6 +554,7 @@ <stat_view name="simpathfinding" label="Pathfinding" + follows="left|top|right" show_label="true"> <stat_bar name="simsimaistepmsec" @@ -614,8 +565,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -628,8 +577,6 @@ bar_min="0" bar_max="45" tick_spacing="4" - label_spacing="8" - show_per_sec="false" show_bar="false"> </stat_bar> <stat_bar @@ -640,9 +587,7 @@ bar_min="0" bar_max="100" tick_spacing="10" - label_spacing="20" precision="1" - show_per_sec="false" show_bar="false" show_mean="true"> </stat_bar> @@ -657,8 +602,6 @@ bar_min="0.f" bar_max="2000.f" tick_spacing="250.f" - label_spacing="1000.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -672,8 +615,6 @@ bar_min="0.f" bar_max="2000.f" tick_spacing="250.f" - label_spacing="1000.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -686,8 +627,6 @@ bar_min="0.f" bar_max="800.f" tick_spacing="100.f" - label_spacing="200.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -700,8 +639,6 @@ bar_min="0.f" bar_max="100.f" tick_spacing="25.f" - label_spacing="50.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -715,8 +652,6 @@ bar_min="0.f" bar_max="100000.f" tick_spacing="25000.f" - label_spacing="50000.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -724,6 +659,7 @@ <stat_view name="simperf" label="Time (ms)" + follows="left|top|right" show_label="true"> <stat_bar name="simframemsec" @@ -734,8 +670,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -749,8 +683,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -764,8 +696,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -779,8 +709,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -794,8 +722,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -809,8 +735,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -824,8 +748,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -839,8 +761,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -848,6 +768,7 @@ <stat_view name="timedetails" label="Time Details (ms)" + follows="left|top|right" show_label="true"> <stat_bar name="simsimphysicsstepmsec" @@ -858,8 +779,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -872,8 +791,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -886,8 +803,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -900,8 +815,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> @@ -914,8 +827,6 @@ bar_min="0.f" bar_max="40.f" tick_spacing="10.f" - label_spacing="20.f" - show_per_sec="false" show_bar="false" show_mean="false" > </stat_bar> diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml index a11cd13fdb..d50b7b18e7 100755 --- a/indra/newview/skins/default/xui/en/menu_viewer.xml +++ b/indra/newview/skins/default/xui/en/menu_viewer.xml @@ -1300,7 +1300,7 @@ parameter="hud" /> </menu_item_call>--> <menu_item_separator/> - + <menu_item_call label="User’s guide" name="User’s guide"> @@ -1475,6 +1475,14 @@ function="Floater.Toggle" parameter="stats" /> </menu_item_check> + <menu_item_call + label="Scene Load Statistics" + name="Scene Load Statistics" + shortcut="control|shift|2"> + <on_click + function="Floater.Show" + parameter="scene_load_stats" /> + </menu_item_call> <menu_item_check label="Show Draw Weight for Avatars" name="Avatar Rendering Cost"> @@ -2080,6 +2088,16 @@ function="Advanced.ToggleConsole" parameter="scene view" /> </menu_item_check> + <menu_item_check + label="Scene Loading Monitor" + name="Scene Loading Monitor"> + <menu_item_check.on_check + function="Advanced.CheckConsole" + parameter="scene monitor" /> + <menu_item_check.on_click + function="Advanced.ToggleConsole" + parameter="scene monitor" /> + </menu_item_check> <menu_item_call enabled="false" visible="false" @@ -2831,6 +2849,16 @@ function="ToggleControl" parameter="RenderHoverGlowEnable" /> </menu_item_check> + <menu_item_separator /> + + <menu_item_call + enabled="true" + label="Clear Cache Immediately" + name="Cache Clear"> + <menu_item_call.on_click + function="Develop.ClearCache" /> + </menu_item_call> + </menu> <menu diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 970a11c6c4..540618ef9a 100755 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6923,7 +6923,7 @@ Do not allow access if you do not fully understand why it wants access to your a [FOOTERTEXT] </footer> </notification> - + <notification icon="notify.tga" name="UnknownScriptQuestion" diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 3b57ff5fd6..e0a85877eb 100755 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -416,7 +416,7 @@ Please try logging in again in a minute.</string> <string name="OverrideYourAnimations">Replace your default animations</string> <string name="ScriptReturnObjects">Return objects on your behalf</string> <string name="UnknownScriptPermission">(unknown)!</string> - + <!-- Sim Access labels --> <string name="SIM_ACCESS_PG">General</string> <string name="SIM_ACCESS_MATURE">Moderate</string> diff --git a/indra/newview/skins/default/xui/es/floater_lagmeter.xml b/indra/newview/skins/default/xui/es/floater_lagmeter.xml deleted file mode 100755 index 227689a194..0000000000 --- a/indra/newview/skins/default/xui/es/floater_lagmeter.xml +++ /dev/null @@ -1,154 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="MEDIDOR DEL LAG"> - <floater.string name="max_title_msg"> - Medidor del lag - </floater.string> - <floater.string name="max_width_px"> - 360 - </floater.string> - <floater.string name="min_title_msg"> - Lag - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - Cliente - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - Normal, ventana en segundo plano - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - Frames del cliente valorados por debajo de [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - Frames del cliente valorados entre [CLIENT_FRAME_RATE_CRITICAL] y [CLIENT_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - Posible causa: distancia de dibujo fijada muy alta - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - Posible causa: imágenes cargándose - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - Posible causa: demasiadas imágenes en la memoria - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - Posible causa: demasiados objetos complejos en la escena - </floater.string> - <floater.string name="network_text_msg"> - Red - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - La conexión deja caer más del [NETWORK_PACKET_LOSS_CRITICAL]% de los paquetes - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - La conexión deja caer [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]% de los paquetes - </floater.string> - <floater.string name="network_performance_normal_msg"> - Normal - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - El tiempo de conexión -ping- supera los [NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_ping_warning_msg"> - El tiempo de conexión -ping- es de [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - Quizá una mala conexión o un ancho de banda fijado demasiado alto. - </floater.string> - <floater.string name="network_ping_cause_msg"> - Quizá una mala conexión o una aplicación de archivos compartidos. - </floater.string> - <floater.string name="server_text_msg"> - Servidor - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - Frecuencia (framerate) por debajo de [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - Frecuencia (framerate) entre [SERVER_FRAME_RATE_CRITICAL] y [SERVER_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="server_physics_cause_msg"> - Posible causa: demasiados objetos físicos - </floater.string> - <floater.string name="server_scripts_cause_msg"> - Posible causa: demasiados objetos con script - </floater.string> - <floater.string name="server_net_cause_msg"> - Posible causa: demasiado tráfico en la red - </floater.string> - <floater.string name="server_agent_cause_msg"> - Posible causa: demasiada gente moviéndose en la región - </floater.string> - <floater.string name="server_images_cause_msg"> - Posible causa: demasiados cálculos de imáganes - </floater.string> - <floater.string name="server_generic_cause_msg"> - Posible causa: carga del simulador muy pesada - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button label="" label_selected="" name="client_lagmeter" tool_tip="Estado del lag del cliente"/> - <text name="client"> - Cliente - </text> - <text font="SansSerifSmall" name="client_text"> - Normal - </text> - <text left="30" name="client_lag_cause" right="-10"/> - <button label="" label_selected="" name="network_lagmeter" tool_tip="Estado del lag de la red"/> - <text name="network"> - Red - </text> - <text font="SansSerifSmall" name="network_text"> - Normal - </text> - <text left="30" name="network_lag_cause" right="-10"/> - <button label="" label_selected="" name="server_lagmeter" tool_tip="Estado del lag del servidor"/> - <text name="server"> - Servidor - </text> - <text font="SansSerifSmall" name="server_text"> - Normal - </text> - <text left="30" name="server_lag_cause" right="-32"/> - <button label=">>" name="minimize" tool_tip="Cambia el tamaño de la ventana"/> -</floater> diff --git a/indra/newview/skins/default/xui/fr/floater_lagmeter.xml b/indra/newview/skins/default/xui/fr/floater_lagmeter.xml deleted file mode 100755 index 39a861d8bd..0000000000 --- a/indra/newview/skins/default/xui/fr/floater_lagmeter.xml +++ /dev/null @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="MESURE DU LAG"> - <floater.string name="max_title_msg"> - Mesure du lag - </floater.string> - <floater.string name="max_width_px"> - 360 - </floater.string> - <floater.string name="min_title_msg"> - Lag - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - Client - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - Normal, fenêtre en arrière-plan - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - Taux de défilement [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - Taux de défilement entre [CLIENT_FRAME_RATE_CRITICAL] et [CLIENT_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - Cause possible : limite d'affichage trop élevée - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - Cause possible : images en cours de chargement - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - Cause possible : trop d'images en mémoire - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - Cause possible : trop d'objets complexes - </floater.string> - <floater.string name="network_text_msg"> - Réseau - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - La connexion perd plus de [NETWORK_PACKET_LOSS_CRITICAL] % de paquets - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - La connexion perd entre [NETWORK_PACKET_LOSS_WARNING] % et [NETWORK_PACKET_LOSS_CRITICAL] % de paquets - </floater.string> - <floater.string name="network_performance_normal_msg"> - Normal - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - Connexion ping > [NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_ping_warning_msg"> - Connexion ping entre [NETWORK_PING_WARNING] et [NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - Mauvaise connexion possible ou réglage de la bande passante trop élevé. - </floater.string> - <floater.string name="network_ping_cause_msg"> - Mauvaise connexion possible ou app. de partage des fichiers - </floater.string> - <floater.string name="server_text_msg"> - Serveur - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - Défilement du simulateur < [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - Défilement simulateur entre [SERVER_FRAME_RATE_CRITICAL] et [SERVER_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="server_physics_cause_msg"> - Cause possible : trop d'objets physiques - </floater.string> - <floater.string name="server_scripts_cause_msg"> - Cause possible : trop d'objets scriptés - </floater.string> - <floater.string name="server_net_cause_msg"> - Cause possible : trop de trafic réseau - </floater.string> - <floater.string name="server_agent_cause_msg"> - Cause possible : trop de personnes en mouvement - </floater.string> - <floater.string name="server_images_cause_msg"> - Cause possible : trop de calculs d'images - </floater.string> - <floater.string name="server_generic_cause_msg"> - Cause possible : charge simulateur trop lourde - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button name="client_lagmeter" tool_tip="Statut du lag client"/> - <text name="client"> - Client - </text> - <text name="client_text"> - Normal - </text> - <button name="network_lagmeter" tool_tip="Statut du lag réseau"/> - <text name="network"> - Réseau - </text> - <text name="network_text"> - Normal - </text> - <button name="server_lagmeter" tool_tip="Statut du lag serveur"/> - <text name="server"> - Serveur - </text> - <text name="server_text"> - Normal - </text> - <button label=">>" name="minimize" tool_tip="Activer/désactiver la taille du floater"/> -</floater> diff --git a/indra/newview/skins/default/xui/it/floater_lagmeter.xml b/indra/newview/skins/default/xui/it/floater_lagmeter.xml deleted file mode 100755 index f7b2b1ab4a..0000000000 --- a/indra/newview/skins/default/xui/it/floater_lagmeter.xml +++ /dev/null @@ -1,154 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="MISURATORE LAG"> - <floater.string name="max_title_msg"> - Misuratore del lag - </floater.string> - <floater.string name="max_width_px"> - 360 - </floater.string> - <floater.string name="min_title_msg"> - Lag - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - Programma in locale - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - Normale, finestra sullo sfondo - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - Velocità dei frame al di sotto di [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - Velocità dei frame tra [CLIENT_FRAME_RATE_CRITICAL] e [CLIENT_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - Normale - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - Possibile causa: Campo visivo impostato troppo alto - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - Possibile causa: Caricamento immagini - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - Possibile causa: Troppe immagini in memoria - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - Possibile causa: Troppi oggetti complessi intorno - </floater.string> - <floater.string name="network_text_msg"> - Network - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - La connessione sta calando al di sotto del [NETWORK_PACKET_LOSS_CRITICAL]% di pacchetti - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - La connessione sta calando tra il [NETWORK_PACKET_LOSS_WARNING]% e il [NETWORK_PACKET_LOSS_CRITICAL]% di pacchetti - </floater.string> - <floater.string name="network_performance_normal_msg"> - Normale - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - Il tempo di ping della connessione è al di sopra di [NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_ping_warning_msg"> - Il tempo di ping della connessione è tra [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - Possibile cattiva connessione o la larghezza di banda impostata nelle preferenze troppo alta. - </floater.string> - <floater.string name="network_ping_cause_msg"> - Possibile cattiva connessione o l'apertura di un programma di scambio files. - </floater.string> - <floater.string name="server_text_msg"> - Server - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - Velocità dei frame al di sotto di [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - Velocità dei frame tra [SERVER_FRAME_RATE_CRITICAL] e [SERVER_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - Normale - </floater.string> - <floater.string name="server_physics_cause_msg"> - Possibile causa: troppi oggetti fisici - </floater.string> - <floater.string name="server_scripts_cause_msg"> - Possibile causa: troppi oggetti scriptati - </floater.string> - <floater.string name="server_net_cause_msg"> - Possibile causa: eccessivo traffico sulla rete - </floater.string> - <floater.string name="server_agent_cause_msg"> - Possibile causa: troppi residenti in movimento nella regione - </floater.string> - <floater.string name="server_images_cause_msg"> - Possibile causa: troppe elaborazioni di immagini - </floater.string> - <floater.string name="server_generic_cause_msg"> - Possibile causa: carico eccessivo del simulatore - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button label="" label_selected="" name="client_lagmeter" tool_tip="Stato del lag del programma in locale"/> - <text name="client"> - Client - </text> - <text font="SansSerifSmall" left="145" name="client_text"> - Normale - </text> - <text left="30" name="client_lag_cause" right="-10"/> - <button label="" label_selected="" name="network_lagmeter" tool_tip="Stato del lag del network"/> - <text name="network"> - Rete - </text> - <text font="SansSerifSmall" name="network_text"> - Normale - </text> - <text left="30" name="network_lag_cause" right="-10"/> - <button label="" label_selected="" name="server_lagmeter" tool_tip="Stato del lag del server"/> - <text name="server"> - Server - </text> - <text font="SansSerifSmall" name="server_text"> - Normale - </text> - <text left="30" name="server_lag_cause" right="-32"/> - <button label=">>" name="minimize" tool_tip="Cambia dimensioni floater"/> -</floater> diff --git a/indra/newview/skins/default/xui/ja/floater_lagmeter.xml b/indra/newview/skins/default/xui/ja/floater_lagmeter.xml deleted file mode 100755 index e3546cd837..0000000000 --- a/indra/newview/skins/default/xui/ja/floater_lagmeter.xml +++ /dev/null @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="ラグメーター"> - <floater.string name="max_title_msg"> - ラグ メーター - </floater.string> - <floater.string name="max_width_px"> - 350 - </floater.string> - <floater.string name="min_title_msg"> - ラグ - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - クライアント - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - ノーマル、ウィンドウは背景に - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - クライアント フレームレート < [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - クライアント フレームレート: [CLIENT_FRAME_RATE_CRITICAL] ~ [CLIENT_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - ノーマル - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - 考えられる原因: 描画距離の設定が大きすぎる - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - 考えられる原因: 画像のロード中 - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - 考えられる原因: メモリ内の画像数が多すぎる - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - 考えられる原因: 画面に含まれる複雑なオブジェクトが多すぎる - </floater.string> - <floater.string name="network_text_msg"> - ネットワーク - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - 接続でドロップされるパケットの割合: > [NETWORK_PACKET_LOSS_CRITICAL] - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - 接続でドロップされるパケットの割合:[NETWORK_PACKET_LOSS_WARNING] ~ [NETWORK_PACKET_LOSS_CRITICAL] - </floater.string> - <floater.string name="network_performance_normal_msg"> - ノーマル - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - 接続の ping 時間: > [NETWORK_PING_CRITICAL] ミリ秒 - </floater.string> - <floater.string name="network_ping_warning_msg"> - 接続の ping 時間: [NETWORK_PING_WARNING] ~ [NETWORK_PING_CRITICAL] ミリ秒 - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - 接続不良になっているか、帯域幅設定が高すぎます。 - </floater.string> - <floater.string name="network_ping_cause_msg"> - 接続不良になっているか、ファイル共有アプリケーションに問題があります。 - </floater.string> - <floater.string name="server_text_msg"> - サーバー - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - シミュレーターのフレームレート: < [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - シミュレーターのフレームレート: [SERVER_FRAME_RATE_CRITICAL] ~ [SERVER_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - ノーマル - </floater.string> - <floater.string name="server_physics_cause_msg"> - 考えられる原因: 物理的オブジェクトが多すぎる - </floater.string> - <floater.string name="server_scripts_cause_msg"> - 考えられる原因: スクリプトを含むオブジェクトが多すぎる - </floater.string> - <floater.string name="server_net_cause_msg"> - 考えられる原因: ネットワーク トラフィック過大 - </floater.string> - <floater.string name="server_agent_cause_msg"> - 考えられる原因: 地域内にて動いているアバターが多すぎる - </floater.string> - <floater.string name="server_images_cause_msg"> - 考えられる原因: 画像計算が多すぎる - </floater.string> - <floater.string name="server_generic_cause_msg"> - 考えられる原因: シミュレーターの過負荷 - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button name="client_lagmeter" tool_tip="クライアント ラグ ステータス"/> - <text name="client"> - クライアント - </text> - <text name="client_text"> - ノーマル - </text> - <button name="network_lagmeter" tool_tip="ネットワーク ラグ ステータス"/> - <text name="network"> - ネットワーク - </text> - <text name="network_text"> - ノーマル - </text> - <button name="server_lagmeter" tool_tip="サーバー ラグ ステータス"/> - <text name="server"> - サーバー - </text> - <text name="server_text"> - ノーマル - </text> - <button label=">> " name="minimize" tool_tip="フローターのサイズをトグル"/> -</floater> diff --git a/indra/newview/skins/default/xui/pl/floater_lagmeter.xml b/indra/newview/skins/default/xui/pl/floater_lagmeter.xml deleted file mode 100755 index 8038550bcb..0000000000 --- a/indra/newview/skins/default/xui/pl/floater_lagmeter.xml +++ /dev/null @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="POMIAR LAGÓW"> - <floater.string name="max_title_msg"> - Pomiar lagów - </floater.string> - <floater.string name="max_width_px"> - 360 - </floater.string> - <floater.string name="min_title_msg"> - Lag - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - Klient - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - W normie, okno w tle - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - Ilość klatek na sekundę klienta poniżej [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - Ilość klatek na sekundę pomiędzy [CLIENT_FRAME_RATE_CRITICAL] i [CLIENT_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - W normie - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - Przyczyna: dystans rysowania jest za wysoki - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - Przyczyna: ładowanie obrazu - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - Przyczyna: za dużo obrazów w pamięci - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - Przyczyna: za dużo złożonych obiektów - </floater.string> - <floater.string name="network_text_msg"> - Sieć - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - Utrata pakietów przekracza [NETWORK_PACKET_LOSS_CRITICAL]% - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - Utrata pakietów przekracza [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]% - </floater.string> - <floater.string name="network_performance_normal_msg"> - W normie - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - Fatalny ping - [NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_ping_warning_msg"> - Wolny ping - [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - Złe połączenie lub przepustowość. - </floater.string> - <floater.string name="network_ping_cause_msg"> - Złe połączenie lub aplikacja współdzieląca pliki. - </floater.string> - <floater.string name="server_text_msg"> - Serwer - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - Ilość klatek na sekundę poniżej [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - Ilość klatek na sekundę pomiędzy [SERVER_FRAME_RATE_CRITICAL] i [SERVER_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - W normie - </floater.string> - <floater.string name="server_physics_cause_msg"> - Przyczyna: za dużo obiektów fizycznych - </floater.string> - <floater.string name="server_scripts_cause_msg"> - Przyczyna: za dużo obieków skryptowanych - </floater.string> - <floater.string name="server_net_cause_msg"> - Przyczyna: za duży ruch w sieci - </floater.string> - <floater.string name="server_agent_cause_msg"> - Przyczyna: za dużo poruszających się awatarów w regionie - </floater.string> - <floater.string name="server_images_cause_msg"> - Przyczyna: za dużo kalkulacji obrazu - </floater.string> - <floater.string name="server_generic_cause_msg"> - Przyczyna: symulator ładuje się zbyt powoli - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button label="" label_selected="" name="client_lagmeter" tool_tip="Status lagów klienta"/> - <text name="client"> - Klient - </text> - <text name="client_text"> - W normie - </text> - <button label="" label_selected="" name="network_lagmeter" tool_tip="Network lag status"/> - <text name="network"> - Sieć - </text> - <text name="network_text"> - W normie - </text> - <button label="" label_selected="" name="server_lagmeter" tool_tip="Server lag status"/> - <text name="server"> - Serwer - </text> - <text name="server_text"> - W normie - </text> - <button label=">>" name="minimize" tool_tip="Złącz rozmiar pliku xml"/> -</floater> diff --git a/indra/newview/skins/default/xui/pt/floater_lagmeter.xml b/indra/newview/skins/default/xui/pt/floater_lagmeter.xml deleted file mode 100755 index 9932318293..0000000000 --- a/indra/newview/skins/default/xui/pt/floater_lagmeter.xml +++ /dev/null @@ -1,154 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="LAG - Índice"> - <floater.string name="max_title_msg"> - Medidor de Atraso - </floater.string> - <floater.string name="max_width_px"> - 360 - </floater.string> - <floater.string name="min_title_msg"> - Atraso - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - Cliente - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - Normal, janela por baixo - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - Taxa de quadros do Cliente abaixo de [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - Taxa de quadros do Cliente entre [CLIENT_FRAME_RATE_CRITICAL] e [CLIENT_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - Causa possível: Distância de desenho ajustada muito alta - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - Causa possível: Carregamento de Imagens - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - Causa possível: Muitas imagens na memória - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - Causa possível: Muitos objetos complexos na cena - </floater.string> - <floater.string name="network_text_msg"> - Rede - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - Conexão está caindo para cerca de [NETWORK_PACKET_LOSS_CRITICAL]% de pacotes - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - Conexão está caindo [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]% de pacotes - </floater.string> - <floater.string name="network_performance_normal_msg"> - Normal - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - Tempo de conexão de ping é cerca de [NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_ping_warning_msg"> - Tempo de conexão de ping é [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - Possível conexão ruim ou 'Largura de Banda' escolhida muito alta. - </floater.string> - <floater.string name="network_ping_cause_msg"> - Possível conexão ruim ou aplicativos compartilhando arquivos. - </floater.string> - <floater.string name="server_text_msg"> - Servidor - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - Taxa de quadros abaixo de [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - Taxa de quadros entre [SERVER_FRAME_RATE_CRITICAL] e [SERVER_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="server_physics_cause_msg"> - Causa possível: Muitos objetos físicos - </floater.string> - <floater.string name="server_scripts_cause_msg"> - Causa possível: Muitos objetos com scripts - </floater.string> - <floater.string name="server_net_cause_msg"> - Causa possível: Muito tráfego na rede - </floater.string> - <floater.string name="server_agent_cause_msg"> - Causa possível: Muitas pessoas se movendo na região - </floater.string> - <floater.string name="server_images_cause_msg"> - Causa possível: Muitos cálculos de imagem - </floater.string> - <floater.string name="server_generic_cause_msg"> - Causa possível: Carga no simulador muito pesada - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button label="" label_selected="" name="client_lagmeter" tool_tip="Status de atraso no Cliente"/> - <text name="client"> - Cliente - </text> - <text font="SansSerifSmall" name="client_text"> - Normal - </text> - <text left="30" name="client_lag_cause" right="-10"/> - <button label="" label_selected="" name="network_lagmeter" tool_tip="Status de atraso na rede"/> - <text name="network"> - Rede - </text> - <text font="SansSerifSmall" name="network_text"> - Normal - </text> - <text left="30" name="network_lag_cause" right="-10"/> - <button label="" label_selected="" name="server_lagmeter" tool_tip="Status de atraso no servidor"/> - <text name="server"> - Servidor - </text> - <text font="SansSerifSmall" name="server_text"> - Normal - </text> - <text left="30" name="server_lag_cause" right="-32"/> - <button label=">>" name="minimize" tool_tip="Alternar o tamanho da janela"/> -</floater> diff --git a/indra/newview/skins/default/xui/ru/floater_lagmeter.xml b/indra/newview/skins/default/xui/ru/floater_lagmeter.xml deleted file mode 100755 index c420006a03..0000000000 --- a/indra/newview/skins/default/xui/ru/floater_lagmeter.xml +++ /dev/null @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="УРОВЕНЬ ЛАГОВ"> - <floater.string name="max_title_msg"> - Уровень лагов - </floater.string> - <floater.string name="max_width_px"> - 360 - </floater.string> - <floater.string name="min_title_msg"> - Лаг - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - Клиент - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - Нормально, окно в фоне - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - Частота кадров клиента ниже [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - Частота кадров клиента от [CLIENT_FRAME_RATE_CRITICAL] до [CLIENT_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - Нормально - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - Возможная причина: дальность отрисовки слишком велика - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - Возможная причина: загрузка изображений - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - Возможная причина: слишком много изображений в памяти - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - Возможная причина: слишком много сложных объектов в сцене - </floater.string> - <floater.string name="network_text_msg"> - Сеть - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - Сеть теряет более [NETWORK_PACKET_LOSS_CRITICAL]% пакетов - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - Сеть теряет [NETWORK_PACKET_LOSS_WARNING]–[NETWORK_PACKET_LOSS_CRITICAL]% пакетов - </floater.string> - <floater.string name="network_performance_normal_msg"> - Нормально - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - Пинг соединения более [NETWORK_PING_CRITICAL] мс - </floater.string> - <floater.string name="network_ping_warning_msg"> - Пинг соединения [NETWORK_PING_WARNING]–[NETWORK_PING_CRITICAL] мс - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - Возможно, плохое соединение, или параметр «Ширина канала» слишком велик. - </floater.string> - <floater.string name="network_ping_cause_msg"> - Возможно, плохое соединение или есть работающие файлообменные программы. - </floater.string> - <floater.string name="server_text_msg"> - Сервер - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - Частота кадров сервера ниже [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - Частота кадров сервера [SERVER_FRAME_RATE_CRITICAL]–[SERVER_FRAME_RATE_WARNING] - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - Нормально - </floater.string> - <floater.string name="server_physics_cause_msg"> - Возможная причина: слишком много физических объектов - </floater.string> - <floater.string name="server_scripts_cause_msg"> - Возможная причина: слишком много скриптовых объектов - </floater.string> - <floater.string name="server_net_cause_msg"> - Возможная причина: слишком большой сетевой трафик - </floater.string> - <floater.string name="server_agent_cause_msg"> - Возможная причина: слишком много людей в регионе - </floater.string> - <floater.string name="server_images_cause_msg"> - Возможная причина: слишком много изображений - </floater.string> - <floater.string name="server_generic_cause_msg"> - Возможная причина: сервер сильно загружен - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button name="client_lagmeter" tool_tip="Уровень лагов клиента"/> - <text name="client"> - Клиент - </text> - <text name="client_text"> - Нормально - </text> - <button name="network_lagmeter" tool_tip="Уровень лагов сети"/> - <text name="network"> - Сеть - </text> - <text name="network_text"> - Нормально - </text> - <button name="server_lagmeter" tool_tip="Уровень лагов сервера"/> - <text name="server"> - Сервер - </text> - <text name="server_text"> - Нормально - </text> - <button label=">>" name="minimize" tool_tip="Переключение размера"/> -</floater> diff --git a/indra/newview/skins/default/xui/tr/floater_lagmeter.xml b/indra/newview/skins/default/xui/tr/floater_lagmeter.xml deleted file mode 100755 index 736c50be90..0000000000 --- a/indra/newview/skins/default/xui/tr/floater_lagmeter.xml +++ /dev/null @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="GECİKME ÖLÇER"> - <floater.string name="max_title_msg"> - Gecikme Ölçer - </floater.string> - <floater.string name="max_width_px"> - 360 - </floater.string> - <floater.string name="min_title_msg"> - Gecikme - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - İstemci - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - Normal, pencere alt zeminde - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - İstemci kare hızı [CLIENT_FRAME_RATE_CRITICAL] altında - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - İstemci kare hızı [CLIENT_FRAME_RATE_CRITICAL] ile [CLIENT_FRAME_RATE_WARNING] arasınad - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - Muhtemel neden: Çizme mesafesi çok yüksek - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - Muhtemel neden: Görüntüler yükleniyor - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - Muhtemel neden: Bellekte çok fazla görüntü - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - Muhtemel neden: Sahnede çok fazla karmaşık nesne - </floater.string> - <floater.string name="network_text_msg"> - Ağ - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - Bağlantı paketlerin % [NETWORK_PACKET_LOSS_CRITICAL]'sinden fazlasını bırakıyor - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - Bağlantı paketlerin % [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]'sini bırakıyor - </floater.string> - <floater.string name="network_performance_normal_msg"> - Normal - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - Bağlantı ping süresi [NETWORK_PING_CRITICAL] ms.den fazla - </floater.string> - <floater.string name="network_ping_warning_msg"> - Bağlantı ping süresi [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] ms - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - Muhtemel yetersiz bağlantı veya 'Bant Genişliği' tercihi çok yüksek. - </floater.string> - <floater.string name="network_ping_cause_msg"> - Muhtemel yetersiz bağlantı veya dosya paylaşım uygulaması. - </floater.string> - <floater.string name="server_text_msg"> - Sunucu - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - Simülatör kare hızı [SERVER_FRAME_RATE_CRITICAL] altında - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - Simülatör kare hızı [SERVER_FRAME_RATE_CRITICAL] ve [SERVER_FRAME_RATE_WARNING] arasında - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - Normal - </floater.string> - <floater.string name="server_physics_cause_msg"> - Muhtemel Neden: Çok fazla fiziki nesne - </floater.string> - <floater.string name="server_scripts_cause_msg"> - Muhtemel Neden: Çok fazla komut dosyalı nesne - </floater.string> - <floater.string name="server_net_cause_msg"> - Muhtemel Neden: Çok fazla ağ trafiği - </floater.string> - <floater.string name="server_agent_cause_msg"> - Muhtemel Neden: Bölgede hareket eden çok fazla insan var - </floater.string> - <floater.string name="server_images_cause_msg"> - Muhtemel Neden: Çok fazla görüntü hesabı - </floater.string> - <floater.string name="server_generic_cause_msg"> - Muhtemel Neden: Simülatör yükü çok ağır - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button name="client_lagmeter" tool_tip="İstemci gecikme durumu"/> - <text name="client"> - İstemci - </text> - <text name="client_text"> - Normal - </text> - <button name="network_lagmeter" tool_tip="Ağ gecikme durumu"/> - <text name="network"> - Ağ - </text> - <text name="network_text"> - Normal - </text> - <button name="server_lagmeter" tool_tip="Sunucu gecikme durumu"/> - <text name="server"> - Sunucu - </text> - <text name="server_text"> - Normal - </text> - <button label=">>" name="minimize" tool_tip="Gezdirici büyüklüğünü değiştir"/> -</floater> diff --git a/indra/newview/skins/default/xui/zh/floater_lagmeter.xml b/indra/newview/skins/default/xui/zh/floater_lagmeter.xml deleted file mode 100755 index e9a082288a..0000000000 --- a/indra/newview/skins/default/xui/zh/floater_lagmeter.xml +++ /dev/null @@ -1,151 +0,0 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes"?> -<floater name="floater_lagmeter" title="LAG 測量器"> - <floater.string name="max_title_msg"> - Lag 測量器 - </floater.string> - <floater.string name="max_width_px"> - 360 - </floater.string> - <floater.string name="min_title_msg"> - 延遲 - </floater.string> - <floater.string name="min_width_px"> - 90 - </floater.string> - <floater.string name="client_text_msg"> - 客戶端 - </floater.string> - <floater.string name="client_frame_rate_critical_fps"> - 10 - </floater.string> - <floater.string name="client_frame_rate_warning_fps"> - 15 - </floater.string> - <floater.string name="client_frame_time_window_bg_msg"> - 正常,視窗位於背景 - </floater.string> - <floater.string name="client_frame_time_critical_msg"> - 客戶端幀率低於 [CLIENT_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="client_frame_time_warning_msg"> - 客戶端幀率介於 [CLIENT_FRAME_RATE_CRITICAL] 和 [CLIENT_FRAME_RATE_WARNING] 之間 - </floater.string> - <floater.string name="client_frame_time_normal_msg"> - 正常 - </floater.string> - <floater.string name="client_draw_distance_cause_msg"> - 可能原因:可視距離設得太遠 - </floater.string> - <floater.string name="client_texture_loading_cause_msg"> - 可能原因:正在載入圖像 - </floater.string> - <floater.string name="client_texture_memory_cause_msg"> - 可能原因:記憶體裡圖像太多 - </floater.string> - <floater.string name="client_complex_objects_cause_msg"> - 可能原因:場景內複雜物件太多 - </floater.string> - <floater.string name="network_text_msg"> - 網路 - </floater.string> - <floater.string name="network_packet_loss_critical_pct"> - 10 - </floater.string> - <floater.string name="network_packet_loss_warning_pct"> - 5 - </floater.string> - <floater.string name="network_packet_loss_critical_msg"> - 這次連通丟失了至少 [NETWORK_PACKET_LOSS_CRITICAL]% 的封包 - </floater.string> - <floater.string name="network_packet_loss_warning_msg"> - 這次連通丟失了 [NETWORK_PACKET_LOSS_WARNING]%-[NETWORK_PACKET_LOSS_CRITICAL]% 的封包 - </floater.string> - <floater.string name="network_performance_normal_msg"> - 正常 - </floater.string> - <floater.string name="network_ping_critical_ms"> - 600 - </floater.string> - <floater.string name="network_ping_warning_ms"> - 300 - </floater.string> - <floater.string name="network_ping_critical_msg"> - 探測連通回應時間超過 [NETWORK_PING_CRITICAL] 毫秒 - </floater.string> - <floater.string name="network_ping_warning_msg"> - 探測連通回應時間為 [NETWORK_PING_WARNING]-[NETWORK_PING_CRITICAL] 毫秒 - </floater.string> - <floater.string name="network_packet_loss_cause_msg"> - 可能連通不良,或所設的偏好連通頻寬過高。 - </floater.string> - <floater.string name="network_ping_cause_msg"> - 可能連通不良,或使用檔案分享應用程式。 - </floater.string> - <floater.string name="server_text_msg"> - 伺服器 - </floater.string> - <floater.string name="server_frame_rate_critical_fps"> - 20 - </floater.string> - <floater.string name="server_frame_rate_warning_fps"> - 30 - </floater.string> - <floater.string name="server_single_process_max_time_ms"> - 20 - </floater.string> - <floater.string name="server_frame_time_critical_msg"> - 模擬器 framerate 低於 [SERVER_FRAME_RATE_CRITICAL] - </floater.string> - <floater.string name="server_frame_time_warning_msg"> - 模擬器 framerate 介於 [SERVER_FRAME_RATE_CRITICAL] 與 [SERVER_FRAME_RATE_WARNING] 之間 - </floater.string> - <floater.string name="server_frame_time_normal_msg"> - 正常 - </floater.string> - <floater.string name="server_physics_cause_msg"> - 可能原因:太多物理物件 - </floater.string> - <floater.string name="server_scripts_cause_msg"> - 可能原因:太多腳本物件 - </floater.string> - <floater.string name="server_net_cause_msg"> - 可能原因:太多網路流量 - </floater.string> - <floater.string name="server_agent_cause_msg"> - 可能原因:地區有太多移動的人 - </floater.string> - <floater.string name="server_images_cause_msg"> - 可能原因:太多圖像計算 - </floater.string> - <floater.string name="server_generic_cause_msg"> - 可能原因:模擬器負載過重 - </floater.string> - <floater.string name="smaller_label"> - >> - </floater.string> - <floater.string name="bigger_label"> - << - </floater.string> - <button name="client_lagmeter" tool_tip="客戶端 lag 狀態"/> - <text name="client"> - 客戶端 - </text> - <text name="client_text"> - 正常 - </text> - <button name="network_lagmeter" tool_tip="網路 lag 狀態"/> - <text name="network"> - 網路 - </text> - <text name="network_text"> - 正常 - </text> - <button name="server_lagmeter" tool_tip="伺服器 lag 狀態"/> - <text name="server"> - 伺服器 - </text> - <text name="server_text"> - 正常 - </text> - <button label=">>" name="minimize" tool_tip="切換浮動視窗尺寸"/> -</floater> diff --git a/indra/newview/tests/llviewerassetstats_test.cpp b/indra/newview/tests/llviewerassetstats_test.cpp index a331d9aa9e..561c2bb286 100755 --- a/indra/newview/tests/llviewerassetstats_test.cpp +++ b/indra/newview/tests/llviewerassetstats_test.cpp @@ -37,6 +37,35 @@ #include "llregionhandle.h" #include "../llvoavatar.h" +namespace LLStatViewer +{ + LLTrace::SampleStatHandle<> FPS_SAMPLE("fpssample"); +} + +void LLVOAvatar::getNearbyRezzedStats(std::vector<S32>& counts) +{ + counts.resize(3); + counts[0] = 0; + counts[1] = 0; + counts[2] = 1; +} + +// static +std::string LLVOAvatar::rezStatusToString(S32 rez_status) +{ + if (rez_status==0) return "cloud"; + if (rez_status==1) return "gray"; + if (rez_status==2) return "textured"; + return "unknown"; +} + +// static +LLViewerStats::StatsAccumulator& LLViewerStats::PhaseMap::getPhaseStats(const std::string& phase_name) +{ + static LLViewerStats::StatsAccumulator junk; + return junk; +} + static const char * all_keys[] = { "duration", @@ -199,7 +228,18 @@ get_region(const LLSD & sd, U64 region_handle1) namespace tut { struct tst_viewerassetstats_index - {}; + { + tst_viewerassetstats_index() + { + LLTrace::init(); + } + + ~tst_viewerassetstats_index() + { + LLTrace::cleanup(); + } + + }; typedef test_group<tst_viewerassetstats_index> tst_viewerassetstats_index_t; typedef tst_viewerassetstats_index_t::object tst_viewerassetstats_index_object_t; tut::tst_viewerassetstats_index_t tut_tst_viewerassetstats_index("tst_viewerassetstats_test"); @@ -209,24 +249,24 @@ namespace tut void tst_viewerassetstats_index_object_t::test<1>() { // Check that helpers aren't bothered by missing global stats - ensure("Global gViewerAssetStatsMain should be NULL", (NULL == gViewerAssetStatsMain)); + ensure("Global gViewerAssetStats should be NULL", (NULL == gViewerAssetStats)); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_response_main(LLViewerAssetType::AT_GESTURE, false, false, 12300000ULL); + LLViewerAssetStatsFF::record_response(LLViewerAssetType::AT_GESTURE, false, false, 12300000ULL); } // Create a non-global instance and check the structure template<> template<> void tst_viewerassetstats_index_object_t::test<2>() { - ensure("Global gViewerAssetStatsMain should be NULL", (NULL == gViewerAssetStatsMain)); + ensure("Global gViewerAssetStats should be NULL", (NULL == gViewerAssetStats)); LLViewerAssetStats * it = new LLViewerAssetStats(); - ensure("Global gViewerAssetStatsMain should still be NULL", (NULL == gViewerAssetStatsMain)); + ensure("Global gViewerAssetStats should still be NULL", (NULL == gViewerAssetStats)); LLSD sd_full = it->asLLSD(false); @@ -293,17 +333,18 @@ namespace tut template<> template<> void tst_viewerassetstats_index_object_t::test<4>() { - gViewerAssetStatsMain = new LLViewerAssetStats(); - LLViewerAssetStatsFF::set_region_main(region1_handle); + gViewerAssetStats = new LLViewerAssetStats(); + LLViewerAssetStatsFF::set_region(region1_handle); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, false, false); + gViewerAssetStats->updateStats(); LLSD sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd["regions"][0]; @@ -316,11 +357,11 @@ namespace tut // Reset and check zeros... // Reset leaves current region in place - gViewerAssetStatsMain->reset(); - sd = gViewerAssetStatsMain->asLLSD(false)["regions"][region1_handle_str]; + gViewerAssetStats->reset(); + sd = gViewerAssetStats->asLLSD(false)["regions"][region1_handle_str]; - delete gViewerAssetStatsMain; - gViewerAssetStatsMain = NULL; + delete gViewerAssetStats; + gViewerAssetStats = NULL; ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); @@ -330,20 +371,18 @@ namespace tut template<> template<> void tst_viewerassetstats_index_object_t::test<5>() { - gViewerAssetStatsThread1 = new LLViewerAssetStats(); - gViewerAssetStatsMain = new LLViewerAssetStats(); - LLViewerAssetStatsFF::set_region_main(region1_handle); + gViewerAssetStats = new LLViewerAssetStats(); + LLViewerAssetStatsFF::set_region(region1_handle); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, false, false); - LLSD sd = gViewerAssetStatsThread1->asLLSD(false); - ensure("Other collector is empty", is_no_stats_map(sd)); - sd = gViewerAssetStatsMain->asLLSD(false); - ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); + gViewerAssetStats->updateStats(); + LLSD sd = gViewerAssetStatsMain->asLLSD(false); + ensure("Correct single-key LLSD map root", is_triple_key_map(sd, "regions", "duration", "avatar")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); sd = sd["regions"][0]; @@ -356,13 +395,11 @@ namespace tut // Reset and check zeros... // Reset leaves current region in place - gViewerAssetStatsMain->reset(); - sd = gViewerAssetStatsMain->asLLSD(false)["regions"][0]; + gViewerAssetStats->reset(); + sd = gViewerAssetStats->asLLSD(false)["regions"][0]; - delete gViewerAssetStatsMain; - gViewerAssetStatsMain = NULL; - delete gViewerAssetStatsThread1; - gViewerAssetStatsThread1 = NULL; + delete gViewerAssetStats; + gViewerAssetStats = NULL; ensure("sd[get_texture_non_temp_udp][enqueued] is reset", (0 == sd["get_texture_non_temp_udp"]["enqueued"].asInteger())); ensure("sd[get_gesture_udp][dequeued] is reset", (0 == sd["get_gesture_udp"]["dequeued"].asInteger())); @@ -372,24 +409,25 @@ namespace tut template<> template<> void tst_viewerassetstats_index_object_t::test<6>() { - gViewerAssetStatsMain = new LLViewerAssetStats(); + gViewerAssetStats = new LLViewerAssetStats(); - LLViewerAssetStatsFF::set_region_main(region1_handle); + LLViewerAssetStatsFF::set_region(region1_handle); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::set_region_main(region2_handle); + LLViewerAssetStatsFF::set_region(region2_handle); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); - LLSD sd = gViewerAssetStatsMain->asLLSD(false); + gViewerAssetStats->updateStats(); + LLSD sd = gViewerAssetStats->asLLSD(false); // std::cout << sd << std::endl; @@ -420,8 +458,8 @@ namespace tut ensure("Correct single-slot LLSD array regions (p2)", is_single_slot_array(sd["regions"], region2_handle)); sd2 = sd["regions"][0]; - delete gViewerAssetStatsMain; - gViewerAssetStatsMain = NULL; + delete gViewerAssetStats; + gViewerAssetStats = NULL; ensure("sd2[get_texture_non_temp_udp][enqueued] is reset", (0 == sd2["get_texture_non_temp_udp"]["enqueued"].asInteger())); ensure("sd2[get_gesture_udp][enqueued] is reset", (0 == sd2["get_gesture_udp"]["enqueued"].asInteger())); @@ -431,39 +469,40 @@ namespace tut template<> template<> void tst_viewerassetstats_index_object_t::test<7>() { - gViewerAssetStatsMain = new LLViewerAssetStats(); + gViewerAssetStats = new LLViewerAssetStats(); - LLViewerAssetStatsFF::set_region_main(region1_handle); + LLViewerAssetStatsFF::set_region(region1_handle); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::set_region_main(region2_handle); + LLViewerAssetStatsFF::set_region(region2_handle); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); - LLViewerAssetStatsFF::set_region_main(region1_handle); + LLViewerAssetStatsFF::set_region(region1_handle); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, true, true); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, true, true); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, true, true); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, true, true); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::set_region_main(region2_handle); + LLViewerAssetStatsFF::set_region(region2_handle); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_GESTURE, false, false); - LLSD sd = gViewerAssetStatsMain->asLLSD(false); + gViewerAssetStats->updateStats(); + LLSD sd = gViewerAssetStats->asLLSD(false); ensure("Correct double-key LLSD map root", is_double_key_map(sd, "duration", "regions")); ensure("Correct double-slot LLSD array regions", is_double_slot_array(sd["regions"], region1_handle, region2_handle)); @@ -493,8 +532,8 @@ namespace tut sd2 = get_region(sd, region2_handle); ensure("Region2 is present in results", sd2.isMap()); - delete gViewerAssetStatsMain; - gViewerAssetStatsMain = NULL; + delete gViewerAssetStats; + gViewerAssetStats = NULL; ensure_equals("sd2[get_texture_non_temp_udp][enqueued] is reset", sd2["get_texture_non_temp_udp"]["enqueued"].asInteger(), 0); ensure_equals("sd2[get_gesture_udp][enqueued] is reset", sd2["get_gesture_udp"]["enqueued"].asInteger(), 0); @@ -504,35 +543,33 @@ namespace tut template<> template<> void tst_viewerassetstats_index_object_t::test<8>() { - gViewerAssetStatsThread1 = new LLViewerAssetStats(); - gViewerAssetStatsMain = new LLViewerAssetStats(); - LLViewerAssetStatsFF::set_region_main(region1_handle); + gViewerAssetStats = new LLViewerAssetStats(); + LLViewerAssetStatsFF::set_region(region1_handle); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_TEXTURE, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_TEXTURE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, false, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, false, true); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, false, true); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, false, true); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, false, true); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, true, false); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, true, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, true, false); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, true, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_BODYPART, true, true); - LLViewerAssetStatsFF::record_dequeue_main(LLViewerAssetType::AT_BODYPART, true, true); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_BODYPART, true, true); + LLViewerAssetStatsFF::record_dequeue(LLViewerAssetType::AT_BODYPART, true, true); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, false, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_LSL_BYTECODE, false, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, false, true); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_LSL_BYTECODE, false, true); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, false); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_LSL_BYTECODE, true, false); - LLViewerAssetStatsFF::record_enqueue_main(LLViewerAssetType::AT_LSL_BYTECODE, true, true); + LLViewerAssetStatsFF::record_enqueue(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - LLSD sd = gViewerAssetStatsThread1->asLLSD(false); - ensure("Other collector is empty", is_no_stats_map(sd)); + gViewerAssetStats->updateStats(); sd = gViewerAssetStatsMain->asLLSD(false); ensure("Correct single-key LLSD map root", is_double_key_map(sd, "regions", "duration")); ensure("Correct single-slot LLSD array regions", is_single_slot_array(sd["regions"], region1_handle)); @@ -551,445 +588,14 @@ namespace tut // Reset and check zeros... // Reset leaves current region in place - gViewerAssetStatsMain->reset(); - sd = get_region(gViewerAssetStatsMain->asLLSD(false), region1_handle); + gViewerAssetStats->reset(); + sd = get_region(gViewerAssetStats->asLLSD(false), region1_handle); ensure("Region1 is present in results", sd.isMap()); - delete gViewerAssetStatsMain; - gViewerAssetStatsMain = NULL; - delete gViewerAssetStatsThread1; - gViewerAssetStatsThread1 = NULL; + delete gViewerAssetStats; + gViewerAssetStats = NULL; ensure_equals("sd[get_texture_non_temp_udp][enqueued] is reset", sd["get_texture_non_temp_udp"]["enqueued"].asInteger(), 0); ensure_equals("sd[get_gesture_udp][dequeued] is reset", sd["get_gesture_udp"]["dequeued"].asInteger(), 0); } - - - // LLViewerAssetStats::merge() basic functions work - template<> template<> - void tst_viewerassetstats_index_object_t::test<9>() - { - LLViewerAssetStats s1; - LLViewerAssetStats s2; - - s1.setRegion(region1_handle); - s2.setRegion(region1_handle); - - s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 5000000); - s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 6000000); - s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 8000000); - s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 7000000); - s1.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 9000000); - - s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 2000000); - s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 3000000); - s2.recordGetServiced(LLViewerAssetType::AT_TEXTURE, true, true, 4000000); - - s2.merge(s1); - - LLSD s2_llsd = get_region(s2.asLLSD(false), region1_handle); - ensure("Region1 is present in results", s2_llsd.isMap()); - - ensure_equals("count after merge", s2_llsd["get_texture_temp_http"]["resp_count"].asInteger(), 8); - ensure_approximately_equals("min after merge", s2_llsd["get_texture_temp_http"]["resp_min"].asReal(), 2.0, 22); - ensure_approximately_equals("max after merge", s2_llsd["get_texture_temp_http"]["resp_max"].asReal(), 9.0, 22); - ensure_approximately_equals("max after merge", s2_llsd["get_texture_temp_http"]["resp_mean"].asReal(), 5.5, 22); - } - - // LLViewerAssetStats::merge() basic functions work without corrupting source data - template<> template<> - void tst_viewerassetstats_index_object_t::test<10>() - { - LLViewerAssetStats s1; - LLViewerAssetStats s2; - - s1.setRegion(region1_handle); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 23289200); - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 282900); - - - s2.setRegion(region2_handle); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 6500000); - s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 10000); - - { - s2.merge(s1); - - LLSD src = s1.asLLSD(false); - LLSD dst = s2.asLLSD(false); - - ensure_equals("merge src has single region", src["regions"].size(), 1); - ensure_equals("merge dst has dual regions", dst["regions"].size(), 2); - - // Remove time stamps, they're a problem - src.erase("duration"); - src["regions"][0].erase("duration"); - dst.erase("duration"); - dst["regions"][0].erase("duration"); - dst["regions"][1].erase("duration"); - - LLSD s1_llsd = get_region(src, region1_handle); - ensure("Region1 is present in src", s1_llsd.isMap()); - LLSD s2_llsd = get_region(dst, region1_handle); - ensure("Region1 is present in dst", s2_llsd.isMap()); - - ensure("result from src is in dst", llsd_equals(s1_llsd, s2_llsd)); - } - - s1.setRegion(region1_handle); - s2.setRegion(region1_handle); - s1.reset(); - s2.reset(); - - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 23289200); - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 282900); - - - s2.setRegion(region1_handle); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 6500000); - s2.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 10000); - - { - s2.merge(s1); - - LLSD src = s1.asLLSD(false); - LLSD dst = s2.asLLSD(false); - - ensure_equals("merge src has single region (p2)", src["regions"].size(), 1); - ensure_equals("merge dst has single region (p2)", dst["regions"].size(), 1); - - // Remove time stamps, they're a problem - src.erase("duration"); - src["regions"][0].erase("duration"); - dst.erase("duration"); - dst["regions"][0].erase("duration"); - - LLSD s1_llsd = get_region(src, region1_handle); - ensure("Region1 is present in src", s1_llsd.isMap()); - LLSD s2_llsd = get_region(dst, region1_handle); - ensure("Region1 is present in dst", s2_llsd.isMap()); - - ensure_equals("src counts okay (enq)", s1_llsd["get_other"]["enqueued"].asInteger(), 4); - ensure_equals("src counts okay (deq)", s1_llsd["get_other"]["dequeued"].asInteger(), 4); - ensure_equals("src resp counts okay", s1_llsd["get_other"]["resp_count"].asInteger(), 2); - ensure_approximately_equals("src respmin okay", s1_llsd["get_other"]["resp_min"].asReal(), 0.2829, 20); - ensure_approximately_equals("src respmax okay", s1_llsd["get_other"]["resp_max"].asReal(), 23.2892, 20); - - ensure_equals("dst counts okay (enq)", s2_llsd["get_other"]["enqueued"].asInteger(), 12); - ensure_equals("src counts okay (deq)", s2_llsd["get_other"]["dequeued"].asInteger(), 11); - ensure_equals("dst resp counts okay", s2_llsd["get_other"]["resp_count"].asInteger(), 4); - ensure_approximately_equals("dst respmin okay", s2_llsd["get_other"]["resp_min"].asReal(), 0.010, 20); - ensure_approximately_equals("dst respmax okay", s2_llsd["get_other"]["resp_max"].asReal(), 23.2892, 20); - } - } - - - // Maximum merges are interesting when one side contributes nothing - template<> template<> - void tst_viewerassetstats_index_object_t::test<11>() - { - LLViewerAssetStats s1; - LLViewerAssetStats s2; - - s1.setRegion(region1_handle); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - // Want to test negative numbers here but have to work in U64 - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); - - s2.setRegion(region1_handle); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - { - s2.merge(s1); - - LLSD src = s1.asLLSD(false); - LLSD dst = s2.asLLSD(false); - - ensure_equals("merge src has single region", src["regions"].size(), 1); - ensure_equals("merge dst has single region", dst["regions"].size(), 1); - - // Remove time stamps, they're a problem - src.erase("duration"); - src["regions"][0].erase("duration"); - dst.erase("duration"); - dst["regions"][0].erase("duration"); - - LLSD s2_llsd = get_region(dst, region1_handle); - ensure("Region1 is present in dst", s2_llsd.isMap()); - - ensure_equals("dst counts come from src only", s2_llsd["get_other"]["resp_count"].asInteger(), 3); - - ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum", - s2_llsd["get_other"]["resp_max"].asReal(), F64(0.0), 20); - } - - // Other way around - s1.setRegion(region1_handle); - s2.setRegion(region1_handle); - s1.reset(); - s2.reset(); - - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - // Want to test negative numbers here but have to work in U64 - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 0); - - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - { - s1.merge(s2); - - LLSD src = s2.asLLSD(false); - LLSD dst = s1.asLLSD(false); - - ensure_equals("merge src has single region", src["regions"].size(), 1); - ensure_equals("merge dst has single region", dst["regions"].size(), 1); - - // Remove time stamps, they're a problem - src.erase("duration"); - src["regions"][0].erase("duration"); - dst.erase("duration"); - dst["regions"][0].erase("duration"); - - LLSD s2_llsd = get_region(dst, region1_handle); - ensure("Region1 is present in dst", s2_llsd.isMap()); - - ensure_equals("dst counts come from src only (flipped)", s2_llsd["get_other"]["resp_count"].asInteger(), 3); - - ensure_approximately_equals("dst maximum with count 0 does not contribute to merged maximum (flipped)", - s2_llsd["get_other"]["resp_max"].asReal(), F64(0.0), 20); - } - } - - // Minimum merges are interesting when one side contributes nothing - template<> template<> - void tst_viewerassetstats_index_object_t::test<12>() - { - LLViewerAssetStats s1; - LLViewerAssetStats s2; - - s1.setRegion(region1_handle); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 3800000); - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2700000); - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2900000); - - s2.setRegion(region1_handle); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - { - s2.merge(s1); - - LLSD src = s1.asLLSD(false); - LLSD dst = s2.asLLSD(false); - - ensure_equals("merge src has single region", src["regions"].size(), 1); - ensure_equals("merge dst has single region", dst["regions"].size(), 1); - - // Remove time stamps, they're a problem - src.erase("duration"); - src["regions"][0].erase("duration"); - dst.erase("duration"); - dst["regions"][0].erase("duration"); - - LLSD s2_llsd = get_region(dst, region1_handle); - ensure("Region1 is present in dst", s2_llsd.isMap()); - - ensure_equals("dst counts come from src only", s2_llsd["get_other"]["resp_count"].asInteger(), 3); - - ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum", - s2_llsd["get_other"]["resp_min"].asReal(), F64(2.7), 20); - } - - // Other way around - s1.setRegion(region1_handle); - s2.setRegion(region1_handle); - s1.reset(); - s2.reset(); - - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s1.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 3800000); - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2700000); - s1.recordGetServiced(LLViewerAssetType::AT_LSL_BYTECODE, true, true, 2900000); - - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetEnqueued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - s2.recordGetDequeued(LLViewerAssetType::AT_LSL_BYTECODE, true, true); - - { - s1.merge(s2); - - LLSD src = s2.asLLSD(false); - LLSD dst = s1.asLLSD(false); - - ensure_equals("merge src has single region", src["regions"].size(), 1); - ensure_equals("merge dst has single region", dst["regions"].size(), 1); - - // Remove time stamps, they're a problem - src.erase("duration"); - src["regions"][0].erase("duration"); - dst.erase("duration"); - dst["regions"][0].erase("duration"); - - LLSD s2_llsd = get_region(dst, region1_handle); - ensure("Region1 is present in dst", s2_llsd.isMap()); - - ensure_equals("dst counts come from src only (flipped)", s2_llsd["get_other"]["resp_count"].asInteger(), 3); - - ensure_approximately_equals("dst minimum with count 0 does not contribute to merged minimum (flipped)", - s2_llsd["get_other"]["resp_min"].asReal(), F64(2.7), 20); - } - } - } diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt index 31e1d89c68..62b1d9db62 100755 --- a/indra/test/CMakeLists.txt +++ b/indra/test/CMakeLists.txt @@ -56,7 +56,6 @@ set(test_SOURCE_FILES llstreamtools_tut.cpp lltemplatemessagebuilder_tut.cpp lltut.cpp - lluuidhashmap_tut.cpp message_tut.cpp test.cpp ) diff --git a/indra/test/io.cpp b/indra/test/io.cpp index e776a2a3be..261422e9fc 100755 --- a/indra/test/io.cpp +++ b/indra/test/io.cpp @@ -44,6 +44,7 @@ #include "llsdrpcclient.h" #include "llsdrpcserver.h" #include "llsdserialize.h" +#include "llcommon.h" #include "lluuid.h" #include "llinstantmessage.h" @@ -1187,7 +1188,9 @@ namespace tut mResponsePtr(response) { } - ~LLSimpleRPCResponse() {} + ~LLSimpleRPCResponse() + { + } virtual bool response(LLPumpIO* pump) { *mResponsePtr = mReturnValue; diff --git a/indra/test/llhttpdate_tut.cpp b/indra/test/llhttpdate_tut.cpp index 46684bb9dc..ecf734ee90 100755 --- a/indra/test/llhttpdate_tut.cpp +++ b/indra/test/llhttpdate_tut.cpp @@ -29,6 +29,7 @@ #include "lltut.h" #include "lldate.h" +#include "llcommon.h" #include "llframetimer.h" #include <time.h> @@ -38,6 +39,12 @@ namespace tut { struct httpdate_data { + httpdate_data() + { + } + ~httpdate_data() + { + } LLDate some_date; }; typedef test_group<httpdate_data> httpdate_test; diff --git a/indra/test/lliohttpserver_tut.cpp b/indra/test/lliohttpserver_tut.cpp index 2fdc455f45..3fa5c8dd42 100755 --- a/indra/test/lliohttpserver_tut.cpp +++ b/indra/test/lliohttpserver_tut.cpp @@ -31,6 +31,7 @@ #include "lliohttpserver.h" #include "llsdhttpserver.h" #include "llsdserialize.h" +#include "llcommon.h" #include "llpipeutil.h" @@ -81,6 +82,10 @@ namespace tut mRoot.addNode("/delayed/echo", new DelayedEcho(this)); mRoot.addNode("/wire/hello", new LLHTTPNodeForPipe<WireHello>); } + + ~HTTPServiceTestData() + { + } LLHTTPNode mRoot; LLHTTPNode::ResponsePtr mResponse; diff --git a/indra/test/lluuidhashmap_tut.cpp b/indra/test/lluuidhashmap_tut.cpp deleted file mode 100755 index 9712a613f4..0000000000 --- a/indra/test/lluuidhashmap_tut.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/** - * @file lluuidhashmap_tut.cpp - * @author Adroit - * @date 2007-02 - * @brief Test cases for LLUUIDHashMap - * - * $LicenseInfo:firstyear=2007&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 <tut/tut.hpp> -#include "linden_common.h" -#include "lluuidhashmap.h" -#include "llsdserialize.h" -#include "lldir.h" -#include "stringize.h" -#include <iostream> -#include <fstream> - -namespace tut -{ - class UUIDTableEntry - { - public: - UUIDTableEntry() - { - mID.setNull(); - mValue = 0; - } - - UUIDTableEntry(const LLUUID& id, U32 value) - { - mID = id; - mValue = value; - } - - ~UUIDTableEntry(){}; - - static BOOL uuidEq(const LLUUID &uuid, const UUIDTableEntry &id_pair) - { - if (uuid == id_pair.mID) - { - return TRUE; - } - return FALSE; - } - - const LLUUID& getID() { return mID; } - const U32& getValue() { return mValue; } - - protected: - LLUUID mID; - U32 mValue; - }; - - struct hashmap_test - { - }; - - typedef test_group<hashmap_test> hash_index_t; - typedef hash_index_t::object hash_index_object_t; - tut::hash_index_t tut_hash_index("hashmap_test"); - - // stress test - template<> template<> - void hash_index_object_t::test<1>() - { - set_test_name("stress test"); - // As of 2012-10-10, I (nat) have observed sporadic failures of this - // test: "set/get did not work." The trouble is that since test data - // are randomly generated with every run, it is impossible to debug a - // test failure. One is left with the uneasy suspicion that - // LLUUID::generate() can sometimes produce duplicates even within the - // moderately small number requested here. Since rerunning the test - // generally allows it to pass, it's too easy to shrug and forget it. - // The following code is intended to support reproducing such test - // failures. The idea is that, on test failure, we save the generated - // data to a canonical filename in a temp directory. Then on every - // subsequent run, we check for that filename. If it exists, we reload - // that specific data rather than generating fresh data -- which - // should presumably reproduce the same test failure. But we inform - // the user that to resume normal (random) test runs, s/he need only - // delete that file. And since it's in a temp directory, sooner or - // later the system will clean it up anyway. - const char* tempvar = "TEMP"; - const char* tempdir = getenv(tempvar); // Windows convention - if (! tempdir) - { - tempvar = "TMPDIR"; - tempdir = getenv(tempvar); // Mac convention - } - if (! tempdir) - { - // reset tempvar to the first var we check; it's just a - // recommendation - tempvar = "TEMP"; - tempdir = "/tmp"; // Posix in general - } - std::string savefile(gDirUtilp->add(tempdir, "lluuidhashmap_tut.save.txt")); - const int numElementsToCheck = 32*256*32; - std::vector<LLUUID> idList; - if ((! getenv("TEAMCITY_PROJECT_NAME")) && gDirUtilp->fileExists(savefile)) - { - // This is not a TeamCity build, and we have saved data from a - // previous failed run. Reload that data. - std::ifstream inf(savefile.c_str()); - if (! inf.is_open()) - { - fail(STRINGIZE("Although save file '" << savefile << "' exists, it cannot be opened")); - } - std::string item; - while (std::getline(inf, item)) - { - idList.push_back(LLUUID(item)); - } - std::cout << "Reloaded " << idList.size() << " items from '" << savefile << "'"; - if (idList.size() != numElementsToCheck) - { - std::cout << " (expected " << numElementsToCheck << ")"; - } - std::cout << " -- delete this file to generate new data" << std::endl; - } - else - { - // This is a TeamCity build, or (normal case) savefile does not - // exist: regenerate idList from scratch. - for (int i = 0; i < numElementsToCheck; ++i) - { - LLUUID id; - id.generate(); - idList.push_back(id); - } - } - - LLUUIDHashMap<UUIDTableEntry, 32> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry()); - int i; - - for (i = 0; i < idList.size(); ++i) - { - UUIDTableEntry entry(idList[i], i); - hashTable.set(idList[i], entry); - } - - try - { - for (i = 0; i < idList.size(); i++) - { - LLUUID idToCheck = idList[i]; - UUIDTableEntry entryToCheck = hashTable.get(idToCheck); - ensure_equals(STRINGIZE("set/get ID (entry " << i << ")").c_str(), - entryToCheck.getID(), idToCheck); - ensure_equals(STRINGIZE("set/get value (ID " << idToCheck << ")").c_str(), - entryToCheck.getValue(), (size_t)i); - } - - for (i = 0; i < idList.size(); i++) - { - LLUUID idToCheck = idList[i]; - if (i % 2 != 0) - { - hashTable.remove(idToCheck); - } - } - - for (i = 0; i < idList.size(); i++) - { - LLUUID idToCheck = idList[i]; - ensure("remove or check did not work", (i % 2 == 0 && hashTable.check(idToCheck)) || (i % 2 != 0 && !hashTable.check(idToCheck))); - } - } - catch (const failure&) - { - // One of the above tests failed. Try to save idList to repro with - // a later run. - std::ofstream outf(savefile.c_str()); - if (! outf.is_open()) - { - // Sigh, don't use fail() here because we want to preserve - // the original test failure. - std::cout << "Cannot open file '" << savefile - << "' to save data -- check and fix " << tempvar << std::endl; - } - else - { - // outf.is_open() - for (int i = 0; i < idList.size(); ++i) - { - outf << idList[i] << std::endl; - } - std::cout << "Saved " << idList.size() << " entries to '" << savefile - << "' -- rerun test to debug with these" << std::endl; - } - // re-raise the same exception -- we WANT this test failure to - // be reported! We just needed to save the data on the way out. - throw; - } - } - - // test removing all but one element. - template<> template<> - void hash_index_object_t::test<2>() - { - LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry()); - const int numElementsToCheck = 5; - std::vector<LLUUID> idList(numElementsToCheck*10); - int i; - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID id; - id.generate(); - UUIDTableEntry entry(id, i); - hashTable.set(id, entry); - idList[i] = id; - } - - ensure("getLength failed", hashTable.getLength() == numElementsToCheck); - - // remove all but the last element - for (i = 0; i < numElementsToCheck-1; i++) - { - LLUUID idToCheck = idList[i]; - hashTable.remove(idToCheck); - } - - // there should only be one element left now. - ensure("getLength failed", hashTable.getLength() == 1); - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID idToCheck = idList[i]; - if (i != numElementsToCheck - 1) - { - ensure("remove did not work", hashTable.check(idToCheck) == FALSE); - } - else - { - UUIDTableEntry entryToCheck = hashTable.get(idToCheck); - ensure("remove did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i); - } - } - } - - // test overriding of value already set. - template<> template<> - void hash_index_object_t::test<3>() - { - LLUUIDHashMap<UUIDTableEntry, 5> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry()); - const int numElementsToCheck = 10; - std::vector<LLUUID> idList(numElementsToCheck); - int i; - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID id; - id.generate(); - UUIDTableEntry entry(id, i); - hashTable.set(id, entry); - idList[i] = id; - } - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID id = idList[i]; - // set new entry with value = i+numElementsToCheck - UUIDTableEntry entry(id, i+numElementsToCheck); - hashTable.set(id, entry); - } - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID idToCheck = idList[i]; - UUIDTableEntry entryToCheck = hashTable.get(idToCheck); - ensure("set/get did not work", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)(i+numElementsToCheck)); - } - } - - // test removeAll() - template<> template<> - void hash_index_object_t::test<4>() - { - LLUUIDHashMap<UUIDTableEntry, 5> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry()); - const int numElementsToCheck = 10; - std::vector<LLUUID> idList(numElementsToCheck); - int i; - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID id; - id.generate(); - UUIDTableEntry entry(id, i); - hashTable.set(id, entry); - idList[i] = id; - } - - hashTable.removeAll(); - ensure("removeAll failed", hashTable.getLength() == 0); - } - - - // test sparse map - force it by creating 256 entries that fall into 256 different nodes - template<> template<> - void hash_index_object_t::test<5>() - { - LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry()); - const int numElementsToCheck = 256; - std::vector<LLUUID> idList(numElementsToCheck); - int i; - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID id; - id.generate(); - // LLUUIDHashMap uses mData[0] to pick the bucket - // overwrite mData[0] so that it ranges from 0 to 255 - id.mData[0] = i; - UUIDTableEntry entry(id, i); - hashTable.set(id, entry); - idList[i] = id; - } - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID idToCheck = idList[i]; - UUIDTableEntry entryToCheck = hashTable.get(idToCheck); - ensure("set/get did not work for sparse map", entryToCheck.getID() == idToCheck && entryToCheck.getValue() == (size_t)i); - } - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID idToCheck = idList[i]; - if (i % 2 != 0) - { - hashTable.remove(idToCheck); - } - } - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID idToCheck = idList[i]; - ensure("remove or check did not work for sparse map", (i % 2 == 0 && hashTable.check(idToCheck)) || (i % 2 != 0 && !hashTable.check(idToCheck))); - } - } - - // iterator - template<> template<> - void hash_index_object_t::test<6>() - { - LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry()); - LLUUIDHashMapIter<UUIDTableEntry, 2> hashIter(&hashTable); - const int numElementsToCheck = 256; - std::vector<LLUUID> idList(numElementsToCheck); - int i; - - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID id; - id.generate(); - // LLUUIDHashMap uses mData[0] to pick the bucket - // overwrite mData[0] so that it ranges from 0 to 255 - // to create a sparse map - id.mData[0] = i; - UUIDTableEntry entry(id, i); - hashTable.set(id, entry); - idList[i] = id; - } - - hashIter.first(); - int numElementsIterated = 0; - while(!hashIter.done()) - { - numElementsIterated++; - UUIDTableEntry tableEntry = *hashIter; - LLUUID id = tableEntry.getID(); - hashIter.next(); - ensure("Iteration failed for sparse map", tableEntry.getValue() < (size_t)numElementsToCheck && idList[tableEntry.getValue()] == tableEntry.getID()); - } - - ensure("iteration count failed", numElementsIterated == numElementsToCheck); - } - - // remove after middle of iteration - template<> template<> - void hash_index_object_t::test<7>() - { - LLUUIDHashMap<UUIDTableEntry, 2> hashTable(UUIDTableEntry::uuidEq, UUIDTableEntry()); - LLUUIDHashMapIter<UUIDTableEntry, 2> hashIter(&hashTable); - const int numElementsToCheck = 256; - std::vector<LLUUID> idList(numElementsToCheck); - int i; - - LLUUID uuidtoSearch; - for (i = 0; i < numElementsToCheck; i++) - { - LLUUID id; - id.generate(); - // LLUUIDHashMap uses mData[0] to pick the bucket - // overwrite mData[0] so that it ranges from 0 to 255 - // to create a sparse map - id.mData[0] = i; - UUIDTableEntry entry(id, i); - hashTable.set(id, entry); - idList[i] = id; - - // pick uuid somewhere in the middle - if (i == 5) - { - uuidtoSearch = id; - } - } - - hashIter.first(); - int numElementsIterated = 0; - while(!hashIter.done()) - { - numElementsIterated++; - UUIDTableEntry tableEntry = *hashIter; - LLUUID id = tableEntry.getID(); - if (uuidtoSearch == id) - { - break; - } - hashIter.next(); - } - - // current iterator implementation will not allow any remove operations - // until ALL elements have been iterated over. this seems to be - // an unnecessary restriction. Iterator should have a method to - // reset() its state so that further operations (inckuding remove) - // can be performed on the HashMap without having to iterate thru - // all the remaining nodes. - -// hashIter.reset(); -// hashTable.remove(uuidtoSearch); -// ensure("remove after iteration reset failed", hashTable.check(uuidtoSearch) == FALSE); - } -} diff --git a/indra/test/test.cpp b/indra/test/test.cpp index dc8580fe69..28de88201c 100755 --- a/indra/test/test.cpp +++ b/indra/test/test.cpp @@ -40,6 +40,7 @@ #include "tests/wrapllerrs.h" // RecorderProxy #include "stringize.h" #include "namedtempfile.h" +#include "lltrace.h" #include "apr_pools.h" #include "apr_getopt.h" @@ -512,15 +513,11 @@ int main(int argc, char **argv) ctype_workaround(); #endif - apr_initialize(); - apr_pool_t* pool = NULL; - if(APR_SUCCESS != apr_pool_create(&pool, NULL)) - { - std::cerr << "Unable to initialize pool" << std::endl; - return 1; - } + ll_init_apr(); + + LLTrace::init(); apr_getopt_t* os = NULL; - if(APR_SUCCESS != apr_getopt_init(&os, pool, argc, argv)) + if(APR_SUCCESS != apr_getopt_init(&os, gAPRPoolp, argc, argv)) { std::cerr << "apr_getopt_init() failed" << std::endl; return 1; @@ -602,7 +599,7 @@ int main(int argc, char **argv) if (LOGFAIL) { LLError::ELevel level = LLError::decodeLevel(LOGFAIL); - replayer.reset(new LLReplayLogReal(level, pool)); + replayer.reset(new LLReplayLogReal(level, gAPRPoolp)); } else { @@ -646,7 +643,7 @@ int main(int argc, char **argv) s.close(); } - apr_terminate(); + ll_cleanup_apr(); int retval = (success ? 0 : 1); return retval; diff --git a/indra/test_apps/llplugintest/llmediaplugintest.cpp b/indra/test_apps/llplugintest/llmediaplugintest.cpp index 884b00f0cc..fa4f5abd28 100755 --- a/indra/test_apps/llplugintest/llmediaplugintest.cpp +++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp @@ -37,6 +37,12 @@ #include "llmediaplugintest.h" + +#if LL_WINDOWS +#pragma warning(disable: 4263) +#pragma warning(disable: 4264) +#endif + #if __APPLE__ #include <GLUT/glut.h> #include <CoreFoundation/CoreFoundation.h> @@ -46,10 +52,6 @@ #define GLUI_FREEGLUT #endif -#if LL_WINDOWS -#pragma warning(disable: 4263) -#pragma warning(disable: 4264) -#endif #include "glui.h" |