Files
SingularityViewer/indra/newview/llframestatview.cpp

385 lines
9.8 KiB
C++

/**
* @file llframestatview.cpp
* @brief LLFrameStatView class implementation
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llframestatview.h"
#include "llframestats.h"
#include "llrect.h"
#include "llerror.h"
#include "llgl.h"
#include "llmath.h"
#include "llfontgl.h"
#include "llui.h"
#include "llviewercontrol.h"
#include "llstat.h"
LLFrameStatView::LLFrameStatView(const std::string& name, const LLRect& rect)
: LLView(name, rect, TRUE)
{
setVisible(FALSE);
mNumStats = 0;
mTotalTime = 0.05f;
mTickSpacing = 0.01f;
mLabelSpacing = 0.05f;
mShowPercent = TRUE;
mCenterOn = 0;
}
LLFrameStatView::~LLFrameStatView()
{
// Children all cleaned up by default view destructor.
}
void LLFrameStatView::setup(const LLFrameStats &frame_stats)
{
S32 i;
for (i = 0; i < LLFrameStats::NUM_STATS; i++)
{
addStat(&gFrameStats.getStat(i),
gFrameStats.getStatLabel(i),
gFrameStats.getStatColor(i));
}
}
BOOL LLFrameStatView::handleMouseDown(S32 x, S32 y, MASK mask)
{
mShowPercent = !mShowPercent;
return TRUE;
}
BOOL LLFrameStatView::handleMouseUp(S32 x, S32 y, MASK mask)
{
return TRUE;
}
BOOL LLFrameStatView::handleHover(S32 x, S32 y, MASK mask)
{
return FALSE;
}
void LLFrameStatView::draw()
{
S32 i;
S32 j;
LLStat *statp;
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
statp = mStats[0];
if (!statp)
{
return;
}
S32 num_bins = llmin(statp->getNumValues(), (U32)32);
F32 total_width = getRect().getWidth() - 20.f;
F32 total_height = getRect().getHeight() - 30.f;
S32 left, top, right, bottom;
F32 key_height = 16;
S32 bar_spacing = 2;
F32 time_scale = total_width / mTotalTime;
// Draw the window background
gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f));
// Render the key
left = 10;
top = getRect().getHeight() - 10;
BOOL is_active[MAX_STATS];
S32 bin = mStats[0]->getCurBin() - 1;
if (bin < 0)
{
bin += mStats[0]->getNumBins();
}
F64 min_last_time = mStats[0]->getBinTime(bin);
for (i = 0; i < mNumStats; i++)
{
if (mStats[i]->getCurrentTime() >= min_last_time)
{
is_active[i] = TRUE;
}
else
{
is_active[i] = FALSE;
}
}
S32 cur_center = mCenterOn;
if (!is_active[mCenterOn])
{
for (i = 0; i < mNumStats; i++)
{
if (is_active[i])
{
cur_center = i;
break;
}
}
}
for (i = 0; i < mNumStats; i++)
{
// Draw the color key.
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
gl_rect_2d(left, top - 2, left + 10, top - 12, mColors[i]);
left = left + 15;
// Draw the label.
LLFontGL::getFontMonospace()->renderUTF8(mLabels[i], 0, left, top,
LLColor4(1.f, 1.f, 1.f, 1.f),
LLFontGL::LEFT, LLFontGL::TOP);
left = left + LLFontGL::getFontMonospace()->getWidth(mLabels[i]) + 10;
if ((i + 1) < mNumStats)
{
if ((left + LLFontGL::getFontMonospace()->getWidth(mLabels[i+1])) > (getRect().getWidth() - 10))
{
left = 10;
top -= llfloor(LLFontGL::getFontMonospace()->getLineHeight());
key_height += LLFontGL::getFontMonospace()->getLineHeight();
}
}
}
top -= llfloor(LLFontGL::getFontMonospace()->getLineHeight());
bottom = top - llfloor(LLFontGL::getFontMonospace()->getLineHeight());
F32 total_time = 0.f;
F32 bin_means[32];
key_height += 20;
// Draw the "Average" bar
// Draw ticks for the "Average bar"
F32 tick_value;
std::string tick_label;
for (tick_value = 0; tick_value <= 100; tick_value += 10)
{
left = 10 + llfloor(tick_value*(total_width/100.f));
right = left + 1;
gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.2f));
}
// Draw the tick labels (and big ticks).
bottom = bottom - 4;
for (tick_value = 0; tick_value <= 100; tick_value += 20)
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
left = 10 + llfloor(tick_value*(total_width/100.f));
right = left + 1;
gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.2f));
tick_label = llformat("%.2f", tick_value);
// draw labels for the tick marks
LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, left, bottom,
LLColor4(1.f, 1.f, 1.f, 0.5f),
LLFontGL::LEFT, LLFontGL::TOP);
}
for (i = 0; i < mNumStats; i++)
{
bin_means[i] = mStats[i]->getMeanDuration();
total_time += bin_means[i];
}
F32 time_frac = total_width / total_time;
F32 cur_left = .0f;
for (i = 0; i < mNumStats; i++)
{
F32 cur_right = cur_left + bin_means[i] * time_frac;
left = llfloor(cur_left) + 10;
right = llfloor(cur_right) + 10;
gl_rect_2d(left, top, right, bottom, mColors[i]);
cur_left = cur_right;
}
S32 bar_height = llmax(1, (S32)((total_height - bar_spacing*(num_bins-1) - key_height) / num_bins));
S32 graph_height = bar_height * num_bins + bar_spacing * num_bins - 1;
// Draw the tick marks.
top = getRect().getHeight() - llfloor(key_height) - 20;
bottom = top - graph_height - 2;
// Render the ticks and labels
if (mShowPercent)
{
for (tick_value = 0; tick_value <= 100; tick_value += 10)
{
left = 10 + llfloor(tick_value*(total_width/100.f));
right = left + 1;
gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.1f));
}
// Draw the tick labels (and big ticks).
bottom = top - graph_height - 4;
for (tick_value = 0; tick_value <= 100; tick_value += 20)
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
left = 10 + llfloor(tick_value*(total_width/100.f));
right = left + 1;
gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.25f));
tick_label = llformat("%.2f", tick_value);
// draw labels for the tick marks
LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, left, bottom,
LLColor4(1.f, 1.f, 1.f, 0.5f),
LLFontGL::LEFT, LLFontGL::TOP);
}
}
else
{
for (tick_value = 0; tick_value <= mTotalTime; tick_value += mTickSpacing)
{
left = 10 + llfloor(tick_value*time_scale);
right = left + 1;
gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.1f));
}
// Draw the tick labels (and big ticks).
bottom = top - graph_height - 4;
for (tick_value = 0; tick_value <= mTotalTime; tick_value += mLabelSpacing)
{
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
left = 10 + llfloor(tick_value*time_scale);
right = left + 1;
gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.25f));
tick_label = llformat("%.2f", tick_value);
// draw labels for the tick marks
LLFontGL::getFontMonospace()->renderUTF8(tick_label, 0, left, bottom,
LLColor4(1.f, 1.f, 1.f, 0.5f),
LLFontGL::LEFT, LLFontGL::TOP);
}
}
// Draw the graph background
bottom = top - graph_height;
left = 10;
right = left + llfloor(total_width);
gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.25f));
F64 min_time = 0.f;
F64 max_time = 0.f;
// Determine which stats are active.
top = getRect().getHeight() - llfloor(key_height) - 20;
bottom = top - bar_height;
for (i = 0; i < 32; i++)
{
// Find the min time for this set of bins.
min_time = mStats[0]->getPrevBeginTime(i);
max_time = mStats[0]->getPrevBeginTime(i);
for (j = 0; j < mNumStats; j++)
{
if (is_active[j])
{
min_time = llmin(min_time, mStats[j]->getPrevBeginTime(i));
max_time = llmax(max_time, mStats[j]->getPrevTime(i));
}
}
if (mShowPercent)
{
for (j = 0; j < mNumStats; j++)
{
if (is_active[j])
{
statp = mStats[j];
F64 begin = statp->getPrevBeginTime(i) - min_time;
F64 end = statp->getPrevTime(i) - min_time;
F32 begin_frac = (F32)(begin/(max_time - min_time));
F32 end_frac = (F32)(end/(max_time - min_time));
left = llfloor(begin_frac * total_width) + 10;
right = llfloor(end_frac * total_width) + 10;
gl_rect_2d(left, top, right, bottom, mColors[j]);
}
}
}
else
{
F64 center_time = mStats[cur_center]->getPrevBeginTime(i);
center_time = min_time;
// Now, draw the bars for each stat
for (j = 0; j < mNumStats; j++)
{
if (is_active[j])
{
statp = mStats[j];
F64 begin = statp->getPrevBeginTime(i);
F64 end = statp->getPrevTime(i);
F32 begin_frac = (F32)(begin - center_time);
F32 end_frac = (F32)(end - center_time);
left = llfloor(begin_frac * time_scale) + 10;
right = llfloor(end_frac * time_scale) + 10;
gl_rect_2d(left, top, right, bottom, mColors[j]);
}
}
}
top = top - bar_height - bar_spacing;
bottom = top - bar_height;
}
LLView::draw();
}
void LLFrameStatView::addStat(LLStat *statp, const std::string& label, const LLColor4 &color)
{
if( mNumStats >= MAX_STATS )
{
LL_WARNS() << "LLFrameStatView::addStat - too many stats!" << LL_ENDL;
return;
}
mStats[mNumStats] = statp;
mColors[mNumStats] = color;
mLabels[mNumStats] = label;
mNumStats++;
}