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:
parent
88592bfe71
commit
4a94071ed7
9 changed files with 91 additions and 46 deletions
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue