Revamping PStats to support texture memory, etc.
This commit is contained in:
parent
f2009437ef
commit
e50b9eb36c
|
|
@ -20,7 +20,7 @@
|
|||
TypeHandle Character::_type_handle;
|
||||
|
||||
#ifndef CPPPARSER
|
||||
PStatCollector Character::_anim_pcollector("App:Animation", RGBColorf(1,0,1), 30);
|
||||
PStatCollector Character::_anim_pcollector("App:Animation");
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
#include <pStatTimer.h>
|
||||
|
||||
#ifndef CPPPARSER
|
||||
PStatCollector CollisionTraverser::_collisions_pcollector("App:Collisions", RGBColorf(1,0.5,0), 40);
|
||||
PStatCollector CollisionTraverser::_collisions_pcollector("App:Collisions");
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@
|
|||
#include <pointerTo.h>
|
||||
#include <renderRelation.h>
|
||||
#include <pointerTo.h>
|
||||
|
||||
#include <pStatCollector.h>
|
||||
|
||||
#include <set>
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@
|
|||
TypeHandle CullTraverser::_type_handle;
|
||||
|
||||
#ifndef CPPPARSER
|
||||
PStatCollector CullTraverser::_cull_pcollector("Cull", RGBColorf(0,1,0), 10);
|
||||
PStatCollector CullTraverser::_draw_pcollector("Draw", RGBColorf(1,0,0), 20);
|
||||
PStatCollector CullTraverser::_cull_pcollector("Cull");
|
||||
PStatCollector CullTraverser::_draw_pcollector("Draw");
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
#include <pStatCollector.h>
|
||||
|
||||
#ifndef CPPPARSER
|
||||
PStatCollector _dgraph_pcollector("App:Data Graph", RGBColorf(0.5,0.8,0.4), 30);
|
||||
PStatCollector _dgraph_pcollector("App:Data graph");
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -6,12 +6,21 @@
|
|||
#include "graphicsStateGuardian.h"
|
||||
#include "renderBuffer.h"
|
||||
#include "config_display.h"
|
||||
#include "textureContext.h"
|
||||
|
||||
#include <clockObject.h>
|
||||
#include <geomNode.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
#ifndef CPPPARSER
|
||||
PStatCollector GraphicsStateGuardian::_total_texusage_pcollector("Texture usage");
|
||||
PStatCollector GraphicsStateGuardian::_active_texusage_pcollector("Texture usage:Active");
|
||||
PStatCollector GraphicsStateGuardian::_total_texmem_pcollector("Texture memory");
|
||||
PStatCollector GraphicsStateGuardian::_used_texmem_pcollector("Texture memory:In use");
|
||||
#endif
|
||||
|
||||
TypeHandle GraphicsStateGuardian::_type_handle;
|
||||
TypeHandle GraphicsStateGuardian::GsgWindow::_type_handle;
|
||||
|
||||
|
|
@ -420,7 +429,13 @@ end_decal(GeomNode *) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsStateGuardian::
|
||||
mark_prepared_texture(TextureContext *tc) {
|
||||
return _prepared_textures.insert(tc).second;
|
||||
bool prepared = _prepared_textures.insert(tc).second;
|
||||
#ifdef DO_PSTATS
|
||||
if (prepared) {
|
||||
_total_texusage_pcollector.add_level(tc->estimate_texture_memory() / 1048576.0);
|
||||
}
|
||||
#endif
|
||||
return prepared;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -428,22 +443,62 @@ mark_prepared_texture(TextureContext *tc) {
|
|||
// Access: Protected
|
||||
// Description: This is intended to be called from within
|
||||
// release_texture(). It removes the indicated
|
||||
// TextureContext pointer from the _prepared_textures set,
|
||||
// and returns true if it was successfully removed
|
||||
// TextureContext pointer from the _prepared_textures
|
||||
// set, and returns true if it was successfully removed
|
||||
// (i.e. it had been in the set).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool GraphicsStateGuardian::
|
||||
unmark_prepared_texture(TextureContext *tc) {
|
||||
return (_prepared_textures.erase(tc) != 0);
|
||||
bool removed = (_prepared_textures.erase(tc) != 0);
|
||||
#ifdef DO_PSTATS
|
||||
if (removed) {
|
||||
_total_texusage_pcollector.add_level(-(tc->estimate_texture_memory() / 1048576.0));
|
||||
}
|
||||
#endif
|
||||
return removed;
|
||||
}
|
||||
|
||||
void GraphicsStateGuardian::traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg) {
|
||||
for (Textures::const_iterator ti = _prepared_textures.begin(); ti != _prepared_textures.end();
|
||||
++ti) {
|
||||
bool bResult=(*pertex_callbackfn)(*ti,callback_arg);
|
||||
if(!bResult)
|
||||
return;
|
||||
}
|
||||
#ifdef DO_PSTATS
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::add_to_texture_record
|
||||
// Access: Protected
|
||||
// Description: Records that the indicated texture has been applied
|
||||
// this frame, and thus must be present in current
|
||||
// texture memory. This function is only used to update
|
||||
// the PStats current_texmem collector; it gets compiled
|
||||
// out if we aren't using PStats.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
add_to_texture_record(TextureContext *tc) {
|
||||
if (_current_textures.insert(tc).second) {
|
||||
_active_texusage_pcollector.add_level(tc->estimate_texture_memory() / 1048576.0);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GraphicsStateGuardian::clear_texture_record
|
||||
// Access: Protected
|
||||
// Description: Empties the texture record at the beginning of the
|
||||
// frame, in preparation for calling
|
||||
// add_to_texture_record() each time a texture is
|
||||
// applied.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GraphicsStateGuardian::
|
||||
clear_texture_record() {
|
||||
_current_textures.clear();
|
||||
_active_texusage_pcollector.set_level(0);
|
||||
}
|
||||
#endif // DO_PSTATS
|
||||
|
||||
|
||||
void GraphicsStateGuardian::
|
||||
traverse_prepared_textures(bool (*pertex_callbackfn)(TextureContext *,void *),void *callback_arg) {
|
||||
for (Textures::const_iterator ti = _prepared_textures.begin(); ti != _prepared_textures.end();
|
||||
++ti) {
|
||||
bool bResult=(*pertex_callbackfn)(*ti,callback_arg);
|
||||
if(!bResult)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -461,8 +516,8 @@ get_factory() {
|
|||
return (*_factory);
|
||||
}
|
||||
|
||||
void GraphicsStateGuardian::read_priorities(void)
|
||||
{
|
||||
void GraphicsStateGuardian::
|
||||
read_priorities(void) {
|
||||
GsgFactory &factory = get_factory();
|
||||
if (factory.get_num_preferred() == 0) {
|
||||
Config::ConfigTable::Symbol::iterator i;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include <coordinateSystem.h>
|
||||
#include <factory.h>
|
||||
#include <renderTraverser.h>
|
||||
#include <pStatCollector.h>
|
||||
|
||||
#include <list>
|
||||
|
||||
|
|
@ -133,6 +134,17 @@ protected:
|
|||
bool mark_prepared_texture(TextureContext *tc);
|
||||
bool unmark_prepared_texture(TextureContext *tc);
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
// These functions are used to update the current texture memory
|
||||
// usage record in Pstats.
|
||||
void add_to_texture_record(TextureContext *tc);
|
||||
void clear_texture_record();
|
||||
set<TextureContext *> _current_textures;
|
||||
#else
|
||||
INLINE void add_to_texture_record(TextureContext *) { }
|
||||
INLINE void clear_texture_record() { }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
int _buffer_mask;
|
||||
NodeAttributes _state;
|
||||
|
|
@ -158,6 +170,12 @@ protected:
|
|||
|
||||
CoordinateSystem _coordinate_system;
|
||||
|
||||
// Statistics
|
||||
static PStatCollector _total_texusage_pcollector;
|
||||
static PStatCollector _active_texusage_pcollector;
|
||||
static PStatCollector _total_texmem_pcollector;
|
||||
static PStatCollector _used_texmem_pcollector;
|
||||
|
||||
private:
|
||||
typedef set<TextureContext *> Textures;
|
||||
Textures _prepared_textures; // NOTE: on win32 another DLL (e.g. libpandadx.dll) cannot access set directly due to exported template issue
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@ TypeHandle GraphicsWindow::WindowPipe::_type_handle;
|
|||
GraphicsWindow::WindowFactory *GraphicsWindow::_factory = NULL;
|
||||
|
||||
#ifndef CPPPARSER
|
||||
PStatCollector GraphicsWindow::_app_pcollector("App", RGBColorf(0,1,1));
|
||||
PStatCollector GraphicsWindow::_show_code_pcollector("App:Show Code", RGBColorf(0.8,0.2,1));
|
||||
PStatCollector GraphicsWindow::_swap_pcollector("Draw:Swap Buffers", RGBColorf(0.5,1,0.8));
|
||||
PStatCollector GraphicsWindow::_clear_pcollector("Draw:Clear", RGBColorf(0.5,0.7,0.7));
|
||||
PStatCollector GraphicsWindow::_show_fps_pcollector("Draw:Show fps", RGBColorf(0.5,0.8,1));
|
||||
PStatCollector GraphicsWindow::_make_current_pcollector("Draw:Make Current", RGBColorf(1,0.6,0.3));
|
||||
PStatCollector GraphicsWindow::_app_pcollector("App");
|
||||
PStatCollector GraphicsWindow::_show_code_pcollector("App:Show code");
|
||||
PStatCollector GraphicsWindow::_swap_pcollector("Draw:Swap buffers");
|
||||
PStatCollector GraphicsWindow::_clear_pcollector("Draw:Clear");
|
||||
PStatCollector GraphicsWindow::_show_fps_pcollector("Draw:Show fps");
|
||||
PStatCollector GraphicsWindow::_make_current_pcollector("Draw:Make current");
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -5,4 +5,81 @@
|
|||
|
||||
#include "textureContext.h"
|
||||
|
||||
#include <texture.h>
|
||||
#include <pixelBuffer.h>
|
||||
|
||||
TypeHandle TextureContext::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TextureContext::estimate_texture_memory
|
||||
// Access: Public, Virtual
|
||||
// Description: Estimates the amount of texture memory that will be
|
||||
// consumed by loading this texture. This is mainly
|
||||
// useful for debugging and reporting purposes.
|
||||
//
|
||||
// Returns a value in bytes.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
size_t TextureContext::
|
||||
estimate_texture_memory() {
|
||||
PixelBuffer *pb = _texture->_pbuffer;
|
||||
|
||||
size_t pixels = pb->get_xsize() * pb->get_ysize();
|
||||
|
||||
size_t bpp = 1;
|
||||
switch (pb->get_format()) {
|
||||
case PixelBuffer::F_rgb332:
|
||||
case PixelBuffer::F_alpha:
|
||||
case PixelBuffer::F_red:
|
||||
case PixelBuffer::F_green:
|
||||
case PixelBuffer::F_blue:
|
||||
case PixelBuffer::F_luminance:
|
||||
case PixelBuffer::F_luminance_alpha:
|
||||
case PixelBuffer::F_luminance_alphamask:
|
||||
case PixelBuffer::F_color_index:
|
||||
case PixelBuffer::F_stencil_index:
|
||||
case PixelBuffer::F_depth_component:
|
||||
bpp = 1;
|
||||
break;
|
||||
|
||||
case PixelBuffer::F_rgba:
|
||||
case PixelBuffer::F_rgba4:
|
||||
case PixelBuffer::F_rgbm:
|
||||
case PixelBuffer::F_rgb:
|
||||
case PixelBuffer::F_rgb5:
|
||||
case PixelBuffer::F_rgba5:
|
||||
bpp = 2;
|
||||
break;
|
||||
|
||||
case PixelBuffer::F_rgb8:
|
||||
case PixelBuffer::F_rgba8:
|
||||
bpp = 4;
|
||||
break;
|
||||
|
||||
case PixelBuffer::F_rgba12:
|
||||
case PixelBuffer::F_rgb12:
|
||||
bpp = 6;
|
||||
break;
|
||||
}
|
||||
|
||||
size_t bytes = pixels * bpp;
|
||||
|
||||
bool use_mipmaps;
|
||||
switch (_texture->get_minfilter()) {
|
||||
case Texture::FT_nearest_mipmap_nearest:
|
||||
case Texture::FT_linear_mipmap_nearest:
|
||||
case Texture::FT_nearest_mipmap_linear:
|
||||
case Texture::FT_linear_mipmap_linear:
|
||||
use_mipmaps = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
use_mipmaps = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (use_mipmaps) {
|
||||
bytes += bytes / 3;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,8 @@ class EXPCL_PANDA TextureContext : public TypedObject {
|
|||
public:
|
||||
INLINE TextureContext(Texture *tex);
|
||||
|
||||
virtual size_t estimate_texture_memory();
|
||||
|
||||
// This cannot be a PT(Texture), because the texture and the GSG
|
||||
// both own their TextureContexts! That would create a circular
|
||||
// reference count.
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ issue_texcoord_gl(const Geom *geom, Geom::TexCoordIterator &tciterator) {
|
|||
|
||||
static void
|
||||
issue_color_gl(const Geom *geom, Geom::ColorIterator &citerator,
|
||||
const GraphicsStateGuardianBase *) {
|
||||
const GraphicsStateGuardianBase *) {
|
||||
const Colorf &color = geom->get_next_color(citerator);
|
||||
// glgsg_cat.debug() << "Issuing color " << color << "\n";
|
||||
glColor4fv(color.get_data());
|
||||
|
|
@ -123,7 +123,7 @@ issue_color_gl(const Geom *geom, Geom::ColorIterator &citerator,
|
|||
|
||||
static void
|
||||
issue_transformed_color_gl(const Geom *geom, Geom::ColorIterator &citerator,
|
||||
const GraphicsStateGuardianBase *gsg) {
|
||||
const GraphicsStateGuardianBase *gsg) {
|
||||
const GLGraphicsStateGuardian *glgsg = DCAST(GLGraphicsStateGuardian, gsg);
|
||||
const Colorf &color = geom->get_next_color(citerator);
|
||||
|
||||
|
|
@ -468,11 +468,24 @@ render_frame(const AllAttributesWrapper &initial_state) {
|
|||
<< " --------------------------------------------" << endl;
|
||||
#endif
|
||||
|
||||
_lighting_enabled_this_frame = false;
|
||||
|
||||
_win->begin_frame();
|
||||
report_errors();
|
||||
_decal_level = 0;
|
||||
_lighting_enabled_this_frame = false;
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
// For Pstats to track our current texture memory usage, we have to
|
||||
// reset the set of current textures each frame.
|
||||
clear_texture_record();
|
||||
|
||||
// But since we don't get sent a new issue_texture() unless our
|
||||
// texture state has changed, we have to be sure to clear the
|
||||
// current texture state now. A bit unfortunate, but probably not
|
||||
// measurably expensive.
|
||||
NodeAttributes state;
|
||||
state.set_attribute(TextureTransition::get_class_type(), new TextureAttribute);
|
||||
set_state(state, false);
|
||||
#endif
|
||||
|
||||
if (_clear_buffer_type != 0) {
|
||||
// First, clear the entire window.
|
||||
|
|
@ -723,10 +736,10 @@ draw_point(const GeomPoint *geom) {
|
|||
}
|
||||
|
||||
GeomIssuer issuer(geom, this,
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
|
||||
// Draw overall
|
||||
issuer.issue_color(G_OVERALL, ci);
|
||||
|
|
@ -1224,10 +1237,10 @@ draw_polygon(const GeomPolygon *geom) {
|
|||
}
|
||||
|
||||
GeomIssuer issuer(geom, this,
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
|
||||
// If we have per-vertex colors or normals, we need smooth shading.
|
||||
// Otherwise we want flat shading for performance reasons.
|
||||
|
|
@ -1295,10 +1308,10 @@ draw_tri(const GeomTri *geom) {
|
|||
}
|
||||
|
||||
GeomIssuer issuer(geom, this,
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
|
||||
// If we have per-vertex colors or normals, we need smooth shading.
|
||||
// Otherwise we want flat shading for performance reasons.
|
||||
|
|
@ -1362,10 +1375,10 @@ draw_quad(const GeomQuad *geom) {
|
|||
}
|
||||
|
||||
GeomIssuer issuer(geom, this,
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
|
||||
// If we have per-vertex colors or normals, we need smooth shading.
|
||||
// Otherwise we want flat shading for performance reasons.
|
||||
|
|
@ -1430,10 +1443,10 @@ draw_tristrip(const GeomTristrip *geom) {
|
|||
}
|
||||
|
||||
GeomIssuer issuer(geom, this,
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
|
||||
// If we have per-vertex colors or normals, we need smooth shading.
|
||||
// Otherwise we want flat shading for performance reasons.
|
||||
|
|
@ -1519,10 +1532,10 @@ draw_trifan(const GeomTrifan *geom) {
|
|||
}
|
||||
|
||||
GeomIssuer issuer(geom, this,
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
issue_vertex_gl,
|
||||
issue_normal_gl,
|
||||
issue_texcoord_gl,
|
||||
issue_color);
|
||||
|
||||
// If we have per-vertex colors or normals, we need smooth shading.
|
||||
// Otherwise we want flat shading for performance reasons.
|
||||
|
|
@ -1700,6 +1713,7 @@ prepare_texture(Texture *tex) {
|
|||
void GLGraphicsStateGuardian::
|
||||
apply_texture(TextureContext *tc) {
|
||||
// activate();
|
||||
add_to_texture_record(tc);
|
||||
bind_texture(tc);
|
||||
|
||||
/*
|
||||
|
|
@ -1754,7 +1768,7 @@ static int binary_log_cap(const int x) {
|
|||
// Function: GLGraphicsStateGuardian::copy_texture
|
||||
// Access: Public, Virtual
|
||||
// Description: Copy the pixel region indicated by the display
|
||||
// region from the framebuffer into texture memory
|
||||
// region from the framebuffer into texture memory
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GLGraphicsStateGuardian::
|
||||
copy_texture(TextureContext *tc, const DisplayRegion *dr) {
|
||||
|
|
@ -3496,20 +3510,20 @@ bind_texture(TextureContext *tc) {
|
|||
void GLGraphicsStateGuardian::
|
||||
specify_texture(Texture *tex) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
|
||||
get_texture_wrap_mode(tex->get_wrapu()));
|
||||
get_texture_wrap_mode(tex->get_wrapu()));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
|
||||
get_texture_wrap_mode(tex->get_wrapv()));
|
||||
get_texture_wrap_mode(tex->get_wrapv()));
|
||||
|
||||
if (gl_force_mipmaps) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
|
||||
get_texture_filter_type(tex->get_minfilter()));
|
||||
get_texture_filter_type(tex->get_minfilter()));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
|
||||
get_texture_filter_type(tex->get_magfilter()));
|
||||
get_texture_filter_type(tex->get_magfilter()));
|
||||
}
|
||||
report_errors();
|
||||
}
|
||||
|
|
@ -3554,20 +3568,20 @@ apply_texture_immediate(Texture *tex) {
|
|||
if (use_mipmaps || gl_force_mipmaps) {
|
||||
#ifndef NDEBUG
|
||||
if (gl_show_mipmaps) {
|
||||
build_phony_mipmaps(tex);
|
||||
return;
|
||||
build_phony_mipmaps(tex);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
gluBuild2DMipmaps(GL_TEXTURE_2D, internal_format,
|
||||
pb->get_xsize(), pb->get_ysize(),
|
||||
external_format, type, pb->_image);
|
||||
pb->get_xsize(), pb->get_ysize(),
|
||||
external_format, type, pb->_image);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
glTexImage2D( GL_TEXTURE_2D, 0, internal_format,
|
||||
pb->get_xsize(), pb->get_ysize(), pb->get_border(),
|
||||
external_format, type, pb->_image );
|
||||
pb->get_xsize(), pb->get_ysize(), pb->get_border(),
|
||||
external_format, type, pb->_image );
|
||||
report_errors();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,8 @@
|
|||
pStatCollector.I pStatCollector.h \
|
||||
pStatCollectorDef.cxx \
|
||||
pStatCollectorDef.h pStatFrameData.I pStatFrameData.cxx \
|
||||
pStatFrameData.h pStatServerControlMessage.cxx \
|
||||
pStatFrameData.h pStatProperties.cxx pStatProperties.h \
|
||||
pStatServerControlMessage.cxx \
|
||||
pStatServerControlMessage.h \
|
||||
pStatThread.I pStatThread.h \
|
||||
pStatTimer.I pStatTimer.h
|
||||
|
|
@ -31,6 +32,11 @@
|
|||
#end lib_target
|
||||
|
||||
#begin test_bin_target
|
||||
#define LOCAL_LIBS \
|
||||
pstatclient
|
||||
#define OTHER_LIBS \
|
||||
pystub
|
||||
|
||||
#define TARGET test_client
|
||||
|
||||
#define SOURCES \
|
||||
|
|
|
|||
|
|
@ -18,18 +18,18 @@ string get_pstats_name() {
|
|||
return config_pstats.GetString("pstats-name", "Panda Stats");
|
||||
}
|
||||
|
||||
double get_pstats_max_rate() {
|
||||
return config_pstats.GetDouble("pstats-max-rate", 30.0);
|
||||
float get_pstats_max_rate() {
|
||||
return config_pstats.GetFloat("pstats-max-rate", 30.0);
|
||||
}
|
||||
|
||||
const string pstats_host = config_pstats.GetString("pstats-host", "localhost");
|
||||
const int pstats_port = config_pstats.GetInt("pstats-port", 5180);
|
||||
const double pstats_target_frame_rate = config_pstats.GetDouble("pstats-target-frame-rate", 30.0);
|
||||
const float pstats_target_frame_rate = config_pstats.GetFloat("pstats-target-frame-rate", 30.0);
|
||||
|
||||
// The rest are different in that they directly control the server,
|
||||
// not the client.
|
||||
const bool pstats_scroll_mode = config_pstats.GetBool("pstats-scroll-mode", true);
|
||||
const double pstats_history = config_pstats.GetDouble("pstats-history", 30.0);
|
||||
const float pstats_history = config_pstats.GetFloat("pstats-history", 30.0);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: init_libpstatclient
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@
|
|||
NotifyCategoryDecl(pstats, EXPCL_PANDA, EXPTP_PANDA);
|
||||
|
||||
extern EXPCL_PANDA string get_pstats_name();
|
||||
extern EXPCL_PANDA double get_pstats_max_rate();
|
||||
extern EXPCL_PANDA float get_pstats_max_rate();
|
||||
extern EXPCL_PANDA const string pstats_host;
|
||||
extern EXPCL_PANDA const int pstats_port;
|
||||
extern EXPCL_PANDA const double pstats_target_frame_rate;
|
||||
extern EXPCL_PANDA const float pstats_target_frame_rate;
|
||||
|
||||
extern EXPCL_PANDA const bool pstats_scroll_mode;
|
||||
extern EXPCL_PANDA const double pstats_history;
|
||||
extern EXPCL_PANDA const float pstats_history;
|
||||
|
||||
extern EXPCL_PANDA void init_libpstatclient();
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ get_client_name() const {
|
|||
// thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatClient::
|
||||
set_max_rate(double rate) {
|
||||
set_max_rate(float rate) {
|
||||
_max_rate = rate;
|
||||
}
|
||||
|
||||
|
|
@ -53,7 +53,7 @@ set_max_rate(double rate) {
|
|||
// sent to the server per second, per thread. See
|
||||
// set_max_rate().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatClient::
|
||||
INLINE float PStatClient::
|
||||
get_max_rate() const {
|
||||
return _max_rate;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
#include "pStatCollector.h"
|
||||
#include "pStatThread.h"
|
||||
#include "config_pstats.h"
|
||||
#include "pStatProperties.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
|
|
@ -25,6 +26,18 @@
|
|||
|
||||
PStatClient *PStatClient::_global_pstats = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::PerThreadData::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatClient::PerThreadData::
|
||||
PerThreadData() {
|
||||
_has_level = false;
|
||||
_level = 0.0;
|
||||
_nested_count = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::Constructor
|
||||
// Access: Public
|
||||
|
|
@ -196,36 +209,55 @@ get_main_thread() const {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::make_collector
|
||||
// Function: PStatClient::make_collector_with_relname
|
||||
// Access: Private
|
||||
// Description: Returns a PStatCollector suitable for measuring
|
||||
// categories with the indicated name. This is normally
|
||||
// called by a PStatCollector constructor.
|
||||
//
|
||||
// The name may contain colons; if it does, it specifies
|
||||
// a relative path to the client indicated by the parent
|
||||
// index.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatCollector PStatClient::
|
||||
make_collector(int parent_index, string fullname) {
|
||||
if (fullname.empty()) {
|
||||
fullname = "Unnamed";
|
||||
make_collector_with_relname(int parent_index, string relname) {
|
||||
if (relname.empty()) {
|
||||
relname = "Unnamed";
|
||||
}
|
||||
|
||||
// Skip any colons at the beginning of the name.
|
||||
size_t start = 0;
|
||||
while (start < fullname.size() && fullname[start] == ':') {
|
||||
while (start < relname.size() && relname[start] == ':') {
|
||||
start++;
|
||||
}
|
||||
|
||||
// If the name contains a colon (after the initial colon), it means
|
||||
// we are making a nested collector.
|
||||
size_t colon = fullname.find(':', start);
|
||||
if (colon != string::npos) {
|
||||
string parent_name = fullname.substr(start, colon - start);
|
||||
size_t colon = relname.find(':', start);
|
||||
while (colon != string::npos) {
|
||||
string parent_name = relname.substr(start, colon - start);
|
||||
PStatCollector parent_collector =
|
||||
make_collector(parent_index, parent_name);
|
||||
return make_collector(parent_collector._index, fullname.substr(colon + 1));
|
||||
make_collector_with_name(parent_index, parent_name);
|
||||
parent_index = parent_collector._index;
|
||||
relname = relname.substr(colon + 1);
|
||||
colon = relname.find(':', start);
|
||||
}
|
||||
|
||||
string name = fullname.substr(start);
|
||||
string name = relname.substr(start);
|
||||
return make_collector_with_name(parent_index, name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::make_collector_with_name
|
||||
// Access: Private
|
||||
// Description: Returns a PStatCollector suitable for measuring
|
||||
// categories with the indicated name. This is normally
|
||||
// called by a PStatCollector constructor.
|
||||
//
|
||||
// The name should not contain colons.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatCollector PStatClient::
|
||||
make_collector_with_name(int parent_index, const string &name) {
|
||||
nassertr(parent_index >= 0 && parent_index < (int)_collectors.size(),
|
||||
PStatCollector());
|
||||
|
||||
|
|
@ -251,53 +283,22 @@ make_collector(int parent_index, string fullname) {
|
|||
int new_index = _collectors.size();
|
||||
parent._children.insert(ThingsByName::value_type(name, new_index));
|
||||
|
||||
Collector collector;
|
||||
// Extending the vector invalidates the parent reference, above.
|
||||
_collectors.push_back(Collector());
|
||||
Collector &collector = _collectors.back();
|
||||
collector._def = new PStatCollectorDef(new_index, name);
|
||||
collector._def->_parent_index = parent_index;
|
||||
|
||||
// We need one nested_count for each thread.
|
||||
while (collector._nested_count.size() < _threads.size()) {
|
||||
collector._nested_count.push_back(0);
|
||||
collector._def->set_parent(*_collectors[parent_index]._def);
|
||||
initialize_collector_def(this, collector._def);
|
||||
|
||||
// We need one PerThreadData for each thread.
|
||||
while (collector._per_thread.size() < _threads.size()) {
|
||||
collector._per_thread.push_back(PerThreadData());
|
||||
}
|
||||
|
||||
_collectors.push_back(collector);
|
||||
|
||||
return PStatCollector(this, new_index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::make_collector
|
||||
// Access: Private
|
||||
// Description: This flavor of make_collector will make a new
|
||||
// collector and automatically set up some of its
|
||||
// properties.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatCollector PStatClient::
|
||||
make_collector(int parent_index, const string &fullname,
|
||||
const RGBColorf &suggested_color, int sort) {
|
||||
PStatCollector c = make_collector(parent_index, fullname);
|
||||
nassertr(c._client == this, PStatCollector());
|
||||
nassertr(c._index >= 0 && c._index < (int)_collectors.size(), PStatCollector());
|
||||
|
||||
PStatCollectorDef *def = _collectors[c._index]._def;
|
||||
nassertr(def != (PStatCollectorDef *)NULL, PStatCollector());
|
||||
|
||||
if (suggested_color != RGBColorf::zero() &&
|
||||
def->_suggested_color != suggested_color) {
|
||||
// We need to change the suggested color.
|
||||
def->_suggested_color = suggested_color;
|
||||
_collectors_reported = min(_collectors_reported, c._index);
|
||||
}
|
||||
|
||||
if (sort != -1 && def->_sort != sort) {
|
||||
// We need to change the sort.
|
||||
def->_sort = sort;
|
||||
_collectors_reported = min(_collectors_reported, c._index);
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::make_thread
|
||||
// Access: Private
|
||||
|
|
@ -329,12 +330,12 @@ make_thread(const string &name) {
|
|||
|
||||
_threads.push_back(thread);
|
||||
|
||||
// We need an additional nested_count for this thread in all of the
|
||||
// We need an additional PerThreadData for this thread in all of the
|
||||
// collectors.
|
||||
Collectors::iterator ci;
|
||||
for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) {
|
||||
(*ci)._nested_count.push_back(0);
|
||||
nassertr((*ci)._nested_count.size() == _threads.size(), PStatThread());
|
||||
(*ci)._per_thread.push_back(PerThreadData());
|
||||
nassertr((*ci)._per_thread.size() == _threads.size(), PStatThread());
|
||||
}
|
||||
|
||||
return PStatThread(this, new_index);
|
||||
|
|
@ -440,11 +441,11 @@ ns_disconnect() {
|
|||
|
||||
Collectors::iterator ci;
|
||||
for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) {
|
||||
vector_int::iterator ii;
|
||||
for (ii = (*ci)._nested_count.begin();
|
||||
ii != (*ci)._nested_count.end();
|
||||
PerThread::iterator ii;
|
||||
for (ii = (*ci)._per_thread.begin();
|
||||
ii != (*ci)._per_thread.end();
|
||||
++ii) {
|
||||
(*ii) = 0;
|
||||
(*ii)._nested_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -464,20 +465,20 @@ ns_is_connected() const {
|
|||
// Access: Private
|
||||
// Description: Marks the indicated collector index as started.
|
||||
// Normally you would not use this interface directly;
|
||||
// instead, call pStatCollector::start().
|
||||
// instead, call PStatCollector::start().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
start(int collector_index, int thread_index, double as_of) {
|
||||
start(int collector_index, int thread_index, float as_of) {
|
||||
nassertv(collector_index >= 0 && collector_index < (int)_collectors.size());
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||
|
||||
if (_threads[thread_index]._is_active) {
|
||||
if (_collectors[collector_index]._nested_count[thread_index] == 0) {
|
||||
if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) {
|
||||
// This collector wasn't already started in this thread; record
|
||||
// a new data point.
|
||||
_threads[thread_index]._frame_data.add_start(collector_index, as_of);
|
||||
}
|
||||
_collectors[collector_index]._nested_count[thread_index]++;
|
||||
_collectors[collector_index]._per_thread[thread_index]._nested_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -486,15 +487,15 @@ start(int collector_index, int thread_index, double as_of) {
|
|||
// Access: Private
|
||||
// Description: Marks the indicated collector index as stopped.
|
||||
// Normally you would not use this interface directly;
|
||||
// instead, call pStatCollector::stop().
|
||||
// instead, call PStatCollector::stop().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
stop(int collector_index, int thread_index, double as_of) {
|
||||
stop(int collector_index, int thread_index, float as_of) {
|
||||
nassertv(collector_index >= 0 && collector_index < (int)_collectors.size());
|
||||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||
|
||||
if (_threads[thread_index]._is_active) {
|
||||
if (_collectors[collector_index]._nested_count[thread_index] == 0) {
|
||||
if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) {
|
||||
pstats_cat.warning()
|
||||
<< "Collector " << get_collector_fullname(collector_index)
|
||||
<< " was already stopped in thread " << get_thread_name(thread_index)
|
||||
|
|
@ -502,9 +503,9 @@ stop(int collector_index, int thread_index, double as_of) {
|
|||
return;
|
||||
}
|
||||
|
||||
_collectors[collector_index]._nested_count[thread_index]--;
|
||||
_collectors[collector_index]._per_thread[thread_index]._nested_count--;
|
||||
|
||||
if (_collectors[collector_index]._nested_count[thread_index] == 0) {
|
||||
if (_collectors[collector_index]._per_thread[thread_index]._nested_count == 0) {
|
||||
// This collector has now been completely stopped; record a new
|
||||
// data point.
|
||||
_threads[thread_index]._frame_data.add_stop(collector_index, as_of);
|
||||
|
|
@ -512,6 +513,54 @@ stop(int collector_index, int thread_index, double as_of) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::clear_level
|
||||
// Access: Private
|
||||
// Description: Removes the level value from the indicated collector.
|
||||
// The collector will no longer be reported as having
|
||||
// any particular level value.
|
||||
//
|
||||
// Normally you would not use this interface directly;
|
||||
// instead, call PStatCollector::clear_level().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
clear_level(int collector_index, int thread_index) {
|
||||
_collectors[collector_index]._per_thread[thread_index]._has_level = false;
|
||||
_collectors[collector_index]._per_thread[thread_index]._level = 0.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::set_level
|
||||
// Access: Private
|
||||
// Description: Sets the level value for the indicated collector to
|
||||
// the given amount.
|
||||
//
|
||||
// Normally you would not use this interface directly;
|
||||
// instead, call PStatCollector::set_level().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
set_level(int collector_index, int thread_index, float level) {
|
||||
_collectors[collector_index]._per_thread[thread_index]._has_level = true;
|
||||
_collectors[collector_index]._per_thread[thread_index]._level = level;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::add_level
|
||||
// Access: Private
|
||||
// Description: Adds the given value (which may be negative) to the
|
||||
// current value for the given collector. If the
|
||||
// collector does not already have a level value, it is
|
||||
// initialized to 0.
|
||||
//
|
||||
// Normally you would not use this interface directly;
|
||||
// instead, call PStatCollector::add_level().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClient::
|
||||
add_level(int collector_index, int thread_index, float increment) {
|
||||
_collectors[collector_index]._per_thread[thread_index]._has_level = true;
|
||||
_collectors[collector_index]._per_thread[thread_index]._level += increment;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClient::new_frame
|
||||
// Access: Private
|
||||
|
|
@ -542,28 +591,21 @@ new_frame(int thread_index) {
|
|||
return;
|
||||
}
|
||||
|
||||
double frame_start = _clock.get_real_time();
|
||||
float frame_start = _clock.get_real_time();
|
||||
|
||||
if (!thread._frame_data.is_empty()) {
|
||||
// Collector 0 is the whole frame.
|
||||
stop(0, thread_index, frame_start);
|
||||
|
||||
/*
|
||||
We don't need to do this, since the stats server will do it.
|
||||
Why should we waste our time?
|
||||
|
||||
// Make sure all of our Collectors have turned themselves off now
|
||||
// at the end of the frame.
|
||||
Collectors::iterator ci;
|
||||
for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) {
|
||||
if ((*ci)._nested_count > 0) {
|
||||
pstats_cat.warning()
|
||||
<< "Collector " << get_collector_fullname((*ci)._def->_index)
|
||||
<< " wasn't stopped!\n";
|
||||
(*ci)._nested_count = 0;
|
||||
// Fill up the level data for all the collectors who have level
|
||||
// data for this thread.
|
||||
int num_collectors = _collectors.size();
|
||||
for (int i = 0; i < num_collectors; i++) {
|
||||
const PerThreadData &ptd = _collectors[i]._per_thread[thread_index];
|
||||
if (ptd._has_level) {
|
||||
thread._frame_data.add_level(i, ptd._level);
|
||||
}
|
||||
} */
|
||||
|
||||
}
|
||||
transmit_frame_data(thread_index);
|
||||
}
|
||||
|
||||
|
|
@ -586,8 +628,8 @@ transmit_frame_data(int thread_index) {
|
|||
// We don't want to send too many packets in a hurry and flood the
|
||||
// server. In fact, we don't want to send more than
|
||||
// _max_rate packets per second, per thread.
|
||||
double min_packet_delay = 1.0 / _max_rate;
|
||||
double now = _clock.get_real_time();
|
||||
float min_packet_delay = 1.0 / _max_rate;
|
||||
float now = _clock.get_real_time();
|
||||
|
||||
if (now - _threads[thread_index]._last_packet > min_packet_delay) {
|
||||
nassertv(_got_udp_port);
|
||||
|
|
|
|||
|
|
@ -11,10 +11,10 @@
|
|||
#include "pStatFrameData.h"
|
||||
|
||||
#include <clockObject.h>
|
||||
#include <vector_int.h>
|
||||
#include <luse.h>
|
||||
#include <map>
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
#ifdef HAVE_NET
|
||||
#include <connectionManager.h>
|
||||
#include <queuedConnectionReader.h>
|
||||
#include <connectionWriter.h>
|
||||
|
|
@ -43,8 +43,8 @@ public:
|
|||
|
||||
INLINE void set_client_name(const string &name);
|
||||
INLINE string get_client_name() const;
|
||||
INLINE void set_max_rate(double rate);
|
||||
INLINE double get_max_rate() const;
|
||||
INLINE void set_max_rate(float rate);
|
||||
INLINE float get_max_rate() const;
|
||||
|
||||
int get_num_collectors() const;
|
||||
PStatCollector get_collector(int index) const;
|
||||
|
|
@ -72,13 +72,16 @@ private:
|
|||
void ns_disconnect();
|
||||
bool ns_is_connected() const;
|
||||
|
||||
PStatCollector make_collector(int parent_index, string fullname);
|
||||
PStatCollector make_collector(int parent_index, const string &fullname,
|
||||
const RGBColorf &suggested_color, int sort);
|
||||
PStatCollector make_collector_with_relname(int parent_index, string relname);
|
||||
PStatCollector make_collector_with_name(int parent_index, const string &name);
|
||||
PStatThread make_thread(const string &name);
|
||||
|
||||
void start(int collector_index, int thread_index, double as_of);
|
||||
void stop(int collector_index, int thread_index, double as_of);
|
||||
void start(int collector_index, int thread_index, float as_of);
|
||||
void stop(int collector_index, int thread_index, float as_of);
|
||||
|
||||
void clear_level(int collector_index, int thread_index);
|
||||
void set_level(int collector_index, int thread_index, float level);
|
||||
void add_level(int collector_index, int thread_index, float increment);
|
||||
|
||||
void new_frame(int thread_index);
|
||||
void transmit_frame_data(int thread_index);
|
||||
|
|
@ -91,27 +94,45 @@ private:
|
|||
typedef map<string, int> ThingsByName;
|
||||
ThingsByName _threads_by_name;
|
||||
|
||||
// This is for the data that is per-collector, per-thread. A vector
|
||||
// of these is stored in each Collector object, below, indexed by
|
||||
// thread index.
|
||||
class PerThreadData {
|
||||
public:
|
||||
PerThreadData();
|
||||
bool _has_level;
|
||||
float _level;
|
||||
int _nested_count;
|
||||
};
|
||||
typedef vector<PerThreadData> PerThread;
|
||||
|
||||
// This is where the meat of the Collector data is stored. (All the
|
||||
// stuff in PStatCollector and PStatCollectorDef is just fluff.)
|
||||
class Collector {
|
||||
public:
|
||||
PStatCollectorDef *_def;
|
||||
vector_int _nested_count;
|
||||
ThingsByName _children;
|
||||
|
||||
PerThread _per_thread;
|
||||
};
|
||||
typedef vector<Collector> Collectors;
|
||||
Collectors _collectors;
|
||||
|
||||
// This defines a single thread, i.e. a separate chain of execution,
|
||||
// independent of all other threads. Timing and level data are
|
||||
// maintained separately for each thread.
|
||||
class Thread {
|
||||
public:
|
||||
string _name;
|
||||
PStatFrameData _frame_data;
|
||||
bool _is_active;
|
||||
int _frame_number;
|
||||
double _last_packet;
|
||||
float _last_packet;
|
||||
};
|
||||
|
||||
typedef vector<Thread> Threads;
|
||||
Threads _threads;
|
||||
|
||||
|
||||
private:
|
||||
// Networking stuff
|
||||
string get_hostname();
|
||||
|
|
@ -137,7 +158,7 @@ private:
|
|||
|
||||
string _hostname;
|
||||
string _client_name;
|
||||
double _max_rate;
|
||||
float _max_rate;
|
||||
|
||||
static PStatClient *_global_pstats;
|
||||
friend class PStatCollector;
|
||||
|
|
|
|||
|
|
@ -52,13 +52,11 @@ PStatCollector(PStatClient *client, int index) :
|
|||
// otherwise, the global client is used.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PStatCollector::
|
||||
PStatCollector(const string &name, const RGBColorf &suggested_color,
|
||||
int sort, PStatClient *client) {
|
||||
PStatCollector(const string &name, PStatClient *client) {
|
||||
if (client == (PStatClient *)NULL) {
|
||||
client = PStatClient::get_global_pstats();
|
||||
}
|
||||
PStatCollector collector(client->make_collector(0, name, suggested_color, sort));
|
||||
(*this) = collector;
|
||||
(*this) = client->make_collector_with_relname(0, name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -85,12 +83,10 @@ PStatCollector(const string &name, const RGBColorf &suggested_color,
|
|||
// as its parent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE PStatCollector::
|
||||
PStatCollector(const PStatCollector &parent, const string &name,
|
||||
const RGBColorf &suggested_color, int sort) {
|
||||
PStatCollector(const PStatCollector &parent, const string &name) {
|
||||
nassertv(parent._client != (PStatClient *)NULL);
|
||||
PStatCollector collector(parent._client->make_collector
|
||||
(parent._index, name, suggested_color, sort));
|
||||
(*this) = collector;
|
||||
(*this) =
|
||||
parent._client->make_collector_with_relname(parent._index, name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -147,7 +143,7 @@ start(const PStatThread &thread) {
|
|||
// a monotonically increasing series of time values.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
start(const PStatThread &thread, double as_of) {
|
||||
start(const PStatThread &thread, float as_of) {
|
||||
_client->start(_index, thread._index, as_of);
|
||||
}
|
||||
|
||||
|
|
@ -182,8 +178,86 @@ stop(const PStatThread &thread) {
|
|||
// a monotonically increasing series of time values.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
stop(const PStatThread &thread, double as_of) {
|
||||
stop(const PStatThread &thread, float as_of) {
|
||||
_client->stop(_index, thread._index, as_of);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::clear_level
|
||||
// Access: Public
|
||||
// Description: Removes the level setting associated with this
|
||||
// collector for the main thread. The collector
|
||||
// will no longer show up on any level graphs in the
|
||||
// main thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
clear_level() {
|
||||
_client->clear_level(_index, 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::clear_level
|
||||
// Access: Public
|
||||
// Description: Removes the level setting associated with this
|
||||
// collector for the indicated thread. The collector
|
||||
// will no longer show up on any level graphs in this
|
||||
// thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
clear_level(const PStatThread &thread) {
|
||||
_client->clear_level(_index, thread._index);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::set_level
|
||||
// Access: Public
|
||||
// Description: Sets the level setting associated with this
|
||||
// collector for the main thread to the indicated
|
||||
// value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
set_level(float level) {
|
||||
_client->set_level(_index, 0, level);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::set_level
|
||||
// Access: Public
|
||||
// Description: Sets the level setting associated with this
|
||||
// collector for the indicated thread to the indicated
|
||||
// value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
set_level(const PStatThread &thread, float level) {
|
||||
_client->set_level(_index, thread._index, level);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::add_level
|
||||
// Access: Public
|
||||
// Description: Adds the indicated increment (which may be negative)
|
||||
// to the level setting associated with this collector
|
||||
// for the main thread. If the collector did not
|
||||
// already have a level setting for the main thread, it
|
||||
// is initialized to 0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
add_level(float increment) {
|
||||
_client->add_level(_index, 0, increment);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollector::add_level
|
||||
// Access: Public
|
||||
// Description: Adds the indicated increment (which may be negative)
|
||||
// to the level setting associated with this collector
|
||||
// for the indicated thread. If the collector did not
|
||||
// already have a level setting for this thread, it is
|
||||
// initialized to 0.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatCollector::
|
||||
add_level(const PStatThread &thread, float increment) {
|
||||
_client->add_level(_index, thread._index, increment);
|
||||
}
|
||||
|
||||
#endif // DO_PSTATS
|
||||
|
|
|
|||
|
|
@ -16,8 +16,26 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PStatCollector
|
||||
// Description : A lightweight class that represents a single element
|
||||
// that may be timed via stats. Bracket the code to be
|
||||
// timed with calls to start() and stop().
|
||||
// that may be timed and/or counted via stats.
|
||||
//
|
||||
// Collectors can be used to measure two different kinds
|
||||
// of values: elapsed time, and "other".
|
||||
//
|
||||
// To measure elapsed time, call start() and stop() as
|
||||
// appropriate to bracket the section of code you want
|
||||
// to time (or use a PStatTimer to do this
|
||||
// automatically).
|
||||
//
|
||||
// To measure anything else, call set_level() and/or
|
||||
// add_level() to set the "level" value associated with
|
||||
// this collector. The meaning of the value set for the
|
||||
// "level" is entirely up to the user; it may represent
|
||||
// the number of triangles rendered or the kilobytes of
|
||||
// texture memory consumed, for instance. The level set
|
||||
// will remain fixed across multiple frames until it is
|
||||
// reset via another set_level() or adjusted via a call
|
||||
// to add_level(). It may also be completely removed
|
||||
// via clear_level().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA PStatCollector {
|
||||
#ifdef DO_PSTATS
|
||||
|
|
@ -28,24 +46,27 @@ private:
|
|||
|
||||
public:
|
||||
INLINE PStatCollector(const string &name,
|
||||
const RGBColorf &suggested_color = RGBColorf::zero(),
|
||||
int sort = -1,
|
||||
PStatClient *client = NULL);
|
||||
INLINE PStatCollector(const PStatCollector &parent,
|
||||
const string &name,
|
||||
const RGBColorf &suggested_color = RGBColorf::zero(),
|
||||
int sort = -1);
|
||||
const string &name);
|
||||
|
||||
INLINE PStatCollector(const PStatCollector ©);
|
||||
INLINE void operator = (const PStatCollector ©);
|
||||
|
||||
INLINE void start();
|
||||
INLINE void start(const PStatThread &thread);
|
||||
INLINE void start(const PStatThread &thread, double as_of);
|
||||
INLINE void start(const PStatThread &thread, float as_of);
|
||||
|
||||
INLINE void stop();
|
||||
INLINE void stop(const PStatThread &thread);
|
||||
INLINE void stop(const PStatThread &thread, double as_of);
|
||||
INLINE void stop(const PStatThread &thread, float as_of);
|
||||
|
||||
INLINE void clear_level();
|
||||
INLINE void clear_level(const PStatThread &thread);
|
||||
INLINE void set_level(float level);
|
||||
INLINE void set_level(const PStatThread &thread, float level);
|
||||
INLINE void add_level(float increment);
|
||||
INLINE void add_level(const PStatThread &thread, float increment);
|
||||
|
||||
private:
|
||||
PStatClient *_client;
|
||||
|
|
@ -66,11 +87,18 @@ public:
|
|||
|
||||
INLINE void start() { }
|
||||
INLINE void start(const PStatThread &) { }
|
||||
INLINE void start(const PStatThread &, double) { }
|
||||
INLINE void start(const PStatThread &, float) { }
|
||||
|
||||
INLINE void stop() { }
|
||||
INLINE void stop(const PStatThread &) { }
|
||||
INLINE void stop(const PStatThread &, double) { }
|
||||
INLINE void stop(const PStatThread &, float) { }
|
||||
|
||||
INLINE void clear_level() { }
|
||||
INLINE void clear_level(const PStatThread &) { }
|
||||
INLINE void set_level(float) { }
|
||||
INLINE void set_level(const PStatThread &, float) { }
|
||||
INLINE void add_level(float) { }
|
||||
INLINE void add_level(const PStatThread &, float) { }
|
||||
|
||||
#endif // DO_PSTATS
|
||||
};
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ PStatCollectorDef() {
|
|||
_parent_index = 0;
|
||||
_suggested_color.set(0.0, 0.0, 0.0);
|
||||
_sort = -1;
|
||||
_suggested_scale = 0.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -35,8 +36,23 @@ PStatCollectorDef(int index, const string &name) :
|
|||
_parent_index = 0;
|
||||
_suggested_color.set(0.0, 0.0, 0.0);
|
||||
_sort = -1;
|
||||
_suggested_scale = 0.0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollectorDef::set_parent
|
||||
// Access: Public
|
||||
// Description: This is normally called only by the PStatClient when
|
||||
// the new PStatCollectorDef is created; it sets the
|
||||
// parent of the CollectorDef and inherits whatever
|
||||
// properties are appropriate.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatCollectorDef::
|
||||
set_parent(const PStatCollectorDef &parent) {
|
||||
_parent_index = parent._index;
|
||||
_level_units = parent._level_units;
|
||||
_suggested_scale = parent._suggested_scale;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatCollectorDef::write_datagram
|
||||
|
|
@ -51,6 +67,8 @@ write_datagram(Datagram &destination) const {
|
|||
destination.add_int16(_parent_index);
|
||||
_suggested_color.write_datagram(destination);
|
||||
destination.add_int16(_sort);
|
||||
destination.add_string(_level_units);
|
||||
destination.add_float32(_suggested_scale);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -64,8 +82,7 @@ read_datagram(DatagramIterator &source) {
|
|||
_name = source.get_string();
|
||||
_parent_index = source.get_int16();
|
||||
_suggested_color.read_datagram(source);
|
||||
|
||||
if (source.get_remaining_size() > 0) {
|
||||
_sort = source.get_int16();
|
||||
}
|
||||
_sort = source.get_int16();
|
||||
_level_units = source.get_string();
|
||||
_suggested_scale = source.get_float32();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ class EXPCL_PANDA PStatCollectorDef {
|
|||
public:
|
||||
PStatCollectorDef();
|
||||
PStatCollectorDef(int index, const string &name);
|
||||
void set_parent(const PStatCollectorDef &parent);
|
||||
|
||||
void write_datagram(Datagram &destination) const;
|
||||
void read_datagram(DatagramIterator &source);
|
||||
|
|
@ -32,6 +33,8 @@ public:
|
|||
int _parent_index;
|
||||
RGBColorf _suggested_color;
|
||||
int _sort;
|
||||
string _level_units;
|
||||
float _suggested_scale;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5,14 +5,36 @@
|
|||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatFrameData::is_empty
|
||||
// Function: PStatFrameData::is_time_empty
|
||||
// Access: Public
|
||||
// Description: Returns true if there are no data points in the frame
|
||||
// Description: Returns true if there are no time events in the frame
|
||||
// data, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PStatFrameData::
|
||||
is_time_empty() const {
|
||||
return _time_data.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatFrameData::is_level_empty
|
||||
// Access: Public
|
||||
// Description: Returns true if there are no levels indicated in the
|
||||
// frame data, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PStatFrameData::
|
||||
is_level_empty() const {
|
||||
return _level_data.empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatFrameData::is_empty
|
||||
// Access: Public
|
||||
// Description: Returns true if the FrameData has no time or level
|
||||
// data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PStatFrameData::
|
||||
is_empty() const {
|
||||
return _data.empty();
|
||||
return is_time_empty() && is_level_empty();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -23,7 +45,8 @@ is_empty() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatFrameData::
|
||||
clear() {
|
||||
_data.clear();
|
||||
_time_data.clear();
|
||||
_level_data.clear();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -33,11 +56,12 @@ clear() {
|
|||
// data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatFrameData::
|
||||
add_start(int index, double time) {
|
||||
add_start(int index, float time) {
|
||||
nassertv((index & 0x7fff) == index);
|
||||
DataPoint dp;
|
||||
dp._index = index;
|
||||
dp._time = time;
|
||||
_data.push_back(dp);
|
||||
dp._value = time;
|
||||
_time_data.push_back(dp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -47,11 +71,27 @@ add_start(int index, double time) {
|
|||
// data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatFrameData::
|
||||
add_stop(int index, double time) {
|
||||
add_stop(int index, float time) {
|
||||
nassertv((index & 0x7fff) == index);
|
||||
DataPoint dp;
|
||||
dp._index = index | 0x8000;
|
||||
dp._time = time;
|
||||
_data.push_back(dp);
|
||||
dp._value = time;
|
||||
_time_data.push_back(dp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatFrameData::add_level
|
||||
// Access: Public
|
||||
// Description: Adds a particular level value associated with a given
|
||||
// collector to the frame data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatFrameData::
|
||||
add_level(int index, float level) {
|
||||
nassertv((index & 0xffff) == index);
|
||||
DataPoint dp;
|
||||
dp._index = index;
|
||||
dp._value = level;
|
||||
_level_data.push_back(dp);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -61,11 +101,11 @@ add_stop(int index, double time) {
|
|||
// data. This will generally be the time of the start
|
||||
// of the frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatFrameData::
|
||||
INLINE float PStatFrameData::
|
||||
get_start() const {
|
||||
nassertr(!is_empty(), 0.0);
|
||||
|
||||
return _data.front()._time;
|
||||
return _time_data.front()._value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -75,11 +115,11 @@ get_start() const {
|
|||
// data. This will generally be the time of the end
|
||||
// of the frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatFrameData::
|
||||
INLINE float PStatFrameData::
|
||||
get_end() const {
|
||||
nassertr(!is_empty(), 0.0);
|
||||
|
||||
return _data.back()._time;
|
||||
return _time_data.back()._value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -87,11 +127,11 @@ get_end() const {
|
|||
// Access: Public
|
||||
// Description: Returns the total time elapsed for the frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatFrameData::
|
||||
INLINE float PStatFrameData::
|
||||
get_net_time() const {
|
||||
nassertr(!is_empty(), 0.0);
|
||||
|
||||
return _data.back()._time - _data.front()._time;
|
||||
return _time_data.back()._value - _time_data.front()._value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -102,23 +142,31 @@ get_net_time() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PStatFrameData::
|
||||
get_num_events() const {
|
||||
return _data.size();
|
||||
return _time_data.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatFrameData::get_collector
|
||||
// Function: PStatFrameData::get_time_collector
|
||||
// Access: Public
|
||||
// Description: Returns the index of the collector associated with
|
||||
// the nth event. If this is the first time the
|
||||
// collector appears in the event list, it indicates the
|
||||
// collector has started; if it is the second time, it
|
||||
// indicates the collector has stopped. Similarly for
|
||||
// repeated appearances of the same collector.
|
||||
// the nth event.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PStatFrameData::
|
||||
get_collector(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_data.size(), 0);
|
||||
return _data[n]._index;
|
||||
get_time_collector(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_time_data.size(), 0);
|
||||
return _time_data[n]._index & 0x7fff;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatFrameData::is_start
|
||||
// Access: Public
|
||||
// Description: Returns true if the nth event represents a start
|
||||
// event, or false if it represents a stop event.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool PStatFrameData::
|
||||
is_start(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_time_data.size(), 0);
|
||||
return (_time_data[n]._index & 0x8000) == 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -129,8 +177,42 @@ get_collector(int n) const {
|
|||
// guaranteed to be shared among all events returned
|
||||
// from a given client).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatFrameData::
|
||||
INLINE float PStatFrameData::
|
||||
get_time(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_data.size(), 0);
|
||||
return _data[n]._time;
|
||||
nassertr(n >= 0 && n < (int)_time_data.size(), 0);
|
||||
return _time_data[n]._value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatFrameData::get_num_levels
|
||||
// Access: Public
|
||||
// Description: Returns the number of individual level values stored
|
||||
// in the FrameData.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PStatFrameData::
|
||||
get_num_levels() const {
|
||||
return _level_data.size();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatFrameData::get_level_collector
|
||||
// Access: Public
|
||||
// Description: Returns the index of the collector associated with
|
||||
// the nth level value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PStatFrameData::
|
||||
get_level_collector(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_level_data.size(), 0);
|
||||
return _level_data[n]._index;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatFrameData::get_level
|
||||
// Access: Public
|
||||
// Description: Returns the height of the nth level value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE float PStatFrameData::
|
||||
get_level(int n) const {
|
||||
nassertr(n >= 0 && n < (int)_level_data.size(), 0);
|
||||
return _level_data[n]._value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,9 +17,15 @@
|
|||
void PStatFrameData::
|
||||
write_datagram(Datagram &destination) const {
|
||||
Data::const_iterator di;
|
||||
for (di = _data.begin(); di != _data.end(); ++di) {
|
||||
destination.add_uint16(_time_data.size());
|
||||
for (di = _time_data.begin(); di != _time_data.end(); ++di) {
|
||||
destination.add_uint16((*di)._index);
|
||||
destination.add_float64((*di)._time);
|
||||
destination.add_float32((*di)._value);
|
||||
}
|
||||
destination.add_uint16(_level_data.size());
|
||||
for (di = _level_data.begin(); di != _level_data.end(); ++di) {
|
||||
destination.add_uint16((*di)._index);
|
||||
destination.add_float32((*di)._value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -31,11 +37,23 @@ write_datagram(Datagram &destination) const {
|
|||
void PStatFrameData::
|
||||
read_datagram(DatagramIterator &source) {
|
||||
clear();
|
||||
while (source.get_remaining_size() > 0) {
|
||||
|
||||
int i;
|
||||
int time_size = source.get_uint16();
|
||||
for (i = 0; i < time_size; i++) {
|
||||
nassertv(source.get_remaining_size() > 0);
|
||||
DataPoint dp;
|
||||
dp._index = source.get_uint16();
|
||||
dp._time = source.get_float64();
|
||||
_data.push_back(dp);
|
||||
dp._value = source.get_float32();
|
||||
_time_data.push_back(dp);
|
||||
}
|
||||
int level_size = source.get_uint16();
|
||||
for (i = 0; i < level_size; i++) {
|
||||
nassertv(source.get_remaining_size() > 0);
|
||||
DataPoint dp;
|
||||
dp._index = source.get_uint16();
|
||||
dp._value = source.get_float32();
|
||||
_level_data.push_back(dp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,22 +17,34 @@ class DatagramIterator;
|
|||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PStatFrameData
|
||||
// Description : Defines the raw timing data for a single frame.
|
||||
// Description : Contains the raw timing and level data for a single
|
||||
// frame. This is a sequence of start/stop events, as
|
||||
// well as a table of level values, associated with a
|
||||
// number of collectors within a single frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA PStatFrameData {
|
||||
public:
|
||||
INLINE bool is_time_empty() const;
|
||||
INLINE bool is_level_empty() const;
|
||||
INLINE bool is_empty() const;
|
||||
INLINE void clear();
|
||||
INLINE void add_start(int index, double time);
|
||||
INLINE void add_stop(int index, double time);
|
||||
|
||||
INLINE double get_start() const;
|
||||
INLINE double get_end() const;
|
||||
INLINE double get_net_time() const;
|
||||
INLINE void add_start(int index, float time);
|
||||
INLINE void add_stop(int index, float time);
|
||||
INLINE void add_level(int index, float level);
|
||||
|
||||
INLINE float get_start() const;
|
||||
INLINE float get_end() const;
|
||||
INLINE float get_net_time() const;
|
||||
|
||||
INLINE int get_num_events() const;
|
||||
INLINE int get_collector(int n) const;
|
||||
INLINE double get_time(int n) const;
|
||||
INLINE int get_time_collector(int n) const;
|
||||
INLINE bool is_start(int n) const;
|
||||
INLINE float get_time(int n) const;
|
||||
|
||||
INLINE int get_num_levels() const;
|
||||
INLINE int get_level_collector(int n) const;
|
||||
INLINE float get_level(int n) const;
|
||||
|
||||
void write_datagram(Datagram &destination) const;
|
||||
void read_datagram(DatagramIterator &source);
|
||||
|
|
@ -41,11 +53,11 @@ private:
|
|||
class DataPoint {
|
||||
public:
|
||||
int _index;
|
||||
double _time;
|
||||
float _value;
|
||||
};
|
||||
typedef vector<DataPoint> Data;
|
||||
|
||||
Data _data;
|
||||
Data _time_data, _level_data;
|
||||
};
|
||||
|
||||
#include "pStatFrameData.I"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
// Filename: pStatProperties.cxx
|
||||
// Created by: drose (17May01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pStatProperties.h"
|
||||
#include "pStatCollectorDef.h"
|
||||
#include "pStatClient.h"
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This file defines the predefined properties (color, sort, etc.) for
|
||||
// the various PStatCollectors that may be defined within Panda or
|
||||
// even elsewhere.
|
||||
//
|
||||
// It is a little strange to defined these properties here instead of
|
||||
// where the collectors are actually declared, but it's handy to have
|
||||
// them all in one place, so we can easily see which colors are
|
||||
// available, etc. It also makes the declarations a lot simpler,
|
||||
// since there are quite a few esoteric parameters to specify.
|
||||
//
|
||||
// We could define these in some external data file that is read in at
|
||||
// runtime, so that you could extend this list without having to
|
||||
// relink panda, but then there are the usual problems with ensuring
|
||||
// that the file is available to you at runtime. The heck with it.
|
||||
//
|
||||
// At least, no other file depends on this file, so it may be modified
|
||||
// without forcing anything else to be recompiled.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct ColorDef {
|
||||
float r, g, b;
|
||||
};
|
||||
|
||||
struct TimeCollectorProperties {
|
||||
const char *name;
|
||||
ColorDef color;
|
||||
float suggested_scale;
|
||||
};
|
||||
|
||||
struct LevelCollectorProperties {
|
||||
const char *name;
|
||||
ColorDef color;
|
||||
const char *units;
|
||||
float suggested_scale;
|
||||
};
|
||||
|
||||
static TimeCollectorProperties time_properties[] = {
|
||||
{ "App", { 0.0, 1.0, 1.0 }, 1.0 / 30.0 },
|
||||
{ "App:Animation", { 1.0, 0.0, 1.0 } },
|
||||
{ "App:Collisions", { 1.0, 0.5, 0.0 } },
|
||||
{ "App:Data graph", { 0.5, 0.8, 0.4 } },
|
||||
{ "App:Show code", { 0.8, 0.2, 1.0 } },
|
||||
{ "Cull", { 0.0, 1.0, 0.0 }, 1.0 / 30.0 },
|
||||
{ "Draw", { 1.0, 0.0, 0.0 }, 1.0 / 30.0 },
|
||||
{ "Draw:Swap buffers", { 0.5, 1.0, 0.8 } },
|
||||
{ "Draw:Clear", { 0.5, 0.7, 0.7 } },
|
||||
{ "Draw:Show fps", { 0.5, 0.8, 1.0 } },
|
||||
{ "Draw:Make current", { 1.0, 0.6, 0.3 } },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static LevelCollectorProperties level_properties[] = {
|
||||
{ "Texture usage", { 1.0, 0.0, 0.0 }, "MB", 8.0 },
|
||||
{ "Texture usage:Active", { 1.0, 1.0, 0.0 } },
|
||||
{ "Texture memory", { 0.0, 0.0, 1.0 }, "MB", 8.0 },
|
||||
{ "Texture memory:In use", { 0.0, 1.0, 1.0 } },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: initialize_collector_def
|
||||
// Description: This is the only accessor function into this table.
|
||||
// The PStatCollectorDef constructor calls it when a new
|
||||
// PStatCollectorDef is created. It should look up in
|
||||
// the table and find a matching definition for this def
|
||||
// by name; if one is found, the properties are applied.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void
|
||||
initialize_collector_def(PStatClient *client, PStatCollectorDef *def) {
|
||||
int i;
|
||||
string fullname;
|
||||
|
||||
if (def->_index == 0) {
|
||||
fullname = def->_name;
|
||||
} else {
|
||||
fullname = client->get_collector_fullname(def->_index);
|
||||
}
|
||||
|
||||
for (i = 0;
|
||||
time_properties[i].name != (const char *)NULL;
|
||||
i++) {
|
||||
const TimeCollectorProperties &tp = time_properties[i];
|
||||
if (fullname == tp.name) {
|
||||
def->_sort = i;
|
||||
def->_suggested_color.set(tp.color.r, tp.color.g, tp.color.b);
|
||||
if (tp.suggested_scale != 0.0) {
|
||||
def->_suggested_scale = tp.suggested_scale;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0;
|
||||
level_properties[i].name != (const char *)NULL;
|
||||
i++) {
|
||||
const LevelCollectorProperties &lp = level_properties[i];
|
||||
if (fullname == lp.name) {
|
||||
def->_sort = i;
|
||||
def->_suggested_color.set(lp.color.r, lp.color.g, lp.color.b);
|
||||
if (lp.suggested_scale != 0.0) {
|
||||
def->_suggested_scale = lp.suggested_scale;
|
||||
}
|
||||
if (lp.units != (const char *)NULL) {
|
||||
def->_level_units = lp.units;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif // DO_PSTATS
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Filename: pStatProperties.h
|
||||
// Created by: drose (17May01)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef PSTATPROPERTIES_H
|
||||
#define PSTATPROPERTIES_H
|
||||
|
||||
#include <pandabase.h>
|
||||
|
||||
#ifdef DO_PSTATS
|
||||
|
||||
class PStatClient;
|
||||
class PStatCollectorDef;
|
||||
|
||||
void initialize_collector_def(PStatClient *client, PStatCollectorDef *def);
|
||||
|
||||
#endif // DO_PSTATS
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -27,33 +27,34 @@ void signal_handler(int) {
|
|||
|
||||
struct SampleData {
|
||||
const char *category;
|
||||
RGBColorf color;
|
||||
int min_ms;
|
||||
int max_ms;
|
||||
float min_ms;
|
||||
float max_ms;
|
||||
bool is_level;
|
||||
};
|
||||
|
||||
SampleData dataset_zero[] = {
|
||||
{ "Draw", RGBColorf(0,0,1), 10, 10 },
|
||||
{ "Cull", RGBColorf(0,1,1), 5, 6 },
|
||||
{ "App", RGBColorf(1,0,0), 0, 5 },
|
||||
{ "Draw", 10, 10, false },
|
||||
{ "Cull", 5, 6, false },
|
||||
{ "App", 0, 5, false },
|
||||
{ "Texture memory", 1, 0.01, true },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
SampleData dataset_one[] = {
|
||||
{ "Draw", RGBColorf(0,0,1), 10, 12 },
|
||||
{ "Squeak", RGBColorf(1,1,0), 25, 30 },
|
||||
{ "Draw", 10, 12, false },
|
||||
{ "Squeak", 25, 30, false },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
SampleData dataset_two[] = {
|
||||
{ "Squeak", RGBColorf(1,1,0), 40, 45 },
|
||||
{ "Cull", RGBColorf(0,1,1), 20, 22 },
|
||||
{ "Draw", RGBColorf(0,0,1), 10, 20 },
|
||||
{ "Animation", RGBColorf(0.5,1,0.5), 0, 0 },
|
||||
{ "Animation:mickey", RGBColorf(0,0,0), 5, 6 },
|
||||
{ "Animation:donald", RGBColorf(0,0,0), 5, 6 },
|
||||
{ "Animation:goofy", RGBColorf(0,0,0), 5, 6 },
|
||||
{ "Animation:pluto", RGBColorf(0,0,0), 5, 6 },
|
||||
{ "Squeak", 40, 45, false },
|
||||
{ "Cull", 20, 22, false },
|
||||
{ "Draw", 10, 20, false },
|
||||
{ "Animation", 0, 0, false },
|
||||
{ "Animation:mickey", 5, 6, false },
|
||||
{ "Animation:donald", 5, 6, false },
|
||||
{ "Animation:goofy", 5, 6, false },
|
||||
{ "Animation:pluto", 5, 6, false },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
|
@ -65,7 +66,7 @@ SampleData *datasets[NUM_DATASETS] = {
|
|||
|
||||
class WaitRequest {
|
||||
public:
|
||||
double _time;
|
||||
float _time;
|
||||
int _index;
|
||||
bool _start;
|
||||
|
||||
|
|
@ -111,10 +112,10 @@ main(int argc, char *argv[]) {
|
|||
ds_index = atoi(argv[3]);
|
||||
} else {
|
||||
// Pick a random Dataset.
|
||||
ds_index = (int)((double)NUM_DATASETS * rand() / (RAND_MAX + 1.0));
|
||||
ds_index = (int)((float)NUM_DATASETS * rand() / (RAND_MAX + 1.0));
|
||||
}
|
||||
if (ds_index < 0 || ds_index >= NUM_DATASETS) {
|
||||
nout << "Invalid datasets; choose a number in the range 0 to "
|
||||
nout << "Invalid dataset; choose a number in the range 0 to "
|
||||
<< NUM_DATASETS - 1 << "\n";
|
||||
exit(1);
|
||||
}
|
||||
|
|
@ -124,39 +125,49 @@ main(int argc, char *argv[]) {
|
|||
vector<PStatCollector> _collectors;
|
||||
int i = 0;
|
||||
while (ds[i].category != (const char *)NULL) {
|
||||
_collectors.push_back(PStatCollector(ds[i].category, ds[i].color, i));
|
||||
_collectors.push_back(PStatCollector(ds[i].category));
|
||||
if (ds[i].is_level) {
|
||||
_collectors[i].set_level(ds[i].min_ms);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
while (!user_interrupted && client->is_connected()) {
|
||||
client->get_main_thread().new_frame();
|
||||
|
||||
double total_ms = 0.0;
|
||||
double now = client->get_clock().get_real_time();
|
||||
float total_ms = 0.0;
|
||||
float now = client->get_clock().get_real_time();
|
||||
|
||||
typedef vector<WaitRequest> Wait;
|
||||
Wait wait;
|
||||
|
||||
// Make up some random intervals to "wait".
|
||||
for (i = 0; i < _collectors.size(); i++) {
|
||||
// A bit of random jitter so the collectors might overlap some.
|
||||
double jitter_ms = (5.0 * rand() / (RAND_MAX + 1.0));
|
||||
for (i = 0; i < (int)_collectors.size(); i++) {
|
||||
if (ds[i].is_level) {
|
||||
// Make up an amount to add/delete to the level this frame.
|
||||
float increment = ds[i].max_ms * (rand() / (RAND_MAX + 1.0) - 0.5);
|
||||
_collectors[i].add_level(increment);
|
||||
|
||||
WaitRequest wr;
|
||||
wr._time = now + jitter_ms / 1000.0;
|
||||
wr._index = i;
|
||||
wr._start = true;
|
||||
wait.push_back(wr);
|
||||
|
||||
int ms_range = ds[i].max_ms - ds[i].min_ms;
|
||||
double ms = (double)ds[i].min_ms +
|
||||
((double)ms_range * rand() / (RAND_MAX + 1.0));
|
||||
now += ms / 1000.0;
|
||||
total_ms += ms;
|
||||
|
||||
wr._time = now + jitter_ms / 1000.0;
|
||||
wr._start = false;
|
||||
wait.push_back(wr);
|
||||
} else {
|
||||
// A bit of random jitter so the collectors might overlap some.
|
||||
float jitter_ms = (5.0 * rand() / (RAND_MAX + 1.0));
|
||||
|
||||
WaitRequest wr;
|
||||
wr._time = now + jitter_ms / 1000.0;
|
||||
wr._index = i;
|
||||
wr._start = true;
|
||||
wait.push_back(wr);
|
||||
|
||||
float ms_range = ds[i].max_ms - ds[i].min_ms;
|
||||
float ms = (float)ds[i].min_ms +
|
||||
(ms_range * rand() / (RAND_MAX + 1.0));
|
||||
now += ms / 1000.0;
|
||||
total_ms += ms;
|
||||
|
||||
wr._time = now + jitter_ms / 1000.0;
|
||||
wr._start = false;
|
||||
wait.push_back(wr);
|
||||
}
|
||||
}
|
||||
|
||||
// Put the wait requests in order, to allow for the jitter, and
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@
|
|||
TypeHandle DirectRenderTraverser::_type_handle;
|
||||
|
||||
#ifndef CPPPARSER
|
||||
PStatCollector DirectRenderTraverser::_draw_pcollector("Draw", RGBColorf(1,0,0), 20);
|
||||
PStatCollector DirectRenderTraverser::_draw_pcollector("Draw");
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ GtkStatsGuide(PStatStripChart *chart) :
|
|||
get_style()->gtkobj()->fg_gc[GTK_WIDGET_STATE (GTK_WIDGET(gtkobj()))];
|
||||
|
||||
Gdk_Font font = fg_gc.get_font();
|
||||
int text_width = font.string_width("000");
|
||||
int text_width = font.string_width("0000");
|
||||
set_usize(text_width, 0);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ GtkStatsLabel(PStatMonitor *monitor, int collector_index,
|
|||
_bg_color.set_rgb_p(rgb[0], rgb[1], rgb[2]);
|
||||
|
||||
// Should our foreground be black or white?
|
||||
double bright =
|
||||
float bright =
|
||||
rgb[0] * 0.299 +
|
||||
rgb[1] * 0.587 +
|
||||
rgb[2] * 0.114;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
GtkStatsMonitor::
|
||||
GtkStatsMonitor() {
|
||||
_destructing = false;
|
||||
_new_collector = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -81,7 +82,7 @@ get_monitor_name() {
|
|||
void GtkStatsMonitor::
|
||||
initialized() {
|
||||
// Create a default window: a strip chart for the main thread.
|
||||
new GtkStatsStripWindow(this, 0, 0, 400, 100);
|
||||
new GtkStatsStripWindow(this, 0, 0, false, 400, 100);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -99,6 +100,22 @@ got_hello() {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GtkStatsMonitor::new_collector
|
||||
// Access: Public, Virtual
|
||||
// Description: Called whenever a new Collector definition is
|
||||
// received from the client. Generally, the client will
|
||||
// send all of its collectors over shortly after
|
||||
// connecting, but there's no guarantee that they will
|
||||
// all be received before the first frames are received.
|
||||
// The monitor should be prepared to accept new Collector
|
||||
// definitions midstream.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsMonitor::
|
||||
new_collector(int) {
|
||||
_new_collector = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GtkStatsMonitor::new_data
|
||||
// Access: Public, Virtual
|
||||
|
|
@ -142,6 +159,7 @@ idle() {
|
|||
for (wi = _windows.begin(); wi != _windows.end(); ++wi) {
|
||||
(*wi)->idle();
|
||||
}
|
||||
_new_collector = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ public:
|
|||
|
||||
virtual void initialized();
|
||||
virtual void got_hello();
|
||||
virtual void new_collector(int collector_index);
|
||||
virtual void new_data(int thread_index, int frame_number);
|
||||
virtual void lost_connection();
|
||||
virtual void idle();
|
||||
|
|
@ -46,6 +47,7 @@ public:
|
|||
Windows _windows;
|
||||
|
||||
bool _destructing;
|
||||
bool _new_collector;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ begin_draw() {
|
|||
int num_guide_bars = get_num_guide_bars();
|
||||
for (int i = 0; i < num_guide_bars; i++) {
|
||||
const GuideBar &bar = get_guide_bar(i);
|
||||
int x = (int)((double)get_xsize() * bar._height / get_horizontal_scale());
|
||||
int x = (int)((float)get_xsize() * bar._height / get_horizontal_scale());
|
||||
|
||||
if (x >= 5 && x <= get_xsize() - 5) {
|
||||
// Only draw it if it's not too close to either edge.
|
||||
|
|
@ -162,7 +162,7 @@ end_draw() {
|
|||
int num_guide_bars = get_num_guide_bars();
|
||||
for (int i = 0; i < num_guide_bars; i++) {
|
||||
const GuideBar &bar = get_guide_bar(i);
|
||||
int x = (int)((double)get_xsize() * bar._height / get_horizontal_scale());
|
||||
int x = (int)((float)get_xsize() * bar._height / get_horizontal_scale());
|
||||
|
||||
if (x >= 5 && x <= get_xsize() - 5) {
|
||||
// Only draw it if it's not too close to either edge.
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ mark_dead() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsPianoWindow::
|
||||
idle() {
|
||||
GtkStatsWindow::idle();
|
||||
_chart->update();
|
||||
}
|
||||
|
||||
|
|
@ -62,28 +63,28 @@ setup_menu() {
|
|||
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("0.1 Hz",
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 0.1)));
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 0.1f)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("1 Hz",
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 1.0)));
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 1.0f)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("5 Hz",
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 5.0)));
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 5.0f)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("10 Hz",
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 10.0)));
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 10.0f)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("20 Hz",
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 20.0)));
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 20.0f)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("30 Hz",
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 30.0)));
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 30.0f)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("60 Hz",
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 60.0)));
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 60.0f)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("120 Hz",
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 120.0)));
|
||||
bind(slot(this, &GtkStatsPianoWindow::menu_hscale), 120.0f)));
|
||||
|
||||
_menu->items().push_back(MenuElem("Scale", *manage(scale_menu)));
|
||||
}
|
||||
|
|
@ -108,7 +109,7 @@ menu_new_window() {
|
|||
// The units is in Hz.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsPianoWindow::
|
||||
menu_hscale(double hz) {
|
||||
menu_hscale(float hz) {
|
||||
_chart->set_horizontal_scale(1.0 / hz);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ public:
|
|||
protected:
|
||||
virtual void setup_menu();
|
||||
virtual void menu_new_window();
|
||||
void menu_hscale(double hz);
|
||||
void menu_hscale(float hz);
|
||||
|
||||
private:
|
||||
void layout_window(int chart_xsize, int chart_ysize);
|
||||
|
|
|
|||
|
|
@ -174,13 +174,22 @@ draw_slice(int x, int frame_number) {
|
|||
// Start by clearing the band first.
|
||||
_pixmap.draw_line(_white_gc, x, 0, x, get_ysize());
|
||||
|
||||
double overall_time = 0.0;
|
||||
float overall_time = 0.0;
|
||||
int y = get_ysize();
|
||||
|
||||
FrameData::const_iterator fi;
|
||||
for (fi = frame.begin(); fi != frame.end(); ++fi) {
|
||||
const ColorData &cd = (*fi);
|
||||
overall_time += cd._net_time;
|
||||
overall_time += cd._net_value;
|
||||
|
||||
if (overall_time > get_vertical_scale()) {
|
||||
// Off the top. Go ahead and clamp it by hand, in case it's so
|
||||
// far off the top we'd overflow the 16-bit pixel value.
|
||||
_pixmap.draw_line(get_collector_gc(cd._collector_index), x, y, x, 0);
|
||||
// And we can consider ourselves done now.
|
||||
return;
|
||||
}
|
||||
|
||||
int top_y = height_to_pixel(overall_time);
|
||||
_pixmap.draw_line(get_collector_gc(cd._collector_index), x, y, x, top_y);
|
||||
y = top_y;
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public:
|
|||
|
||||
Gdk_GC get_collector_gc(int collector_index);
|
||||
|
||||
// This signal is thrown when the user double-clicks on a label or
|
||||
// This signal is thrown when the user float-clicks on a label or
|
||||
// on a band of color.
|
||||
SigC::Signal1<void, int> collector_picked;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,9 @@
|
|||
#include "gtkStatsStripChart.h"
|
||||
#include "gtkStatsGuide.h"
|
||||
|
||||
#include <pStatCollectorDef.h>
|
||||
#include <string_utils.h>
|
||||
|
||||
#include <stdio.h> // for sprintf
|
||||
|
||||
|
||||
|
|
@ -21,15 +23,20 @@ using Gtk::Menu_Helpers::SeparatorElem;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
GtkStatsStripWindow::
|
||||
GtkStatsStripWindow(GtkStatsMonitor *monitor, int thread_index,
|
||||
int collector_index, int chart_xsize, int chart_ysize) :
|
||||
int collector_index, bool show_level,
|
||||
int chart_xsize, int chart_ysize) :
|
||||
GtkStatsWindow(monitor),
|
||||
_thread_index(thread_index),
|
||||
_collector_index(collector_index)
|
||||
_collector_index(collector_index),
|
||||
_show_level(show_level)
|
||||
{
|
||||
_title_unknown = false;
|
||||
_setup_scale_menu = false;
|
||||
|
||||
setup_menu();
|
||||
layout_window(chart_xsize, chart_ysize);
|
||||
|
||||
new_collector(); // To set up the menus in case we can.
|
||||
show();
|
||||
}
|
||||
|
||||
|
|
@ -47,6 +54,40 @@ mark_dead() {
|
|||
_chart->mark_dead();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GtkStatsStripWindow::new_collector
|
||||
// Access: Public, Virtual
|
||||
// Description: Called when a new collector has become known.
|
||||
//
|
||||
// For the GtkStatsStripWindow, this forces a rebuild of
|
||||
// the menu that selects the collectors available for
|
||||
// picking levels.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsStripWindow::
|
||||
new_collector() {
|
||||
const PStatClientData *client_data = _monitor->get_client_data();
|
||||
_levels_menu->items().clear();
|
||||
|
||||
int num_collectors = client_data->get_num_collectors();
|
||||
for (int i = 0; i < num_collectors; i++) {
|
||||
if (client_data->has_collector(i) &&
|
||||
client_data->get_collector_has_level(i)) {
|
||||
const PStatCollectorDef &def =
|
||||
client_data->get_collector_def(i);
|
||||
|
||||
// Normally, we only put top-level entries on the menu. The
|
||||
// lower entries can take care of themselves.
|
||||
if (def._parent_index == 0) {
|
||||
_levels_menu->items().push_back
|
||||
(MenuElem(client_data->get_collector_name(i),
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_show_levels), i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setup_scale_menu();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GtkStatsStripWindow::idle
|
||||
// Access: Public, Virtual
|
||||
|
|
@ -54,11 +95,12 @@ mark_dead() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsStripWindow::
|
||||
idle() {
|
||||
GtkStatsWindow::idle();
|
||||
_chart->update();
|
||||
|
||||
const PStatThreadData *thread_data = _chart->get_view().get_thread_data();
|
||||
if (!thread_data->is_empty()) {
|
||||
double frame_rate = thread_data->get_frame_rate();
|
||||
float frame_rate = thread_data->get_frame_rate();
|
||||
char buffer[128];
|
||||
sprintf(buffer, "Frame rate: %0.1f Hz", frame_rate);
|
||||
_frame_rate_label->set_text(buffer);
|
||||
|
|
@ -82,51 +124,102 @@ setup_menu() {
|
|||
|
||||
speed_menu->items().push_back
|
||||
(MenuElem("1", // 1 chart width scrolls by per minute.
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_hscale), 1.0)));
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_hscale), 1.0f)));
|
||||
speed_menu->items().push_back
|
||||
(MenuElem("2", // 2 chart widths scroll by per minute.
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_hscale), 2.0)));
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_hscale), 2.0f)));
|
||||
speed_menu->items().push_back
|
||||
(MenuElem("3",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_hscale), 3.0)));
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_hscale), 3.0f)));
|
||||
speed_menu->items().push_back
|
||||
(MenuElem("6",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_hscale), 6.0)));
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_hscale), 6.0f)));
|
||||
speed_menu->items().push_back
|
||||
(MenuElem("12",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_hscale), 12.0)));
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_hscale), 12.0f)));
|
||||
|
||||
_menu->items().push_back(MenuElem("Speed", *manage(speed_menu)));
|
||||
|
||||
|
||||
Gtk::Menu *scale_menu = new Gtk::Menu;
|
||||
_scale_menu = new Gtk::Menu;
|
||||
_scale_menu->items().push_back
|
||||
(MenuElem("Auto scale",
|
||||
slot(this, &GtkStatsStripWindow::menu_auto_vscale)));
|
||||
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("10000 ms (0.1 Hz)",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_vscale), 0.1)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("1000 ms (1 Hz)",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_vscale), 1.0)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("200 ms (5 Hz)",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_vscale), 5.0)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("100 ms (10 Hz)",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_vscale), 10.0)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("50.0 ms (20 Hz)",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_vscale), 20.0)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("33.3 ms (30 Hz)",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_vscale), 30.0)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("16.7 ms (60 Hz)",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_vscale), 60.0)));
|
||||
scale_menu->items().push_back
|
||||
(MenuElem("8.3 ms (120 Hz)",
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_vscale), 120.0)));
|
||||
_menu->items().push_back(MenuElem("Scale", *manage(_scale_menu)));
|
||||
|
||||
_menu->items().push_back(MenuElem("Scale", *manage(scale_menu)));
|
||||
_levels_menu = new Gtk::Menu;
|
||||
_menu->items().push_back(MenuElem("Levels", *manage(_levels_menu)));
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GtkStatsStripWindow::setup_scale_menu
|
||||
// Access: Protected
|
||||
// Description: Sets up the options on the scale menu. We can't do
|
||||
// this until we have initialized the _chart member and
|
||||
// we have gotten our first collector_index.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsStripWindow::
|
||||
setup_scale_menu() {
|
||||
if (_setup_scale_menu) {
|
||||
// Already done it.
|
||||
return;
|
||||
}
|
||||
|
||||
const PStatClientData *client_data = _monitor->get_client_data();
|
||||
if (!client_data->has_collector(_collector_index)) {
|
||||
// Can't set up the scale menu yet.
|
||||
return;
|
||||
}
|
||||
|
||||
const PStatCollectorDef &def = client_data->get_collector_def(_collector_index);
|
||||
float base_scale = 1.0;
|
||||
string unit_name = def._level_units;
|
||||
|
||||
if (_show_level) {
|
||||
_chart->set_guide_bar_unit_name(unit_name);
|
||||
_chart->set_guide_bar_units(PStatGraph::GBU_named);
|
||||
|
||||
} else {
|
||||
_chart->set_guide_bar_units(PStatGraph::GBU_ms);
|
||||
}
|
||||
|
||||
if (def._suggested_scale != 0.0) {
|
||||
base_scale = def._suggested_scale;
|
||||
} else if (!_show_level) {
|
||||
base_scale = 1.0 / _chart->get_target_frame_rate();
|
||||
}
|
||||
|
||||
static const float scales[] = {
|
||||
50.0,
|
||||
10.0,
|
||||
5.0,
|
||||
2.0,
|
||||
1.0,
|
||||
0.5,
|
||||
0.2,
|
||||
0.1,
|
||||
0.02,
|
||||
};
|
||||
static const int num_scales = sizeof(scales) / sizeof(float);
|
||||
|
||||
for (int i = 0; i < num_scales; i++) {
|
||||
float scale = base_scale * scales[i];
|
||||
string label;
|
||||
|
||||
if (_show_level) {
|
||||
label = _chart->format_number(scale, PStatGraph::GBU_named | PStatGraph::GBU_show_units, unit_name);
|
||||
} else {
|
||||
label = _chart->format_number(scale, PStatGraph::GBU_ms | PStatGraph::GBU_hz | PStatGraph::GBU_show_units);
|
||||
}
|
||||
|
||||
_scale_menu->items().push_back
|
||||
(MenuElem(label,
|
||||
bind(slot(this, &GtkStatsStripWindow::menu_vscale), scale)));
|
||||
}
|
||||
|
||||
_setup_scale_menu = true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -136,8 +229,9 @@ setup_menu() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsStripWindow::
|
||||
menu_new_window() {
|
||||
new GtkStatsStripWindow(_monitor, _thread_index, _collector_index,
|
||||
_chart->get_xsize(), _chart->get_ysize());
|
||||
new GtkStatsStripWindow(_monitor, _thread_index, _collector_index,
|
||||
_show_level,
|
||||
_chart->get_xsize(), _chart->get_ysize());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -151,7 +245,7 @@ menu_new_window() {
|
|||
// The units is in chart width per minute.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsStripWindow::
|
||||
menu_hscale(double wpm) {
|
||||
menu_hscale(float wpm) {
|
||||
_chart->set_horizontal_scale(60.0 / wpm);
|
||||
}
|
||||
|
||||
|
|
@ -161,11 +255,36 @@ menu_hscale(double wpm) {
|
|||
// Description: Selects a new vertical scale for the strip chart.
|
||||
// This is done from the menu called "Scale".
|
||||
//
|
||||
// The units is in Hz.
|
||||
// The units is in seconds, or whatever the units
|
||||
// of choice are.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsStripWindow::
|
||||
menu_vscale(double hz) {
|
||||
_chart->set_vertical_scale(1.0 / hz);
|
||||
menu_vscale(float max_height) {
|
||||
_chart->set_vertical_scale(max_height);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GtkStatsStripWindow::menu_auto_vscale
|
||||
// Access: Protected
|
||||
// Description: Selects a suitable vertical scale based on the data
|
||||
// already visible in the chart.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsStripWindow::
|
||||
menu_auto_vscale() {
|
||||
_chart->set_auto_vertical_scale();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GtkStatsStripWindow::menu_show_levels
|
||||
// Access: Protected
|
||||
// Description: Shows the level values known for the indicated
|
||||
// collector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsStripWindow::
|
||||
menu_show_levels(int collector_index) {
|
||||
new GtkStatsStripWindow(_monitor, _thread_index, collector_index,
|
||||
true,
|
||||
_chart->get_xsize(), _chart->get_ysize());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -180,7 +299,8 @@ menu_vscale(double hz) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsStripWindow::
|
||||
open_subchart(int collector_index) {
|
||||
new GtkStatsStripWindow(_monitor, _thread_index, collector_index,
|
||||
new GtkStatsStripWindow(_monitor, _thread_index, collector_index,
|
||||
_show_level,
|
||||
_chart->get_xsize(), _chart->get_ysize());
|
||||
}
|
||||
|
||||
|
|
@ -224,10 +344,18 @@ layout_window(int chart_xsize, int chart_ysize) {
|
|||
frame->show();
|
||||
chart_table->attach(*manage(frame), 1, 2, 1, 2);
|
||||
|
||||
_chart = new GtkStatsStripChart(_monitor,
|
||||
_monitor->get_view(_thread_index),
|
||||
_collector_index,
|
||||
chart_xsize, chart_ysize);
|
||||
if (_show_level) {
|
||||
_chart = new GtkStatsStripChart(_monitor,
|
||||
_monitor->get_level_view(_collector_index, _thread_index),
|
||||
_collector_index,
|
||||
chart_xsize, chart_ysize);
|
||||
} else {
|
||||
_chart = new GtkStatsStripChart(_monitor,
|
||||
_monitor->get_view(_thread_index),
|
||||
_collector_index,
|
||||
chart_xsize, chart_ysize);
|
||||
}
|
||||
|
||||
_chart->collector_picked.
|
||||
connect(slot(this, &GtkStatsStripWindow::open_subchart));
|
||||
frame->add(*manage(_chart));
|
||||
|
|
@ -254,7 +382,16 @@ get_title_text() {
|
|||
|
||||
const PStatClientData *client_data = _monitor->get_client_data();
|
||||
if (client_data->has_collector(_collector_index)) {
|
||||
text = client_data->get_collector_name(_collector_index) + " time";
|
||||
const PStatCollectorDef &def = client_data->get_collector_def(_collector_index);
|
||||
if (_show_level) {
|
||||
if (def._level_units.empty()) {
|
||||
text = def._name;
|
||||
} else {
|
||||
text = def._name + " (" + def._level_units + ")";
|
||||
}
|
||||
} else {
|
||||
text = def._name + " time";
|
||||
}
|
||||
} else {
|
||||
_title_unknown = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,16 +21,21 @@ class GtkStatsStripChart;
|
|||
class GtkStatsStripWindow : public GtkStatsWindow {
|
||||
public:
|
||||
GtkStatsStripWindow(GtkStatsMonitor *monitor, int thread_index,
|
||||
int collector_index, int chart_xsize, int chart_ysize);
|
||||
int collector_index, bool show_level,
|
||||
int chart_xsize, int chart_ysize);
|
||||
|
||||
virtual void mark_dead();
|
||||
virtual void new_collector();
|
||||
virtual void idle();
|
||||
|
||||
protected:
|
||||
virtual void setup_menu();
|
||||
void setup_scale_menu();
|
||||
virtual void menu_new_window();
|
||||
void menu_hscale(double wpm);
|
||||
void menu_vscale(double hz);
|
||||
void menu_hscale(float wpm);
|
||||
void menu_vscale(float max_height);
|
||||
void menu_auto_vscale();
|
||||
void menu_show_levels(int collector_index);
|
||||
void open_subchart(int collector_index);
|
||||
|
||||
private:
|
||||
|
|
@ -40,11 +45,16 @@ private:
|
|||
private:
|
||||
int _thread_index;
|
||||
int _collector_index;
|
||||
bool _show_level;
|
||||
bool _title_unknown;
|
||||
bool _setup_scale_menu;
|
||||
|
||||
Gtk::Label *_title_label;
|
||||
Gtk::Label *_frame_rate_label;
|
||||
GtkStatsStripChart *_chart;
|
||||
|
||||
Gtk::Menu *_scale_menu;
|
||||
Gtk::Menu *_levels_menu;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -81,17 +81,7 @@ mark_dead() {
|
|||
// the window cares.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsWindow::
|
||||
new_collector(int) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: GtkStatsWindow::new_thread
|
||||
// Access: Public, Virtual
|
||||
// Description: Called when a new thread has become known, in case
|
||||
// the window cares.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsWindow::
|
||||
new_thread(int) {
|
||||
new_collector() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -101,6 +91,9 @@ new_thread(int) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsWindow::
|
||||
idle() {
|
||||
if (_monitor->_new_collector) {
|
||||
new_collector();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -150,7 +143,7 @@ setup_menu() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void GtkStatsWindow::
|
||||
menu_open_strip_chart() {
|
||||
new GtkStatsStripWindow(_monitor, 0, 0, 400, 100);
|
||||
new GtkStatsStripWindow(_monitor, 0, 0, false, 400, 100);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@ public:
|
|||
|
||||
virtual void update_title();
|
||||
virtual void mark_dead();
|
||||
virtual void new_collector(int collector_index);
|
||||
virtual void new_thread(int thread_index);
|
||||
virtual void new_collector();
|
||||
virtual void idle();
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ PStatClientData::
|
|||
~PStatClientData() {
|
||||
Collectors::const_iterator ci;
|
||||
for (ci = _collectors.begin(); ci != _collectors.end(); ++ci) {
|
||||
delete (*ci);
|
||||
delete (*ci)._def;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ get_num_collectors() const {
|
|||
bool PStatClientData::
|
||||
has_collector(int index) const {
|
||||
return (index >= 0 && index < (int)_collectors.size() &&
|
||||
_collectors[index] != (PStatCollectorDef *)NULL);
|
||||
_collectors[index]._def != (PStatCollectorDef *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -98,7 +98,7 @@ get_collector_def(int index) const {
|
|||
if (!has_collector(index)) {
|
||||
return _null_collector;
|
||||
}
|
||||
return *_collectors[index];
|
||||
return *_collectors[index]._def;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -111,7 +111,7 @@ get_collector_name(int index) const {
|
|||
if (!has_collector(index)) {
|
||||
return "Unknown";
|
||||
}
|
||||
const PStatCollectorDef *def = _collectors[index];
|
||||
const PStatCollectorDef *def = _collectors[index]._def;
|
||||
return def->_name;
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +129,7 @@ get_collector_fullname(int index) const {
|
|||
return "Unknown";
|
||||
}
|
||||
|
||||
const PStatCollectorDef *def = _collectors[index];
|
||||
const PStatCollectorDef *def = _collectors[index]._def;
|
||||
if (def->_parent_index == 0) {
|
||||
return def->_name;
|
||||
} else {
|
||||
|
|
@ -137,6 +137,34 @@ get_collector_fullname(int index) const {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientData::set_collector_has_level
|
||||
// Access: Public
|
||||
// Description: Indicates whether the given collector has level data
|
||||
// (and consequently, whether it should appear on the
|
||||
// Levels menu).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientData::
|
||||
set_collector_has_level(int index, bool flag) {
|
||||
slot_collector(index);
|
||||
nassertv(index >= 0 && index < (int)_collectors.size());
|
||||
_collectors[index]._is_level = flag;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientData::get_collector_has_level
|
||||
// Access: Public
|
||||
// Description: Returns whether the given collector has level data
|
||||
// (and consequently, whether it should appear on the
|
||||
// Levels menu).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool PStatClientData::
|
||||
get_collector_has_level(int index) const {
|
||||
return (index >= 0 && index < (int)_collectors.size() &&
|
||||
_collectors[index]._is_level);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientData::get_num_threads
|
||||
// Access: Public
|
||||
|
|
@ -228,20 +256,15 @@ get_child_distance(int parent, int child) const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientData::
|
||||
add_collector(PStatCollectorDef *def) {
|
||||
// A sanity check on the index number.
|
||||
nassertv(def->_index < 1000);
|
||||
slot_collector(def->_index);
|
||||
nassertv(def->_index >= 0 && def->_index < (int)_collectors.size());
|
||||
|
||||
// Make sure we have enough slots allocated.
|
||||
while ((int)_collectors.size() <= def->_index) {
|
||||
_collectors.push_back(NULL);
|
||||
if (_collectors[def->_index]._def != (PStatCollectorDef *)NULL) {
|
||||
// Free the old definition, if any.
|
||||
delete _collectors[def->_index]._def;
|
||||
}
|
||||
|
||||
if (_collectors[def->_index] != (PStatCollectorDef *)NULL) {
|
||||
// Free any old definition.
|
||||
delete _collectors[def->_index];
|
||||
}
|
||||
|
||||
_collectors[def->_index] = def;
|
||||
_collectors[def->_index]._def = def;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -288,3 +311,22 @@ record_new_frame(int thread_index, int frame_number,
|
|||
nassertv(thread_index >= 0 && thread_index < (int)_threads.size());
|
||||
_threads[thread_index]._data->record_new_frame(frame_number, frame_data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatClientData::slot_collector
|
||||
// Access: Private
|
||||
// Description: Makes sure there is an entry in the array for a
|
||||
// collector with the given index number.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatClientData::
|
||||
slot_collector(int collector_index) {
|
||||
// A sanity check on the index number.
|
||||
nassertv(collector_index < 1000);
|
||||
|
||||
while ((int)_collectors.size() <= collector_index) {
|
||||
Collector collector;
|
||||
collector._def = (PStatCollectorDef *)NULL;
|
||||
collector._is_level = false;
|
||||
_collectors.push_back(collector);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,6 +36,8 @@ public:
|
|||
const PStatCollectorDef &get_collector_def(int index) const;
|
||||
string get_collector_name(int index) const;
|
||||
string get_collector_fullname(int index) const;
|
||||
void set_collector_has_level(int index, bool flag);
|
||||
bool get_collector_has_level(int index) const;
|
||||
|
||||
int get_num_threads() const;
|
||||
bool has_thread(int index) const;
|
||||
|
|
@ -50,12 +52,21 @@ public:
|
|||
|
||||
void record_new_frame(int thread_index, int frame_number,
|
||||
PStatFrameData *frame_data);
|
||||
private:
|
||||
void slot_collector(int collector_index);
|
||||
|
||||
|
||||
private:
|
||||
bool _is_alive;
|
||||
PStatReader *_reader;
|
||||
|
||||
typedef vector<PStatCollectorDef *> Collectors;
|
||||
class Collector {
|
||||
public:
|
||||
PStatCollectorDef *_def;
|
||||
bool _is_level;
|
||||
};
|
||||
|
||||
typedef vector<Collector> Collectors;
|
||||
Collectors _collectors;
|
||||
|
||||
class Thread {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ get_label_color(int n) const {
|
|||
// placement of guide bars.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatGraph::
|
||||
set_target_frame_rate(double frame_rate) {
|
||||
set_target_frame_rate(float frame_rate) {
|
||||
if (_target_frame_rate != frame_rate) {
|
||||
_target_frame_rate = frame_rate;
|
||||
normal_guide_bars();
|
||||
|
|
@ -80,7 +80,7 @@ set_target_frame_rate(double frame_rate) {
|
|||
// Description: Returns the indicated target frame rate in Hz. See
|
||||
// set_target_frame_rate().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatGraph::
|
||||
INLINE float PStatGraph::
|
||||
get_target_frame_rate() const {
|
||||
return _target_frame_rate;
|
||||
}
|
||||
|
|
@ -131,3 +131,27 @@ INLINE int PStatGraph::
|
|||
get_guide_bar_units() const {
|
||||
return _guide_bar_units;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatGraph::set_guide_bar_unit_name
|
||||
// Access: Public
|
||||
// Description: Sets the name of the units to be used for the guide
|
||||
// bars if the units type is set to GBU_named |
|
||||
// GBU_show_units.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatGraph::
|
||||
set_guide_bar_unit_name(const string &unit_name) {
|
||||
_unit_name = unit_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatGraph::get_guide_bar_unit_name
|
||||
// Access: Public
|
||||
// Description: Returns the name of the units to be used for the guide
|
||||
// bars if the units type is set to GBU_named |
|
||||
// GBU_show_units.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const string &PStatGraph::
|
||||
get_guide_bar_unit_name() const {
|
||||
return _unit_name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatGraph::GuideBar::
|
||||
GuideBar(double height, const string &label, bool is_target) :
|
||||
GuideBar(float height, const string &label, bool is_target) :
|
||||
_height(height),
|
||||
_label(label),
|
||||
_is_target(is_target)
|
||||
|
|
@ -98,6 +98,80 @@ get_guide_bar(int n) const {
|
|||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatGraph::format_number
|
||||
// Access: Public, Static
|
||||
// Description: Returns a string representing the value nicely
|
||||
// formatted for its range.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PStatGraph::
|
||||
format_number(float value) {
|
||||
char buffer[128];
|
||||
|
||||
if (value < 0.01) {
|
||||
sprintf(buffer, "%0.4f", value);
|
||||
} else if (value < 0.1) {
|
||||
sprintf(buffer, "%0.3f", value);
|
||||
} else if (value < 1.0) {
|
||||
sprintf(buffer, "%0.2f", value);
|
||||
} else if (value < 10.0) {
|
||||
sprintf(buffer, "%0.1f", value);
|
||||
} else {
|
||||
sprintf(buffer, "%0.0f", value);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatGraph::format_number
|
||||
// Access: Public, Static
|
||||
// Description: Returns a string representing the value nicely
|
||||
// formatted for its range, including the units
|
||||
// as indicated.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
string PStatGraph::
|
||||
format_number(float value, int guide_bar_units, const string &unit_name) {
|
||||
string label;
|
||||
|
||||
if ((guide_bar_units & GBU_named) != 0) {
|
||||
// Units are whatever is specified by unit_name, not a time unit
|
||||
// at all.
|
||||
label = format_number(value);
|
||||
if ((guide_bar_units & GBU_show_units) != 0 && !unit_name.empty()) {
|
||||
label += " ";
|
||||
label += unit_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Units are either milliseconds or hz, or both.
|
||||
if ((guide_bar_units & GBU_ms) != 0) {
|
||||
float ms = value * 1000.0;
|
||||
label += format_number(ms);
|
||||
if ((guide_bar_units & GBU_show_units) != 0) {
|
||||
label += " ms";
|
||||
}
|
||||
}
|
||||
|
||||
if ((guide_bar_units & GBU_hz) != 0) {
|
||||
float hz = 1.0 / value;
|
||||
|
||||
if ((guide_bar_units & GBU_ms) != 0) {
|
||||
label += " (";
|
||||
}
|
||||
label += format_number(hz);
|
||||
if ((guide_bar_units & GBU_show_units) != 0) {
|
||||
label += " Hz";
|
||||
}
|
||||
if ((guide_bar_units & GBU_ms) != 0) {
|
||||
label += ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
// STL function object for sorting labels in order by the collector's
|
||||
// sort index, used in update_labels(), below.
|
||||
class SortCollectorLabels {
|
||||
|
|
@ -122,7 +196,7 @@ public:
|
|||
// Description: Resets the list of guide bars.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatGraph::
|
||||
update_guide_bars(int num_bars, double scale) {
|
||||
update_guide_bars(int num_bars, float scale) {
|
||||
_guide_bars.clear();
|
||||
|
||||
// We'd like to draw about num_bars bars on the chart. But we also
|
||||
|
|
@ -133,9 +207,9 @@ update_guide_bars(int num_bars, double scale) {
|
|||
// Choose a suitable harmonic of the target frame rate near the
|
||||
// bottom part of the chart.
|
||||
|
||||
double bottom = (double)num_bars / scale;
|
||||
float bottom = (float)num_bars / scale;
|
||||
|
||||
double harmonic;
|
||||
float harmonic;
|
||||
if (_target_frame_rate < bottom) {
|
||||
// n * tfr
|
||||
harmonic = floor(bottom / _target_frame_rate + 0.5) * _target_frame_rate;
|
||||
|
|
@ -153,50 +227,24 @@ update_guide_bars(int num_bars, double scale) {
|
|||
_guide_bars_changed = true;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatGraph::make_guide_bar
|
||||
// Access: Protected
|
||||
// Description: Makes a guide bar for the indicated frame rate.
|
||||
// Description: Makes a guide bar for the indicated elapsed time or
|
||||
// level units.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatGraph::GuideBar PStatGraph::
|
||||
make_guide_bar(double time) const {
|
||||
string label;
|
||||
make_guide_bar(float value) const {
|
||||
string label = format_number(value, _guide_bar_units, _unit_name);
|
||||
|
||||
char buffer[128];
|
||||
bool is_target = false;
|
||||
|
||||
if ((_guide_bar_units & GBU_ms) != 0) {
|
||||
double ms = time * 1000.0;
|
||||
if (ms < 10.0) {
|
||||
sprintf(buffer, "%0.1f", ms);
|
||||
} else {
|
||||
sprintf(buffer, "%0.0f", ms);
|
||||
}
|
||||
label += buffer;
|
||||
if ((_guide_bar_units & GBU_show_units) != 0) {
|
||||
label += " ms";
|
||||
}
|
||||
if ((_guide_bar_units & GBU_named) == 0) {
|
||||
// If it's a time unit, check to see if it matches our target
|
||||
// frame rate.
|
||||
float hz = 1.0 / value;
|
||||
is_target = IS_NEARLY_EQUAL(hz, _target_frame_rate);
|
||||
}
|
||||
|
||||
if ((_guide_bar_units & GBU_hz) != 0) {
|
||||
double frame_rate = 1.0 / time;
|
||||
if (frame_rate < 10.0) {
|
||||
sprintf(buffer, "%0.1f", frame_rate);
|
||||
} else {
|
||||
sprintf(buffer, "%0.0f", frame_rate);
|
||||
}
|
||||
if ((_guide_bar_units & GBU_ms) != 0) {
|
||||
label += " (";
|
||||
}
|
||||
label += buffer;
|
||||
if ((_guide_bar_units & GBU_show_units) != 0) {
|
||||
label += " Hz";
|
||||
}
|
||||
if ((_guide_bar_units & GBU_ms) != 0) {
|
||||
label += ")";
|
||||
}
|
||||
}
|
||||
|
||||
return GuideBar(time, label,
|
||||
IS_NEARLY_EQUAL(1.0 / time, _target_frame_rate));
|
||||
return GuideBar(value, label, is_target);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,18 +36,18 @@ public:
|
|||
INLINE string get_label_name(int n) const;
|
||||
INLINE RGBColorf get_label_color(int n) const;
|
||||
|
||||
INLINE void set_target_frame_rate(double frame_rate);
|
||||
INLINE double get_target_frame_rate() const;
|
||||
INLINE void set_target_frame_rate(float frame_rate);
|
||||
INLINE float get_target_frame_rate() const;
|
||||
|
||||
INLINE int get_xsize() const;
|
||||
INLINE int get_ysize() const;
|
||||
|
||||
class GuideBar {
|
||||
public:
|
||||
GuideBar(double height, const string &label, bool is_target);
|
||||
GuideBar(float height, const string &label, bool is_target);
|
||||
GuideBar(const GuideBar ©);
|
||||
|
||||
double _height;
|
||||
float _height;
|
||||
string _label;
|
||||
bool _is_target;
|
||||
};
|
||||
|
|
@ -55,7 +55,8 @@ public:
|
|||
enum GuideBarUnits {
|
||||
GBU_hz = 0x0001,
|
||||
GBU_ms = 0x0002,
|
||||
GBU_show_units = 0x0004,
|
||||
GBU_named = 0x0004,
|
||||
GBU_show_units = 0x0008,
|
||||
};
|
||||
|
||||
int get_num_guide_bars() const;
|
||||
|
|
@ -63,18 +64,24 @@ public:
|
|||
|
||||
INLINE void set_guide_bar_units(int unit_mask);
|
||||
INLINE int get_guide_bar_units() const;
|
||||
INLINE void set_guide_bar_unit_name(const string &unit_name);
|
||||
INLINE const string &get_guide_bar_unit_name() const;
|
||||
|
||||
static string format_number(float value);
|
||||
static string format_number(float value, int guide_bar_units,
|
||||
const string &unit_name = string());
|
||||
|
||||
protected:
|
||||
virtual void normal_guide_bars()=0;
|
||||
void update_guide_bars(int num_bars, double scale);
|
||||
GuideBar make_guide_bar(double time) const;
|
||||
void update_guide_bars(int num_bars, float scale);
|
||||
GuideBar make_guide_bar(float value) const;
|
||||
|
||||
bool _labels_changed;
|
||||
bool _guide_bars_changed;
|
||||
|
||||
PT(PStatMonitor) _monitor;
|
||||
|
||||
double _target_frame_rate;
|
||||
float _target_frame_rate;
|
||||
|
||||
int _xsize;
|
||||
int _ysize;
|
||||
|
|
@ -87,6 +94,7 @@ protected:
|
|||
typedef vector<GuideBar> GuideBars;
|
||||
GuideBars _guide_bars;
|
||||
int _guide_bar_units;
|
||||
string _unit_name;
|
||||
};
|
||||
|
||||
#include "pStatGraph.I"
|
||||
|
|
|
|||
|
|
@ -112,9 +112,9 @@ get_collector_color(int collector_index) {
|
|||
|
||||
// We didn't have a color for the collector; make one up.
|
||||
RGBColorf random_color;
|
||||
random_color[0] = (double)rand() / (double)RAND_MAX;
|
||||
random_color[1] = (double)rand() / (double)RAND_MAX;
|
||||
random_color[2] = (double)rand() / (double)RAND_MAX;
|
||||
random_color[0] = (float)rand() / (float)RAND_MAX;
|
||||
random_color[1] = (float)rand() / (float)RAND_MAX;
|
||||
random_color[2] = (float)rand() / (float)RAND_MAX;
|
||||
|
||||
ci = _colors.insert(Colors::value_type(collector_index, random_color)).first;
|
||||
return (*ci).second;
|
||||
|
|
@ -139,6 +139,33 @@ get_view(int thread_index) {
|
|||
return (*vi).second;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatMonitor::get_level_view
|
||||
// Access: Public
|
||||
// Description: Returns a view on the level value (as opposed to
|
||||
// elapsed time) for the given collector over the given
|
||||
// thread. If there is no such view already for the
|
||||
// indicated thread, this will create one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
PStatView &PStatMonitor::
|
||||
get_level_view(int collector_index, int thread_index) {
|
||||
LevelViews::iterator lvi;
|
||||
lvi = _level_views.find(collector_index);
|
||||
if (lvi == _level_views.end()) {
|
||||
lvi = _level_views.insert(LevelViews::value_type(collector_index, Views())).first;
|
||||
}
|
||||
Views &views = (*lvi).second;
|
||||
|
||||
Views::iterator vi;
|
||||
vi = views.find(thread_index);
|
||||
if (vi == views.end()) {
|
||||
vi = views.insert(Views::value_type(thread_index, PStatView())).first;
|
||||
(*vi).second.set_thread_data(_client_data->get_thread_data(thread_index));
|
||||
(*vi).second.constrain(collector_index, true);
|
||||
}
|
||||
return (*vi).second;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatMonitor::initialized
|
||||
// Access: Public, Virtual
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ public:
|
|||
INLINE string get_client_progname() const;
|
||||
|
||||
PStatView &get_view(int thread_index);
|
||||
PStatView &get_level_view(int collector_index, int thread_index);
|
||||
|
||||
|
||||
// The following virtual methods may be overridden by a derived
|
||||
|
|
@ -84,6 +85,8 @@ private:
|
|||
|
||||
typedef map<int, PStatView> Views;
|
||||
Views _views;
|
||||
typedef map<int, Views> LevelViews;
|
||||
LevelViews _level_views;
|
||||
|
||||
typedef map<int, RGBColorf> Colors;
|
||||
Colors _colors;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
// horizontal axis represents. This may force a redraw.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatPianoRoll::
|
||||
set_horizontal_scale(double time_width) {
|
||||
set_horizontal_scale(float time_width) {
|
||||
if (_time_width != time_width) {
|
||||
_time_width = time_width;
|
||||
normal_guide_bars();
|
||||
|
|
@ -24,7 +24,7 @@ set_horizontal_scale(double time_width) {
|
|||
// Description: Returns the amount of total time the width of the
|
||||
// horizontal axis represents.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatPianoRoll::
|
||||
INLINE float PStatPianoRoll::
|
||||
get_horizontal_scale() const {
|
||||
return _time_width;
|
||||
}
|
||||
|
|
@ -35,8 +35,8 @@ get_horizontal_scale() const {
|
|||
// Description: Converts a timestamp to a horizontal pixel offset.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PStatPianoRoll::
|
||||
timestamp_to_pixel(double time) const {
|
||||
return (int)((double)_xsize * (time - _start_time) / _time_width);
|
||||
timestamp_to_pixel(float time) const {
|
||||
return (int)((float)_xsize * (time - _start_time) / _time_width);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -44,7 +44,7 @@ timestamp_to_pixel(double time) const {
|
|||
// Access: Public
|
||||
// Description: Converts a horizontal pixel offset to a timestamp.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatPianoRoll::
|
||||
INLINE float PStatPianoRoll::
|
||||
pixel_to_timestamp(int x) const {
|
||||
return _time_width * (double)x / (double)_xsize + _start_time;
|
||||
return _time_width * (float)x / (float)_xsize + _start_time;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ clear() {
|
|||
// second data point turns it off (ends the bar).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatPianoRoll::BarBuilder::
|
||||
add_data_point(double time) {
|
||||
add_data_point(float time) {
|
||||
if (_color_bars.empty() || _color_bars.back()._end >= 0.0) {
|
||||
// This is an odd-numbered data point: start the bar.
|
||||
ColorBar bar;
|
||||
|
|
@ -63,7 +63,7 @@ add_data_point(double time) {
|
|||
// by a corresponding end-bar data point.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatPianoRoll::BarBuilder::
|
||||
finish(double time) {
|
||||
finish(float time) {
|
||||
if (!_color_bars.empty() && _color_bars.back()._end < 0.0) {
|
||||
nout << "Warning: collector was left on at the end of the frame.\n";
|
||||
_color_bars.back()._end = time;
|
||||
|
|
@ -262,7 +262,7 @@ public:
|
|||
// -1 appear to be a very large positive integer, thus placing
|
||||
// collectors with a -1 sort value at the very end.
|
||||
return
|
||||
(unsigned int)_client_data->get_collector_def(a)._sort <
|
||||
(unsigned int)_client_data->get_collector_def(a)._sort >
|
||||
(unsigned int)_client_data->get_collector_def(b)._sort;
|
||||
}
|
||||
const PStatClientData *_client_data;
|
||||
|
|
@ -287,8 +287,8 @@ compute_page(const PStatFrameData &frame_data) {
|
|||
|
||||
int num_events = frame_data.get_num_events();
|
||||
for (int i = 0; i < num_events; i++) {
|
||||
int collector_index = (frame_data.get_collector(i) & 0x7fff);
|
||||
double time = frame_data.get_time(i);
|
||||
int collector_index = frame_data.get_time_collector(i);
|
||||
float time = frame_data.get_time(i);
|
||||
_page_data[collector_index].add_data_point(time);
|
||||
}
|
||||
|
||||
|
|
@ -312,7 +312,7 @@ compute_page(const PStatFrameData &frame_data) {
|
|||
}
|
||||
|
||||
// Finally, make sure all of the bars are closed.
|
||||
double time = frame_data.get_end();
|
||||
float time = frame_data.get_end();
|
||||
for (pi = _page_data.begin(); pi != _page_data.end(); ++pi) {
|
||||
(*pi).second.finish(time);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@ public:
|
|||
|
||||
void update();
|
||||
|
||||
INLINE void set_horizontal_scale(double time_width);
|
||||
INLINE double get_horizontal_scale() const;
|
||||
INLINE void set_horizontal_scale(float time_width);
|
||||
INLINE float get_horizontal_scale() const;
|
||||
|
||||
INLINE int timestamp_to_pixel(double time) const;
|
||||
INLINE double pixel_to_timestamp(int x) const;
|
||||
INLINE int timestamp_to_pixel(float time) const;
|
||||
INLINE float pixel_to_timestamp(int x) const;
|
||||
|
||||
protected:
|
||||
void changed_size(int xsize, int ysize);
|
||||
|
|
@ -62,13 +62,13 @@ private:
|
|||
|
||||
int _thread_index;
|
||||
|
||||
double _time_width;
|
||||
double _start_time;
|
||||
float _time_width;
|
||||
float _start_time;
|
||||
|
||||
class ColorBar {
|
||||
public:
|
||||
double _start;
|
||||
double _end;
|
||||
float _start;
|
||||
float _end;
|
||||
};
|
||||
typedef vector<ColorBar> ColorBars;
|
||||
|
||||
|
|
@ -76,8 +76,8 @@ private:
|
|||
public:
|
||||
BarBuilder();
|
||||
void clear();
|
||||
void add_data_point(double time);
|
||||
void finish(double time);
|
||||
void add_data_point(float time);
|
||||
void finish(float time);
|
||||
|
||||
bool _is_new;
|
||||
ColorBars _color_bars;
|
||||
|
|
|
|||
|
|
@ -225,6 +225,18 @@ handle_client_udp_data(const Datagram &datagram) {
|
|||
PStatFrameData *frame_data = new PStatFrameData;
|
||||
frame_data->read_datagram(source);
|
||||
|
||||
// Check to see if any new collectors have level data.
|
||||
int num_levels = frame_data->get_num_levels();
|
||||
for (int i = 0; i < num_levels; i++) {
|
||||
int collector_index = frame_data->get_level_collector(i);
|
||||
if (!_client_data->get_collector_has_level(collector_index)) {
|
||||
// This collector is now reporting level data, and it wasn't
|
||||
// before.
|
||||
_client_data->set_collector_has_level(collector_index, true);
|
||||
_monitor->new_collector(collector_index);
|
||||
}
|
||||
}
|
||||
|
||||
_client_data->record_new_frame(thread_index, frame_number, frame_data);
|
||||
_monitor->new_data(thread_index, frame_number);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ get_collector_index() const {
|
|||
// horizontal axis represents. This may force a redraw.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatStripChart::
|
||||
set_horizontal_scale(double time_width) {
|
||||
set_horizontal_scale(float time_width) {
|
||||
if (_time_width != time_width) {
|
||||
if (_scroll_mode) {
|
||||
_start_time += _time_width - time_width;
|
||||
|
|
@ -49,7 +49,7 @@ set_horizontal_scale(double time_width) {
|
|||
// Description: Returns the amount of total time the width of the
|
||||
// horizontal axis represents.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatStripChart::
|
||||
INLINE float PStatStripChart::
|
||||
get_horizontal_scale() const {
|
||||
return _time_width;
|
||||
}
|
||||
|
|
@ -57,38 +57,27 @@ get_horizontal_scale() const {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatStripChart::set_vertical_scale
|
||||
// Access: Public
|
||||
// Description: Changes the amount of time the height of the
|
||||
// vertical axis represents. This may force a redraw.
|
||||
// Description: Changes the value the height of the vertical axis
|
||||
// represents. This may force a redraw.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatStripChart::
|
||||
set_vertical_scale(double time_height) {
|
||||
if (_time_height != time_height) {
|
||||
_time_height = time_height;
|
||||
set_vertical_scale(float value_height) {
|
||||
if (_value_height != value_height) {
|
||||
_value_height = value_height;
|
||||
normal_guide_bars();
|
||||
force_redraw();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatStripChart::set_default_vertical_scale
|
||||
// Access: Public
|
||||
// Description: Sets the vertical scale to center the target frame
|
||||
// rate bar.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatStripChart::
|
||||
set_default_vertical_scale() {
|
||||
set_vertical_scale(2.0 / get_target_frame_rate());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatStripChart::get_vertical_scale
|
||||
// Access: Public
|
||||
// Description: Returns the amount of total time the height of the
|
||||
// vertical axis represents.
|
||||
// Description: Returns total value the height of the vertical axis
|
||||
// represents.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatStripChart::
|
||||
INLINE float PStatStripChart::
|
||||
get_vertical_scale() const {
|
||||
return _time_height;
|
||||
return _value_height;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -127,8 +116,8 @@ get_scroll_mode() const {
|
|||
// Description: Converts a timestamp to a horizontal pixel offset.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PStatStripChart::
|
||||
timestamp_to_pixel(double time) const {
|
||||
return (int)((double)get_xsize() * (time - _start_time) / _time_width);
|
||||
timestamp_to_pixel(float time) const {
|
||||
return (int)((float)get_xsize() * (time - _start_time) / _time_width);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -136,29 +125,29 @@ timestamp_to_pixel(double time) const {
|
|||
// Access: Public
|
||||
// Description: Converts a horizontal pixel offset to a timestamp.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatStripChart::
|
||||
INLINE float PStatStripChart::
|
||||
pixel_to_timestamp(int x) const {
|
||||
return _time_width * (double)x / (double)get_xsize() + _start_time;
|
||||
return _time_width * (float)x / (float)get_xsize() + _start_time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatStripChart::height_to_pixel
|
||||
// Access: Public
|
||||
// Description: Converts an elapsed time (e.g. a "height" in the
|
||||
// strip chart) to a vertical pixel offset.
|
||||
// Description: Converts a value (i.e. a "height" in the strip chart)
|
||||
// to a vertical pixel offset.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int PStatStripChart::
|
||||
height_to_pixel(double elapsed_time) const {
|
||||
return get_ysize() - (int)((double)get_ysize() * elapsed_time / _time_height);
|
||||
height_to_pixel(float value) const {
|
||||
return get_ysize() - (int)((float)get_ysize() * value / _value_height);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatStripChart::pixel_to_height
|
||||
// Access: Public
|
||||
// Description: Converts a vertical pixel offset to an elapsed time
|
||||
// (a "height" in the strip chart).
|
||||
// Description: Converts a vertical pixel offset to a value (a
|
||||
// "height" in the strip chart).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatStripChart::
|
||||
INLINE float PStatStripChart::
|
||||
pixel_to_height(int x) const {
|
||||
return _time_height * (double)(get_ysize() - x) / (double)get_ysize();
|
||||
return _value_height * (float)(get_ysize() - x) / (float)get_ysize();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,13 +4,14 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pStatStripChart.h"
|
||||
#include "pStatClientData.h"
|
||||
#include "pStatMonitor.h"
|
||||
|
||||
#include <pStatFrameData.h>
|
||||
#include <pStatCollectorDef.h>
|
||||
#include <string_utils.h>
|
||||
#include <config_pstats.h>
|
||||
|
||||
#include <stdio.h> // for sprintf
|
||||
#include <algorithm>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -32,11 +33,20 @@ PStatStripChart(PStatMonitor *monitor, PStatView &view,
|
|||
_cursor_pixel = 0;
|
||||
|
||||
_time_width = 20.0;
|
||||
_time_height = 1.0/10.0;
|
||||
_value_height = 1.0/10.0;
|
||||
_start_time = 0.0;
|
||||
|
||||
_level_index = 0;
|
||||
|
||||
const PStatClientData *client_data = _monitor->get_client_data();
|
||||
if (client_data->has_collector(_collector_index)) {
|
||||
const PStatCollectorDef &def = client_data->get_collector_def(_collector_index);
|
||||
_unit_name = def._level_units;
|
||||
if (!_unit_name.empty()) {
|
||||
_guide_bar_units = GBU_named;
|
||||
}
|
||||
}
|
||||
|
||||
set_default_vertical_scale();
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +95,7 @@ update() {
|
|||
_next_frame = latest;
|
||||
|
||||
// Clean out the old data.
|
||||
double oldest_time =
|
||||
float oldest_time =
|
||||
thread_data->get_frame(latest).get_start() - _time_width;
|
||||
|
||||
Data::iterator di;
|
||||
|
|
@ -116,6 +126,66 @@ first_data() const {
|
|||
return _first_data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatStripChart::set_default_vertical_scale
|
||||
// Access: Public
|
||||
// Description: Sets the vertical scale according to the suggested
|
||||
// scale of the base collector, if any, or to center the
|
||||
// target frame rate bar otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatStripChart::
|
||||
set_default_vertical_scale() {
|
||||
const PStatClientData *client_data = _monitor->get_client_data();
|
||||
if (client_data->has_collector(_collector_index)) {
|
||||
const PStatCollectorDef &def =
|
||||
client_data->get_collector_def(_collector_index);
|
||||
if (def._suggested_scale != 0.0) {
|
||||
set_vertical_scale(def._suggested_scale);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
set_vertical_scale(2.0 / get_target_frame_rate());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatStripChart::set_auto_vertical_scale
|
||||
// Access: Public
|
||||
// Description: Sets the vertical scale to make all the data visible.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatStripChart::
|
||||
set_auto_vertical_scale() {
|
||||
const PStatThreadData *thread_data = _view.get_thread_data();
|
||||
|
||||
float max_value = 0.0;
|
||||
|
||||
for (int x = 0; x <= _xsize; x++) {
|
||||
float time = pixel_to_timestamp(x);
|
||||
int frame_number =
|
||||
thread_data->get_frame_number_at_time(time, frame_number);
|
||||
|
||||
if (thread_data->has_frame(frame_number)) {
|
||||
const FrameData &frame = get_frame_data(frame_number);
|
||||
|
||||
float overall_value = 0.0;
|
||||
FrameData::const_iterator fi;
|
||||
for (fi = frame.begin(); fi != frame.end(); ++fi) {
|
||||
const ColorData &cd = (*fi);
|
||||
overall_value += cd._net_value;
|
||||
}
|
||||
max_value = max(max_value, overall_value);
|
||||
}
|
||||
}
|
||||
|
||||
// Ok, now we know what the max value visible in the chart is.
|
||||
// Choose a scale that will show all of this sensibly.
|
||||
if (max_value == 0.0) {
|
||||
set_vertical_scale(1.0);
|
||||
} else {
|
||||
set_vertical_scale(max_value * 1.1);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatStripChart::get_collector_under_pixel
|
||||
// Access: Public
|
||||
|
|
@ -127,23 +197,23 @@ int PStatStripChart::
|
|||
get_collector_under_pixel(int xpoint, int ypoint) {
|
||||
// First, we need to know what frame it was; to know that, we need
|
||||
// to determine the time corresponding to the x pixel.
|
||||
double time = pixel_to_timestamp(xpoint);
|
||||
float time = pixel_to_timestamp(xpoint);
|
||||
|
||||
// Now use that time to determine the frame.
|
||||
const PStatThreadData *thread_data = _view.get_thread_data();
|
||||
int frame_number = thread_data->get_frame_number_at_time(time);
|
||||
|
||||
// And now we can determine which collector within the frame,
|
||||
// based on the time height.
|
||||
// based on the value height.
|
||||
const FrameData &frame = get_frame_data(frame_number);
|
||||
double overall_time = 0.0;
|
||||
float overall_value = 0.0;
|
||||
int y = get_ysize();
|
||||
|
||||
FrameData::const_iterator fi;
|
||||
for (fi = frame.begin(); fi != frame.end(); ++fi) {
|
||||
const ColorData &cd = (*fi);
|
||||
overall_time += cd._net_time;
|
||||
y = height_to_pixel(overall_time);
|
||||
overall_value += cd._net_value;
|
||||
y = height_to_pixel(overall_value);
|
||||
if (y <= ypoint) {
|
||||
return cd._collector_index;
|
||||
}
|
||||
|
|
@ -179,18 +249,18 @@ get_frame_data(int frame_number) {
|
|||
const PStatViewLevel *child = level->get_child(i);
|
||||
ColorData cd;
|
||||
cd._collector_index = child->get_collector();
|
||||
cd._net_time = child->get_net_time();
|
||||
if (cd._net_time != 0.0) {
|
||||
cd._net_value = child->get_net_value();
|
||||
if (cd._net_value != 0.0) {
|
||||
data.push_back(cd);
|
||||
}
|
||||
}
|
||||
|
||||
// Also, there might be some time in the overall Collector that
|
||||
// Also, there might be some value in the overall Collector that
|
||||
// wasn't included in all of the children.
|
||||
ColorData cd;
|
||||
cd._collector_index = level->get_collector();
|
||||
cd._net_time = level->get_time_alone();
|
||||
if (cd._net_time != 0.0) {
|
||||
cd._net_value = level->get_value_alone();
|
||||
if (cd._net_value != 0.0) {
|
||||
data.push_back(cd);
|
||||
}
|
||||
|
||||
|
|
@ -218,7 +288,7 @@ changed_size(int xsize, int ysize) {
|
|||
|
||||
} else {
|
||||
// Redraw the stats that were there before.
|
||||
double old_start_time = _start_time;
|
||||
float old_start_time = _start_time;
|
||||
|
||||
// Back up a bit to draw the stuff to the right of the cursor.
|
||||
_start_time -= _time_width;
|
||||
|
|
@ -366,7 +436,7 @@ public:
|
|||
// -1 appear to be a very large positive integer, thus placing
|
||||
// collectors with a -1 sort value at the very end.
|
||||
return
|
||||
(unsigned int)_client_data->get_collector_def(a)._sort <
|
||||
(unsigned int)_client_data->get_collector_def(a)._sort >
|
||||
(unsigned int)_client_data->get_collector_def(b)._sort;
|
||||
}
|
||||
const PStatClientData *_client_data;
|
||||
|
|
@ -407,7 +477,7 @@ update_labels() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void PStatStripChart::
|
||||
normal_guide_bars() {
|
||||
update_guide_bars(4, _time_height);
|
||||
update_guide_bars(4, _value_height);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -468,7 +538,7 @@ draw_frames(int first_frame, int last_frame) {
|
|||
copy_region(slide_pixels, first_pixel, 0);
|
||||
first_pixel -= slide_pixels;
|
||||
last_pixel -= slide_pixels;
|
||||
_start_time += (double)slide_pixels / (double)_xsize * _time_width;
|
||||
_start_time += (float)slide_pixels / (float)_xsize * _time_width;
|
||||
draw_pixels(first_pixel, last_pixel);
|
||||
|
||||
} else {
|
||||
|
|
@ -499,7 +569,7 @@ draw_pixels(int first_pixel, int last_pixel) {
|
|||
draw_cursor(x);
|
||||
|
||||
} else {
|
||||
double time = pixel_to_timestamp(x);
|
||||
float time = pixel_to_timestamp(x);
|
||||
frame_number = thread_data->get_frame_number_at_time(time, frame_number);
|
||||
|
||||
if (thread_data->has_frame(frame_number)) {
|
||||
|
|
|
|||
|
|
@ -23,9 +23,8 @@ class PStatView;
|
|||
// Class : PStatStripChart
|
||||
// Description : This is an abstract class that presents the interface
|
||||
// for drawing a basic strip-chart, showing the relative
|
||||
// time elapsed over an interval of time for several
|
||||
// different collectors, differentiated by bands of
|
||||
// color.
|
||||
// value over an interval of time for several different
|
||||
// collectors, differentiated by bands of color.
|
||||
//
|
||||
// This class just manages all the strip-chart logic;
|
||||
// the actual nuts and bolts of drawing pixels is left
|
||||
|
|
@ -44,26 +43,27 @@ public:
|
|||
INLINE PStatView &get_view() const;
|
||||
INLINE int get_collector_index() const;
|
||||
|
||||
INLINE void set_horizontal_scale(double time_width);
|
||||
INLINE double get_horizontal_scale() const;
|
||||
INLINE void set_vertical_scale(double time_height);
|
||||
INLINE void set_default_vertical_scale();
|
||||
INLINE double get_vertical_scale() const;
|
||||
INLINE void set_horizontal_scale(float time_width);
|
||||
INLINE float get_horizontal_scale() const;
|
||||
INLINE void set_vertical_scale(float value_height);
|
||||
void set_default_vertical_scale();
|
||||
void set_auto_vertical_scale();
|
||||
INLINE float get_vertical_scale() const;
|
||||
|
||||
INLINE void set_scroll_mode(bool scroll_mode);
|
||||
INLINE bool get_scroll_mode() const;
|
||||
|
||||
int get_collector_under_pixel(int xpoint, int ypoint);
|
||||
INLINE int timestamp_to_pixel(double time) const;
|
||||
INLINE double pixel_to_timestamp(int x) const;
|
||||
INLINE int height_to_pixel(double elapsed_time) const;
|
||||
INLINE double pixel_to_height(int y) const;
|
||||
INLINE int timestamp_to_pixel(float time) const;
|
||||
INLINE float pixel_to_timestamp(int x) const;
|
||||
INLINE int height_to_pixel(float value) const;
|
||||
INLINE float pixel_to_height(int y) const;
|
||||
|
||||
protected:
|
||||
class ColorData {
|
||||
public:
|
||||
int _collector_index;
|
||||
double _net_time;
|
||||
float _net_value;
|
||||
};
|
||||
typedef vector<ColorData> FrameData;
|
||||
typedef map<int, FrameData> Data;
|
||||
|
|
@ -101,9 +101,9 @@ private:
|
|||
|
||||
int _level_index;
|
||||
|
||||
double _time_width;
|
||||
double _start_time;
|
||||
double _time_height;
|
||||
float _time_width;
|
||||
float _start_time;
|
||||
float _value_height;
|
||||
};
|
||||
|
||||
#include "pStatStripChart.I"
|
||||
|
|
|
|||
|
|
@ -122,7 +122,7 @@ get_frame(int frame_number) const {
|
|||
// Description: Returns the timestamp (in seconds elapsed since
|
||||
// connection) of the latest available frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double PStatThreadData::
|
||||
float PStatThreadData::
|
||||
get_latest_time() const {
|
||||
nassertr(!_frames.empty(), 0.0);
|
||||
return _frames.back()->get_start();
|
||||
|
|
@ -134,7 +134,7 @@ get_latest_time() const {
|
|||
// Description: Returns the timestamp (in seconds elapsed since
|
||||
// connection) of the oldest available frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double PStatThreadData::
|
||||
float PStatThreadData::
|
||||
get_oldest_time() const {
|
||||
nassertr(!_frames.empty(), 0.0);
|
||||
return _frames.front()->get_start();
|
||||
|
|
@ -147,7 +147,7 @@ get_oldest_time() const {
|
|||
// latest frame not later than the indicated time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
const PStatFrameData &PStatThreadData::
|
||||
get_frame_at_time(double time) const {
|
||||
get_frame_at_time(float time) const {
|
||||
return get_frame(get_frame_number_at_time(time));
|
||||
}
|
||||
|
||||
|
|
@ -162,7 +162,7 @@ get_frame_at_time(double time) const {
|
|||
// which may speed the search for the frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PStatThreadData::
|
||||
get_frame_number_at_time(double time, int hint) const {
|
||||
get_frame_number_at_time(float time, int hint) const {
|
||||
hint -= _first_frame_number;
|
||||
if (hint >= 0 && hint < (int)_frames.size()) {
|
||||
if (_frames[hint] != (PStatFrameData *)NULL &&
|
||||
|
|
@ -211,8 +211,8 @@ get_latest_frame() const {
|
|||
// of seconds, by counting up the number of frames
|
||||
// elapsed in that time interval.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double PStatThreadData::
|
||||
get_frame_rate(double time) const {
|
||||
float PStatThreadData::
|
||||
get_frame_rate(float time) const {
|
||||
if (_frames.empty()) {
|
||||
// No frames in the data at all; nothing to base the frame rate
|
||||
// on.
|
||||
|
|
@ -229,8 +229,8 @@ get_frame_rate(double time) const {
|
|||
}
|
||||
nassertr(_frames[now_i] != (PStatFrameData *)NULL, 0.0);
|
||||
|
||||
double now = _frames[now_i]->get_end();
|
||||
double then = now - time;
|
||||
float now = _frames[now_i]->get_end();
|
||||
float then = now - time;
|
||||
|
||||
int then_i = now_i;
|
||||
int last_good_i = now_i;
|
||||
|
|
@ -246,7 +246,7 @@ get_frame_rate(double time) const {
|
|||
nassertr(_frames[last_good_i] != (PStatFrameData *)NULL, 0.0);
|
||||
|
||||
int num_frames = now_i - last_good_i + 1;
|
||||
return (double)num_frames / (now - _frames[last_good_i]->get_start());
|
||||
return (float)num_frames / (now - _frames[last_good_i]->get_start());
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -259,7 +259,7 @@ get_frame_rate(double time) const {
|
|||
// frame that may be queried is.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatThreadData::
|
||||
set_history(double time) {
|
||||
set_history(float time) {
|
||||
_history = time;
|
||||
}
|
||||
|
||||
|
|
@ -271,7 +271,7 @@ set_history(double time) {
|
|||
// new frame is added. This affects how old the oldest
|
||||
// frame that may be queried is.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double PStatThreadData::
|
||||
float PStatThreadData::
|
||||
get_history() const {
|
||||
return _history;
|
||||
}
|
||||
|
|
@ -292,11 +292,11 @@ void PStatThreadData::
|
|||
record_new_frame(int frame_number, PStatFrameData *frame_data) {
|
||||
nassertv(frame_data != (PStatFrameData *)NULL);
|
||||
nassertv(!frame_data->is_empty());
|
||||
double time = frame_data->get_start();
|
||||
float time = frame_data->get_start();
|
||||
|
||||
// First, remove all the old frames that fall outside of our
|
||||
// history window.
|
||||
double oldest_allowable_time = time - _history;
|
||||
float oldest_allowable_time = time - _history;
|
||||
while (!_frames.empty() &&
|
||||
(_frames.front() == (PStatFrameData *)NULL ||
|
||||
_frames.front()->is_empty() ||
|
||||
|
|
|
|||
|
|
@ -40,18 +40,18 @@ public:
|
|||
bool has_frame(int frame_number) const;
|
||||
const PStatFrameData &get_frame(int frame_number) const;
|
||||
|
||||
double get_latest_time() const;
|
||||
double get_oldest_time() const;
|
||||
const PStatFrameData &get_frame_at_time(double time) const;
|
||||
int get_frame_number_at_time(double time, int hint = -1) const;
|
||||
float get_latest_time() const;
|
||||
float get_oldest_time() const;
|
||||
const PStatFrameData &get_frame_at_time(float time) const;
|
||||
int get_frame_number_at_time(float time, int hint = -1) const;
|
||||
|
||||
const PStatFrameData &get_latest_frame() const;
|
||||
|
||||
double get_frame_rate(double time = 3.0) const;
|
||||
float get_frame_rate(float time = 3.0) const;
|
||||
|
||||
|
||||
void set_history(double time);
|
||||
double get_history() const;
|
||||
void set_history(float time);
|
||||
float get_history() const;
|
||||
|
||||
void record_new_frame(int frame_number, PStatFrameData *frame_data);
|
||||
|
||||
|
|
@ -61,7 +61,7 @@ private:
|
|||
typedef deque<PStatFrameData *> Frames;
|
||||
Frames _frames;
|
||||
int _first_frame_number;
|
||||
double _history;
|
||||
float _history;
|
||||
|
||||
static PStatFrameData _null_frame;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ set_to_frame(int frame_number) {
|
|||
// set_to_frame.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PStatView::
|
||||
set_to_time(double time) {
|
||||
set_to_time(float time) {
|
||||
set_to_frame(_thread_data->get_frame_at_time(time));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
// Class : FrameSample
|
||||
// Description : This class is used within this module only--in fact,
|
||||
// within PStatView::set_to_frame() only--to help
|
||||
// collect data out of the PStatFrameData object and
|
||||
// boil it down to a list of elapsed times.
|
||||
// collect event data out of the PStatFrameData object
|
||||
// and boil it down to a list of elapsed times.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class FrameSample {
|
||||
public:
|
||||
|
|
@ -31,10 +31,25 @@ public:
|
|||
_pushed = false;
|
||||
_net_time = 0.0;
|
||||
}
|
||||
void data_point(double time, Started &started) {
|
||||
void data_point(float time, bool is_start, Started &started) {
|
||||
_touched = true;
|
||||
_is_started = !_is_started;
|
||||
|
||||
// We only consider events that change the start/stop state.
|
||||
// With two consecutive 'start' events, for instance, we ignore
|
||||
// the second one.
|
||||
|
||||
// *** That's not quite the right thing to do. We should keep
|
||||
// track of the nesting level and bracket things correctly, so
|
||||
// that we ignore the second start and the *first* stop, but
|
||||
// respect the outer start/stop. For the short term, this
|
||||
// works, because the client is already doing this logic and
|
||||
// won't send us nested start/stop pairs, but we'd like to
|
||||
// generalize this in the future so we can deal with these
|
||||
// nested pairs properly.
|
||||
nassertv(is_start != _is_started);
|
||||
|
||||
_is_started = is_start;
|
||||
|
||||
if (_pushed) {
|
||||
nassertv(!_is_started);
|
||||
Started::iterator si = find(started.begin(), started.end(), this);
|
||||
|
|
@ -43,19 +58,19 @@ public:
|
|||
|
||||
} else {
|
||||
if (_is_started) {
|
||||
_net_time -= time;
|
||||
push_all(time, started);
|
||||
started.push_back(this);
|
||||
_net_time -= time;
|
||||
push_all(time, started);
|
||||
started.push_back(this);
|
||||
} else {
|
||||
_net_time += time;
|
||||
Started::iterator si = find(started.begin(), started.end(), this);
|
||||
nassertv(si != started.end());
|
||||
started.erase(si);
|
||||
pop_one(time, started);
|
||||
_net_time += time;
|
||||
Started::iterator si = find(started.begin(), started.end(), this);
|
||||
nassertv(si != started.end());
|
||||
started.erase(si);
|
||||
pop_one(time, started);
|
||||
}
|
||||
}
|
||||
}
|
||||
void push(double time) {
|
||||
void push(float time) {
|
||||
if (!_pushed) {
|
||||
_pushed = true;
|
||||
if (_is_started) {
|
||||
|
|
@ -63,7 +78,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
void pop(double time) {
|
||||
void pop(float time) {
|
||||
if (_pushed) {
|
||||
_pushed = false;
|
||||
if (_is_started) {
|
||||
|
|
@ -72,14 +87,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void push_all(double time, Started &started) {
|
||||
void push_all(float time, Started &started) {
|
||||
Started::iterator si;
|
||||
for (si = started.begin(); si != started.end(); ++si) {
|
||||
(*si)->push(time);
|
||||
}
|
||||
}
|
||||
|
||||
void pop_one(double time, Started &started) {
|
||||
void pop_one(float time, Started &started) {
|
||||
Started::reverse_iterator si;
|
||||
for (si = started.rbegin(); si != started.rend(); ++si) {
|
||||
if ((*si)->_pushed) {
|
||||
|
|
@ -92,7 +107,7 @@ public:
|
|||
bool _touched;
|
||||
bool _is_started;
|
||||
bool _pushed;
|
||||
double _net_time;
|
||||
float _net_time;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -105,6 +120,7 @@ public:
|
|||
PStatView::
|
||||
PStatView() {
|
||||
_constraint = 0;
|
||||
_show_level = false;
|
||||
_all_collectors_known = false;
|
||||
_level_index = 0;
|
||||
}
|
||||
|
|
@ -130,13 +146,20 @@ PStatView::
|
|||
// reporting only the collector and its immediate
|
||||
// parents.
|
||||
//
|
||||
// When you constrain the view, you may also specify
|
||||
// whether the view should show time data or level data
|
||||
// for the indicated collector. If level data, it
|
||||
// reports the levels for the collector, and all of its
|
||||
// children; otherwise, it collects the elapsed time.
|
||||
//
|
||||
// Changing the constraint causes the current frame's
|
||||
// data to become invalidated; you must then call
|
||||
// set_to_frame() again to get any useful data out.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatView::
|
||||
constrain(int collector) {
|
||||
constrain(int collector, bool show_level) {
|
||||
_constraint = collector;
|
||||
_show_level = show_level;
|
||||
clear_levels();
|
||||
}
|
||||
|
||||
|
|
@ -148,7 +171,7 @@ constrain(int collector) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void PStatView::
|
||||
unconstrain() {
|
||||
constrain(0);
|
||||
constrain(0, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -184,95 +207,10 @@ set_to_frame(const PStatFrameData &frame_data) {
|
|||
nassertv(!_thread_data.is_null());
|
||||
nassertv(!_client_data.is_null());
|
||||
|
||||
int num_events = frame_data.get_num_events();
|
||||
|
||||
typedef vector<FrameSample> Samples;
|
||||
Samples samples(_client_data->get_num_collectors());
|
||||
|
||||
FrameSample::Started started;
|
||||
|
||||
_all_collectors_known = true;
|
||||
|
||||
|
||||
// This tracks the set of samples we actually care about.
|
||||
typedef set<int> GotSamples;
|
||||
GotSamples got_samples;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < num_events; i++) {
|
||||
int collector_index = (frame_data.get_collector(i) & 0x7fff);
|
||||
|
||||
if (!_client_data->has_collector(collector_index)) {
|
||||
_all_collectors_known = false;
|
||||
|
||||
} else {
|
||||
nassertv(collector_index >= 0 && collector_index < (int)samples.size());
|
||||
|
||||
if (_client_data->get_child_distance(_constraint, collector_index) >= 0) {
|
||||
// Here's a data point we care about: anything at constraint
|
||||
// level or below.
|
||||
samples[collector_index].data_point(frame_data.get_time(i), started);
|
||||
got_samples.insert(collector_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure everything is stopped.
|
||||
|
||||
Samples::iterator si;
|
||||
for (i = 0, si = samples.begin(); si != samples.end(); ++i, ++si) {
|
||||
if ((*si)._is_started) {
|
||||
nout << _client_data->get_collector_fullname(i)
|
||||
<< " was not stopped at frame end!\n";
|
||||
(*si).data_point(frame_data.get_end(), started);
|
||||
}
|
||||
}
|
||||
|
||||
nassertv(started.empty());
|
||||
|
||||
bool any_new_levels = false;
|
||||
|
||||
// Now match these samples we got up with those we already had in
|
||||
// the levels.
|
||||
Levels::iterator li, lnext;
|
||||
li = _levels.begin();
|
||||
while (li != _levels.end()) {
|
||||
// Be careful while traversing a container and calling functions
|
||||
// that could modify that container.
|
||||
lnext = li;
|
||||
++lnext;
|
||||
|
||||
PStatViewLevel *level = (*li).second;
|
||||
if (reset_level(level)) {
|
||||
any_new_levels = true;
|
||||
}
|
||||
|
||||
int collector_index = level->_collector;
|
||||
GotSamples::iterator gi;
|
||||
gi = got_samples.find(collector_index);
|
||||
if (gi != got_samples.end()) {
|
||||
level->_time_alone = samples[collector_index]._net_time;
|
||||
got_samples.erase(gi);
|
||||
}
|
||||
|
||||
li = lnext;
|
||||
}
|
||||
|
||||
// Finally, any samples left over in the got_samples set are new
|
||||
// collectors that we need to add to the Levels list.
|
||||
if (!got_samples.empty()) {
|
||||
any_new_levels = true;
|
||||
|
||||
GotSamples::const_iterator gi;
|
||||
for (gi = got_samples.begin(); gi != got_samples.end(); ++gi) {
|
||||
int collector_index = (*gi);
|
||||
PStatViewLevel *level = get_level(collector_index);
|
||||
level->_time_alone = samples[*gi]._net_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (any_new_levels) {
|
||||
_level_index++;
|
||||
if (_show_level) {
|
||||
update_level_data(frame_data);
|
||||
} else {
|
||||
update_time_data(frame_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -291,19 +229,19 @@ all_collectors_known() const {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatView::get_net_time
|
||||
// Function: PStatView::get_net_value
|
||||
// Access: Public
|
||||
// Description: Returns the total time accounted for by the frame (or
|
||||
// Description: Returns the total value accounted for by the frame (or
|
||||
// by whatever Collector we are constrained to). This
|
||||
// is the sum of all of the individual levels'
|
||||
// get_net_time() value.
|
||||
// get_net_value() value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double PStatView::
|
||||
get_net_time() const {
|
||||
double net = 0.0;
|
||||
float PStatView::
|
||||
get_net_value() const {
|
||||
float net = 0.0;
|
||||
Levels::const_iterator li;
|
||||
for (li = _levels.begin(); li != _levels.end(); ++li) {
|
||||
net += (*li).second->_time_alone;
|
||||
net += (*li).second->_value_alone;
|
||||
}
|
||||
|
||||
return net;
|
||||
|
|
@ -362,6 +300,211 @@ get_level(int collector) {
|
|||
return level;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatView::update_time_data
|
||||
// Access: Private
|
||||
// Description: The implementation of set_to_frame() for views that
|
||||
// show elapsed time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatView::
|
||||
update_time_data(const PStatFrameData &frame_data) {
|
||||
int num_events = frame_data.get_num_events();
|
||||
|
||||
typedef vector<FrameSample> Samples;
|
||||
Samples samples(_client_data->get_num_collectors());
|
||||
|
||||
FrameSample::Started started;
|
||||
|
||||
_all_collectors_known = true;
|
||||
|
||||
|
||||
// This tracks the set of samples we actually care about.
|
||||
typedef set<int> GotSamples;
|
||||
GotSamples got_samples;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < num_events; i++) {
|
||||
int collector_index = frame_data.get_time_collector(i);
|
||||
bool is_start = frame_data.is_start(i);
|
||||
|
||||
if (!_client_data->has_collector(collector_index)) {
|
||||
_all_collectors_known = false;
|
||||
|
||||
} else {
|
||||
nassertv(collector_index >= 0 && collector_index < (int)samples.size());
|
||||
|
||||
if (_client_data->get_child_distance(_constraint, collector_index) >= 0) {
|
||||
// Here's a data point we care about: anything at constraint
|
||||
// level or below.
|
||||
samples[collector_index].data_point(frame_data.get_time(i), is_start, started);
|
||||
got_samples.insert(collector_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure everything is stopped.
|
||||
|
||||
Samples::iterator si;
|
||||
for (i = 0, si = samples.begin(); si != samples.end(); ++i, ++si) {
|
||||
if ((*si)._is_started) {
|
||||
nout << _client_data->get_collector_fullname(i)
|
||||
<< " was not stopped at frame end!\n";
|
||||
(*si).data_point(frame_data.get_end(), false, started);
|
||||
}
|
||||
}
|
||||
|
||||
nassertv(started.empty());
|
||||
|
||||
bool any_new_levels = false;
|
||||
|
||||
// Now match these samples we got up with those we already had in
|
||||
// the levels.
|
||||
Levels::iterator li, lnext;
|
||||
li = _levels.begin();
|
||||
while (li != _levels.end()) {
|
||||
// Be careful while traversing a container and calling functions
|
||||
// that could modify that container.
|
||||
lnext = li;
|
||||
++lnext;
|
||||
|
||||
PStatViewLevel *level = (*li).second;
|
||||
if (reset_level(level)) {
|
||||
any_new_levels = true;
|
||||
}
|
||||
|
||||
int collector_index = level->_collector;
|
||||
GotSamples::iterator gi;
|
||||
gi = got_samples.find(collector_index);
|
||||
if (gi != got_samples.end()) {
|
||||
level->_value_alone = samples[collector_index]._net_time;
|
||||
got_samples.erase(gi);
|
||||
}
|
||||
|
||||
li = lnext;
|
||||
}
|
||||
|
||||
// Finally, any samples left over in the got_samples set are new
|
||||
// collectors that we need to add to the Levels list.
|
||||
if (!got_samples.empty()) {
|
||||
any_new_levels = true;
|
||||
|
||||
GotSamples::const_iterator gi;
|
||||
for (gi = got_samples.begin(); gi != got_samples.end(); ++gi) {
|
||||
int collector_index = (*gi);
|
||||
PStatViewLevel *level = get_level(collector_index);
|
||||
level->_value_alone = samples[*gi]._net_time;
|
||||
}
|
||||
}
|
||||
|
||||
if (any_new_levels) {
|
||||
_level_index++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatView::update_level_data
|
||||
// Access: Private
|
||||
// Description: The implementation of set_to_frame() for views that
|
||||
// show level values.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PStatView::
|
||||
update_level_data(const PStatFrameData &frame_data) {
|
||||
_all_collectors_known = true;
|
||||
|
||||
|
||||
// This tracks the set of level values we got.
|
||||
typedef map<int, float> GotValues;
|
||||
GotValues net_values;
|
||||
|
||||
int i;
|
||||
int num_levels = frame_data.get_num_levels();
|
||||
for (i = 0; i < num_levels; i++) {
|
||||
int collector_index = frame_data.get_level_collector(i);
|
||||
float value = frame_data.get_level(i);
|
||||
|
||||
if (!_client_data->has_collector(collector_index)) {
|
||||
_all_collectors_known = false;
|
||||
|
||||
} else {
|
||||
if (_client_data->get_child_distance(_constraint, collector_index) >= 0) {
|
||||
net_values[collector_index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we've counted up the net level for each collector,
|
||||
// compute the level for each collector alone by subtracting out
|
||||
// each child from its parents. If a parent has no data, nothing is
|
||||
// subtracted.
|
||||
GotValues alone_values = net_values;
|
||||
|
||||
GotValues::iterator gi;
|
||||
for (gi = net_values.begin(); gi != net_values.end(); ++gi) {
|
||||
int collector_index = (*gi).first;
|
||||
float value = (*gi).second;
|
||||
|
||||
// Walk up to the top.
|
||||
while (collector_index != 0 && collector_index != _constraint) {
|
||||
const PStatCollectorDef &def =
|
||||
_client_data->get_collector_def(collector_index);
|
||||
int parent_index = def._parent_index;
|
||||
GotValues::iterator pi = alone_values.find(parent_index);
|
||||
if (pi != alone_values.end()) {
|
||||
// The parent has data; subtract it.
|
||||
(*pi).second -= value;
|
||||
}
|
||||
|
||||
collector_index = parent_index;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool any_new_levels = false;
|
||||
|
||||
// Now match these samples we got up with those we already had in
|
||||
// the levels.
|
||||
Levels::iterator li, lnext;
|
||||
li = _levels.begin();
|
||||
while (li != _levels.end()) {
|
||||
// Be careful while traversing a container and calling functions
|
||||
// that could modify that container.
|
||||
lnext = li;
|
||||
++lnext;
|
||||
|
||||
PStatViewLevel *level = (*li).second;
|
||||
if (reset_level(level)) {
|
||||
any_new_levels = true;
|
||||
}
|
||||
|
||||
int collector_index = level->_collector;
|
||||
GotValues::iterator gi;
|
||||
gi = alone_values.find(collector_index);
|
||||
if (gi != alone_values.end()) {
|
||||
level->_value_alone = (*gi).second;
|
||||
alone_values.erase(gi);
|
||||
}
|
||||
|
||||
li = lnext;
|
||||
}
|
||||
|
||||
// Finally, any values left over in the alone_values set are new
|
||||
// collectors that we need to add to the Levels list.
|
||||
if (!alone_values.empty()) {
|
||||
any_new_levels = true;
|
||||
|
||||
GotValues::const_iterator gi;
|
||||
for (gi = alone_values.begin(); gi != alone_values.end(); ++gi) {
|
||||
int collector_index = (*gi).first;
|
||||
PStatViewLevel *level = get_level(collector_index);
|
||||
level->_value_alone = (*gi).second;
|
||||
}
|
||||
}
|
||||
|
||||
if (any_new_levels) {
|
||||
_level_index++;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatView::clear_levels
|
||||
// Access: Private
|
||||
|
|
@ -379,7 +522,7 @@ clear_levels() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatView::reset_level
|
||||
// Access: Private
|
||||
// Description: Resets the total time of the Level to zero, and also
|
||||
// Description: Resets the total value of the Level to zero, and also
|
||||
// makes sure it is parented to the right Level
|
||||
// corresponding to its Collector's parent. Since the
|
||||
// client might change its mind from time to time about
|
||||
|
|
@ -392,7 +535,7 @@ clear_levels() {
|
|||
bool PStatView::
|
||||
reset_level(PStatViewLevel *level) {
|
||||
bool any_changed = false;
|
||||
level->_time_alone = 0.0;
|
||||
level->_value_alone = 0.0;
|
||||
|
||||
if (level->_collector == _constraint) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public:
|
|||
PStatView();
|
||||
~PStatView();
|
||||
|
||||
void constrain(int collector);
|
||||
void constrain(int collector, bool show_level);
|
||||
void unconstrain();
|
||||
|
||||
void set_thread_data(const PStatThreadData *thread_data);
|
||||
|
|
@ -36,10 +36,10 @@ public:
|
|||
|
||||
void set_to_frame(const PStatFrameData &frame_data);
|
||||
INLINE void set_to_frame(int frame_number);
|
||||
INLINE void set_to_time(double time);
|
||||
INLINE void set_to_time(float time);
|
||||
|
||||
bool all_collectors_known() const;
|
||||
double get_net_time() const;
|
||||
float get_net_value() const;
|
||||
|
||||
const PStatViewLevel *get_top_level();
|
||||
|
||||
|
|
@ -49,10 +49,14 @@ public:
|
|||
INLINE int get_level_index() const;
|
||||
|
||||
private:
|
||||
void update_time_data(const PStatFrameData &frame_data);
|
||||
void update_level_data(const PStatFrameData &frame_data);
|
||||
|
||||
void clear_levels();
|
||||
bool reset_level(PStatViewLevel *level);
|
||||
|
||||
int _constraint;
|
||||
bool _show_level;
|
||||
bool _all_collectors_known;
|
||||
|
||||
typedef map<int, PStatViewLevel *> Levels;
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ get_collector() const {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatViewLevel::get_time_alone
|
||||
// Function: PStatViewLevel::get_value_alone
|
||||
// Access: Public
|
||||
// Description: Returns the total elapsed time spent by this
|
||||
// Collector, not including any time spent in its child
|
||||
// Collectors.
|
||||
// Description: Returns the total level value (or elapsed time value)
|
||||
// for this Collector, not including any values
|
||||
// accounted for by its child Collectors.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double PStatViewLevel::
|
||||
get_time_alone() const {
|
||||
return _time_alone;
|
||||
INLINE float PStatViewLevel::
|
||||
get_value_alone() const {
|
||||
return _value_alone;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,19 +12,19 @@
|
|||
#include <algorithm>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PStatViewLevel::get_net_time
|
||||
// Function: PStatViewLevel::get_net_value
|
||||
// Access: Public
|
||||
// Description: Returns the total elapsed time spent by this
|
||||
// Collector, including all time spent in its child
|
||||
// Collectors.
|
||||
// Description: Returns the total level value (or elapsed time)
|
||||
// represented by this Collector, including all values
|
||||
// in its child Collectors.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
double PStatViewLevel::
|
||||
get_net_time() const {
|
||||
double net = _time_alone;
|
||||
float PStatViewLevel::
|
||||
get_net_value() const {
|
||||
float net = _value_alone;
|
||||
|
||||
Children::const_iterator ci;
|
||||
for (ci = _children.begin(); ci != _children.end(); ++ci) {
|
||||
net += (*ci)->get_net_time();
|
||||
net += (*ci)->get_net_value();
|
||||
}
|
||||
|
||||
return net;
|
||||
|
|
@ -66,9 +66,9 @@ sort_children(const PStatClientData *client_data) {
|
|||
// Function: PStatViewLevel::get_num_children
|
||||
// Access: Public
|
||||
// Description: Returns the number of children of this
|
||||
// Level/Collector. These are the Collectors whose time
|
||||
// is considered to be part of the total time of this
|
||||
// level's Collector.
|
||||
// Level/Collector. These are the Collectors whose
|
||||
// value is considered to be part of the total value of
|
||||
// this level's Collector.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int PStatViewLevel::
|
||||
get_num_children() const {
|
||||
|
|
|
|||
|
|
@ -15,15 +15,17 @@ class PStatClientData;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PStatViewLevel
|
||||
// Description : This is a single level value, or band of color,
|
||||
// within a View. It generally indicates the elapsed
|
||||
// time for a particular Collector within a given frame
|
||||
// for a particular thread.
|
||||
// within a View.
|
||||
//
|
||||
// It generally indicates either the elapsed time, or
|
||||
// the "level" value, for a particular Collector within
|
||||
// a given frame for a particular thread.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class PStatViewLevel {
|
||||
public:
|
||||
INLINE int get_collector() const;
|
||||
INLINE double get_time_alone() const;
|
||||
double get_net_time() const;
|
||||
INLINE float get_value_alone() const;
|
||||
float get_net_value() const;
|
||||
|
||||
void sort_children(const PStatClientData *client_data);
|
||||
|
||||
|
|
@ -32,7 +34,7 @@ public:
|
|||
|
||||
private:
|
||||
int _collector;
|
||||
double _time_alone;
|
||||
float _value_alone;
|
||||
PStatViewLevel *_parent;
|
||||
|
||||
typedef vector<PStatViewLevel *> Children;
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ new_data(int thread_index, int frame_number) {
|
|||
nout << "\rThread "
|
||||
<< get_client_data()->get_thread_name(thread_index)
|
||||
<< " frame " << frame_number << ", "
|
||||
<< view.get_net_time() * 1000.0 << " ms ("
|
||||
<< view.get_net_value() * 1000.0 << " ms ("
|
||||
<< thread_data->get_frame_rate() << " Hz):\n";
|
||||
const PStatViewLevel *level = view.get_top_level();
|
||||
int num_children = level->get_num_children();
|
||||
|
|
@ -113,7 +113,7 @@ show_level(const PStatViewLevel *level, int indent_level) {
|
|||
|
||||
indent(nout, indent_level)
|
||||
<< get_client_data()->get_collector_name(collector_index)
|
||||
<< " = " << level->get_net_time() * 1000.0 << " ms\n";
|
||||
<< " = " << level->get_net_value() * 1000.0 << " ms\n";
|
||||
|
||||
int num_children = level->get_num_children();
|
||||
for (int i = 0; i < num_children; i++) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue