diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llfasttimerview.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 1103 |
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 | |||
49 | static const S32 MAX_VISIBLE_HISTORY = 10; | ||
50 | static const S32 LINE_GRAPH_HEIGHT = 240; | ||
51 | |||
52 | struct 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 | |||
61 | static LLColor4 red0(0.5f, 0.0f, 0.0f, 1.0f); | ||
62 | static LLColor4 green0(0.0f, 0.5f, 0.0f, 1.0f); | ||
63 | static LLColor4 blue0(0.0f, 0.0f, 0.5f, 1.0f); | ||
64 | static LLColor4 blue7(0.0f, 0.0f, 0.5f, 1.0f); | ||
65 | |||
66 | static LLColor4 green7(0.6f, 1.0f, 0.4f, 1.0f); | ||
67 | static LLColor4 green8(0.4f, 1.0f, 0.6f, 1.0f); | ||
68 | static 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) | ||
72 | static 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 | }; | ||
162 | static int ft_display_didcalc = 0; | ||
163 | static const int FTV_DISPLAY_NUM = (sizeof(ft_display_table)/sizeof(ft_display_table[0])); | ||
164 | |||
165 | S32 ft_display_idx[FTV_DISPLAY_NUM]; // line of table entry for display purposes (for collapse) | ||
166 | |||
167 | LLFastTimerView::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 | |||
223 | LLFastTimerView::~LLFastTimerView() | ||
224 | { | ||
225 | delete[] mBarStart; | ||
226 | delete[] mBarEnd; | ||
227 | } | ||
228 | |||
229 | EWidgetType LLFastTimerView::getWidgetType() const | ||
230 | { | ||
231 | return WIDGET_TYPE_FAST_TIMER_VIEW; | ||
232 | } | ||
233 | |||
234 | LLString LLFastTimerView::getWidgetTag() const | ||
235 | { | ||
236 | return LL_FAST_TIMER_VIEW_TAG; | ||
237 | } | ||
238 | |||
239 | BOOL 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 | |||
251 | S32 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 | |||
262 | BOOL 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 | |||
308 | BOOL LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask) | ||
309 | { | ||
310 | return FALSE; | ||
311 | } | ||
312 | |||
313 | |||
314 | BOOL 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 | |||
350 | BOOL 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 | |||
362 | BOOL 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 | |||
389 | void 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 | |||
1077 | F64 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 | } | ||