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"),
|
_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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 )
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Add table
Reference in a new issue