1
0
Fork 0

Canvas: Performance improvements.

- Only render the canvas if something has actually changed
   (Currently checked by looking for modified properties).
 - Only write bounding box to property tree if it has been
   recalculated (until now this happened every frame).
This commit is contained in:
Thomas Geymayer 2012-09-21 21:20:35 +02:00
parent 88592bfe71
commit 4a94071ed7
9 changed files with 91 additions and 46 deletions

View file

@ -99,6 +99,7 @@ Canvas::Canvas(SGPropertyNode* node):
_mouse_event(node, "mouse/event"),
_sampling_dirty(false),
_color_dirty(true),
_render_dirty(true),
_root_group( new canvas::Group(node) ),
_render_always(false)
{
@ -155,6 +156,11 @@ void Canvas::update(double delta_time_sec)
_root_group->update(delta_time_sec);
_texture.setRender(_render_dirty);
// Always render if sampling or color has changed
_render_dirty = _sampling_dirty || _color_dirty;
if( _sampling_dirty )
{
_texture.setSampling(
@ -318,9 +324,12 @@ void Canvas::childRemoved( SGPropertyNode * parent,
//----------------------------------------------------------------------------
void Canvas::valueChanged(SGPropertyNode* node)
{
if( boost::starts_with(node->getNameString(), "status") )
if( boost::starts_with(node->getNameString(), "status")
|| node->getParent()->getNameString() == "bounding-box" )
return;
_render_dirty = true;
bool handled = true;
if( node->getParent()->getParent() == _node )
{
@ -365,6 +374,8 @@ void Canvas::valueChanged(SGPropertyNode* node)
else if( node->getIndex() == 1 )
setViewHeight( node->getIntValue() );
}
else if( node->getNameString() == "freeze" )
_texture.setRender( node->getBoolValue() );
else
handled = false;
}

View file

@ -142,7 +142,8 @@ class Canvas:
_mouse_event;
bool _sampling_dirty,
_color_dirty;
_color_dirty,
_render_dirty;
FGODGauge _texture;
std::auto_ptr<canvas::Group> _root_group;

View file

@ -73,7 +73,7 @@ namespace canvas
{
//----------------------------------------------------------------------------
Image::Image(SGPropertyNode_ptr node, const Style& parent_style):
Element(node, parent_style, BOUNDING_BOX),
Element(node, parent_style),
_texture(new osg::Texture2D),
_node_src_rect( node->getNode("source", 0, true) )
{
@ -132,6 +132,7 @@ namespace canvas
_attributes_dirty &= ~DEST_SIZE;
_geom->dirtyBound();
setBoundingBox(_geom->getBound());
}
if( _attributes_dirty & SRC_RECT )

View file

@ -105,17 +105,6 @@ namespace canvas
_transform->setMatrix(m);
_transform_dirty = false;
}
if( !_bounding_box.empty() )
{
assert( _drawable );
const osg::BoundingBox& bb = _drawable->getBound();
_bounding_box[0]->setFloatValue(bb._min.x());
_bounding_box[1]->setFloatValue(bb._min.y());
_bounding_box[2]->setFloatValue(bb._max.x());
_bounding_box[3]->setFloatValue(bb._max.y());
}
}
//----------------------------------------------------------------------------
@ -229,12 +218,28 @@ namespace canvas
childChanged(child);
}
//----------------------------------------------------------------------------
void Element::setBoundingBox(const osg::BoundingBox& bb)
{
if( _bounding_box.empty() )
{
SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
_bounding_box.resize(4);
_bounding_box[0] = bb_node->getChild("min-x", 0, true);
_bounding_box[1] = bb_node->getChild("min-y", 0, true);
_bounding_box[2] = bb_node->getChild("max-x", 0, true);
_bounding_box[3] = bb_node->getChild("max-y", 0, true);
}
_bounding_box[0]->setFloatValue(bb._min.x());
_bounding_box[1]->setFloatValue(bb._min.y());
_bounding_box[2]->setFloatValue(bb._max.x());
_bounding_box[3]->setFloatValue(bb._max.y());
}
//----------------------------------------------------------------------------
Element::Element( SGPropertyNode_ptr node,
const Style& parent_style,
uint32_t attributes_used ):
_attributes_used( attributes_used ),
_attributes_dirty( attributes_used ),
const Style& parent_style ):
_transform_dirty( false ),
_transform( new osg::MatrixTransform ),
_node( node ),
@ -271,16 +276,6 @@ namespace canvas
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(_drawable);
_transform->addChild(geode);
if( _attributes_used & BOUNDING_BOX )
{
SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
_bounding_box.resize(4);
_bounding_box[0] = bb_node->getChild("min-x", 0, true);
_bounding_box[1] = bb_node->getChild("min-y", 0, true);
_bounding_box[2] = bb_node->getChild("max-x", 0, true);
_bounding_box[3] = bb_node->getChild("max-y", 0, true);
}
}
//----------------------------------------------------------------------------

View file

@ -21,6 +21,7 @@
#include <simgear/props/props.hxx>
#include <simgear/misc/stdint.hxx> // for uint32_t
#include <osg/BoundingBox>
#include <osg/MatrixTransform>
#include <boost/bind.hpp>
@ -63,12 +64,16 @@ namespace canvas
SGPropertyNode * child );
virtual void valueChanged(SGPropertyNode * child);
/**
* Write the given bounding box to the property tree
*/
void setBoundingBox(const osg::BoundingBox& bb);
protected:
enum Attributes
{
BOUNDING_BOX = 0x0001,
LAST_ATTRIBUTE = BOUNDING_BOX
LAST_ATTRIBUTE = 0x0001
};
enum TransformType
@ -80,7 +85,6 @@ namespace canvas
TT_SCALE
};
uint32_t _attributes_used;
uint32_t _attributes_dirty;
bool _transform_dirty;
@ -93,8 +97,7 @@ namespace canvas
std::vector<SGPropertyNode_ptr> _bounding_box;
Element( SGPropertyNode_ptr node,
const Style& parent_style,
uint32_t attributes_used = 0 );
const Style& parent_style );
template<typename T, class C1, class C2>
Element::StyleSetter
@ -137,9 +140,9 @@ namespace canvas
virtual void childRemoved(SGPropertyNode * child){}
virtual void childChanged(SGPropertyNode * child){}
void setDrawable( osg::Drawable* drawable );
void setupStyle();
void setDrawable(osg::Drawable* drawable);
void setupStyle();
bool setStyle(const SGPropertyNode* child);
private:

