summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/llcommon/llfasttimer.cpp45
-rw-r--r--indra/llcommon/llfasttimer.h13
-rw-r--r--indra/llcommon/lltrace.h24
-rw-r--r--indra/llcommon/lltracerecording.cpp29
-rw-r--r--indra/llcommon/lltracerecording.h11
-rw-r--r--indra/llcommon/lltracethreadrecorder.cpp33
-rw-r--r--indra/llcommon/lltracethreadrecorder.h12
-rw-r--r--indra/llui/llui.cpp26
-rw-r--r--indra/llui/llui.h2
-rw-r--r--indra/newview/llfasttimerview.cpp424
-rw-r--r--indra/newview/llfasttimerview.h35
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;