diff options
| author | Richard Linden <none@none> | 2013-01-24 01:18:49 -0800 | 
|---|---|---|
| committer | Richard Linden <none@none> | 2013-01-24 01:18:49 -0800 | 
| commit | 096b2738c2213281b463d0de093c08a406f53946 (patch) | |
| tree | 2c28c798ceb4479353e3646463789113f1e5b66a /indra | |
| parent | 28ab53d0cd1fb43a255990e90e0ad1ee78a566bb (diff) | |
SH-3275 WIP interesting Update viewer metrics system to be more flexible
clean up LLFastTimerView so it can be converted to handling LLTrace data
Diffstat (limited to 'indra')
| -rw-r--r-- | indra/newview/llfasttimerview.cpp | 1284 | ||||
| -rw-r--r-- | indra/newview/llfasttimerview.h | 19 | 
2 files changed, 665 insertions, 638 deletions
| diff --git a/indra/newview/llfasttimerview.cpp b/indra/newview/llfasttimerview.cpp index ba298ed819..59a52fdaea 100644 --- a/indra/newview/llfasttimerview.cpp +++ b/indra/newview/llfasttimerview.cpp @@ -106,7 +106,9 @@ LLFastTimerView::LLFastTimerView(const LLSD& key)  	mPrintStats(-1),  	mRecording(&get_frame_recording()),  	mPauseHistory(false) -{} +{ +	mBarRects = new std::vector<LLRect>[MAX_VISIBLE_HISTORY]; +}  LLFastTimerView::~LLFastTimerView()  { @@ -115,6 +117,7 @@ LLFastTimerView::~LLFastTimerView()  		delete mRecording;  	}  	mRecording = NULL; +	delete [] mBarRects;  }  void LLFastTimerView::onPause() @@ -250,13 +253,11 @@ BOOL LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask)  BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)  { -	PeriodicRecording& frame_recording = *mRecording; -  	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 = llclamp(	mScrollIndex, 0, frame_recording.getNumPeriods()); +		mScrollIndex = llclamp(	mScrollIndex, 0, mRecording->getNumPeriods());  		return TRUE;  	}  	mHoverTimer = NULL; @@ -281,8 +282,7 @@ BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)  			++it, ++i)  		{  			// is mouse over bar for this timer? -			if (x > mBarStart[mHoverBarIndex][i] && -				x < mBarEnd[mHoverBarIndex][i]) +			if (mBarRects[mHoverBarIndex][i].pointInRect(x, y))  			{  				mHoverID = (*it);  				if (mHoverTimer != *it) @@ -294,10 +294,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 = mBarRects[mHoverBarIndex][i];  			}  			if ((*it)->getCollapsed()) @@ -376,16 +373,16 @@ BOOL LLFastTimerView::handleToolTip(S32 x, S32 y, MASK mask)  BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)  { -	PeriodicRecording& frame_recording = *mRecording; -  	mPauseHistory = true;  	mScrollIndex = llclamp(	mScrollIndex + clicks,  							0, -							llmin(frame_recording.getNumPeriods(), (S32)HISTORY_NUM - MAX_VISIBLE_HISTORY)); +							llmin(mRecording->getNumPeriods(), (S32)HISTORY_NUM - MAX_VISIBLE_HISTORY));  	return TRUE;  }  static TimeBlock FTM_RENDER_TIMER("Timers", true); +static const S32 MARGIN = 10; +static const S32 LEGEND_WIDTH = 220;  static std::map<TimeBlock*, LLColor4> sTimerColors; @@ -393,639 +390,31 @@ void LLFastTimerView::draw()  {  	LLFastTimer t(FTM_RENDER_TIMER); -	PeriodicRecording& frame_recording = *mRecording; - -	std::string tdesc; - -	const S32 margin = 10; -	const S32 height = getRect().getHeight(); -	const 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; -	const S32 texth = (S32)LLFontGL::getFontMonospace()->getLineHeight(); -	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)); -	 -	// Draw some help -	{ -		x = margin; -		y = height - margin; - -		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 = margin, 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(frame_recording.getNumPeriods()+1, MAX_VISIBLE_HISTORY); -		 -	const S32 ytop = y; -	y -= (texth + 2); - -	// generate unique colors -	{ -		sTimerColors[&getFrameTimer()] = LLColor4::grey; - -		F32 hue = 0.f; - -		for (timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); -			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; -		} -	} - -	// draw legend -	const S32 LEGEND_WIDTH = 220; -	const S32 x_start = margin + LEGEND_WIDTH + 8; -	{ -		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(getFrameTimer()); -			it != timer_tree_iterator_t(); -			++it) -		{ -			TimeBlock* idp = (*it); -			display_line[idp] = cur_line; -			ft_display_idx.push_back(idp); -			cur_line++; - -			x = margin; - -			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]); - -			LLUnit<LLUnits::Milliseconds, F32> ms = 0; -			S32 calls = 0; -			if (mHoverBarIndex > 0 && mHoverID) -			{ -				S32 hidx = mScrollIndex + mHoverBarIndex; -				ms = frame_recording.getPrevRecordingPeriod(hidx).getSum(*idp); -				calls = frame_recording.getPrevRecordingPeriod(hidx).getSum(idp->callCount()); -			} -			else -			{ -				ms = LLUnit<LLUnits::Seconds, F64>(frame_recording.getPeriodMean(*idp)); -				calls = (S32)frame_recording.getPeriodMean(idp->callCount()); -			} - -			if (mDisplayCalls) -			{ -				tdesc = llformat("%s (%d)",idp->getName().c_str(),calls); -			} -			else -			{ -				tdesc = llformat("%s [%.1f]",idp->getName().c_str(),ms.value()); -			} -			dx = (texth+4) + get_depth(idp)*8; - -			LLColor4 color = LLColor4::white; -			if (get_depth(idp) > 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) + ((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); -				} -			} +	gl_rect_2d(getLocalRect(), LLColor4(0.f, 0.f, 0.f, 0.25f)); -			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(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(); -			} -		} -	} +	S32 y = drawHelp(getRect().getHeight() - MARGIN); +	drawLegend(y - ((S32)LLFontGL::getFontMonospace()->getLineHeight() - 2));  	// update rectangle that includes timer bars -	mBarRect.mLeft = x_start; -	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 - x_start - margin; - -	// Draw the history bars -	LLUnit<LLUnits::Seconds, F64> total_time; -	switch(mDisplayMode) -	{ -	case 0: -		total_time = frame_recording.getPeriodMean(getFrameTimer())*2; -		break; -	case 1: -		total_time = mAllTimeMax; -		break; -	case 2: -		// Calculate the max total ticks for the current history -		total_time = frame_recording.getPeriodMax(getFrameTimer()); -		break; -	default: -		total_time = LLUnit<LLUnits::Milliseconds, F32>(100); -		break; -	} - -	if (total_time > 0) -	{ -		LLLocalClipRect clip(LLRect(x_start, ytop, getRect().getWidth() - margin, margin)); - -		mAllTimeMax = llmax(mAllTimeMax, frame_recording.getLastRecordingPeriod().getSum(getFrameTimer())); -		 -		// Draw MS ticks -		{ -			LLUnit<LLUnits::Milliseconds, U32> ms = total_time; - -			tdesc = llformat("%.1f ms |", (F32)ms.value()*.25f); -			x = x_start + 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.value()*.50f); -			x = x_start + 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.value()*.75f); -			x = x_start + (barw*3)/4 - LLFontGL::getFontMonospace()->getWidth(tdesc); -			LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, -											LLFontGL::LEFT, LLFontGL::TOP); -			 -			tdesc = llformat( "%d ms |", (U32)ms.value()); -			x = x_start + 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(x_start-5, by, getRect().getWidth()-5, y+5, FALSE); - -			//tree view -			gl_rect_2d(5, by, x_start-10, 5, FALSE); - -			by = y + 5; -			//average bar -			gl_rect_2d(x_start-5, by, getRect().getWidth()-5, by-barh-dy-5, FALSE); -			 -			by -= barh*2+dy; -			 -			//current frame bar -			gl_rect_2d(x_start-5, by, getRect().getWidth()-5, by-barh-dy-2, FALSE); -			 -			by -= barh+dy+1; -			 -			//history bars -			gl_rect_2d(x_start-5, by, getRect().getWidth()-5, LINE_GRAPH_HEIGHT-barh-dy-2, FALSE);			 -			 -			by = LINE_GRAPH_HEIGHT-barh-dy-7; -			 -			//line graph -			mGraphRect = LLRect(x_start-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 = j + 1 + mScrollIndex; -			} -			else -			{ -				tidx = -1; -			} -			 -			x = x_start; -			 -			// draw the bars for each stat -			std::vector<S32> xpos; -			std::vector<S32> deltax; -			xpos.push_back(x_start); -			 -			TimeBlock* prev_id = NULL; - -			S32 i = 0; -			for(timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); -				it != end_timer_tree(); -				++it, ++i) -			{ -				TimeBlock* idp = (*it); -				F32 frac = tidx == -1 -					? (frame_recording.getPeriodMean(*idp) / total_time)  -					: (frame_recording.getPrevRecordingPeriod(tidx).getSum(*idp).value() / total_time.value()); -		 -				dx = llround(frac * (F32)barw); -				S32 prev_delta_x = deltax.empty() ? 0 : deltax.back(); -				deltax.push_back(dx); -				 -				int level = get_depth(idp) - 1; -				 -				while ((S32)xpos.size() > level + 1) -				{ -					xpos.pop_back(); -				} -				left = xpos.back(); -				 -				if (level == 0) -				{ -					sublevel_left[level] = x_start; -					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; - -					for (TimeBlock::child_const_iter it = prev_id->beginChildren(); -						it != prev_id->endChildren(); -						++it) -					{ -						sublevelticks += (tidx == -1) -							? frame_recording.getPeriodMean(**it).value() -							: frame_recording.getPrevRecordingPeriod(tidx).getSum(**it).value(); -					} - -					F32 subfrac = (F32)sublevelticks / (F32)total_time.value(); -					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); -					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(); -					} - -					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 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 tdesc; -		if (mDisplayCalls) -			tdesc = llformat("%d calls", (int)max_calls); -		else if (mDisplayHz) -			tdesc = llformat("%d Hz", (int)(1.f / max_time.value())); -		else -			tdesc = llformat("%4.2f ms", max_time.value()); -							 -		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 = HISTORY_NUM - mScrollIndex; -			S32 last_frame = first_frame - MAX_VISIBLE_HISTORY; -				 -			F32 frame_delta = ((F32) (mGraphRect.getWidth()))/(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(); -			} -		} -			 -		LLUnit<LLUnits::Seconds, F32> cur_max = 0; -		U32 cur_max_calls = 0; -		for(timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); -			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 && -				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 = frame_recording.getNumPeriods(); -				j > 0; -				j--) -			{ -				LLUnit<LLUnits::Seconds, F32> time = llmax(frame_recording.getPrevRecordingPeriod(j).getSum(*idp), LLUnit<LLUnits::Seconds, F64>(0.000001)); -				U32 calls = frame_recording.getPrevRecordingPeriod(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())/(HISTORY_NUM-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(), LLCriticalDamp::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, LLCriticalDamp::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, 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) -		{ -			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(getFrameTimer()); -			it != end_timer_tree(); -			++it) -		{ -			TimeBlock* idp = (*it); - -			if (!first) -			{ -				timer_stat += ", "; -			} -			first = false; - -			LLUnit<LLUnits::Seconds, F32> ticks; -			if (mPrintStats > 0) -			{ -				ticks = frame_recording.getPrevRecordingPeriod(mPrintStats).getSum(*idp); -			} -			else -			{ -				ticks = frame_recording.getPeriodMean(*idp); -			} -			LLUnit<LLUnits::Milliseconds, F32> ms = ticks; +	const S32 LEGEND_WIDTH = 220; -			timer_stat += llformat("%.1f",ms.value()); +	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->getLastRecordingPeriod().getSum(getFrameTimer()));  	mHoverID = NULL;  	mHoverBarIndex = -1; - -	LLView::draw();  }  F64 LLFastTimerView::getTime(const std::string& name) @@ -1551,4 +940,629 @@ TimeBlock& LLFastTimerView::getFrameTimer()  	return FTM_FRAME;  } +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(getFrameTimer()); +			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(getFrameTimer()); +			it != end_timer_tree(); +			++it) +		{ +			TimeBlock* idp = (*it); + +			if (!first) +			{ +				timer_stat += ", "; +			} +			first = false; + +			LLUnit<LLUnits::Seconds, F32> ticks; +			if (mPrintStats > 0) +			{ +				ticks = mRecording->getPrevRecordingPeriod(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; +	} +} + +void LLFastTimerView::drawLineGraph() +{ +	//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", 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 = HISTORY_NUM - mScrollIndex; +		S32 last_frame = first_frame - MAX_VISIBLE_HISTORY; + +		F32 frame_delta = ((F32) (mGraphRect.getWidth()))/(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(); +		} +	} + +	LLUnit<LLUnits::Seconds, F32> cur_max = 0; +	U32 cur_max_calls = 0; +	for(timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); +		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 && +			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 = mRecording->getNumPeriods(); +			j > 0; +			j--) +		{ +			LLUnit<LLUnits::Seconds, F32> time = llmax(mRecording->getPrevRecordingPeriod(j).getSum(*idp), LLUnit<LLUnits::Seconds, F64>(0.000001)); +			U32 calls = mRecording->getPrevRecordingPeriod(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())/(HISTORY_NUM-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(), LLCriticalDamp::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, LLCriticalDamp::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, 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); +	}					 +} + +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(getFrameTimer()); +			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->getPrevRecordingPeriod(hidx).getSum(*idp); +				calls = mRecording->getPrevRecordingPeriod(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[&getFrameTimer()] = LLColor4::grey; + +		F32 hue = 0.f; + +		for (timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); +			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 ) +{ +	// 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( LLUnit<LLUnits::Seconds, F64> total_time ) +{ +	// Draw MS ticks +	{ +		LLUnit<LLUnits::Milliseconds, U32> ms = total_time; +		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); +	} +} + +LLUnit<LLUnits::Seconds, F64> LLFastTimerView::getTotalTime() +{ +	LLUnit<LLUnits::Seconds, F64> total_time; +	switch(mDisplayMode) +	{ +	case 0: +		total_time = mRecording->getPeriodMean(getFrameTimer())*2; +		break; +	case 1: +		total_time = mAllTimeMax; +		break; +	case 2: +		// Calculate the max total ticks for the current history +		total_time = mRecording->getPeriodMax(getFrameTimer()); +		break; +	default: +		total_time = LLUnit<LLUnits::Milliseconds, F32>(100); +		break; +	} +	return total_time; +} + +void LLFastTimerView::drawBars() +{ +	LLUnit<LLUnits::Seconds, F64> total_time = getTotalTime(); +	if (total_time <= 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 vpad = llmax(1, bar_height / 4); // spacing between bars +	bar_height -= vpad; + +	drawTicks(total_time); +	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); + +	for (S32 j = -1; j < histmax && y > LINE_GRAPH_HEIGHT; j++) +	{ +		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 +			: -1; + +		// draw the bars for each stat +		std::vector<S32> xpos; +		S32 deltax = 0; +		xpos.push_back(mBarRect.mLeft); + +		TimeBlock* prev_id = NULL; + +		S32 i = 0; +		for(timer_tree_iterator_t it = begin_timer_tree(getFrameTimer()); +			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 dx = llround(frac * (F32)mBarRect.getWidth()); +			S32 prev_delta_x = deltax; +			deltax = dx; + +			const int level = get_depth(idp) - 1; +			while ((S32)xpos.size() > level + 1) +			{ +				xpos.pop_back(); +			} + +			LLRect bar_rect; +			bar_rect.setLeftTopAndSize(xpos.back(), y, dx, bar_height); +			mBarRects[llmax(j, 0)].push_back(bar_rect); + +			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; + +				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(); +				} + +				F32 subfrac = (F32)sublevelticks / (F32)total_time.value(); +				sublevel_dx[level] = (int)(subfrac * (F32)mBarRect.getWidth() + .5f); + +				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]); +				} + +				sublevel_left[level] = bar_rect.mLeft; +				sublevel_right[level] = sublevel_left[level] + sublevel_dx[level]; +			}				 + +			xpos.back() = bar_rect.mRight; +			xpos.push_back(bar_rect.mLeft); + +			if (bar_rect.getWidth() > 0) +			{ +				LLColor4 color = sTimerColors[idp]; +				S32 scale_offset = 0; + +				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(); +				} + +				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)(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); +			} + +			if ((*it)->getCollapsed()) +			{ +				it.skipDescendants(); +			} + +			prev_id = idp; +		} +		y -= (bar_height + vpad); +		if (j < 0) +			y -= bar_height; +	} +	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); +} + + + + + + + + + + + diff --git a/indra/newview/llfasttimerview.h b/indra/newview/llfasttimerview.h index 07662bb795..09be137027 100644 --- a/indra/newview/llfasttimerview.h +++ b/indra/newview/llfasttimerview.h @@ -62,15 +62,28 @@ public:  	virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks);  	virtual void draw(); + +  	LLTrace::TimeBlock* getLegendID(S32 y);  	F64 getTime(const std::string& name);  protected:  	virtual	void	onClickCloseBtn(); +  private:	 -	typedef std::vector<std::vector<S32> > bar_positions_t; -	bar_positions_t mBarStart; -	bar_positions_t mBarEnd; +	void drawTicks(LLUnit<LLUnits::Seconds, F64> total_time); +	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(); +	LLUnit<LLUnits::Seconds, F64> getTotalTime(); + + +	std::vector<LLRect>* mBarRects;  	S32 mDisplayMode;  	typedef enum child_alignment | 
