From 4a94071ed78efdb6c8a9c5d44102dd48a001d920 Mon Sep 17 00:00:00 2001 From: Thomas Geymayer Date: Fri, 21 Sep 2012 21:20:35 +0200 Subject: [PATCH] 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). --- src/Canvas/canvas.cxx | 13 ++++++++- src/Canvas/canvas.hxx | 3 +- src/Canvas/elements/CanvasImage.cxx | 3 +- src/Canvas/elements/element.cxx | 45 +++++++++++++---------------- src/Canvas/elements/element.hxx | 17 ++++++----- src/Canvas/elements/path.cxx | 19 ++++++++---- src/Canvas/elements/text.cxx | 19 ++++++++++-- src/Instrumentation/od_gauge.cxx | 10 +++++-- src/Instrumentation/od_gauge.hxx | 8 ++++- 9 files changed, 91 insertions(+), 46 deletions(-) diff --git a/src/Canvas/canvas.cxx b/src/Canvas/canvas.cxx index 1e64f7958..5c08061a5 100644 --- a/src/Canvas/canvas.cxx +++ b/src/Canvas/canvas.cxx @@ -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; } diff --git a/src/Canvas/canvas.hxx b/src/Canvas/canvas.hxx index dbfae12fe..ce75df921 100644 --- a/src/Canvas/canvas.hxx +++ b/src/Canvas/canvas.hxx @@ -142,7 +142,8 @@ class Canvas: _mouse_event; bool _sampling_dirty, - _color_dirty; + _color_dirty, + _render_dirty; FGODGauge _texture; std::auto_ptr _root_group; diff --git a/src/Canvas/elements/CanvasImage.cxx b/src/Canvas/elements/CanvasImage.cxx index 17dd5e0cf..8eb1e3e0c 100644 --- a/src/Canvas/elements/CanvasImage.cxx +++ b/src/Canvas/elements/CanvasImage.cxx @@ -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 ) diff --git a/src/Canvas/elements/element.cxx b/src/Canvas/elements/element.cxx index 9b2d446a6..b996c1a81 100644 --- a/src/Canvas/elements/element.cxx +++ b/src/Canvas/elements/element.cxx @@ -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 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); - } } //---------------------------------------------------------------------------- diff --git a/src/Canvas/elements/element.hxx b/src/Canvas/elements/element.hxx index 3aae17364..d9df155f2 100644 --- a/src/Canvas/elements/element.hxx +++ b/src/Canvas/elements/element.hxx @@ -21,6 +21,7 @@ #include #include // for uint32_t +#include #include #include @@ -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 _bounding_box; Element( SGPropertyNode_ptr node, - const Style& parent_style, - uint32_t attributes_used = 0 ); + const Style& parent_style ); template 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: diff --git a/src/Canvas/elements/path.cxx b/src/Canvas/elements/path.cxx index 02e616348..f7c9ddafe 100644 --- a/src/Canvas/elements/path.cxx +++ b/src/Canvas/elements/path.cxx @@ -31,11 +31,13 @@ namespace canvas typedef std::vector CmdList; typedef std::vector 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(); diff --git a/src/Canvas/elements/text.cxx b/src/Canvas/elements/text.cxx index 3159d8c7c..a7f44c4f1 100644 --- a/src/Canvas/elements/text.cxx +++ b/src/Canvas/elements/text.cxx @@ -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); diff --git a/src/Instrumentation/od_gauge.cxx b/src/Instrumentation/od_gauge.cxx index 2a003706f..c6be269e4 100644 --- a/src/Instrumentation/od_gauge.cxx +++ b/src/Instrumentation/od_gauge.cxx @@ -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(); diff --git a/src/Instrumentation/od_gauge.hxx b/src/Instrumentation/od_gauge.hxx index 13ae90751..7c4ee00ed 100644 --- a/src/Instrumentation/od_gauge.hxx +++ b/src/Instrumentation/od_gauge.hxx @@ -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, -- 2.39.5