]> git.mxchange.org Git - flightgear.git/commitdiff
Canvas: Performance improvements.
authorThomas Geymayer <tomgey@gmail.com>
Fri, 21 Sep 2012 19:20:35 +0000 (21:20 +0200)
committerThomas Geymayer <tomgey@gmail.com>
Fri, 21 Sep 2012 20:03:58 +0000 (22:03 +0200)
 - 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
src/Canvas/canvas.hxx
src/Canvas/elements/CanvasImage.cxx
src/Canvas/elements/element.cxx
src/Canvas/elements/element.hxx
src/Canvas/elements/path.cxx
src/Canvas/elements/text.cxx
src/Instrumentation/od_gauge.cxx
src/Instrumentation/od_gauge.hxx

index 1e64f795892cdb027bfdac71a98bb18b9ac1a7c3..5c08061a5cc5bb17d3a03412d48110e2e7eca1a5 100644 (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;
   }
index dbfae12fe664c9fcdefba6575bd5f94c8b063ae1..ce75df921a76793ba28aafca96fda7c993fe0459 100644 (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;
index 17dd5e0cfcd41a2aa9db4f02d9bb7c71fffc7a49..8eb1e3e0c8f47ad2e108ffabfdc4645baf43617e 100644 (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 )
index 9b2d446a6aa1c8ddbf414f179914f8d325866b6b..b996c1a8129da9809a8a2716304cb1cc7d3971b0 100644 (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);
-    }
   }
 
   //----------------------------------------------------------------------------
index 3aae173644bc3779622276af9c40180ab99ad17a..d9df155f23dd679812d962ab6e04a2193e31567e 100644 (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:
index 02e616348ae72925ccdb6063b0d61f4e985a0445..f7c9ddafe55cc2504a153ca8a8ceeccc82a3d9ac 100644 (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();
index 3159d8c7c9b6284712f12635c26ca93238ebe955..a7f44c4f123a38d12a12dd18391290c0e010b7d5 100644 (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);
index 2a003706f4d963229c09a1fac88571294e2c09f9..c6be269e4e5e5e3074c4b1d0d562f92914c92d36 100644 (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();
 
index 13ae907519aa88fb31200fea4e318d2c07d4fbf5..7c4ee00edb5889976e4976f11e4a3f6ae2e64cfe 100644 (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,