View file

@ -31,11 +31,13 @@ namespace canvas
typedef std::vector<VGubyte> CmdList;
typedef std::vector<VGfloat> CoordList;
class Path;
class PathDrawable:
public osg::Drawable
{
public:
PathDrawable():
PathDrawable(Path* path):
_path_element(path),
_path(VG_INVALID_HANDLE),
_paint(VG_INVALID_HANDLE),
_paint_fill(VG_INVALID_HANDLE),
@ -58,8 +60,8 @@ namespace canvas
}
virtual const char* className() const { return "PathDrawable"; }
virtual osg::Object* cloneType() const { return new PathDrawable; }
virtual osg::Object* clone(const osg::CopyOp&) const { return new PathDrawable; }
virtual osg::Object* cloneType() const { return new PathDrawable(_path_element); }
virtual osg::Object* clone(const osg::CopyOp&) const { return new PathDrawable(_path_element); }
/**
* Replace the current path segments with the new ones
@ -239,11 +241,14 @@ namespace canvas
// vgPathBounds doesn't take stroke width into account
float ext = 0.5 * _stroke_width;
return osg::BoundingBox
osg::BoundingBox bb
(
min[0] - ext, min[1] - ext, -0.1,
min[0] + size[0] + ext, min[1] + size[1] + ext, 0.1
);
_path_element->setBoundingBox(bb);
return bb;
}
private:
@ -258,6 +263,8 @@ namespace canvas
BOUNDING_BOX = FILL_COLOR << 1
};
Path *_path_element;
mutable VGPath _path;
mutable VGPaint _paint;
mutable VGPaint _paint_fill;
@ -347,8 +354,8 @@ namespace canvas
//----------------------------------------------------------------------------
Path::Path(SGPropertyNode_ptr node, const Style& parent_style):
Element(node, parent_style, BOUNDING_BOX),
_path( new PathDrawable() )
Element(node, parent_style),
_path( new PathDrawable(this) )
{
setDrawable(_path);
PathDrawable *path = _path.get();

View file

@ -31,6 +31,8 @@ namespace canvas
{
public:
TextOSG(canvas::Text* text);
void setCharacterAspect(float aspect);
void setFill(const std::string& fill);
void setBackgroundColor(const std::string& fill);
@ -38,8 +40,19 @@ namespace canvas
osg::Vec2 handleHit(float x, float y);
virtual osg::BoundingBox computeBound() const;
protected:
canvas::Text *_text_element;
};
//----------------------------------------------------------------------------
Text::TextOSG::TextOSG(canvas::Text* text):
_text_element(text)
{
}
//----------------------------------------------------------------------------
void Text::TextOSG::setCharacterAspect(float aspect)
{
@ -152,13 +165,15 @@ namespace canvas
bb._min.y() += _offset.y();
bb._max.y() += _offset.y();
_text_element->setBoundingBox(bb);
return bb;
}
//----------------------------------------------------------------------------
Text::Text(SGPropertyNode_ptr node, const Style& parent_style):
Element(node, parent_style, BOUNDING_BOX),
_text( new Text::TextOSG() )
Element(node, parent_style),
_text( new Text::TextOSG(this) )
{
setDrawable(_text);
_text->setCharacterSizeMode(osgText::Text::OBJECT_COORDS);

View file

@ -149,6 +149,13 @@ void FGODGauge::setSampling( bool mipmapping,
updateSampling();
}
//------------------------------------------------------------------------------
void FGODGauge::setRender(bool render)
{
// Only the far camera should trigger this texture to be rendered.
camera->setNodeMask(render ? simgear::BACKGROUND_BIT : 0);
}
//------------------------------------------------------------------------------
bool FGODGauge::serviceable(void)
{
@ -160,8 +167,6 @@ void FGODGauge::allocRT(osg::NodeCallback* camera_cull_callback)
{
camera = new osg::Camera;
camera->setDataVariance(osg::Object::DYNAMIC);
// Only the far camera should trigger this texture to be rendered.
camera->setNodeMask(simgear::BACKGROUND_BIT);
camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setRenderOrder(osg::Camera::PRE_RENDER);
camera->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f , 0.0f));
@ -172,6 +177,7 @@ void FGODGauge::allocRT(osg::NodeCallback* camera_cull_callback)
if( camera_cull_callback )
camera->setCullCallback(camera_cull_callback);
setRender(true);
updateCoordinateFrame();
updateStencil();

View file

@ -98,6 +98,12 @@ class FGODGauge
int coverage_samples = 0,
int color_samples = 0 );
/**
* Enable/Disable updating the texture (If disabled the contents of the
* texture remains with the outcome of the last rendering pass)
*/
void setRender(bool render);
/**
* Say if we can render to a texture.
* @return true if rtt is available
@ -145,7 +151,7 @@ class FGODGauge
// Real initialization function. Bad name.
void allocRT(osg::NodeCallback* camera_cull_callback = 0);
private:
private:
int _size_x,
_size_y,
_view_width,