diff options
Diffstat (limited to 'indra')
-rw-r--r-- | indra/llcommon/llfasttimer.cpp | 45 | ||||
-rw-r--r-- | indra/llcommon/llfasttimer.h | 13 | ||||
-rw-r--r-- | indra/llcommon/lltrace.h | 24 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.cpp | 29 | ||||
-rw-r--r-- | indra/llcommon/lltracerecording.h | 11 | ||||
-rw-r--r-- | indra/llcommon/lltracethreadrecorder.cpp | 33 | ||||
-rw-r--r-- | indra/llcommon/lltracethreadrecorder.h | 12 | ||||
-rw-r--r-- | indra/llui/llui.cpp | 26 | ||||
-rw-r--r-- | indra/llui/llui.h | 2 | ||||
-rw-r--r-- | indra/newview/llfasttimerview.cpp | 424 | ||||
-rw-r--r-- | indra/newview/llfasttimerview.h | 35 |
11 files changed, 398 insertions, 256 deletions
diff --git a/indra/llcommon/llfasttimer.cpp b/indra/llcommon/llfasttimer.cpp index a144a8c94e..0ea91d7e51 100644 --- a/indra/llcommon/llfasttimer.cpp +++ b/indra/llcommon/llfasttimer.cpp @@ -256,12 +256,16 @@ void TimeBlock::processTimes() while(cur_timer && cur_timer->mParentTimerData.mActiveTimer != cur_timer) { U64 cumulative_time_delta = cur_time - cur_timer->mStartTime; - - accumulator->mTotalTimeCounter += cumulative_time_delta; - accumulator->mChildTimeCounter += stack_record->mChildTime; + U64 child_time = stack_record->mChildTime + - (accumulator->mSelfTimeCounter - cur_timer->mStartSelfTimeCounter) + - (accumulator->mChildTimeCounter - cur_timer->mStartChildTimeCounter); + accumulator->mChildTimeCounter += child_time; + accumulator->mSelfTimeCounter += cumulative_time_delta - child_time; stack_record->mChildTime = 0; cur_timer->mStartTime = cur_time; + cur_timer->mStartSelfTimeCounter = accumulator->mSelfTimeCounter; + cur_timer->mStartChildTimeCounter = accumulator->mChildTimeCounter; stack_record = &cur_timer->mParentTimerData; accumulator = stack_record->mTimeBlock->getPrimaryAccumulator(); @@ -401,7 +405,9 @@ void TimeBlock::writeLog(std::ostream& os) TimeBlockAccumulator::TimeBlockAccumulator() : mChildTimeCounter(0), - mTotalTimeCounter(0), + mSelfTimeCounter(0), + mStartChildTimeCounter(0), + mStartSelfTimeCounter(0), mCalls(0), mLastCaller(NULL), mActiveCount(0), @@ -411,8 +417,8 @@ TimeBlockAccumulator::TimeBlockAccumulator() void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other ) { - mChildTimeCounter += other.mChildTimeCounter; - mTotalTimeCounter += other.mTotalTimeCounter; + mChildTimeCounter += other.mChildTimeCounter - other.mStartChildTimeCounter; + mSelfTimeCounter += other.mSelfTimeCounter - other.mStartSelfTimeCounter; mCalls += other.mCalls; mLastCaller = other.mLastCaller; mActiveCount = other.mActiveCount; @@ -422,9 +428,32 @@ void TimeBlockAccumulator::addSamples( const TimeBlockAccumulator& other ) void TimeBlockAccumulator::reset( const TimeBlockAccumulator* other ) { - mTotalTimeCounter = 0; - mChildTimeCounter = 0; mCalls = 0; + if (other) + { + mStartSelfTimeCounter = other->mSelfTimeCounter; + mSelfTimeCounter = mStartSelfTimeCounter; + mStartChildTimeCounter = other->mChildTimeCounter; + mChildTimeCounter = mStartChildTimeCounter; + + mLastCaller = other->mLastCaller; + mActiveCount = other->mActiveCount; + mMoveUpTree = other->mMoveUpTree; + mParent = other->mParent; + } + else + { + mStartSelfTimeCounter = mSelfTimeCounter; + mStartChildTimeCounter = mChildTimeCounter; + } } +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 726db70fbe..28e54a37de 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -71,9 +71,13 @@ public: BlockTimer(TimeBlock& timer); ~BlockTimer(); + LLUnit<LLUnits::Seconds, F64> getElapsedTime(); + private: U64 mStartTime; + U64 mStartSelfTimeCounter; + U64 mStartChildTimeCounter; BlockTimerStackRecord mParentTimerData; }; @@ -279,6 +283,8 @@ LL_FORCE_INLINE BlockTimer::BlockTimer(TimeBlock& timer) BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists(); TimeBlockAccumulator* accumulator = timer.getPrimaryAccumulator(); accumulator->mActiveCount++; + mStartSelfTimeCounter = accumulator->mSelfTimeCounter; + mStartChildTimeCounter = accumulator->mChildTimeCounter; // keep current parent as long as it is active when we are accumulator->mMoveUpTree |= (accumulator->mParent->getPrimaryAccumulator()->mActiveCount == 0); @@ -298,9 +304,12 @@ LL_FORCE_INLINE BlockTimer::~BlockTimer() BlockTimerStackRecord* cur_timer_data = ThreadTimerStack::getIfExists(); TimeBlockAccumulator* accumulator = cur_timer_data->mTimeBlock->getPrimaryAccumulator(); + U64 child_time = cur_timer_data->mChildTime + - (accumulator->mSelfTimeCounter - mStartSelfTimeCounter) + - (accumulator->mChildTimeCounter - mStartChildTimeCounter); accumulator->mCalls++; - accumulator->mChildTimeCounter += cur_timer_data->mChildTime; - accumulator->mTotalTimeCounter += total_time; + accumulator->mChildTimeCounter += child_time; + accumulator->mSelfTimeCounter += total_time - cur_timer_data->mChildTime; accumulator->mActiveCount--; // store last caller to bootstrap tree creation diff --git a/indra/llcommon/lltrace.h b/indra/llcommon/lltrace.h index 0f927bad53..8c3259eea9 100644 --- a/indra/llcommon/lltrace.h +++ b/indra/llcommon/lltrace.h @@ -243,8 +243,6 @@ namespace LLTrace : public LLInstanceTracker<TraceType<ACCUMULATOR>, std::string> { public: - typedef typename MeanValueType<TraceType<ACCUMULATOR> >::type mean_t; - TraceType(const char* name, const char* description = NULL) : LLInstanceTracker<TraceType<ACCUMULATOR>, std::string>(name), mName(name), @@ -446,8 +444,10 @@ namespace LLTrace // // members // - U64 mChildTimeCounter, - mTotalTimeCounter; + U64 mStartChildTimeCounter, + mStartSelfTimeCounter, + mChildTimeCounter, + mSelfTimeCounter; U32 mCalls; class TimeBlock* mParent; // last acknowledged parent of this time block class TimeBlock* mLastCaller; // used to bootstrap tree construction @@ -468,7 +468,6 @@ namespace LLTrace : public TraceType<TimeBlockAccumulator> { public: - typedef F32 mean_t; TraceType(const char* name, const char* description = "") : TraceType<TimeBlockAccumulator>(name, description) @@ -476,17 +475,30 @@ namespace LLTrace }; template<> + struct MeanValueType<TraceType<TimeBlockAccumulator::CallCountAspect> > + { + typedef F64 type; + }; + + + template<> class TraceType<TimeBlockAccumulator::SelfTimeAspect> : public TraceType<TimeBlockAccumulator> { public: - typedef F32 mean_t; TraceType(const char* name, const char* description = "") : TraceType<TimeBlockAccumulator>(name, description) {} }; + template<> + struct MeanValueType<TraceType<TimeBlockAccumulator::SelfTimeAspect> > + { + typedef LLUnit<LLUnits::Seconds, F64> type; + }; + + class TimeBlock; class TimeBlockTreeNode { diff --git a/indra/llcommon/lltracerecording.cpp b/indra/llcommon/lltracerecording.cpp index 913c4cbdad..2af9041863 100644 --- a/indra/llcommon/lltracerecording.cpp +++ b/indra/llcommon/lltracerecording.cpp @@ -109,9 +109,17 @@ void Recording::handleSplitTo(Recording& other) { stop(); other.restart(); + syncTo(other); +} + +void Recording::syncTo(Recording& other) +{ + other.mCountsFloat.write()->reset(mCountsFloat); other.mMeasurementsFloat.write()->reset(mMeasurementsFloat); + other.mCounts.write()->reset(mCounts); other.mMeasurements.write()->reset(mMeasurements); - //TODO: figure out how to get seamless handoff of timing stats + other.mStackTimers.write()->reset(mStackTimers); + other.mMemStats.write()->reset(mMemStats); } void Recording::makePrimary() @@ -174,12 +182,15 @@ void Recording::mergeRecording( const Recording& other) LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator>& stat) const { - return (F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter / (F64)LLTrace::TimeBlock::countsPerSecond(); + const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()]; + return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter + accumulator.mChildTimeCounter - accumulator.mStartChildTimeCounter) + / (F64)LLTrace::TimeBlock::countsPerSecond(); } LLUnit<LLUnits::Seconds, F64> Recording::getSum(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const { - return ((F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter - (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond(); + const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()]; + return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter) / (F64)LLTrace::TimeBlock::countsPerSecond(); } @@ -190,12 +201,18 @@ U32 Recording::getSum(const TraceType<TimeBlockAccumulator::CallCountAspect>& st LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator>& stat) const { - return (F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); + const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()]; + + return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter + accumulator.mChildTimeCounter - accumulator.mStartChildTimeCounter) + / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); } LLUnit<LLUnits::Seconds, F64> Recording::getPerSec(const TraceType<TimeBlockAccumulator::SelfTimeAspect>& stat) const { - return ((F64)(*mStackTimers)[stat.getIndex()].mTotalTimeCounter - (F64)(*mStackTimers)[stat.getIndex()].mChildTimeCounter) / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); + const TimeBlockAccumulator& accumulator = (*mStackTimers)[stat.getIndex()]; + + return (F64)(accumulator.mSelfTimeCounter - accumulator.mStartSelfTimeCounter) + / ((F64)LLTrace::TimeBlock::countsPerSecond() * mElapsedSeconds); } F32 Recording::getPerSec(const TraceType<TimeBlockAccumulator::CallCountAspect>& stat) const @@ -520,7 +537,7 @@ void ExtendableRecording::splitFrom(ExtendableRecording& other) PeriodicRecording& get_frame_recording() { - static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(64, PeriodicRecording::STARTED)); + static LLThreadLocalPointer<PeriodicRecording> sRecording(new PeriodicRecording(200, PeriodicRecording::STARTED)); return *sRecording; } diff --git a/indra/llcommon/lltracerecording.h b/indra/llcommon/lltracerecording.h index 05e1577a5a..16fee04979 100644 --- a/indra/llcommon/lltracerecording.h +++ b/indra/llcommon/lltracerecording.h @@ -119,6 +119,7 @@ namespace LLTrace // 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(); // Timer accessors @@ -217,6 +218,8 @@ namespace LLTrace LLUnit<LLUnits::Seconds, F64> getDuration() const { return LLUnit<LLUnits::Seconds, F64>(mElapsedSeconds); } + void syncTo(Recording& other); + private: friend class ThreadRecorder; @@ -337,9 +340,9 @@ namespace LLTrace } template <typename T> - typename TraceType<T>::mean_t getPeriodMean(const TraceType<T>& stat) const + typename MeanValueType<TraceType<T> >::type getPeriodMean(const TraceType<T>& stat) const { - typename TraceType<T>::mean_t mean = 0.0; + typename MeanValueType<TraceType<T> >::type mean = 0.0; for (S32 i = 0; i < mNumPeriods; i++) { if (mRecordingPeriods[i].getDuration() > 0.f) @@ -352,9 +355,9 @@ namespace LLTrace } template <typename T> - typename TraceType<T>::mean_t getPeriodMeanPerSec(const TraceType<T>& stat) const + typename MeanValueType<TraceType<T> >::type getPeriodMeanPerSec(const TraceType<T>& stat) const { - typename TraceType<T>::mean_t mean = 0.0; + typename MeanValueType<TraceType<T> >::type mean = 0.0; for (S32 i = 0; i < mNumPeriods; i++) { if (mRecordingPeriods[i].getDuration() > 0.f) diff --git a/indra/llcommon/lltracethreadrecorder.cpp b/indra/llcommon/lltracethreadrecorder.cpp index 7b493a651e..113febcca8 100644 --- a/indra/llcommon/lltracethreadrecorder.cpp +++ b/indra/llcommon/lltracethreadrecorder.cpp @@ -76,7 +76,7 @@ ThreadRecorder::~ThreadRecorder() while(mActiveRecordings.size()) { - mActiveRecordings.front().mTargetRecording->stop(); + mActiveRecordings.front()->mTargetRecording->stop(); } set_thread_recorder(NULL); delete[] mTimeBlockTreeNodes; @@ -94,31 +94,37 @@ TimeBlockTreeNode* ThreadRecorder::getTimeBlockTreeNode(S32 index) void ThreadRecorder::activate( Recording* recording ) { - mActiveRecordings.push_front(ActiveRecording(recording)); - mActiveRecordings.front().mBaseline.makePrimary(); + ActiveRecording* active_recording = new ActiveRecording(recording); + if (!mActiveRecordings.empty()) + { + mActiveRecordings.front()->mBaseline.syncTo(active_recording->mBaseline); + } + mActiveRecordings.push_front(active_recording); + + mActiveRecordings.front()->mBaseline.makePrimary(); } -std::list<ThreadRecorder::ActiveRecording>::iterator ThreadRecorder::update( Recording* recording ) +ThreadRecorder::active_recording_list_t::iterator ThreadRecorder::update( Recording* recording ) { - std::list<ActiveRecording>::iterator it, end_it; + active_recording_list_t::iterator it, end_it; for (it = mActiveRecordings.begin(), end_it = mActiveRecordings.end(); it != end_it; ++it) { - std::list<ActiveRecording>::iterator next_it = it; + active_recording_list_t::iterator next_it = it; ++next_it; // if we have another recording further down in the stack... if (next_it != mActiveRecordings.end()) { // ...push our gathered data down to it - next_it->mBaseline.appendRecording(it->mBaseline); + (*next_it)->mBaseline.appendRecording((*it)->mBaseline); } // copy accumulated measurements into result buffer and clear accumulator (mBaseline) - it->moveBaselineToTarget(); + (*it)->moveBaselineToTarget(); - if (it->mTargetRecording == recording) + if ((*it)->mTargetRecording == recording) { // found the recording, so return it break; @@ -142,17 +148,18 @@ AccumulatorBuffer<MemStatAccumulator> gMemStats; void ThreadRecorder::deactivate( Recording* recording ) { - std::list<ActiveRecording>::iterator it = update(recording); + active_recording_list_t::iterator it = update(recording); if (it != mActiveRecordings.end()) { // and if we've found the recording we wanted to update - std::list<ActiveRecording>::iterator next_it = it; + active_recording_list_t::iterator next_it = it; ++next_it; if (next_it != mActiveRecordings.end()) { - next_it->mTargetRecording->makePrimary(); + (*next_it)->mTargetRecording->makePrimary(); } + delete *it; mActiveRecordings.erase(it); } } @@ -244,7 +251,7 @@ void MasterThreadRecorder::pullFromSlaveThreads() LLMutexLock lock(&mSlaveListMutex); - Recording& target_recording = mActiveRecordings.front().mBaseline; + Recording& target_recording = mActiveRecordings.front()->mBaseline; for (slave_thread_recorder_list_t::iterator it = mSlaveThreadRecorders.begin(), end_it = mSlaveThreadRecorders.end(); it != end_it; ++it) diff --git a/indra/llcommon/lltracethreadrecorder.h b/indra/llcommon/lltracethreadrecorder.h index 337035974c..0e6c091900 100644 --- a/indra/llcommon/lltracethreadrecorder.h +++ b/indra/llcommon/lltracethreadrecorder.h @@ -39,13 +39,14 @@ namespace LLTrace { protected: struct ActiveRecording; + typedef std::list<ActiveRecording*> active_recording_list_t; public: ThreadRecorder(); virtual ~ThreadRecorder(); void activate(Recording* recording); - std::list<struct ActiveRecording>::iterator update(Recording* recording); + active_recording_list_t::iterator update(Recording* recording); void deactivate(Recording* recording); virtual void pushToMaster() = 0; @@ -63,11 +64,12 @@ namespace LLTrace void moveBaselineToTarget(); }; Recording mThreadRecording; - std::list<ActiveRecording> mActiveRecordings; - class BlockTimer* mRootTimer; - TimeBlockTreeNode* mTimeBlockTreeNodes; - size_t mNumTimeBlockTreeNodes; + active_recording_list_t mActiveRecordings; + + class BlockTimer* mRootTimer; + TimeBlockTreeNode* mTimeBlockTreeNodes; + size_t mNumTimeBlockTreeNodes; }; class LL_COMMON_API MasterThreadRecorder : public ThreadRecorder diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp index 6a87977718..b9d935847b 100644 --- a/indra/llui/llui.cpp +++ b/indra/llui/llui.cpp @@ -1147,6 +1147,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, @@ -1156,6 +1158,7 @@ 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); @@ -1306,10 +1309,7 @@ void gl_segmented_rect_2d_tex(const S32 left, } //FIXME: rewrite to use scissor? -void gl_segmented_rect_2d_fragment_tex(const S32 left, - const S32 top, - const S32 right, - const S32 bottom, +void gl_segmented_rect_2d_fragment_tex(const LLRect& rect, const S32 texture_width, const S32 texture_height, const S32 border_size, @@ -1317,6 +1317,11 @@ void gl_segmented_rect_2d_fragment_tex(const S32 left, 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); @@ -1354,9 +1359,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 @@ -1446,10 +1451,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); @@ -1500,6 +1505,7 @@ void gl_segmented_rect_3d_tex(const LLVector2& border_scale, const LLVector3& bo const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, const U32 edges) { + LLFastTimer _(FTM_RENDER_SEGMENTED_RECT); LLVector3 left_border_width = ((edges & (~(U32)ROUNDED_RECT_RIGHT)) != 0) ? border_width : LLVector3::zero; LLVector3 right_border_width = ((edges & (~(U32)ROUNDED_RECT_LEFT)) != 0) ? border_width : LLVector3::zero; diff --git a/indra/llui/llui.h b/indra/llui/llui.h index 90a4617c4e..dfb9fa60c9 100644 --- a/indra/llui/llui.h +++ b/indra/llui/llui.h @@ -128,7 +128,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 LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec, U32 edges = ROUNDED_RECT_ALL); void gl_segmented_rect_3d_tex_top(const LLVector2& border_scale, const LLVector3& border_width, const LLVector3& border_height, const LLVector3& width_vec, const LLVector3& height_vec); diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index 7858378f00..1a1a4a8b44 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -58,9 +58,7 @@ using namespace LLTrace; static const S32 MAX_VISIBLE_HISTORY = 10; static const S32 LINE_GRAPH_HEIGHT = 240; - -const S32 FTV_MAX_DEPTH = 8; -const S32 HISTORY_NUM = 300; +static const S32 MIN_BAR_HEIGHT = 3; std::vector<TimeBlock*> ft_display_idx; // line of table entry for display purposes (for collapse) @@ -107,7 +105,7 @@ LLFastTimerView::LLFastTimerView(const LLSD& key) mRecording(&get_frame_recording()), mPauseHistory(false) { - mBarRects = new std::vector<LLRect>[MAX_VISIBLE_HISTORY + 1]; + mTimerBars = new std::vector<TimerBar>[MAX_VISIBLE_HISTORY + 1]; } LLFastTimerView::~LLFastTimerView() @@ -117,29 +115,37 @@ LLFastTimerView::~LLFastTimerView() delete mRecording; } mRecording = NULL; - delete [] mBarRects; + delete [] mTimerBars; } void LLFastTimerView::onPause() { - mPauseHistory = !mPauseHistory; + setPauseState(!mPauseHistory); +} + +void LLFastTimerView::setPauseState(bool pause_state) +{ + if (pause_state == mPauseHistory) return; + // reset scroll to bottom when unpausing - if (!mPauseHistory) - { - mRecording = new PeriodicRecording(get_frame_recording()); - mScrollIndex = 0; - getChild<LLButton>("pause_btn")->setLabel(getString("pause")); - } - else + if (!pause_state) { 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() @@ -177,7 +183,7 @@ BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask) 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()) { @@ -256,7 +262,7 @@ 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)(HISTORY_NUM - MAX_VISIBLE_HISTORY)); + mScrollIndex = llround( lerp * (F32)(mRecording->getNumPeriods() - MAX_VISIBLE_HISTORY)); mScrollIndex = llclamp( mScrollIndex, 0, mRecording->getNumPeriods()); return TRUE; } @@ -265,8 +271,9 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) if(mPauseHistory && mBarRect.pointInRect(x, y)) { - mHoverBarIndex = llmin(mRecording->getNumPeriods() - 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, + mRecording->getNumPeriods() - 1, + MAX_VISIBLE_HISTORY); if (mHoverBarIndex == 0) { return TRUE; @@ -282,7 +289,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) ++it, ++i) { // is mouse over bar for this timer? - if (mBarRects[mHoverBarIndex][i].pointInRect(x, y)) + if (mTimerBars[mHoverBarIndex][i].mVisibleRect.pointInRect(x, y)) { mHoverID = (*it); if (mHoverTimer != *it) @@ -294,7 +301,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) mHoverTimer = (*it); } - mToolTipRect = mBarRects[mHoverBarIndex][i]; + mToolTipRect = mTimerBars[mHoverBarIndex][i].mVisibleRect; } if ((*it)->getCollapsed()) @@ -318,17 +325,15 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask) static std::string get_tooltip(TimeBlock& timer, S32 history_index, PeriodicRecording& frame_recording) { - F64 ms_multiplier = 1000.0 / (F64)TimeBlock::countsPerSecond(); - std::string tooltip; - if (history_index < 0) + if (history_index == 0) { // by default, show average number of call - tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)(frame_recording.getPeriodMean(timer) * ms_multiplier).value(), (S32)frame_recording.getPeriodMean(timer.callCount())); + 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)(frame_recording.getPrevRecordingPeriod(history_index).getSum(timer) * ms_multiplier).value(), (S32)frame_recording.getPrevRecordingPeriod(history_index).getSum(timer.callCount())); + tooltip = llformat("%s (%d ms, %d calls)", timer.getName().c_str(), (S32)LLUnit<LLUnits::Milliseconds, F64>(frame_recording.getPrevRecordingPeriod(history_index).getSum(timer)).value(), (S32)frame_recording.getPrevRecordingPeriod(history_index).getSum(timer.callCount())); } return tooltip; } @@ -343,7 +348,7 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask) LLRect screen_rect; localRectToScreen(mToolTipRect, &screen_rect); - std::string tooltip = get_tooltip(*mHoverTimer, mScrollIndex + mHoverBarIndex, *mRecording); + std::string tooltip = get_tooltip(*mHoverTimer, mHoverBarIndex > 0 ? mScrollIndex + mHoverBarIndex : 0, *mRecording); LLToolTipMgr::instance().show(LLToolTip::Params() .message(tooltip) @@ -361,7 +366,7 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask) TimeBlock* idp = getLegendID(y); if (idp) { - LLToolTipMgr::instance().show(get_tooltip(*idp, -1, *mRecording)); + LLToolTipMgr::instance().show(get_tooltip(*idp, 0, *mRecording)); return TRUE; } @@ -373,10 +378,10 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask) BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks) { - mPauseHistory = true; + setPauseState(true); mScrollIndex = llclamp( mScrollIndex + clicks, 0, - llmin(mRecording->getNumPeriods(), (S32)HISTORY_NUM - MAX_VISIBLE_HISTORY)); + llmin(mRecording->getNumPeriods(), (S32)mRecording->getNumPeriods() - MAX_VISIBLE_HISTORY)); return TRUE; } @@ -397,7 +402,7 @@ void LLFastTimerView::draw() gl_rect_2d(getLocalRect(), LLColor4(0.f, 0.f, 0.f, 0.25f)); S32 y = drawHelp(getRect().getHeight() - MARGIN); - drawLegend(y - ((S32)LLFontGL::getFontMonospace()->getLineHeight() - 2)); + drawLegend(y - ((S32)LLFontGL::getFontMonospace()->getLineHeight() + 2)); // update rectangle that includes timer bars const S32 LEGEND_WIDTH = 220; @@ -999,8 +1004,11 @@ void LLFastTimerView::printLineStats() } } +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; @@ -1019,7 +1027,7 @@ void LLFastTimerView::drawLineGraph() else if (mDisplayHz) axis_label = llformat("%d Hz", (int)(1.f / max_time.value())); else - axis_label = llformat("%4.2f ms", max_time.value()); + 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(); @@ -1029,10 +1037,10 @@ void LLFastTimerView::drawLineGraph() //highlight visible range { - S32 first_frame = HISTORY_NUM - mScrollIndex; + S32 first_frame = mRecording->getNumPeriods() - mScrollIndex; S32 last_frame = first_frame - MAX_VISIBLE_HISTORY; - F32 frame_delta = ((F32) (mGraphRect.getWidth()))/(HISTORY_NUM-1); + 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; @@ -1040,9 +1048,9 @@ void LLFastTimerView::drawLineGraph() gGL.color4f(0.5f,0.5f,0.5f,0.3f); gl_rect_2d((S32) left, mGraphRect.mTop, (S32) right, mGraphRect.mBottom); - if (mHoverBarIndex >= 0) + if (mHoverBarIndex > 0) { - S32 bar_frame = first_frame - mHoverBarIndex; + 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); @@ -1074,7 +1082,7 @@ void LLFastTimerView::drawLineGraph() F32 alpha = 1.f; if (mHoverID != NULL && - idp != mHoverID) + mHoverID != idp) { //fade out non-highlighted timers if (idp->getParent() != mHoverID) { @@ -1097,7 +1105,7 @@ void LLFastTimerView::drawLineGraph() cur_max = llmax(cur_max, time); cur_max_calls = llmax(cur_max_calls, calls); } - F32 x = mGraphRect.mRight - j * (F32)(mGraphRect.getWidth())/(HISTORY_NUM-1); + 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(); @@ -1118,7 +1126,7 @@ void LLFastTimerView::drawLineGraph() it.skipDescendants(); } } - + //interpolate towards new maximum max_time = lerp(max_time.value(), cur_max.value(), LLCriticalDamp::getInterpolant(0.1f)); if (max_time - cur_max <= 1 || cur_max - max_time <= 1) @@ -1281,41 +1289,40 @@ void LLFastTimerView::generateUniqueColors() S32 LLFastTimerView::drawHelp( S32 y ) { // 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; + 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( LLUnit<LLUnits::Seconds, F64> total_time ) +void LLFastTimerView::drawTicks() { // Draw MS ticks { - LLUnit<LLUnits::Milliseconds, U32> ms = total_time; + LLUnit<LLUnits::Milliseconds, U32> ms = mTotalTimeDisplay; std::string tick_label; S32 x; S32 barw = mBarRect.getWidth(); @@ -1377,187 +1384,216 @@ void LLFastTimerView::drawBorders( S32 y, const S32 x_start, S32 bar_height, S32 } } -LLUnit<LLUnits::Seconds, F64> LLFastTimerView::getTotalTime() +void LLFastTimerView::updateTotalTime() { - LLUnit<LLUnits::Seconds, F64> total_time; switch(mDisplayMode) { case 0: - total_time = mRecording->getPeriodMean(FTM_FRAME)*2; + mTotalTimeDisplay = mRecording->getPeriodMean(FTM_FRAME)*2; break; case 1: - total_time = mAllTimeMax; + mTotalTimeDisplay = mAllTimeMax; break; case 2: // Calculate the max total ticks for the current history - total_time = mRecording->getPeriodMax(FTM_FRAME); + mTotalTimeDisplay = mRecording->getPeriodMax(FTM_FRAME); break; default: - total_time = LLUnit<LLUnits::Milliseconds, F32>(100); + mTotalTimeDisplay = LLUnit<LLUnits::Milliseconds, F32>(100); break; } - return total_time; + + mTotalTimeDisplay = LLUnit<LLUnits::Milliseconds, F32>(llceil(mTotalTimeDisplay.as<LLUnits::Milliseconds, F32>().value() / (20.f)) * 20.f); } void LLFastTimerView::drawBars() { - LLUnit<LLUnits::Seconds, F64> total_time = getTotalTime(); - if (total_time <= 0.0) return; + updateTotalTime(); + if (mTotalTimeDisplay <= 0.0) return; - LLPointer<LLUIImage> box_imagep = LLUI::getUIImage("Rounded_Square"); LLLocalClipRect clip(mBarRect); - S32 bar_height = (mBarRect.mTop - MARGIN - LINE_GRAPH_HEIGHT) / (MAX_VISIBLE_HISTORY + 2); + S32 bar_height = mBarRect.getHeight() / (MAX_VISIBLE_HISTORY + 2); S32 vpad = llmax(1, bar_height / 4); // spacing between bars bar_height -= vpad; - drawTicks(total_time); + 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 - gGL.getTexUnit(0)->bind(box_imagep->getImage()); - const S32 histmax = llmin(mRecording->getNumPeriods()+1, MAX_VISIBLE_HISTORY); + LLPointer<LLUIImage> bar_image = LLUI::getUIImage("Rounded_Square"); + gGL.getTexUnit(0)->bind(bar_image->getImage()); + const S32 histmax = llmin(mRecording->getNumPeriods(), MAX_VISIBLE_HISTORY) + 1; - for (S32 j = -1; j < histmax && y > LINE_GRAPH_HEIGHT; j++) + for (S32 bar_index = 0; bar_index < histmax && y > LINE_GRAPH_HEIGHT; bar_index++) { - mBarRects[llmax(j, 0)].clear(); - int sublevel_dx[FTV_MAX_DEPTH]; - int sublevel_left[FTV_MAX_DEPTH]; - int sublevel_right[FTV_MAX_DEPTH]; - S32 tidx = (j >= 0) - ? j + 1 + mScrollIndex + 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); +} - // draw the bars for each stat - std::vector<S32> xpos; - S32 deltax = 0; - xpos.push_back(mBarRect.mLeft); +static LLFastTimer::DeclareTimer FTM_UPDATE_TIMER_BAR_WIDTHS("Update timer bar widths"); - TimeBlock* prev_id = NULL; +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->getPrevRecordingPeriod(history_index).getSum(time_block->selfTime()) / mTotalTimeDisplay); - S32 i = 0; - for(timer_tree_iterator_t it = begin_timer_tree(FTM_FRAME); - it != end_timer_tree(); - ++it, ++i) - { - TimeBlock* idp = (*it); - F32 frac = tidx == -1 - ? (mRecording->getPeriodMean(*idp) / total_time) - : (mRecording->getPrevRecordingPeriod(tidx).getSum(*idp).value() / total_time.value()); + S32 self_time_width = llround(self_time_frame_fraction * (F32)mBarRect.getWidth()); + S32 full_width = self_time_width; - S32 dx = llround(frac * (F32)mBarRect.getWidth()); - S32 prev_delta_x = deltax; - deltax = dx; + bool children_visible = visible; - const int level = get_depth(idp) - 1; - while ((S32)xpos.size() > level + 1) - { - xpos.pop_back(); - } + // 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()); + } - LLRect bar_rect; - bar_rect.setLeftTopAndSize(xpos.back(), y, dx, bar_height); - mBarRects[llmax(j, 0)].push_back(bar_rect); + 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 (level == 0) - { - sublevel_left[level] = mBarRect.mLeft; - sublevel_dx[level] = dx; - sublevel_right[level] = sublevel_left[level] + sublevel_dx[level]; - } - else if (prev_id && get_depth(prev_id) < get_depth(idp)) - { - F64 sublevelticks = 0; + if (visible) + { + TimerBar& timer_bar = bars[bar_rect_index]; - for (TimeBlock::child_const_iter it = prev_id->beginChildren(); - it != prev_id->endChildren(); - ++it) - { - sublevelticks += (tidx == -1) - ? mRecording->getPeriodMean(**it).value() - : mRecording->getPrevRecordingPeriod(tidx).getSum(**it).value(); - } + 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(); + } - F32 subfrac = (F32)sublevelticks / (F32)total_time.value(); - sublevel_dx[level] = (int)(subfrac * (F32)mBarRect.getWidth() + .5f); + 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; +} - if (mDisplayCenter == ALIGN_CENTER) - { - bar_rect.mLeft += (prev_delta_x - sublevel_dx[level])/2; - } - else if (mDisplayCenter == ALIGN_RIGHT) - { - bar_rect.mLeft += (prev_delta_x - sublevel_dx[level]); - } +static LLFastTimer::DeclareTimer FTM_UPDATE_TIMER_BAR_FRACTIONS("Update timer bar fractions"); - sublevel_left[level] = bar_rect.mLeft; - sublevel_right[level] = sublevel_left[level] + sublevel_dx[level]; - } +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; - xpos.back() = bar_rect.mRight; - xpos.push_back(bar_rect.mLeft); + 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 (bar_rect.getWidth() > 0) - { - LLColor4 color = sTimerColors[idp]; - S32 scale_offset = 0; + if (children_rect.getHeight() > MIN_BAR_HEIGHT) + { + children_rect.mTop -= 1; + children_rect.mBottom += 1; + } + timer_bar.mChildrenRect = children_rect; - 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(); - } + //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++; - 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); - } + TimerBar& child_timer_bar = bars[timer_bar_index]; + TimeBlock* child_time_block = *it; - gGL.color4fv(color.mV); - F32 start_fragment = llclamp((F32)(bar_rect.mLeft - sublevel_left[level]) / (F32)sublevel_dx[level], 0.f, 1.f); - F32 end_fragment = llclamp((F32)(bar_rect.mRight - sublevel_left[level]) / (F32)sublevel_dx[level], 0.f, 1.f); - gl_segmented_rect_2d_fragment_tex( - sublevel_left[level], - bar_rect.mTop - level + scale_offset, - sublevel_right[level], - bar_rect.mBottom + level - scale_offset, - box_imagep->getTextureWidth(), box_imagep->getTextureHeight(), - 16, - start_fragment, end_fragment); - } + 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); - if ((*it)->getCollapsed()) - { - it.skipDescendants(); - } + timer_bar_index = updateTimerBarFractions(child_time_block, timer_bar_index, bars); - prev_id = idp; + bar_fraction_start = child_timer_bar.mEndFraction; } - y -= (bar_height + vpad); - if (j < 0) - y -= bar_height; } - gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + 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 7eee3c1cb5..f9ceb4423b 100644 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -61,8 +61,6 @@ public: virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); virtual void draw(); - - LLTrace::TimeBlock* getLegendID(S32 y); F64 getTime(const std::string& name); @@ -70,7 +68,7 @@ protected: virtual void onClickCloseBtn(); private: - void drawTicks(LLUnit<LLUnits::Seconds, F64> total_time); + void drawTicks(); void drawLineGraph(); void drawLegend(S32 y); S32 drawHelp(S32 y); @@ -79,10 +77,32 @@ private: void printLineStats(); void generateUniqueColors(); - LLUnit<LLUnits::Seconds, F64> getTotalTime(); + void updateTotalTime(); - - std::vector<LLRect>* mBarRects; + 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 @@ -96,7 +116,8 @@ private: ChildAlignment mDisplayCenter; bool mDisplayCalls, mDisplayHz; - LLUnit<LLUnits::Seconds, F64> mAllTimeMax; + LLUnit<LLUnits::Seconds, F64> mAllTimeMax, + mTotalTimeDisplay; LLRect mBarRect; S32 mScrollIndex; LLTrace::TimeBlock* mHoverID; |