llfasttimerview.cpp

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

Generated on Fri May 16 08:33:21 2008 for SecondLife by  doxygen 1.5.5