00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "indra_constants.h"
00035 #include "llfasttimerview.h"
00036 #include "llviewerwindow.h"
00037 #include "llrect.h"
00038 #include "llerror.h"
00039 #include "llgl.h"
00040 #include "llmath.h"
00041 #include "llfontgl.h"
00042
00043 #include "viewer.h"
00044 #include "llviewerimagelist.h"
00045 #include "llui.h"
00046 #include "llviewercontrol.h"
00047 #include "llstat.h"
00048
00049 #include "llfasttimer.h"
00050
00052
00053 static const S32 MAX_VISIBLE_HISTORY = 10;
00054 static const S32 LINE_GRAPH_HEIGHT = 240;
00055
00056 struct ft_display_info {
00057 int timer;
00058 const char *desc;
00059 LLColor4 *color;
00060 S32 disabled;
00061 int level;
00062 int parent;
00063 };
00064
00065 static LLColor4 red0(0.5f, 0.0f, 0.0f, 1.0f);
00066 static LLColor4 green0(0.0f, 0.5f, 0.0f, 1.0f);
00067 static LLColor4 blue0(0.0f, 0.0f, 0.5f, 1.0f);
00068 static LLColor4 blue7(0.0f, 0.0f, 0.5f, 1.0f);
00069
00070 static LLColor4 green7(0.6f, 1.0f, 0.4f, 1.0f);
00071 static LLColor4 green8(0.4f, 1.0f, 0.6f, 1.0f);
00072 static LLColor4 green9(0.6f, 1.0f, 0.6f, 1.0f);
00073
00074
00075
00076 static struct ft_display_info ft_display_table[] =
00077 {
00078 { LLFastTimer::FTM_FRAME, "Frame", &LLColor4::white, 0 },
00079 { LLFastTimer::FTM_MESSAGES, " Messages", &LLColor4::grey1, 0 },
00080 { LLFastTimer::FTM_SLEEP, " Sleep", &LLColor4::grey2, 0 },
00081 { LLFastTimer::FTM_IDLE, " Idle", &blue0, 0 },
00082 { LLFastTimer::FTM_PUMP, " Pump", &LLColor4::magenta2, 1 },
00083 { LLFastTimer::FTM_CURL, " Curl", &LLColor4::magenta3, 0 },
00084 { LLFastTimer::FTM_INVENTORY, " Inventory Update", &LLColor4::purple6, 1 },
00085 { LLFastTimer::FTM_AUTO_SELECT, " Open and Select", &LLColor4::red, 0 },
00086 { LLFastTimer::FTM_FILTER, " Filter", &LLColor4::red2, 0 },
00087 { LLFastTimer::FTM_ARRANGE, " Arrange", &LLColor4::red3, 0 },
00088 { LLFastTimer::FTM_REFRESH, " Refresh", &LLColor4::red4, 0 },
00089 { LLFastTimer::FTM_SORT, " Sort", &LLColor4::red5, 0 },
00090 { LLFastTimer::FTM_RESET_DRAWORDER, " ResetDrawOrder", &LLColor4::pink1, 0 },
00091 { LLFastTimer::FTM_WORLD_UPDATE, " World Update", &LLColor4::blue1, 1 },
00092 { LLFastTimer::FTM_UPDATE_MOVE, " Move Objects", &LLColor4::pink2, 0 },
00093 { LLFastTimer::FTM_OCTREE_BALANCE, " Octree Balance", &LLColor4::red3, 0 },
00094
00095 { LLFastTimer::FTM_CULL, " Object Cull", &LLColor4::blue2, 1 },
00096 { LLFastTimer::FTM_CULL_REBOUND, " Rebound", &LLColor4::blue3, 0 },
00097 { LLFastTimer::FTM_FRUSTUM_CULL, " Frustum Cull", &LLColor4::blue4, 0 },
00098 { LLFastTimer::FTM_OCCLUSION, " Object Occlude", &LLColor4::pink1, 0 },
00099 { LLFastTimer::FTM_OCCLUSION_READBACK, " Occlusion Read", &LLColor4::red2, 0 },
00100 { LLFastTimer::FTM_HUD_EFFECTS, " HUD Effects", &LLColor4::orange1, 0 },
00101 { LLFastTimer::FTM_HUD_UPDATE, " HUD Update", &LLColor4::orange2, 0 },
00102 { LLFastTimer::FTM_GEO_UPDATE, " Geo Update", &LLColor4::blue3, 0 },
00103 { LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes", &LLColor4::blue4, 0 },
00104 { LLFastTimer::FTM_GEN_VOLUME, " Gen Volume", &LLColor4::yellow3, 0 },
00105 { LLFastTimer::FTM_GEN_FLEX, " Flexible", &LLColor4::yellow4, 0 },
00106 { LLFastTimer::FTM_GEN_TRIANGLES, " Triangles", &LLColor4::yellow5, 0 },
00107 { LLFastTimer::FTM_UPDATE_AVATAR, " Avatar", &LLColor4::yellow1, 0 },
00108 { LLFastTimer::FTM_UPDATE_TREE, " Tree", &LLColor4::yellow2, 0 },
00109 { LLFastTimer::FTM_UPDATE_TERRAIN, " Terrain", &LLColor4::yellow6, 0 },
00110 { LLFastTimer::FTM_UPDATE_CLOUDS, " Clouds", &LLColor4::yellow7, 0 },
00111 { LLFastTimer::FTM_UPDATE_GRASS, " Grass", &LLColor4::yellow8, 0 },
00112 { LLFastTimer::FTM_UPDATE_WATER, " Water", &LLColor4::yellow9, 0 },
00113 { LLFastTimer::FTM_GEO_LIGHT, " Lighting", &LLColor4::yellow1, 0 },
00114 { LLFastTimer::FTM_GEO_SHADOW, " Shadow", &LLColor4::black, 0 },
00115 { LLFastTimer::FTM_UPDATE_PARTICLES, " Particles", &LLColor4::blue5, 0 },
00116 { LLFastTimer::FTM_SIMULATE_PARTICLES, " Particle Sim", &LLColor4::blue4, 0 },
00117 { LLFastTimer::FTM_GEO_RESERVE, " Reserve", &LLColor4::blue6, 0 },
00118 { LLFastTimer::FTM_UPDATE_LIGHTS, " Lights", &LLColor4::yellow2, 0 },
00119 { LLFastTimer::FTM_UPDATE_SKY, " Sky Update", &LLColor4::cyan1, 0 },
00120 { LLFastTimer::FTM_OBJECTLIST_UPDATE, " Object Update", &LLColor4::purple1, 0 },
00121 { LLFastTimer::FTM_AVATAR_UPDATE, " Avatars", &LLColor4::purple2, 0 },
00122 { LLFastTimer::FTM_JOINT_UPDATE, " Joints", &LLColor4::purple3, 0 },
00123 { LLFastTimer::FTM_ATTACHMENT_UPDATE, " Attachments", &LLColor4::purple4, 0 },
00124 { LLFastTimer::FTM_UPDATE_ANIMATION, " Animation", &LLColor4::purple5, 0 },
00125 { LLFastTimer::FTM_FLEXIBLE_UPDATE, " Flex Update", &LLColor4::pink2, 0 },
00126 { LLFastTimer::FTM_LOD_UPDATE, " LOD Update", &LLColor4::magenta1, 0 },
00127
00128 { LLFastTimer::FTM_REGION_UPDATE, " Region Update", &LLColor4::cyan2, 0 },
00129 { LLFastTimer::FTM_NETWORK, " Network", &LLColor4::orange1, 1 },
00130 { LLFastTimer::FTM_IDLE_NETWORK, " Decode Msgs", &LLColor4::orange2, 0 },
00131 { LLFastTimer::FTM_PROCESS_MESSAGES, " Process Msgs", &LLColor4::orange3, 0 },
00132 { LLFastTimer::FTM_PROCESS_OBJECTS, " Object Updates",&LLColor4::orange4, 0 },
00133 { LLFastTimer::FTM_CREATE_OBJECT, " Create Obj", &LLColor4::orange5, 0 },
00134
00135 { LLFastTimer::FTM_PROCESS_IMAGES, " Image Updates",&LLColor4::orange6, 0 },
00136 { LLFastTimer::FTM_PIPELINE, " Pipeline", &LLColor4::magenta4, 0 },
00137 { LLFastTimer::FTM_CLEANUP, " Cleanup", &LLColor4::cyan3, 0 },
00138 { LLFastTimer::FTM_AUDIO_UPDATE, " Audio Update", &LLColor4::yellow3, 0 },
00139 { LLFastTimer::FTM_IMAGE_UPDATE, " Image Update", &LLColor4::yellow4, 1 },
00140 { LLFastTimer::FTM_IMAGE_CREATE, " Image CreateGL",&LLColor4::yellow5, 0 },
00141 { LLFastTimer::FTM_IMAGE_DECODE, " Image Decode", &LLColor4::yellow6, 0 },
00142 { LLFastTimer::FTM_IMAGE_MARK_DIRTY, " Dirty Textures",&LLColor4::red1, 0 },
00143 { LLFastTimer::FTM_VFILE_WAIT, " VFile Wait", &LLColor4::cyan6, 0 },
00144
00145 { LLFastTimer::FTM_RENDER, " Render", &green0, 1 },
00146 { LLFastTimer::FTM_REBUILD, " Rebuild", &LLColor4::green1, 1 },
00147 { LLFastTimer::FTM_STATESORT, " State Sort", &LLColor4::orange1, 1 },
00148 { LLFastTimer::FTM_STATESORT_DRAWABLE, " Drawable", &LLColor4::orange2, 0 },
00149 { LLFastTimer::FTM_STATESORT_POSTSORT, " Post Sort", &LLColor4::orange3, 0 },
00150 { LLFastTimer::FTM_REBUILD_OCCLUSION_VB," Occlusion", &LLColor4::cyan5, 0 },
00151 { LLFastTimer::FTM_REBUILD_VBO, " VBO Rebuild", &LLColor4::red4, 0 },
00152 { LLFastTimer::FTM_REBUILD_VOLUME_VB, " Volume", &LLColor4::blue1, 0 },
00153 { LLFastTimer::FTM_REBUILD_NONE_VB, " Unknown", &LLColor4::cyan5, 0 },
00154 { LLFastTimer::FTM_REBUILD_BRIDGE_VB, " Bridge", &LLColor4::blue2, 0 },
00155 { LLFastTimer::FTM_REBUILD_HUD_VB, " HUD", &LLColor4::blue3, 0 },
00156 { LLFastTimer::FTM_REBUILD_TERRAIN_VB, " Terrain", &LLColor4::blue4, 0 },
00157 { LLFastTimer::FTM_REBUILD_WATER_VB, " Water", &LLColor4::blue5, 0 },
00158 { LLFastTimer::FTM_REBUILD_TREE_VB, " Tree", &LLColor4::cyan1, 0 },
00159 { LLFastTimer::FTM_REBUILD_PARTICLE_VB, " Particle", &LLColor4::cyan2, 0 },
00160 { LLFastTimer::FTM_REBUILD_CLOUD_VB, " Cloud", &LLColor4::cyan3, 0 },
00161 { LLFastTimer::FTM_REBUILD_GRASS_VB, " Grass", &LLColor4::cyan4, 0 },
00162 { LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry", &LLColor4::green2, 1 },
00163 { LLFastTimer::FTM_POOLS, " Pools", &LLColor4::green3, 1 },
00164 { LLFastTimer::FTM_POOLRENDER, " RenderPool", &LLColor4::green4, 1 },
00165 { LLFastTimer::FTM_RENDER_TERRAIN, " Terrain", &LLColor4::green6, 0 },
00166 { LLFastTimer::FTM_RENDER_CHARACTERS, " Avatars", &LLColor4::yellow1, 0 },
00167 { LLFastTimer::FTM_RENDER_SIMPLE, " Simple", &LLColor4::yellow2, 0 },
00168 { LLFastTimer::FTM_RENDER_FULLBRIGHT, " Fullbright", &LLColor4::yellow5, 0 },
00169 { LLFastTimer::FTM_RENDER_GLOW, " Glow", &LLColor4::orange1, 0 },
00170 { LLFastTimer::FTM_RENDER_GRASS, " Grass", &LLColor4::yellow6, 0 },
00171 { LLFastTimer::FTM_RENDER_INVISIBLE, " Invisible", &LLColor4::red2, 0 },
00172 { LLFastTimer::FTM_RENDER_SHINY, " Shiny", &LLColor4::yellow3, 0 },
00173 { LLFastTimer::FTM_RENDER_BUMP, " Bump", &LLColor4::yellow4, 0 },
00174 { LLFastTimer::FTM_RENDER_TREES, " Trees", &LLColor4::yellow8, 0 },
00175 { LLFastTimer::FTM_RENDER_OCCLUSION, " Occlusion", &LLColor4::red1, 0 },
00176 { LLFastTimer::FTM_RENDER_CLOUDS, " Clouds", &LLColor4::yellow5, 0 },
00177 { LLFastTimer::FTM_RENDER_ALPHA, " Alpha", &LLColor4::yellow6, 0 },
00178 { LLFastTimer::FTM_RENDER_HUD, " HUD", &LLColor4::yellow7, 0 },
00179 { LLFastTimer::FTM_RENDER_WATER, " Water", &LLColor4::yellow9, 0 },
00180 { LLFastTimer::FTM_RENDER_UI, " UI", &LLColor4::cyan4, 1 },
00181 { LLFastTimer::FTM_RENDER_TIMER, " Timers", &LLColor4::cyan5, 1, 0 },
00182
00183
00184 { LLFastTimer::FTM_SWAP, " Swap", &LLColor4::pink1, 0 },
00185 { LLFastTimer::FTM_CLIENT_COPY, " Client Copy", &LLColor4::red1, 1},
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 { LLFastTimer::FTM_OTHER, " Other", &red0 }
00197 };
00198 static int ft_display_didcalc = 0;
00199 static const int FTV_DISPLAY_NUM = (sizeof(ft_display_table)/sizeof(ft_display_table[0]));
00200
00201 S32 ft_display_idx[FTV_DISPLAY_NUM];
00202
00203 LLFastTimerView::LLFastTimerView(const std::string& name, const LLRect& rect)
00204 : LLFloater(name, rect, "Fast Timers")
00205 {
00206 setVisible(FALSE);
00207 mDisplayMode = 0;
00208 mAvgCountTotal = 0;
00209 mMaxCountTotal = 0;
00210 mDisplayCenter = 1;
00211 mDisplayCalls = 0;
00212 mScrollIndex = 0;
00213 mHoverIndex = -1;
00214 mHoverBarIndex = -1;
00215 mBarStart = new S32[(MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM];
00216 memset(mBarStart, 0, (MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM * sizeof(S32));
00217 mBarEnd = new S32[(MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM];
00218 memset(mBarEnd, 0, (MAX_VISIBLE_HISTORY + 1) * FTV_DISPLAY_NUM * sizeof(S32));
00219 mSubtractHidden = 0;
00220 mPrintStats = -1;
00221
00222
00223 if (!ft_display_didcalc)
00224 {
00225 int pidx[FTV_DISPLAY_NUM];
00226 int pdisabled[FTV_DISPLAY_NUM];
00227 for (S32 i=0; i < FTV_DISPLAY_NUM; i++)
00228 {
00229 int level = 0;
00230 const char *text = ft_display_table[i].desc;
00231 while(text[0] == ' ')
00232 {
00233 text++;
00234 level++;
00235 }
00236 llassert(level < FTV_DISPLAY_NUM);
00237 ft_display_table[i].desc = text;
00238 ft_display_table[i].level = level;
00239 if (level > 0)
00240 {
00241 ft_display_table[i].parent = pidx[level-1];
00242 if (pdisabled[level-1])
00243 {
00244 ft_display_table[i].disabled = 3;
00245 }
00246 }
00247 else
00248 {
00249 ft_display_table[i].parent = -1;
00250 }
00251 ft_display_idx[i] = i;
00252 pidx[level] = i;
00253 pdisabled[level] = ft_display_table[i].disabled;
00254 }
00255 ft_display_didcalc = 1;
00256 }
00257 }
00258
00259 LLFastTimerView::~LLFastTimerView()
00260 {
00261 delete[] mBarStart;
00262 delete[] mBarEnd;
00263 }
00264
00265 EWidgetType LLFastTimerView::getWidgetType() const
00266 {
00267 return WIDGET_TYPE_FAST_TIMER_VIEW;
00268 }
00269
00270 LLString LLFastTimerView::getWidgetTag() const
00271 {
00272 return LL_FAST_TIMER_VIEW_TAG;
00273 }
00274
00275 BOOL LLFastTimerView::handleRightMouseDown(S32 x, S32 y, MASK mask)
00276 {
00277 if (mBarRect.pointInRect(x, y))
00278 {
00279 S32 bar_idx = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight());
00280 bar_idx = llclamp(bar_idx, 0, MAX_VISIBLE_HISTORY);
00281 mPrintStats = bar_idx;
00282
00283 }
00284 return FALSE;
00285 }
00286
00287 S32 LLFastTimerView::getLegendIndex(S32 y)
00288 {
00289 S32 idx = (mRect.getHeight() - y) / ((S32) LLFontGL::sMonospace->getLineHeight()+2) - 5;
00290 if (idx >= 0 && idx < FTV_DISPLAY_NUM)
00291 {
00292 return ft_display_idx[idx];
00293 }
00294
00295 return -1;
00296 }
00297
00298 BOOL LLFastTimerView::handleMouseDown(S32 x, S32 y, MASK mask)
00299 {
00300 if (x < mBarRect.mLeft)
00301 {
00302 S32 legend_index = getLegendIndex(y);
00303 if (legend_index >= 0 && legend_index < FTV_DISPLAY_NUM)
00304 {
00305 S32 disabled = ft_display_table[legend_index].disabled;
00306 if (++disabled > 2)
00307 disabled = 0;
00308 ft_display_table[legend_index].disabled = disabled;
00309 S32 level = ft_display_table[legend_index].level;
00310
00311
00312 legend_index++;
00313 while (legend_index < FTV_DISPLAY_NUM && ft_display_table[legend_index].level > level)
00314 {
00315 ft_display_table[legend_index].disabled = disabled ? 3 : 0;
00316 legend_index++;
00317 }
00318 }
00319 }
00320 else if (mask & MASK_ALT)
00321 {
00322 if (mask & MASK_SHIFT)
00323 mSubtractHidden = !mSubtractHidden;
00324 else
00325 mDisplayCalls = !mDisplayCalls;
00326 }
00327 else if (mask & MASK_SHIFT)
00328 {
00329 if (++mDisplayMode > 3)
00330 mDisplayMode = 0;
00331 }
00332 else if (mask & MASK_CONTROL)
00333 {
00334 if (++mDisplayCenter > 2)
00335 mDisplayCenter = 0;
00336 }
00337 else
00338 {
00339
00340 LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
00341
00342 if (!LLFastTimer::sPauseHistory)
00343 {
00344 mScrollIndex = 0;
00345 }
00346 }
00347
00348 return TRUE;
00349 }
00350
00351 BOOL LLFastTimerView::handleMouseUp(S32 x, S32 y, MASK mask)
00352 {
00353 return FALSE;
00354 }
00355
00356
00357 BOOL LLFastTimerView::handleHover(S32 x, S32 y, MASK mask)
00358 {
00359 if(LLFastTimer::sPauseHistory && mBarRect.pointInRect(x, y))
00360 {
00361 mHoverIndex = -1;
00362 mHoverBarIndex = MAX_VISIBLE_HISTORY - ((y - mBarRect.mBottom) * (MAX_VISIBLE_HISTORY + 2) / mBarRect.getHeight());
00363 if (mHoverBarIndex == 0)
00364 {
00365 return TRUE;
00366 }
00367 else if (mHoverBarIndex == -1)
00368 {
00369 mHoverBarIndex = 0;
00370 }
00371 for (S32 i = 0; i < FTV_DISPLAY_NUM; i++)
00372 {
00373 if (x > mBarStart[mHoverBarIndex * FTV_DISPLAY_NUM + i] &&
00374 x < mBarEnd[mHoverBarIndex * FTV_DISPLAY_NUM + i] &&
00375 ft_display_table[i].disabled <= 1)
00376 {
00377 mHoverIndex = i;
00378 }
00379 }
00380 }
00381 else if (x < mBarRect.mLeft)
00382 {
00383 S32 legend_index = getLegendIndex(y);
00384 if (legend_index >= 0 && legend_index < FTV_DISPLAY_NUM)
00385 {
00386 mHoverIndex = legend_index;
00387 }
00388 }
00389
00390 return FALSE;
00391 }
00392
00393 BOOL LLFastTimerView::handleScrollWheel(S32 x, S32 y, S32 clicks)
00394 {
00395 if (getVisible() && pointInView(x, y))
00396 {
00397 LLFastTimer::sPauseHistory = TRUE;
00398 mScrollIndex = llclamp(mScrollIndex - clicks,
00399 0, llmin(LLFastTimer::sLastFrameIndex, (S32)LLFastTimer::FTM_HISTORY_NUM-MAX_VISIBLE_HISTORY));
00400 return TRUE;
00401 }
00402 return FALSE;
00403 }
00404
00405 void LLFastTimerView::draw()
00406 {
00407 LLFastTimer t(LLFastTimer::FTM_RENDER_TIMER);
00408
00409 std::string tdesc;
00410
00411 F64 clock_freq = (F64)LLFastTimer::countsPerSecond();
00412 F64 iclock_freq = 1000.0 / clock_freq;
00413
00414 S32 margin = 10;
00415 S32 height = (S32) (gViewerWindow->getVirtualWindowRect().getHeight()*0.75f);
00416 S32 width = (S32) (gViewerWindow->getVirtualWindowRect().getWidth() * 0.75f);
00417
00418 mRect.setLeftTopAndSize(mRect.mLeft, mRect.mTop, width, height);
00419
00420 S32 left, top, right, bottom;
00421 S32 x, y, barw, barh, dx, dy;
00422 S32 texth, textw;
00423 LLViewerImage* box_imagep = gImageList.getImage(LLUUID(gViewerArt.getString("rounded_square.tga")), MIPMAP_FALSE, TRUE);
00424
00425
00426
00427 {
00428 S32 display_timer[LLFastTimer::FTM_NUM_TYPES];
00429 S32 hidx = LLFastTimer::sLastFrameIndex % LLFastTimer::FTM_HISTORY_NUM;
00430 for (S32 i=0; i < LLFastTimer::FTM_NUM_TYPES; i++)
00431 {
00432 display_timer[i] = 0;
00433 }
00434 for (S32 i=0; i < FTV_DISPLAY_NUM; i++)
00435 {
00436 S32 tidx = ft_display_table[i].timer;
00437 display_timer[tidx] = 1;
00438 }
00439 LLFastTimer::sCountHistory[hidx][LLFastTimer::FTM_OTHER] = 0;
00440 LLFastTimer::sCallHistory[hidx][LLFastTimer::FTM_OTHER] = 0;
00441 for (S32 tidx = 0; tidx < LLFastTimer::FTM_NUM_TYPES; tidx++)
00442 {
00443 U64 counts = LLFastTimer::sCountHistory[hidx][tidx];
00444 if (counts > 0 && display_timer[tidx] == 0)
00445 {
00446 LLFastTimer::sCountHistory[hidx][LLFastTimer::FTM_OTHER] += counts;
00447 LLFastTimer::sCallHistory[hidx][LLFastTimer::FTM_OTHER] += 1;
00448 }
00449 }
00450 LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] = 0;
00451 LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] = 0;
00452 for (S32 h = 0; h < LLFastTimer::FTM_HISTORY_NUM; h++)
00453 {
00454 LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] += LLFastTimer::sCountHistory[h][LLFastTimer::FTM_OTHER];
00455 LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] += LLFastTimer::sCallHistory[h][LLFastTimer::FTM_OTHER];
00456 }
00457 LLFastTimer::sCountAverage[LLFastTimer::FTM_OTHER] /= LLFastTimer::FTM_HISTORY_NUM;
00458 LLFastTimer::sCallAverage[LLFastTimer::FTM_OTHER] /= LLFastTimer::FTM_HISTORY_NUM;
00459 }
00460
00461
00462 {
00463 LLGLSNoTexture gls_ui_no_texture;
00464 gl_rect_2d(0, mRect.getHeight(), mRect.getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
00465 }
00466
00467 S32 xleft = margin;
00468 S32 ytop = margin;
00469
00470
00471 {
00472
00473 x = xleft;
00474 y = height - ytop;
00475 texth = (S32)LLFontGL::sMonospace->getLineHeight();
00476
00477 char modedesc[][32] = {
00478 "2 x Average ",
00479 "Max ",
00480 "Recent Max ",
00481 "100 ms "
00482 };
00483 char centerdesc[][32] = {
00484 "Left ",
00485 "Centered ",
00486 "Ordered "
00487 };
00488
00489 tdesc = llformat("Full bar = %s [Click to pause/reset] [SHIFT-Click to toggle]",modedesc[mDisplayMode]);
00490 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
00491
00492 textw = LLFontGL::sMonospace->getWidth(tdesc);
00493
00494 x = xleft, y -= (texth + 2);
00495 tdesc = llformat("Justification = %s [CTRL-Click to toggle]",centerdesc[mDisplayCenter]);
00496 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
00497 y -= (texth + 2);
00498
00499 LLFontGL::sMonospace->renderUTF8("[Right-Click log selected] [ALT-Click toggle counts] [ALT-SHIFT-Click sub hidden]",
00500 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
00501 y -= (texth + 2);
00502 }
00503
00504
00505 S32 histmax = llmin(LLFastTimer::sLastFrameIndex+1, MAX_VISIBLE_HISTORY);
00506 U64 ticks_sum[LLFastTimer::FTM_HISTORY_NUM+1][FTV_DISPLAY_NUM];
00507 for (S32 j=-1; j<LLFastTimer::FTM_HISTORY_NUM; j++)
00508 {
00509 S32 hidx;
00510 if (j >= 0)
00511 hidx = (LLFastTimer::sLastFrameIndex+j) % LLFastTimer::FTM_HISTORY_NUM;
00512 else
00513 hidx = -1;
00514
00515
00516 for (S32 i=0; i < FTV_DISPLAY_NUM; i++)
00517 {
00518 if (mSubtractHidden && ft_display_table[i].disabled > 1)
00519 {
00520 continue;
00521 }
00522
00523 S32 tidx = ft_display_table[i].timer;
00524 if (hidx >= 0)
00525 ticks_sum[j+1][i] = LLFastTimer::sCountHistory[hidx][tidx];
00526 else
00527 ticks_sum[j+1][i] = LLFastTimer::sCountAverage[tidx];
00528 S32 pidx = ft_display_table[i].parent;
00529
00530 while (pidx >= 0)
00531 {
00532 ticks_sum[j+1][pidx] += ticks_sum[j+1][i];
00533 pidx = ft_display_table[pidx].parent;
00534 }
00535 }
00536 }
00537
00538
00539
00540 S32 legendwidth = 0;
00541 xleft = margin;
00542 ytop = y;
00543
00544 y -= (texth + 2);
00545
00546 S32 cur_line = 0;
00547 S32 display_line[FTV_DISPLAY_NUM];
00548 for (S32 i=0; i<FTV_DISPLAY_NUM; i++)
00549 {
00550 S32 disabled = ft_display_table[i].disabled;
00551 if (disabled == 3)
00552 {
00553 continue;
00554 }
00555 display_line[i] = cur_line;
00556 ft_display_idx[cur_line] = i;
00557 cur_line++;
00558 S32 level = ft_display_table[i].level;
00559 S32 parent = ft_display_table[i].parent;
00560
00561 x = xleft;
00562
00563 left = x; right = x + texth;
00564 top = y; bottom = y - texth;
00565 S32 scale_offset = 0;
00566 if (i == mHoverIndex)
00567 {
00568 scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 2.f);
00569 }
00570 gl_rect_2d(left - scale_offset, top + scale_offset, right + scale_offset, bottom - scale_offset, *ft_display_table[i].color);
00571
00572 int tidx = ft_display_table[i].timer;
00573 F32 ms = 0;
00574 S32 calls = 0;
00575 if (mHoverBarIndex > 0 && mHoverIndex >= 0)
00576 {
00577 S32 hidx = (LLFastTimer::sLastFrameIndex + (mHoverBarIndex - 1) - mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM;
00578 S32 bidx = LLFastTimer::FTM_HISTORY_NUM - mScrollIndex - mHoverBarIndex;
00579 U64 ticks = ticks_sum[bidx+1][i];
00580 ms = (F32)((F64)ticks * iclock_freq);
00581 calls = (S32)LLFastTimer::sCallHistory[hidx][tidx];
00582 }
00583 else
00584 {
00585 U64 ticks = ticks_sum[0][i];
00586 ms = (F32)((F64)ticks * iclock_freq);
00587 calls = (S32)LLFastTimer::sCallAverage[tidx];
00588 }
00589 if (mDisplayCalls)
00590 {
00591 tdesc = llformat("%s (%d)",ft_display_table[i].desc,calls);
00592 }
00593 else
00594 {
00595 tdesc = llformat("%s [%.1f]",ft_display_table[i].desc,ms);
00596 }
00597 dx = (texth+4) + level*8;
00598
00599 LLColor4 color = disabled > 1 ? LLColor4::grey : LLColor4::white;
00600 if (level > 0)
00601 {
00602 S32 line_start_y = (top + bottom) / 2;
00603 S32 line_end_y = line_start_y + ((texth + 2) * (display_line[i] - display_line[parent])) - (texth / 2);
00604 gl_line_2d(x + dx - 8, line_start_y, x + dx, line_start_y, color);
00605 S32 line_x = x + (texth + 4) + ((level - 1) * 8);
00606 gl_line_2d(line_x, line_start_y, line_x, line_end_y, color);
00607 if (disabled == 1)
00608 {
00609 gl_line_2d(line_x+4, line_start_y-3, line_x+4, line_start_y+4, color);
00610 }
00611 }
00612
00613 x += dx;
00614 BOOL is_child_of_hover_item = (i == mHoverIndex);
00615 S32 next_parent = ft_display_table[i].parent;
00616 while(!is_child_of_hover_item && next_parent >= 0)
00617 {
00618 is_child_of_hover_item = (mHoverIndex == next_parent);
00619 next_parent = ft_display_table[next_parent].parent;
00620 }
00621
00622 if (is_child_of_hover_item)
00623 {
00624 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP, LLFontGL::BOLD);
00625 }
00626 else
00627 {
00628 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, color, LLFontGL::LEFT, LLFontGL::TOP);
00629 }
00630 y -= (texth + 2);
00631
00632 textw = dx + LLFontGL::sMonospace->getWidth(ft_display_table[i].desc) + 40;
00633 if (textw > legendwidth)
00634 legendwidth = textw;
00635 }
00636 for (S32 i=cur_line; i<FTV_DISPLAY_NUM; i++)
00637 {
00638 ft_display_idx[i] = -1;
00639 }
00640 xleft += legendwidth + 8;
00641
00642
00643
00644 mBarRect.mLeft = xleft;
00645 mBarRect.mRight = mRect.mRight - xleft;
00646 mBarRect.mTop = ytop - ((S32)LLFontGL::sMonospace->getLineHeight() + 4);
00647 mBarRect.mBottom = margin + LINE_GRAPH_HEIGHT;
00648
00649 y = ytop;
00650 barh = (ytop - margin - LINE_GRAPH_HEIGHT) / (MAX_VISIBLE_HISTORY + 2);
00651 dy = barh>>2;
00652 if (dy < 1) dy = 1;
00653 barh -= dy;
00654 barw = width - xleft - margin;
00655
00656
00657 if (LLFastTimer::sLastFrameIndex >= 0)
00658 {
00659 U64 totalticks;
00660 if (!LLFastTimer::sPauseHistory)
00661 {
00662 U64 ticks = 0;
00663 int hidx = (LLFastTimer::sLastFrameIndex - mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM;
00664 for (S32 i=0; i<FTV_DISPLAY_NUM; i++)
00665 {
00666 if (mSubtractHidden && ft_display_table[i].disabled > 1)
00667 {
00668 continue;
00669 }
00670 int tidx = ft_display_table[i].timer;
00671 ticks += LLFastTimer::sCountHistory[hidx][tidx];
00672 }
00673 if (LLFastTimer::sCurFrameIndex >= 10)
00674 {
00675 U64 framec = LLFastTimer::sCurFrameIndex;
00676 U64 avg = (U64)mAvgCountTotal;
00677 mAvgCountTotal = (avg*framec + ticks) / (framec + 1);
00678 if (ticks > mMaxCountTotal)
00679 {
00680 mMaxCountTotal = ticks;
00681 }
00682 }
00683 #if 1
00684 if (ticks < mAvgCountTotal/100 || ticks > mAvgCountTotal*100)
00685 LLFastTimer::sResetHistory = 1;
00686 #endif
00687 if (LLFastTimer::sCurFrameIndex < 10 || LLFastTimer::sResetHistory)
00688 {
00689 mAvgCountTotal = ticks;
00690 mMaxCountTotal = ticks;
00691 }
00692 }
00693
00694 if (mDisplayMode == 0)
00695 {
00696 totalticks = mAvgCountTotal*2;
00697 }
00698 else if (mDisplayMode == 1)
00699 {
00700 totalticks = mMaxCountTotal;
00701 }
00702 else if (mDisplayMode == 2)
00703 {
00704
00705 totalticks = 0;
00706 for (S32 j=0; j<histmax; j++)
00707 {
00708 U64 ticks = 0;
00709 for (S32 i=0; i<FTV_DISPLAY_NUM; i++)
00710 {
00711 if (mSubtractHidden && ft_display_table[i].disabled > 1)
00712 {
00713 continue;
00714 }
00715 int tidx = ft_display_table[i].timer;
00716 ticks += LLFastTimer::sCountHistory[j][tidx];
00717 }
00718 if (ticks > totalticks)
00719 totalticks = ticks;
00720 }
00721 }
00722 else
00723 {
00724 totalticks = (U64)(clock_freq * .1);
00725 }
00726
00727
00728 {
00729 U32 ms = (U32)((F64)totalticks * iclock_freq) ;
00730
00731 tdesc = llformat("%.1f ms |", (F32)ms*.25f);
00732 x = xleft + barw/4 - LLFontGL::sMonospace->getWidth(tdesc);
00733 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white,
00734 LLFontGL::LEFT, LLFontGL::TOP);
00735
00736 tdesc = llformat("%.1f ms |", (F32)ms*.50f);
00737 x = xleft + barw/2 - LLFontGL::sMonospace->getWidth(tdesc);
00738 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white,
00739 LLFontGL::LEFT, LLFontGL::TOP);
00740
00741 tdesc = llformat("%.1f ms |", (F32)ms*.75f);
00742 x = xleft + (barw*3)/4 - LLFontGL::sMonospace->getWidth(tdesc);
00743 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white,
00744 LLFontGL::LEFT, LLFontGL::TOP);
00745
00746 tdesc = llformat( "%d ms |", ms);
00747 x = xleft + barw - LLFontGL::sMonospace->getWidth(tdesc);
00748 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white,
00749 LLFontGL::LEFT, LLFontGL::TOP);
00750 }
00751
00752 LLRect graph_rect;
00753
00754 {
00755 LLGLSNoTexture gls_ui_no_texture;
00756 glColor4f(0.5f,0.5f,0.5f,0.5f);
00757
00758 S32 by = y + 2;
00759
00760 y -= ((S32)LLFontGL::sMonospace->getLineHeight() + 4);
00761
00762
00763 gl_rect_2d(xleft-5, by, mRect.getWidth()-5, y+5, FALSE);
00764
00765
00766 gl_rect_2d(5, by, xleft-10, 5, FALSE);
00767
00768 by = y + 5;
00769
00770 gl_rect_2d(xleft-5, by, mRect.getWidth()-5, by-barh-dy-5, FALSE);
00771
00772 by -= barh*2+dy;
00773
00774
00775 gl_rect_2d(xleft-5, by, mRect.getWidth()-5, by-barh-dy-2, FALSE);
00776
00777 by -= barh+dy+1;
00778
00779
00780 gl_rect_2d(xleft-5, by, mRect.getWidth()-5, LINE_GRAPH_HEIGHT-barh-dy-2, FALSE);
00781
00782 by = LINE_GRAPH_HEIGHT-barh-dy-7;
00783
00784
00785 graph_rect = LLRect(xleft-5, by, mRect.getWidth()-5, 5);
00786
00787 gl_rect_2d(graph_rect, FALSE);
00788 }
00789
00790
00791
00792 LLViewerImage::bindTexture(box_imagep);
00793 for (S32 j=-1; j<histmax && y > LINE_GRAPH_HEIGHT; j++)
00794 {
00795 int sublevel_dx[FTV_DISPLAY_NUM+1];
00796 int sublevel_left[FTV_DISPLAY_NUM+1];
00797 int sublevel_right[FTV_DISPLAY_NUM+1];
00798 S32 tidx;
00799 if (j >= 0)
00800 {
00801 tidx = LLFastTimer::FTM_HISTORY_NUM - j - 1 - mScrollIndex;
00802 }
00803 else
00804 {
00805 tidx = -1;
00806 }
00807
00808 x = xleft;
00809
00810
00811 int xpos[FTV_DISPLAY_NUM+1];
00812 int deltax[FTV_DISPLAY_NUM+1];
00813 xpos[0] = xleft;
00814
00815 for (S32 i = 0; i < FTV_DISPLAY_NUM; i++)
00816 {
00817 if (ft_display_table[i].disabled > 1)
00818 {
00819 continue;
00820 }
00821
00822 F32 frac = (F32)ticks_sum[tidx+1][i] / (F32)totalticks;
00823
00824 dx = llround(frac * (F32)barw);
00825 deltax[i] = dx;
00826
00827 int level = ft_display_table[i].level;
00828 int parent = ft_display_table[i].parent;
00829 llassert(level < FTV_DISPLAY_NUM);
00830 llassert(parent < FTV_DISPLAY_NUM);
00831
00832 left = xpos[level];
00833
00834 S32 prev_idx = i - 1;
00835 while (prev_idx > 0)
00836 {
00837 if (ft_display_table[prev_idx].disabled <= 1)
00838 {
00839 break;
00840 }
00841 prev_idx--;
00842 }
00843 S32 next_idx = i + 1;
00844 while (next_idx < FTV_DISPLAY_NUM)
00845 {
00846 if (ft_display_table[next_idx].disabled <= 1)
00847 {
00848 break;
00849 }
00850 next_idx++;
00851 }
00852
00853 if (level == 0)
00854 {
00855 sublevel_left[level] = xleft;
00856 sublevel_dx[level] = dx;
00857 sublevel_right[level] = sublevel_left[level] + sublevel_dx[level];
00858 }
00859 else if (i==0 || ft_display_table[prev_idx].level < level)
00860 {
00861
00862
00863 U64 sublevelticks = ticks_sum[tidx+1][i];
00864 for (S32 k=i+1; k<FTV_DISPLAY_NUM; k++)
00865 {
00866 if (ft_display_table[k].level < level)
00867 break;
00868 if (ft_display_table[k].disabled <= 1 && ft_display_table[k].level == level)
00869 sublevelticks += ticks_sum[tidx+1][k];
00870 }
00871 F32 subfrac = (F32)sublevelticks / (F32)totalticks;
00872 sublevel_dx[level] = (int)(subfrac * (F32)barw + .5f);
00873
00874 if (mDisplayCenter == 1)
00875 {
00876 left += (deltax[parent] - sublevel_dx[level])/2;
00877 }
00878 else if (mDisplayCenter == 2)
00879 {
00880 left += (deltax[parent] - sublevel_dx[level]);
00881 }
00882
00883 sublevel_left[level] = left;
00884 sublevel_right[level] = sublevel_left[level] + sublevel_dx[level];
00885 }
00886
00887 right = left + dx;
00888 xpos[level] = right;
00889 xpos[level+1] = left;
00890
00891 mBarStart[(j + 1) * FTV_DISPLAY_NUM + i] = left;
00892 mBarEnd[(j + 1) * FTV_DISPLAY_NUM + i] = right;
00893
00894 top = y;
00895 bottom = y - barh;
00896
00897 if (right > left)
00898 {
00899
00900 LLColor4 color = *ft_display_table[i].color;
00901 S32 scale_offset = 0;
00902
00903 BOOL is_child_of_hover_item = (i == mHoverIndex);
00904 S32 next_parent = ft_display_table[i].parent;
00905 while(!is_child_of_hover_item && next_parent >= 0)
00906 {
00907 is_child_of_hover_item = (mHoverIndex == next_parent);
00908 next_parent = ft_display_table[next_parent].parent;
00909 }
00910
00911 if (i == mHoverIndex)
00912 {
00913 scale_offset = llfloor(sinf(mHighlightTimer.getElapsedTimeF32() * 6.f) * 3.f);
00914
00915 }
00916 else if (mHoverIndex >= 0 && !is_child_of_hover_item)
00917 {
00918 color = lerp(color, LLColor4::grey, 0.8f);
00919 }
00920
00921 glColor4fv(color.mV);
00922 F32 start_fragment = llclamp((F32)(left - sublevel_left[level]) / (F32)sublevel_dx[level], 0.f, 1.f);
00923 F32 end_fragment = llclamp((F32)(right - sublevel_left[level]) / (F32)sublevel_dx[level], 0.f, 1.f);
00924 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);
00925
00926 }
00927
00928 }
00929 y -= (barh + dy);
00930 if (j < 0)
00931 y -= barh;
00932 }
00933
00934
00935 {
00936 LLGLSNoTexture no_texture;
00937 LLLocalClipRect clip(graph_rect);
00938
00939
00940 static U64 last_max = 0;
00941 static F32 alpha_interp = 0.f;
00942 U64 max_ticks = llmax(last_max, (U64) 1);
00943 F32 ms = (F32)((F64)max_ticks * iclock_freq);
00944
00945
00946 LLString tdesc = mDisplayCalls ?
00947 llformat("%d calls", max_ticks) :
00948 llformat("%4.2f ms", ms);
00949
00950 x = graph_rect.mRight - LLFontGL::sMonospace->getWidth(tdesc)-5;
00951 y = graph_rect.mTop - ((S32)LLFontGL::sMonospace->getLineHeight());
00952
00953 LLFontGL::sMonospace->renderUTF8(tdesc, 0, x, y, LLColor4::white,
00954 LLFontGL::LEFT, LLFontGL::TOP);
00955
00956
00957 {
00958 S32 first_frame = LLFastTimer::FTM_HISTORY_NUM - mScrollIndex;
00959 S32 last_frame = first_frame - MAX_VISIBLE_HISTORY;
00960
00961 F32 frame_delta = ((F32) (graph_rect.getWidth()))/(LLFastTimer::FTM_HISTORY_NUM-1);
00962
00963 F32 right = (F32) graph_rect.mLeft + frame_delta*first_frame;
00964 F32 left = (F32) graph_rect.mLeft + frame_delta*last_frame;
00965
00966 glColor4f(0.5f,0.5f,0.5f,0.3f);
00967 gl_rect_2d((S32) left, graph_rect.mTop, (S32) right, graph_rect.mBottom);
00968
00969 if (mHoverBarIndex >= 0)
00970 {
00971 S32 bar_frame = first_frame - mHoverBarIndex;
00972 F32 bar = (F32) graph_rect.mLeft + frame_delta*bar_frame;
00973
00974 glColor4f(0.5f,0.5f,0.5f,1);
00975
00976 glBegin(GL_LINES);
00977 glVertex2i((S32)bar, graph_rect.mBottom);
00978 glVertex2i((S32)bar, graph_rect.mTop);
00979 glEnd();
00980 }
00981 }
00982
00983 U64 cur_max = 0;
00984 for (S32 idx = 0; idx < FTV_DISPLAY_NUM; ++idx)
00985 {
00986 if (ft_display_table[idx].disabled > 1)
00987 {
00988 continue;
00989 }
00990
00991
00992 if (mHoverIndex == idx)
00993 {
00994 glLineWidth(3);
00995 }
00996
00997 F32* col = ft_display_table[idx].color->mV;
00998
00999 F32 alpha = 1.f;
01000
01001 if (mHoverIndex >= 0 &&
01002 idx != mHoverIndex)
01003 {
01004 if (ft_display_table[idx].parent != mHoverIndex)
01005 {
01006 alpha = alpha_interp;
01007 }
01008 }
01009
01010 glColor4f(col[0], col[1], col[2], alpha);
01011 glBegin(GL_LINE_STRIP);
01012 for (U32 j = 0; j < LLFastTimer::FTM_HISTORY_NUM; j++)
01013 {
01014 U64 ticks = ticks_sum[j+1][idx];
01015 if (mDisplayCalls)
01016 {
01017 S32 tidx = ft_display_table[idx].timer;
01018 S32 hidx = (LLFastTimer::sLastFrameIndex + j) % LLFastTimer::FTM_HISTORY_NUM;
01019 ticks = (S32)LLFastTimer::sCallHistory[hidx][tidx];
01020 }
01021
01022 if (alpha == 1.f)
01023 {
01024 cur_max = llmax(cur_max, ticks);
01025 }
01026 F32 x = graph_rect.mLeft + ((F32) (graph_rect.getWidth()))/(LLFastTimer::FTM_HISTORY_NUM-1)*j;
01027 F32 y = graph_rect.mBottom + (F32) graph_rect.getHeight()/max_ticks*ticks;
01028 glVertex2f(x,y);
01029 }
01030 glEnd();
01031
01032 if (mHoverIndex == idx)
01033 {
01034 glLineWidth(1);
01035 }
01036 }
01037
01038
01039 F32 dt = gFrameIntervalSeconds*3.f;
01040 last_max = (U64) ((F32) last_max + ((F32) cur_max- (F32) last_max) * dt);
01041 F32 alpha_target = last_max > cur_max ?
01042 llmin((F32) last_max/ (F32) cur_max - 1.f,1.f) :
01043 llmin((F32) cur_max/ (F32) last_max - 1.f,1.f);
01044
01045 alpha_interp = alpha_interp + (alpha_target-alpha_interp) * dt;
01046
01047 }
01048 }
01049
01050
01051 if (mPrintStats >= 0)
01052 {
01053 LLString legend_stat;
01054 S32 stat_num;
01055 S32 first = 1;
01056 for (stat_num = 0; stat_num < FTV_DISPLAY_NUM; stat_num++)
01057 {
01058 if (ft_display_table[stat_num].disabled > 1)
01059 continue;
01060 if (!first)
01061 legend_stat += ", ";
01062 first=0;
01063 legend_stat += ft_display_table[stat_num].desc;
01064 }
01065 llinfos << legend_stat << llendl;
01066
01067 LLString timer_stat;
01068 first = 1;
01069 for (stat_num = 0; stat_num < FTV_DISPLAY_NUM; stat_num++)
01070 {
01071 S32 disabled = ft_display_table[stat_num].disabled;
01072 if (disabled > 1)
01073 continue;
01074 if (!first)
01075 timer_stat += ", ";
01076 first=0;
01077 U64 ticks;
01078 S32 tidx = ft_display_table[stat_num].timer;
01079 if (mPrintStats > 0)
01080 {
01081 S32 hidx = (LLFastTimer::sLastFrameIndex+(mPrintStats-1)-mScrollIndex) % LLFastTimer::FTM_HISTORY_NUM;
01082 ticks = disabled >= 1 ? ticks_sum[mPrintStats][stat_num] : LLFastTimer::sCountHistory[hidx][tidx];
01083 }
01084 else
01085 {
01086 ticks = disabled >= 1 ? ticks_sum[0][stat_num] : LLFastTimer::sCountAverage[tidx];
01087 }
01088 F32 ms = (F32)((F64)ticks * iclock_freq);
01089
01090 timer_stat += llformat("%.1f",ms);
01091 }
01092 llinfos << timer_stat << llendl;
01093 mPrintStats = -1;
01094 }
01095
01096 mHoverIndex = -1;
01097 mHoverBarIndex = -1;
01098
01099 LLView::draw();
01100 }
01101
01102 F64 LLFastTimerView::getTime(LLFastTimer::EFastTimerType tidx)
01103 {
01104
01105 S32 i;
01106 for (i=0; i<FTV_DISPLAY_NUM; i++)
01107 {
01108 if (tidx == ft_display_table[i].timer)
01109 {
01110 break;
01111 }
01112 }
01113
01114 if (i == FTV_DISPLAY_NUM)
01115 {
01116
01117
01118 llwarns << "Timer type " << tidx << " not known." << llendl;
01119 return F64(0.0);
01120 }
01121
01122 S32 table_idx = i;
01123
01124
01125 U64 ticks = LLFastTimer::sCountAverage[tidx];
01126 S32 level = ft_display_table[table_idx].level;
01127 for (i=table_idx+1; i<FTV_DISPLAY_NUM; i++)
01128 {
01129 if (ft_display_table[i].level <= level)
01130 {
01131 break;
01132 }
01133 ticks += LLFastTimer::sCountAverage[ft_display_table[i].timer];
01134 }
01135
01136 return (F64)ticks / (F64)LLFastTimer::countsPerSecond();
01137 }