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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -149,6 +149,13 @@ void FGODGauge::setSampling( bool mipmapping,
updateSampling(); 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) bool FGODGauge::serviceable(void)
{ {
@ -160,8 +167,6 @@ void FGODGauge::allocRT(osg::NodeCallback* camera_cull_callback)
{ {
camera = new osg::Camera; camera = new osg::Camera;
camera->setDataVariance(osg::Object::DYNAMIC); 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->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
camera->setRenderOrder(osg::Camera::PRE_RENDER); camera->setRenderOrder(osg::Camera::PRE_RENDER);
camera->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f , 0.0f)); 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 ) if( camera_cull_callback )
camera->setCullCallback(camera_cull_callback); camera->setCullCallback(camera_cull_callback);
setRender(true);
updateCoordinateFrame(); updateCoordinateFrame();
updateStencil(); updateStencil();

View file

@ -98,6 +98,12 @@ class FGODGauge
int coverage_samples = 0, int coverage_samples = 0,
int color_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. * Say if we can render to a texture.
* @return true if rtt is available * @return true if rtt is available
@ -145,7 +151,7 @@ class FGODGauge
// Real initialization function. Bad name. // Real initialization function. Bad name.
void allocRT(osg::NodeCallback* camera_cull_callback = 0); void allocRT(osg::NodeCallback* camera_cull_callback = 0);
private: private:
int _size_x, int _size_x,
_size_y, _size_y,
_view_width, _view_width,