aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llfasttimerview.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llfasttimerview.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llfasttimerview.cpp')
-rw-r--r--linden/indra/newview/llfasttimerview.cpp1103
1 files changed, 1103 insertions, 0 deletions
diff --git a/linden/indra/newview/llfasttimerview.cpp b/linden/indra/newview/llfasttimerview.cpp
new file mode 100644
index 0000000..3fddc4b
--- /dev/null
+++ b/linden/indra/newview/llfasttimerview.cpp
@@ -0,0 +1,1103 @@
1/**
2 * @file llfasttimerview.cpp
3 * @brief LLFastTimerView class implementation
4 *
5 * Copyright (c) 2004-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "indra_constants.h"
31#include "llfasttimerview.h"
32#include "llviewerwindow.h"
33#include "llrect.h"
34#include "llerror.h"
35#include "llgl.h"
36#include "llmath.h"
37#include "llfontgl.h"
38
39#include "viewer.h"
40#include "llviewerimagelist.h"
41#include "llui.h"
42#include "llviewercontrol.h"
43#include "llstat.h"
44
45#include "llfasttimer.h"
46
47//////////////////////////////////////////////////////////////////////////////
48
49static const S32 MAX_VISIBLE_HISTORY = 10;
50static const S32 LINE_GRAPH_HEIGHT = 240;
51
52struct ft_display_info {
53 int timer;
54 const char *desc;
55 LLColor4 *color;
56 S32 disabled; // initialized to 0
57 int level; // calculated based on desc
58 int parent; // calculated
59};
60
61static LLColor4 red0(0.5f, 0.0f, 0.0f, 1.0f);
62static LLColor4 green0(0.0f, 0.5f, 0.0f, 1.0f);
63static LLColor4 blue0(0.0f, 0.0f, 0.5f, 1.0f);
64static LLColor4 blue7(0.0f, 0.0f, 0.5f, 1.0f);
65
66static LLColor4 green7(0.6f, 1.0f, 0.4f, 1.0f);
67static LLColor4 green8(0.4f, 1.0f, 0.6f, 1.0f);
68static LLColor4 green9(0.6f, 1.0f, 0.6f, 1.0f);
69
70// green(6), blue, yellow, orange, pink(2), cyan
71// red (5) magenta (4)
72static struct ft_display_info ft_display_table[] =
73{
74 { LLFastTimer::FTM_FRAME, "Frame", &LLColor4::white, 0 },
75 { LLFastTimer::FTM_MESSAGES, " Messages", &LLColor4::grey1, 0 },
76 { LLFastTimer::FTM_SLEEP, " Sleep", &LLColor4::grey2, 0 },
77 { LLFastTimer::FTM_IDLE, " Idle", &blue0, 0 },
78 { LLFastTimer::FTM_INVENTORY, " Inventory Update", &LLColor4::purple6, 1 },
79 { LLFastTimer::FTM_AUTO_SELECT, " Open and Select", &LLColor4::red, 0 },
80 { LLFastTimer::FTM_FILTER, " Filter", &LLColor4::red2, 0 },
81 { LLFastTimer::FTM_ARRANGE, " Arrange", &LLColor4::red3, 0 },
82 { LLFastTimer::FTM_REFRESH, " Refresh", &LLColor4::red4, 0 },
83 { LLFastTimer::FTM_SORT, " Sort", &LLColor4::red5, 0 },
84 { LLFastTimer::FTM_RESET_DRAWORDER, " ResetDrawOrder", &LLColor4::pink1, 0 },
85 { LLFastTimer::FTM_WORLD_UPDATE, " World Update", &LLColor4::blue1, 1 },
86 { LLFastTimer::FTM_UPDATE_MOVE, " Move Objects", &LLColor4::pink2, 0 },
87 { LLFastTimer::FTM_OCTREE_BALANCE, " Octree Balance", &LLColor4::red3, 0 },
88 { LLFastTimer::FTM_CULL, " Object Cull", &LLColor4::blue2, 0 },
89 { LLFastTimer::FTM_CULL_REBOUND, " Rebound", &LLColor4::blue3, 0 },
90 { LLFastTimer::FTM_HUD_EFFECTS, " HUD Effects", &LLColor4::orange1, 0 },
91 { LLFastTimer::FTM_HUD_UPDATE, " HUD Update", &LLColor4::orange2, 0 },
92 { LLFastTimer::FTM_OCCLUSION, " Object Occlude",&LLColor4::pink1, 0 },
93 { LLFastTimer::FTM_OCCLUSION_READBACK, " Occlusion Read",&LLColor4::red2, 0 },
94 { LLFastTimer::FTM_GEO_UPDATE, " Geo Update", &LLColor4::blue3, 0 },
95 { LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes", &LLColor4::blue4, 0 },
96 { LLFastTimer::FTM_GEN_VOLUME, " Gen Volume", &LLColor4::yellow3, 0 },
97 { LLFastTimer::FTM_GEN_FLEX, " Flexible", &LLColor4::yellow4, 0 },
98 { LLFastTimer::FTM_GEN_TRIANGLES, " Triangles", &LLColor4::yellow5, 0 },
99 { LLFastTimer::FTM_GEO_LIGHT, " Lighting", &LLColor4::yellow1, 0 },
100 { LLFastTimer::FTM_GEO_SHADOW, " Shadow", &LLColor4::black, 0 },
101 { LLFastTimer::FTM_UPDATE_PARTICLES, " Particles", &LLColor4::blue5, 0 },
102 { LLFastTimer::FTM_GEO_RESERVE, " Reserve", &LLColor4::blue6, 0 },
103 { LLFastTimer::FTM_UPDATE_LIGHTS, " Lights", &LLColor4::yellow2, 0 },
104 { LLFastTimer::FTM_UPDATE_SKY, " Sky Update", &LLColor4::cyan1, 0 },
105 { LLFastTimer::FTM_OBJECTLIST_UPDATE, " Object Update", &LLColor4::purple1, 1 },
106 { LLFastTimer::FTM_AVATAR_UPDATE, " Avatars", &LLColor4::purple2, 0 },
107 { LLFastTimer::FTM_JOINT_UPDATE, " Joints", &LLColor4::purple3, 0 },
108 { LLFastTimer::FTM_ATTACHMENT_UPDATE, " Attachments", &LLColor4::purple4, 0 },
109 { LLFastTimer::FTM_UPDATE_ANIMATION, " Animation", &LLColor4::purple5, 0 },
110 { LLFastTimer::FTM_FLEXIBLE_UPDATE, " Flex Update", &LLColor4::pink2, 0 },
111 { LLFastTimer::FTM_LOD_UPDATE, " LOD Update", &LLColor4::magenta1, 0 },
112 { LLFastTimer::FTM_REGION_UPDATE, " Region Update", &LLColor4::cyan2, 0 },
113 { LLFastTimer::FTM_NETWORK, " Network", &LLColor4::orange1, 1 },
114 { LLFastTimer::FTM_IDLE_NETWORK, " Decode Msgs", &LLColor4::orange2, 0 },
115 { LLFastTimer::FTM_PROCESS_MESSAGES, " Process Msgs", &LLColor4::orange3, 0 },
116 { LLFastTimer::FTM_PROCESS_OBJECTS, " Object Updates",&LLColor4::orange4, 0 },
117 { LLFastTimer::FTM_CREATE_OBJECT, " Create Obj", &LLColor4::orange5, 0 },
118// { LLFastTimer::FTM_LOAD_AVATAR, " Load Avatar", &LLColor4::pink2, 0 },
119 { LLFastTimer::FTM_PROCESS_IMAGES, " Image Updates",&LLColor4::orange6, 0 },
120 { LLFastTimer::FTM_PIPELINE, " Pipeline", &LLColor4::magenta4, 0 },
121 { LLFastTimer::FTM_CLEANUP, " Cleanup", &LLColor4::cyan3, 0 },
122 { LLFastTimer::FTM_AUDIO_UPDATE, " Audio Update", &LLColor4::yellow3, 0 },
123 { LLFastTimer::FTM_IMAGE_UPDATE, " Image Update", &LLColor4::yellow4, 1 },
124 { LLFastTimer::FTM_IMAGE_CREATE, " Image CreateGL",&LLColor4::yellow5, 0 },
125 { LLFastTimer::FTM_IMAGE_DECODE, " Image Decode", &LLColor4::yellow6, 0 },
126 { LLFastTimer::FTM_VFILE_WAIT, " VFile Wait", &LLColor4::cyan6, 0 },
127// { LLFastTimer::FTM_IDLE_CB, " Callbacks", &LLColor4::pink1, 0 },
128 { LLFastTimer::FTM_RENDER, " Render", &green0, 0 },
129 { LLFastTimer::FTM_REBUILD, " Rebuild", &LLColor4::green1, 1 },
130 { LLFastTimer::FTM_STATESORT, " State Sort", &LLColor4::orange1, 1 },
131 { LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry", &LLColor4::green2, 1 },
132 { LLFastTimer::FTM_POOLS, " Pools", &LLColor4::green3, 0 },
133 { LLFastTimer::FTM_POOLRENDER, " RenderPool", &LLColor4::green4, 0 },
134 { LLFastTimer::FTM_RENDER_TERRAIN, " Terrain", &LLColor4::green6, 0 },
135 { LLFastTimer::FTM_RENDER_CHARACTERS, " Avatars", &LLColor4::yellow1, 0 },
136 { LLFastTimer::FTM_RENDER_SIMPLE, " Simple", &LLColor4::yellow2, 0 },
137 { LLFastTimer::FTM_RENDER_SHINY, " Shiny", &LLColor4::yellow3, 0 },
138 { LLFastTimer::FTM_RENDER_BUMP, " Bump", &LLColor4::yellow4, 0 },
139 { LLFastTimer::FTM_RENDER_TREES, " Trees", &LLColor4::yellow8, 0 },
140 { LLFastTimer::FTM_RENDER_OCCLUSION, " Occlusion", &LLColor4::red1, 0 },
141 { LLFastTimer::FTM_RENDER_CLOUDS, " Clouds", &LLColor4::yellow5, 0 },
142 { LLFastTimer::FTM_RENDER_ALPHA, " Alpha", &LLColor4::yellow6, 0 },
143 { LLFastTimer::FTM_RENDER_HUD, " HUD", &LLColor4::yellow7, 0 },
144 { LLFastTimer::FTM_RENDER_WATER, " Water", &LLColor4::yellow9, 0 },
145 { LLFastTimer::FTM_RENDER_UI, " UI", &LLColor4::cyan4, 1 },
146 { LLFastTimer::FTM_RENDER_TIMER, " Timers", &LLColor4::cyan5, 1, 0 },
147// { LLFastTimer::FTM_RENDER_FONTS, " Fonts", &LLColor4::pink1, 0 },
148// { LLFastTimer::FTM_UPDATE_TEXTURES, " Textures", &LLColor4::pink2, 0 },
149 { LLFastTimer::FTM_SWAP, " Swap", &LLColor4::pink1, 0 },
150
151// { LLFastTimer::FTM_TEMP1, " Temp1", &LLColor4::red1, 0 },
152// { LLFastTimer::FTM_TEMP2, " Temp2", &LLColor4::magenta1, 0 },
153// { LLFastTimer::FTM_TEMP3, " Temp3", &LLColor4::red2, 0 },
154// { LLFastTimer::FTM_TEMP4, " Temp4", &LLColor4::magenta2, 0 },
155// { LLFastTimer::FTM_TEMP5, " Temp5", &LLColor4::red3, 0 },
156// { LLFastTimer::FTM_TEMP6, " Temp6", &LLColor4::magenta3, 0 },
157// { LLFastTimer::FTM_TEMP7, " Temp7", &LLColor4::red4, 0 },
158// { LLFastTimer::FTM_TEMP8, " Temp8", &LLColor4::magenta4, 0 },
159
160 { LLFastTimer::FTM_OTHER, " Other", &red0 }
161};
162static int ft_display_didcalc = 0;
163static const int FTV_DISPLAY_NUM = (sizeof(ft_display_table)/sizeof(ft_display_table[0]));
164
165S32 ft_display_idx[FTV_DISPLAY_NUM]; // line of table entry for display purposes (for collapse)
166
167LLFastTimerView::LLFastTimerView(const std::string& name, const LLRect& rect)
168: LLView(name, rect, TRUE)
169{
170 setVisible(FALSE);
171 mDisplayMode = 0;
172 mAvgCountTotal = 0;
173 mMaxCountTotal = 0;
174 mDisplayCenter = 1;
175 mDisplayCalls = 0;
176 mScrollIndex = 0;
177 mHoverIndex = -1;
178 mHoverBarIndex = -1;
179 mBarStart = new S32[(MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM];
180 memset(mBarStart, 0, (MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM * sizeof(S32));
181 mBarEnd = new S32[(MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM];
182 memset(mBarEnd, 0, (MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM * sizeof(S32));
183 mSubtractHidden = 0;
184 mPrintStats = -1;
185
186 // One-time setup
187 if (!ft_display_didcalc)
188 {
189 int pidx[FTV_DISPLAY_NUM];
190 int pdisabled[FTV_DISPLAY_NUM];
191 for (S32 i=0; i < FTV_DISPLAY_NUM; i++)
192 {
193 int level = 0;
194 const char *text = ft_display_table[i].desc;
195 while(text[0] == ' ')
196 {
197 text++;
198 level++;
199 }
200 llassert(level < FTV_DISPLAY_NUM);
201 ft_display_table[i].desc = text;
202 ft_display_table[i].level = level;
203 if (level > 0)
204 {
205 ft_display_table[i].parent = pidx[level-1];
206 if (pdisabled[level-1])
207 {
208 ft_display_table[i].disabled = 3;
209 }
210 }
211 else
212 {
213 ft_display_table[i].parent = -1;
214 }
215 ft_display_idx[i] = i;
216 pidx[level] = i;
217 pdisabled[level] = ft_display_table[i].disabled;
218 }
219 ft_display_didcalc = 1;
220 }
221}
222
223LLFastTimerView::~LLFastTimerView()
224{
225 delete[] mBarStart;
226 delete[] mBarEnd;
227}
228
229EWidgetType LLFastTimerView::getWidgetType() const
230{
231 return WIDGET_TYPE_FAST_TIMER_VIEW;
232}
233
234LLString LLFastTimerView::getWidgetTag() const
235{
236 return LL_FAST_TIMER_VIEW_TAG;
237}
238
239BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)
240{
241 if (mBarRect.pointInRect(x, y))
242 {
243 S32 bar_idx = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight());
244 bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY);
245 mPrintStats = bar_idx;
246// return TRUE; // for now, pass all mouse events through
247 }
248 return FALSE;
249}
250
251S32 LLFastTimerView::getLegendIndex(S32 y)
252{
253 S32 idx = (mRect.getHeight() - y) / ((S32) LLFontGL::sMonospace->getLineHeight()+2) - 5;
254 if (idx >= 0 && idx < FTV_DISPLAY_NUM)
255 {
256 return ft_display_idx[idx];
257 }
258
259 return -1;
260}
261
262BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
263{
264 if (x < mBarRect.mLeft)
265 {
266 S32 legend_index = getLegendIndex(y);
267 if (legend_index >= 0 && legend_index < FTV_DISPLAY_NUM)
268 {
269 S32 disabled = ft_display_table[legend_index].disabled;
270 if (++disabled > 2)
271 disabled = 0;
272 ft_display_table[legend_index].disabled = disabled;
273 S32 level = ft_display_table[legend_index].level;
274
275 // propagate enable/disable to all children
276 legend_index++;
277 while (legend_index < FTV_DISPLAY_NUM && ft_display_table[legend_index].level > level)
278 {
279 ft_display_table[legend_index].disabled = disabled ? 3 : 0;
280 legend_index++;
281 }
282 }
283 }
284 else if (mask & MASK_SHIFT)
285 {
286 if (++mDisplayMode > 3)
287 mDisplayMode = 0;
288 }
289 else if (mask & MASK_CONTROL)
290 {
291 if (++mDisplayCenter > 2)
292 mDisplayCenter = 0;
293 }
294 else
295 {
296 // pause/unpause
297 LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
298 // reset scroll to bottom when unpausing
299 if (!LLFastTimer::sPauseHistory)
300 {
301 mScrollIndex = 0;
302 }
303 }
304 // RN: for now, pass all mouse events through
305 return FALSE;
306}
307
308BOOL LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask)
309{
310 return FALSE;
311}
312
313
314BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
315{
316 if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y))
317 {
318 mHoverIndex = -1;
319 mHoverBarIndex = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight());
320 if (mHoverBarIndex == 0)
321 {
322 return TRUE;
323 }
324 else if (mHoverBarIndex == -1)
325 {
326 mHoverBarIndex = 0;
327 }
328 for (S32 i = 0; i < FTV_DISPLAY_NUM; i++)
329 {
330 if (x > mBarStart[mHoverBarIndex * FTV_DISPLAY_NUM + i] &&
331 x < mBarEnd[mHoverBarIndex * FTV_DISPLAY_NUM + i] &&
332 ft_display_table[i].disabled <= 1)
333 {
334 mHoverIndex = i;
335 }
336 }
337 }
338 else if (x < mBarRect.mLeft)
339 {
340 S32 legend_index = getLegendIndex(y);
341 if (legend_index >= 0 && legend_index < FTV_DISPLAY_NUM)
342 {
343 mHoverIndex = legend_index;
344 }
345 }
346
347 return FALSE;
348}
349
350BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)
351{
352 if (getVisible() && pointInView(x, y))
353 {
354 LLFastTimer::sPauseHistory = TRUE;
355 mScrollIndex = llclamp(mScrollIndex - clicks,
356 0, llmin(LLFastTimer::sLastFrameIndex, (S32)LLFastTimer::FTM_HISTORY_NUM-MAX_VISIBLE_HISTORY));
357 return TRUE;
358 }
359 return FALSE;
360}
361
362BOOL LLFastTimerView::handleKey(KEY key, MASK mask, BOOL called_from_parent)
363{
364 // Otherwise space key gets eaten from the rest of the UI. JC
365 if (getVisible())
366 {
367 switch (key)
368 {
369 case '=':
370 mDisplayCalls = !mDisplayCalls;
371 return TRUE;
372 case '-':
373 mSubtractHidden = !mSubtractHidden;
374 return TRUE;
375 case ' ':
376 // pause/unpause
377 LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
378 // reset scroll to bottom when unpausing
379 if (!LLFastTimer::sPauseHistory)
380 {
381 mScrollIndex = 0;
382 }
383 return TRUE;
384 }
385 }
386 return FALSE;
387}
388
389void LLFastTimerView::draw()
390{
391 LLFastTimer t(LLFastTimer::FTM_RENDER_TIMER);
392
393 std::string tdesc;
394
395 F64 clock_freq = (F64)LLFastTimer::countsPerSecond();
396 F64 iclock_freq = 1000.0 / clock_freq;
397
398 S32 margin = 10;
399 S32 height = (S32) (gViewerWindow->getVirtualWindowRect().getHeight()*0.75f);
400 S32 width = (S32) (gViewerWindow->getVirtualWindowRect().getWidth() * 0.75f);
401
402 mRect.setLeftTopAndSize(mRect.mLeft, mRect.mTop, width, height);
403
404 S32 left, top, right, bottom;
405 S32 x, y, barw, barh, dx, dy;
406 S32 texth, textw;
407 LLViewerImage* box_imagep = gImageList.getImage(LLUUID(gViewerArt.getString("rounded_square.tga")), MIPMAP_FALSE, TRUE);
408
409 // Make sure all timers are accounted for
410 // Set 'FTM_OTHER' to unaccounted ticks last frame
411 {
412 S32 display_timer[LLFastTimer::FTM_NUM_TYPES];
413 S32 hidx = LLFastTimer::sLastFrameIndex % LLFastTimer::FTM_HISTORY_NUM;
414 for (S32 i=0; i < LLFastTimer::FTM_NUM_TYPES; i++)
415 {
416 display_timer[i] = 0;
417 }
418 for (S32 i=0; i < FTV_DISPLAY_NUM; i++)
419 {
420 S32 tidx = ft_display_table[i].timer;
421 display_timer[tidx] = 1;
422 }
423 LLFastTimer::sCountHistory[hidx][LLFastTimer::FTM_OTHER] = 0;
424 LLFastTimer::sCallHistory[hidx][LLFastTimer::FTM_OTHER] = 0;
425 for (S32 tidx = 0; tidx < LLFastTimer::FTM_NUM_TYPES; tidx++)
426 {
427 U64 counts = LLFastTimer::sCountHistory[hidx][tidx];
428 if (counts > 0 && display_timer[tidx] == 0)
429 {
430 LLFastTimer::sCountHistory[hidx][LLFastTimer::FTM_OTHER] += counts;
431 LLFastTimer::sCallHistory[hidx][LLFastTimer::FTM_OTHER] += 1;
432 }
433 }
434 LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] = 0;
435 LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] = 0;
436 for (S32 h = 0; h < LLFastTimer::FTM_HISTORY_NUM; h++)
437 {
438 LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] += LLFastTimer::sCountHistory[h][LLFastTimer::FTM_OTHER];
439 LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] += LLFastTimer::sCallHistory[h][LLFastTimer::FTM_OTHER];
440 }
441 LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] /= LLFastTimer::FTM_HISTORY_NUM;
442 LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] /= LLFastTimer::FTM_HISTORY_NUM;
443 }
444
445 // Draw the window background
446 {
447 LLGLSNoTexture gls_ui_no_texture;
448 gl_rect_2d(0, mRect.getHeight(), mRect.getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
449 }
450
451 S32 xleft = margin;
452 S32 ytop = margin;
453
454 // Draw some help
455 {
456
457 x = xleft;
458 y = height - ytop;
459 texth = (S32)LLFontGL::sMonospace->getLineHeight();
460
461 char modedesc[][32] = {
462 "2 x Average ",
463 "Max ",
464 "Recent Max ",
465 "100 ms "
466 };
467 char centerdesc[][32] = {
468 "Left ",
469 "Centered ",
470 "Ordered "
471 };
472
473 tdesc = llformat("Full bar = %s [Click to pause/reset] [SHIFT-Click to toggle]",modedesc[mDisplayMode]);
474 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
475
476 textw = LLFontGL::sMonospace->getWidth(tdesc);
477
478 x = xleft, y -= (texth + 2);
479 tdesc = llformat("Justification = %s [CTRL-Click to toggle]",centerdesc[mDisplayCenter]);
480 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
481 y -= (texth + 2);
482
483 LLFontGL::sMonospace->renderUTF8("[Right-click to log selected] [= to toggle counts] [- to subtract hidden]",
484 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
485 y -= (texth + 2);
486 }
487
488 // Calc the total ticks
489 S32 histmax = llmin(LLFastTimer::sLastFrameIndex+1, MAX_VISIBLE_HISTORY);
490 U64 ticks_sum[LLFastTimer::FTM_HISTORY_NUM+1][FTV_DISPLAY_NUM];
491 for (S32 j=-1; j<LLFastTimer::FTM_HISTORY_NUM; j++)
492 {
493 S32 hidx;
494 if (j >= 0)
495 hidx = (LLFastTimer::sLastFrameIndex+j) % LLFastTimer::FTM_HISTORY_NUM;
496 else
497 hidx = -1;
498
499 // calculate tick info by adding child ticks to parents
500 for (S32 i=0; i < FTV_DISPLAY_NUM; i++)
501 {
502 if (mSubtractHidden && ft_display_table[i].disabled > 1)
503 {
504 continue;
505 }
506 // Get ticks
507 S32 tidx = ft_display_table[i].timer;
508 if (hidx >= 0)
509 ticks_sum[j+1][i] = LLFastTimer::sCountHistory[hidx][tidx];
510 else
511 ticks_sum[j+1][i] = LLFastTimer::sCountAverage[tidx];
512 S32 pidx = ft_display_table[i].parent;
513 // Add ticks to parents
514 while (pidx >= 0)
515 {
516 ticks_sum[j+1][pidx] += ticks_sum[j+1][i];
517 pidx = ft_display_table[pidx].parent;
518 }
519 }
520 }
521
522 // Draw the legend
523
524 S32 legendwidth = 0;
525 xleft = margin;
526 ytop = y;
527
528 y -= (texth + 2);
529
530 S32 cur_line = 0;
531 S32 display_line[FTV_DISPLAY_NUM];
532 for (S32 i=0; i<FTV_DISPLAY_NUM; i++)
533 {
534 S32 disabled = ft_display_table[i].disabled;
535 if (disabled == 3)
536 {
537 continue; // skip row
538 }
539 display_line[i] = cur_line;
540 ft_display_idx[cur_line] = i;
541 cur_line++;
542 S32 level = ft_display_table[i].level;
543 S32 parent = ft_display_table[i].parent;
544
545 x = xleft;
546
547 left = x; right = x + texth;
548 top = y; bottom = y - texth;
549 S32 scale_offset = 0;
550 if (i == mHoverIndex)
551 {
552 scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f);
553 }
554 gl_rect_2d(left - scale_offset, top + scale_offset, right + scale_offset, bottom - scale_offset, *ft_display_table[i].color);
555
556 int tidx = ft_display_table[i].timer;
557 F32 ms = 0;
558 S32 calls = 0;
559 if (mHoverBarIndex > 0 && mHoverIndex >= 0)
560 {
561 S32 hidx = (LLFastTimer::sLastFrameIndex + (mHoverBarIndex - 1) - mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM;
562 S32 bidx = LLFastTimer::FTM_HISTORY_NUM - mScrollIndex - mHoverBarIndex;
563 U64 ticks = ticks_sum[bidx+1][i]; // : LLFastTimer::sCountHistory[hidx][tidx];
564 ms = (F32)((F64)ticks * iclock_freq);
565 calls = (S32)LLFastTimer::sCallHistory[hidx][tidx];
566 }
567 else
568 {
569 U64 ticks = disabled >= 1 ? ticks_sum[0][i] : LLFastTimer::sCountAverage[tidx];
570 ms = (F32)((F64)ticks * iclock_freq);
571 calls = (S32)LLFastTimer::sCallAverage[tidx];
572 }
573 if (mDisplayCalls)
574 {
575 tdesc = llformat("%s (%d)",ft_display_table[i].desc,calls);
576 }
577 else
578 {
579 tdesc = llformat("%s [%.1f]",ft_display_table[i].desc,ms);
580 }
581 dx = (texth+4) + level*8;
582
583 LLColor4 color = disabled > 1 ? LLColor4::grey : LLColor4::white;
584 if (level > 0)
585 {
586 S32 line_start_y = (top + bottom) / 2;
587 S32 line_end_y = line_start_y + ((texth + 2) * (display_line[i] - display_line[parent])) - (texth / 2);
588 gl_line_2d(x + dx - 8, line_start_y, x + dx, line_start_y, color);
589 S32 line_x = x + (texth + 4) + ((level - 1) * 8);
590 gl_line_2d(line_x, line_start_y, line_x, line_end_y, color);
591 if (disabled == 1)
592 {
593 gl_line_2d(line_x+4, line_start_y-3, line_x+4, line_start_y+4, color);
594 }
595 }
596
597 x += dx;
598 BOOL is_child_of_hover_item = (i == mHoverIndex);
599 S32 next_parent = ft_display_table[i].parent;
600 while(!is_child_of_hover_item && next_parent >= 0)
601 {
602 is_child_of_hover_item = (mHoverIndex == next_parent);
603 next_parent = ft_display_table[next_parent].parent;
604 }
605
606 if (is_child_of_hover_item)
607 {
608 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::BOLD);
609 }
610 else
611 {
612 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP);
613 }
614 y -= (texth + 2);
615
616 textw = dx + LLFontGL::sMonospace->getWidth(ft_display_table[i].desc) + 40;
617 if (textw > legendwidth)
618 legendwidth = textw;
619 }
620 for (S32 i=cur_line; i<FTV_DISPLAY_NUM; i++)
621 {
622 ft_display_idx[i] = -1;
623 }
624 xleft += legendwidth + 8;
625 // ytop = ytop;
626
627 // update rectangle that includes timer bars
628 mBarRect.mLeft = xleft;
629 mBarRect.mRight = mRect.mRight - xleft;
630 mBarRect.mTop = ytop - ((S32)LLFontGL::sMonospace->getLineHeight() + 4);
631 mBarRect.mBottom = margin + LINE_GRAPH_HEIGHT;
632
633 y = ytop;
634 barh = (ytop - margin - LINE_GRAPH_HEIGHT) / (MAX_VISIBLE_HISTORY + 2);
635 dy = barh>>2; // spacing between bars
636 if (dy < 1) dy = 1;
637 barh -= dy;
638 barw = width - xleft - margin;
639
640 // Draw the history bars
641 if (LLFastTimer::sLastFrameIndex >= 0)
642 {
643 U64 totalticks;
644 if (!LLFastTimer::sPauseHistory)
645 {
646 U64 ticks = 0;
647 int hidx = (LLFastTimer::sLastFrameIndex - mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM;
648 for (S32 i=0; i<FTV_DISPLAY_NUM; i++)
649 {
650 if (mSubtractHidden && ft_display_table[i].disabled > 1)
651 {
652 continue;
653 }
654 int tidx = ft_display_table[i].timer;
655 ticks += LLFastTimer::sCountHistory[hidx][tidx];
656 }
657 if (LLFastTimer::sCurFrameIndex >= 10)
658 {
659 U64 framec = LLFastTimer::sCurFrameIndex;
660 U64 avg = (U64)mAvgCountTotal;
661 mAvgCountTotal = (avg*framec + ticks) / (framec + 1);
662 if (ticks > mMaxCountTotal)
663 {
664 mMaxCountTotal = ticks;
665 }
666 }
667#if 1
668 if (ticks < mAvgCountTotal/100 || ticks > mAvgCountTotal*100)
669 LLFastTimer::sResetHistory = 1;
670#endif
671 if (LLFastTimer::sCurFrameIndex < 10 || LLFastTimer::sResetHistory)
672 {
673 mAvgCountTotal = ticks;
674 mMaxCountTotal = ticks;
675 }
676 }
677
678 if (mDisplayMode == 0)
679 {
680 totalticks = mAvgCountTotal*2;
681 }
682 else if (mDisplayMode == 1)
683 {
684 totalticks = mMaxCountTotal;
685 }
686 else if (mDisplayMode == 2)
687 {
688 // Calculate the max total ticks for the current history
689 totalticks = 0;
690 for (S32 j=0; j<histmax; j++)
691 {
692 U64 ticks = 0;
693 for (S32 i=0; i<FTV_DISPLAY_NUM; i++)
694 {
695 if (mSubtractHidden && ft_display_table[i].disabled > 1)
696 {
697 continue;
698 }
699 int tidx = ft_display_table[i].timer;
700 ticks += LLFastTimer::sCountHistory[j][tidx];
701 }
702 if (ticks > totalticks)
703 totalticks = ticks;
704 }
705 }
706 else
707 {
708 totalticks = (U64)(clock_freq * .1); // 100 ms
709 }
710
711 // Draw MS ticks
712 {
713 U32 ms = (U32)((F64)totalticks * iclock_freq) ;
714
715 tdesc = llformat("%.1f ms |", (F32)ms*.25f);
716 x = xleft + barw/4 - LLFontGL::sMonospace->getWidth(tdesc);
717 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white,
718 LLFontGL::LEFT, LLFontGL::TOP);
719
720 tdesc = llformat("%.1f ms |", (F32)ms*.50f);
721 x = xleft + barw/2 - LLFontGL::sMonospace->getWidth(tdesc);
722 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white,
723 LLFontGL::LEFT, LLFontGL::TOP);
724
725 tdesc = llformat("%.1f ms |", (F32)ms*.75f);
726 x = xleft + (barw*3)/4 - LLFontGL::sMonospace->getWidth(tdesc);
727 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white,
728 LLFontGL::LEFT, LLFontGL::TOP);
729
730 tdesc = llformat( "%d ms |", ms);
731 x = xleft + barw - LLFontGL::sMonospace->getWidth(tdesc);
732 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white,
733 LLFontGL::LEFT, LLFontGL::TOP);
734 }
735
736 LLRect graph_rect;
737 // Draw borders
738 {
739 LLGLSNoTexture gls_ui_no_texture;
740 glColor4f(0.5f,0.5f,0.5f,0.5f);
741
742 S32 by = y + 2;
743
744 y -= ((S32)LLFontGL::sMonospace->getLineHeight() + 4);
745
746 //heading
747 gl_rect_2d(xleft-5, by, mRect.getWidth()-5, y+5, FALSE);
748
749 //tree view
750 gl_rect_2d(5, by, xleft-10, 5, FALSE);
751
752 by = y + 5;
753 //average bar
754 gl_rect_2d(xleft-5, by, mRect.getWidth()-5, by-barh-dy-5, FALSE);
755
756 by -= barh*2+dy;
757
758 //current frame bar
759 gl_rect_2d(xleft-5, by, mRect.getWidth()-5, by-barh-dy-2, FALSE);
760
761 by -= barh+dy+1;
762
763 //history bars
764 gl_rect_2d(xleft-5, by, mRect.getWidth()-5, LINE_GRAPH_HEIGHT-barh-dy-2, FALSE);
765
766 by = LINE_GRAPH_HEIGHT-barh-dy-7;
767
768 //line graph
769 graph_rect = LLRect(xleft-5, by, mRect.getWidth()-5, 5);
770
771 gl_rect_2d(graph_rect, FALSE);
772 }
773
774 // Draw bars for each history entry
775 // Special: -1 = show running average
776 LLViewerImage::bindTexture(box_imagep);
777 for (S32 j=-1; j<histmax && y > LINE_GRAPH_HEIGHT; j++)
778 {
779 int sublevel_dx[FTV_DISPLAY_NUM+1];
780 int sublevel_left[FTV_DISPLAY_NUM+1];
781 int sublevel_right[FTV_DISPLAY_NUM+1];
782 S32 tidx;
783 if (j >= 0)
784 {
785 tidx = LLFastTimer::FTM_HISTORY_NUM - j - 1 - mScrollIndex;
786 }
787 else
788 {
789 tidx = -1;
790 }
791
792 x = xleft;
793
794 // draw the bars for each stat
795 int xpos[FTV_DISPLAY_NUM+1];
796 int deltax[FTV_DISPLAY_NUM+1];
797 xpos[0] = xleft;
798
799 for (S32 i = 0; i < FTV_DISPLAY_NUM; i++)
800 {
801 if (ft_display_table[i].disabled > 1)
802 {
803 continue;
804 }
805
806 F32 frac = (F32)ticks_sum[tidx+1][i] / (F32)totalticks;
807
808 dx = llround(frac * (F32)barw);
809 deltax[i] = dx;
810
811 int level = ft_display_table[i].level;
812 int parent = ft_display_table[i].parent;
813 llassert(level < FTV_DISPLAY_NUM);
814 llassert(parent < FTV_DISPLAY_NUM);
815
816 left = xpos[level];
817
818 S32 prev_idx = i - 1;
819 while (prev_idx > 0)
820 {
821 if (ft_display_table[prev_idx].disabled <= 1)
822 {
823 break;
824 }
825 prev_idx--;
826 }
827 S32 next_idx = i + 1;
828 while (next_idx < FTV_DISPLAY_NUM)
829 {
830 if (ft_display_table[next_idx].disabled <= 1)
831 {
832 break;
833 }
834 next_idx++;
835 }
836
837 if (level == 0)
838 {
839 sublevel_left[level] = xleft;
840 sublevel_dx[level] = dx;
841 sublevel_right[level] = sublevel_left[level] + sublevel_dx[level];
842 }
843 else if (i==0 || ft_display_table[prev_idx].level < level)
844 {
845 // If we are the first entry at a new sublevel block, calc the
846 // total width of this sublevel and modify left to align block.
847 U64 sublevelticks = ticks_sum[tidx+1][i];
848 for (S32 k=i+1; k<FTV_DISPLAY_NUM; k++)
849 {
850 if (ft_display_table[k].level < level)
851 break;
852 if (ft_display_table[k].disabled <= 1 && ft_display_table[k].level == level)
853 sublevelticks += ticks_sum[tidx+1][k];
854 }
855 F32 subfrac = (F32)sublevelticks / (F32)totalticks;
856 sublevel_dx[level] = (int)(subfrac * (F32)barw + .5f);
857
858 if (mDisplayCenter == 1) // center aligned
859 {
860 left += (deltax[parent] - sublevel_dx[level])/2;
861 }
862 else if (mDisplayCenter == 2) // right aligned
863 {
864 left += (deltax[parent] - sublevel_dx[level]);
865 }
866
867 sublevel_left[level] = left;
868 sublevel_right[level] = sublevel_left[level] + sublevel_dx[level];
869 }
870
871 right = left + dx;
872 xpos[level] = right;
873 xpos[level+1] = left;
874
875 mBarStart[(j + 1) * FTV_DISPLAY_NUM + i] = left;
876 mBarEnd[(j + 1) * FTV_DISPLAY_NUM + i] = right;
877
878 top = y;
879 bottom = y - barh;
880
881 if (right > left)
882 {
883 //U32 rounded_edges = 0;
884 LLColor4 color = *ft_display_table[i].color;
885 S32 scale_offset = 0;
886
887 BOOL is_child_of_hover_item = (i == mHoverIndex);
888 S32 next_parent = ft_display_table[i].parent;
889 while(!is_child_of_hover_item && next_parent >= 0)
890 {
891 is_child_of_hover_item = (mHoverIndex == next_parent);
892 next_parent = ft_display_table[next_parent].parent;
893 }
894
895 if (i == mHoverIndex)
896 {
897 scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 3.f);
898 //color = lerp(color, LLColor4::black, -0.4f);
899 }
900 else if (mHoverIndex >= 0 && !is_child_of_hover_item)
901 {
902 color = lerp(color, LLColor4::grey, 0.8f);
903 }
904
905 glColor4fv(color.mV);
906 F32 start_fragment = llclamp((F32)(left - sublevel_left[level]) / (F32)sublevel_dx[level], 0.f, 1.f);
907 F32 end_fragment = llclamp((F32)(right - sublevel_left[level]) / (F32)sublevel_dx[level], 0.f, 1.f);
908 gl_segmented_rect_2d_fragment_tex(sublevel_left[level], top - level + scale_offset, sublevel_right[level], bottom + level - scale_offset, box_imagep->getWidth(), box_imagep->getHeight(), 16, start_fragment, end_fragment);
909
910 }
911
912 }
913 y -= (barh + dy);
914 if (j < 0)
915 y -= barh;
916 }
917
918 //draw line graph history
919 {
920 LLGLSNoTexture no_texture;
921 LLGLEnable scissor(GL_SCISSOR_TEST);
922 LLUI::setScissorRegionLocal(graph_rect);
923
924 //normalize based on last frame's maximum
925 static U64 last_max = 0;
926 static F32 alpha_interp = 0.f;
927 U64 max_ticks = llmax(last_max, (U64) 1);
928 F32 ms = (F32)((F64)max_ticks * iclock_freq);
929
930 //display y-axis range
931 LLString tdesc = llformat("%4.2f ms", ms);
932 x = graph_rect.mRight - LLFontGL::sMonospace->getWidth(tdesc)-5;
933 y = graph_rect.mTop - ((S32)LLFontGL::sMonospace->getLineHeight());
934
935 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white,
936 LLFontGL::LEFT, LLFontGL::TOP);
937
938 //highlight visible range
939 {
940 S32 first_frame = LLFastTimer::FTM_HISTORY_NUM - mScrollIndex;
941 S32 last_frame = first_frame - MAX_VISIBLE_HISTORY;
942
943 F32 frame_delta = ((F32) (graph_rect.getWidth()))/(LLFastTimer::FTM_HISTORY_NUM-1);
944
945 F32 right = (F32) graph_rect.mLeft + frame_delta*first_frame;
946 F32 left = (F32) graph_rect.mLeft + frame_delta*last_frame;
947
948 glColor4f(0.5f,0.5f,0.5f,0.3f);
949 gl_rect_2d((S32) left, graph_rect.mTop, (S32) right, graph_rect.mBottom);
950
951 if (mHoverBarIndex >= 0)
952 {
953 S32 bar_frame = first_frame - mHoverBarIndex;
954 F32 bar = (F32) graph_rect.mLeft + frame_delta*bar_frame;
955
956 glColor4f(0.5f,0.5f,0.5f,1);
957
958 glBegin(GL_LINES);
959 glVertex2i((S32)bar, graph_rect.mBottom);
960 glVertex2i((S32)bar, graph_rect.mTop);
961 glEnd();
962 }
963 }
964
965 U64 cur_max = 0;
966 for (S32 idx = 0; idx < FTV_DISPLAY_NUM; ++idx)
967 {
968 if (ft_display_table[idx].disabled > 1)
969 { //skip disabled timers
970 continue;
971 }
972
973 //fatten highlighted timer
974 if (mHoverIndex == idx)
975 {
976 glLineWidth(3);
977 }
978
979 F32* col = ft_display_table[idx].color->mV;
980
981 F32 alpha = 1.f;
982
983 if (mHoverIndex >= 0 &&
984 idx != mHoverIndex)
985 { //fade out non-hihglighted timers
986 if (ft_display_table[idx].parent != mHoverIndex)
987 {
988 alpha = alpha_interp;
989 }
990 }
991
992 glColor4f(col[0], col[1], col[2], alpha);
993 glBegin(GL_LINE_STRIP);
994 for (U32 j = 0; j < LLFastTimer::FTM_HISTORY_NUM; j++)
995 {
996 U64 ticks = ticks_sum[j+1][idx];
997 if (alpha == 1.f)
998 { //normalize to highlighted timer
999 cur_max = llmax(cur_max, ticks);
1000 }
1001 F32 x = graph_rect.mLeft + ((F32) (graph_rect.getWidth()))/(LLFastTimer::FTM_HISTORY_NUM-1)*j;
1002 F32 y = graph_rect.mBottom + (F32) graph_rect.getHeight()/max_ticks*ticks;
1003 glVertex2f(x,y);
1004 }
1005 glEnd();
1006
1007 if (mHoverIndex == idx)
1008 {
1009 glLineWidth(1);
1010 }
1011 }
1012
1013 //interpolate towards new maximum
1014 F32 dt = gFrameIntervalSeconds*3.f;
1015 last_max = (U64) ((F32) last_max + ((F32) cur_max- (F32) last_max) * dt);
1016 F32 alpha_target = last_max > cur_max ?
1017 llmin((F32) last_max/ (F32) cur_max - 1.f,1.f) :
1018 llmin((F32) cur_max/ (F32) last_max - 1.f,1.f);
1019
1020 alpha_interp = alpha_interp + (alpha_target-alpha_interp) * dt;
1021
1022 }
1023 }
1024
1025 // Output stats for clicked bar to log
1026 if (mPrintStats >= 0)
1027 {
1028 LLString legend_stat;
1029 S32 stat_num;
1030 S32 first = 1;
1031 for (stat_num = 0; stat_num < FTV_DISPLAY_NUM; stat_num++)
1032 {
1033 if (ft_display_table[stat_num].disabled > 1)
1034 continue;
1035 if (!first)
1036 legend_stat += ", ";
1037 first=0;
1038 legend_stat += ft_display_table[stat_num].desc;
1039 }
1040 llinfos << legend_stat << llendl;
1041
1042 LLString timer_stat;
1043 first = 1;
1044 for (stat_num = 0; stat_num < FTV_DISPLAY_NUM; stat_num++)
1045 {
1046 S32 disabled = ft_display_table[stat_num].disabled;
1047 if (disabled > 1)
1048 continue;
1049 if (!first)
1050 timer_stat += ", ";
1051 first=0;
1052 U64 ticks;
1053 S32 tidx = ft_display_table[stat_num].timer;
1054 if (mPrintStats > 0)
1055 {
1056 S32 hidx = (LLFastTimer::sLastFrameIndex+(mPrintStats-1)-mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM;
1057 ticks = disabled >= 1 ? ticks_sum[mPrintStats][stat_num] : LLFastTimer::sCountHistory[hidx][tidx];
1058 }
1059 else
1060 {
1061 ticks = disabled >= 1 ? ticks_sum[0][stat_num] : LLFastTimer::sCountAverage[tidx];
1062 }
1063 F32 ms = (F32)((F64)ticks * iclock_freq);
1064
1065 timer_stat += llformat("%.1f",ms);
1066 }
1067 llinfos << timer_stat << llendl;
1068 mPrintStats = -1;
1069 }
1070
1071 mHoverIndex = -1;
1072 mHoverBarIndex = -1;
1073
1074 LLView::draw();
1075}
1076
1077F64 LLFastTimerView::getTime(LLFastTimer::EFastTimerType tidx)
1078{
1079 // Find table index
1080 S32 i;
1081 for (i=0; i<FTV_DISPLAY_NUM; i++)
1082 {
1083 if (tidx == ft_display_table[i].timer)
1084 {
1085 break;
1086 }
1087 }
1088 S32 table_idx = i;
1089
1090 // Add child ticks to parent
1091 U64 ticks = LLFastTimer::sCountAverage[tidx];
1092 S32 level = ft_display_table[table_idx].level;
1093 for (i=table_idx+1; i<FTV_DISPLAY_NUM; i++)
1094 {
1095 if (ft_display_table[i].level <= level)
1096 {
1097 break;
1098 }
1099 ticks += LLFastTimer::sCountAverage[ft_display_table[i].timer];
1100 }
1101
1102 return (F64)ticks / (F64)LLFastTimer::countsPerSecond();
1103}