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 "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; // initialized to 0
00061         int level; // calculated based on desc
00062         int parent; // calculated
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 // green(6), blue, yellow, orange, pink(2), cyan
00075 // red (5) magenta (4)
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 //      { LLFastTimer::FTM_TEMP1,                               "   Blur",                      &LLColor4::red1, 0 },
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 //      { LLFastTimer::FTM_TEMP5,                               "    Check",    &LLColor4::red1, 1},
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 //      { LLFastTimer::FTM_LOAD_AVATAR,                 "       Load Avatar", &LLColor4::pink2, 0 },
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 //      { LLFastTimer::FTM_IDLE_CB,                             "  Callbacks",          &LLColor4::pink1, 0 },
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 //      { LLFastTimer::FTM_RENDER_FONTS,                "   Fonts",                     &LLColor4::pink1, 0 },
00183 //      { LLFastTimer::FTM_UPDATE_TEXTURES,             "  Textures",           &LLColor4::pink2, 0 },
00184         { LLFastTimer::FTM_SWAP,                                "  Swap",                       &LLColor4::pink1, 0 },
00185         { LLFastTimer::FTM_CLIENT_COPY,                 "  Client Copy",        &LLColor4::red1, 1},
00186         
00187 //      { LLFastTimer::FTM_TEMP1,                               " Temp1",                       &LLColor4::red1, 0 },
00188 //      { LLFastTimer::FTM_TEMP2,                               " Temp2",                       &LLColor4::magenta1, 0 },
00189 //      { LLFastTimer::FTM_TEMP3,                               " Temp3",                       &LLColor4::red2, 0 },
00190 //      { LLFastTimer::FTM_TEMP4,                               " Temp4",                       &LLColor4::magenta2, 0 },
00191 //      { LLFastTimer::FTM_TEMP5,                               " Temp5",                       &LLColor4::red3, 0 },
00192 //      { LLFastTimer::FTM_TEMP6,                               " Temp6",                       &LLColor4::magenta3, 0 },
00193 //      { LLFastTimer::FTM_TEMP7,                               " Temp7",                       &LLColor4::red4, 0 },
00194 //      { LLFastTimer::FTM_TEMP8,                               " Temp8",                       &LLColor4::magenta4, 0 },
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]; // line of table entry for display purposes (for collapse)
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         // One-time setup
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 //              return TRUE; // for now, pass all mouse events through
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                         // propagate enable/disable to all children
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                 // pause/unpause
00340                 LLFastTimer::sPauseHistory = !LLFastTimer::sPauseHistory;
00341                 // reset scroll to bottom when unpausing
00342                 if (!LLFastTimer::sPauseHistory)
00343                 {
00344                         mScrollIndex = 0;
00345                 }
00346         }
00347         // SJB: Don't pass mouse clicks through the display
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         // Make sure all timers are accounted for
00426         // Set 'FTM_OTHER' to unaccounted ticks last frame
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         // Draw the window background
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         // Draw some help
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         // Calc the total ticks
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                 // calculate tick info by adding child ticks to parents
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                         // Get ticks
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                         // Add ticks to parents
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         // Draw the legend
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; // skip row
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]; // : LLFastTimer::sCountHistory[hidx][tidx];
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         // ytop = ytop;
00642 
00643         // update rectangle that includes timer bars
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; // spacing between bars
00652         if (dy < 1) dy = 1;
00653         barh -= dy;
00654         barw = width - xleft - margin;
00655 
00656         // Draw the history bars
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                         // Calculate the max total ticks for the current history
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); // 100 ms
00725                 }
00726                 
00727                 // Draw MS ticks
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                 // Draw borders
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                         //heading
00763                         gl_rect_2d(xleft-5, by, mRect.getWidth()-5, y+5, FALSE);
00764 
00765                         //tree view
00766                         gl_rect_2d(5, by, xleft-10, 5, FALSE);
00767 
00768                         by = y + 5;
00769                         //average bar
00770                         gl_rect_2d(xleft-5, by, mRect.getWidth()-5, by-barh-dy-5, FALSE);
00771                         
00772                         by -= barh*2+dy;
00773                         
00774                         //current frame bar
00775                         gl_rect_2d(xleft-5, by, mRect.getWidth()-5, by-barh-dy-2, FALSE);
00776                         
00777                         by -= barh+dy+1;
00778                         
00779                         //history bars
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                         //line graph
00785                         graph_rect = LLRect(xleft-5, by, mRect.getWidth()-5, 5);
00786                         
00787                         gl_rect_2d(graph_rect, FALSE);
00788                 }
00789                 
00790                 // Draw bars for each history entry
00791                 // Special: -1 = show running average
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                         // draw the bars for each stat
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                                         // If we are the first entry at a new sublevel block, calc the
00862                                         //   total width of this sublevel and modify left to align block.
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) // center aligned
00875                                         {
00876                                                 left += (deltax[parent] - sublevel_dx[level])/2;
00877                                         }
00878                                         else if (mDisplayCenter == 2) // right aligned
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                                         //U32 rounded_edges = 0;
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                                                 //color = lerp(color, LLColor4::black, -0.4f);
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                 //draw line graph history
00935                 {
00936                         LLGLSNoTexture no_texture;
00937                         LLLocalClipRect clip(graph_rect);
00938                         
00939                         //normalize based on last frame's maximum
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                         //display y-axis range
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                         //highlight visible range
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                                 {       //skip disabled timers
00988                                         continue;
00989                                 }
00990                                 
00991                                 //fatten highlighted timer
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                                 {       //fade out non-hihglighted timers
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                                         { //normalize to highlighted timer
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                         //interpolate towards new maximum
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         // Output stats for clicked bar to log
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         // Find table index
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                 // walked off the end of ft_display_table without finding
01117                 // the desired timer type
01118                 llwarns << "Timer type " << tidx << " not known." << llendl;
01119                 return F64(0.0);
01120         }
01121 
01122         S32 table_idx = i;
01123         
01124         // Add child ticks to parent
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 }

Generated on Thu Jul 1 06:08:30 2010 for Second Life Viewer by  doxygen 1.4.7