1 #include "Technique.hxx"
4 #include <boost/bind.hpp>
5 #include <boost/foreach.hpp>
9 #include <osg/GLExtensions>
11 #include <osgUtil/CullVisitor>
13 #include <osgDB/Registry>
14 #include <osgDB/Input>
15 #include <osgDB/ParameterOutput>
17 #include <simgear/structure/OSGUtils.hxx>
22 using namespace osgUtil;
27 struct ValidateOperation : GraphicsOperation
29 ValidateOperation(Technique* technique_)
30 : GraphicsOperation(opName, false), technique(technique_)
33 virtual void operator() (GraphicsContext* gc);
34 osg::ref_ptr<Technique> technique;
35 static const std::string opName;
38 const std::string ValidateOperation::opName("ValidateOperation");
41 void ValidateOperation::operator() (GraphicsContext* gc)
43 technique->validateInContext(gc);
47 Technique::Technique(bool alwaysValid)
48 : _alwaysValid(alwaysValid), _glVersion(1.1f)
52 Technique::Technique(const Technique& rhs, const osg::CopyOp& copyop) :
53 _contextMap(rhs._contextMap), _alwaysValid(rhs._alwaysValid),
54 _shadowingStateSet(rhs._shadowingStateSet), _glVersion(rhs._glVersion)
57 using namespace boost;
58 transform(rhs.passes.begin(), rhs.passes.end(),
59 backRefInsertIterator(passes),
60 bind(simgear::clone_ref<Pass>, _1, copyop));
64 Technique::~Technique()
68 Technique::Status Technique::valid(osg::RenderInfo* renderInfo)
72 unsigned contextID = renderInfo->getContextID();
73 ContextInfo& contextInfo = _contextMap[contextID];
74 Status status = contextInfo.valid();
75 if (status != UNKNOWN)
77 Status newStatus = QUERY_IN_PROGRESS;
78 // lock and spawn validity check.
79 if (!contextInfo.valid.compareAndSwap(status, newStatus)) {
80 // Lost the race with another thread spawning a request
81 return contextInfo.valid();
83 ref_ptr<ValidateOperation> validOp = new ValidateOperation(this);
84 renderInfo->getState()->getGraphicsContext()->getGraphicsThread()
89 Technique::Status Technique::getValidStatus(const RenderInfo* renderInfo) const
93 ContextInfo& contextInfo = _contextMap[renderInfo->getContextID()];
94 return contextInfo.valid();
97 void Technique::validateInContext(GraphicsContext* gc)
99 ContextInfo& contextInfo = _contextMap[gc->getState()->getContextID()];
100 Status oldVal = contextInfo.valid();
101 Status newVal = INVALID;
102 if (getGLVersionNumber() >= _glVersion)
104 contextInfo.valid.compareAndSwap(oldVal, newVal);
109 enum NumDrawables {NUM_DRAWABLES = 128};
112 EffectGeode::DrawablesIterator
113 Technique::processDrawables(const EffectGeode::DrawablesIterator& begin,
114 const EffectGeode::DrawablesIterator& end,
116 bool isCullingActive)
118 RefMatrix& matrix = *cv->getModelViewMatrix();
119 float depth[NUM_DRAWABLES];
120 EffectGeode::DrawablesIterator itr = begin;
122 = cv->getComputeNearFarMode() != CullVisitor::DO_NOT_COMPUTE_NEAR_FAR;
123 for (int i = 0; i < NUM_DRAWABLES && itr != end; ++itr, ++i) {
124 Drawable* drawable = itr->get();
125 const BoundingBox& bb = drawable->getBound();
126 if ((drawable->getCullCallback()
127 && drawable->getCullCallback()->cull(cv, drawable,
128 &cv->getRenderInfo()))
129 || (isCullingActive && cv->isCulled(bb))) {
133 if (computeNearFar && bb.valid()) {
134 if (!cv->updateCalculatedNearFar(matrix, *drawable, false)) {
139 depth[i] = (bb.valid()
140 ? cv->getDistanceFromEyePoint(bb.center(), false)
145 EffectGeode::DrawablesIterator drawablesEnd = itr;
146 BOOST_FOREACH(ref_ptr<Pass>& pass, passes)
148 cv->pushStateSet(pass->getStateSet());
150 for (itr = begin; itr != drawablesEnd; ++itr, ++i) {
151 if (depth[i] != FLT_MAX)
152 cv->addDrawableAndDepth(itr->get(), &matrix, depth[i]);
159 void Technique::resizeGLObjectBuffers(unsigned int maxSize)
161 if (_shadowingStateSet.valid())
162 _shadowingStateSet->resizeGLObjectBuffers(maxSize);
163 BOOST_FOREACH(ref_ptr<Pass>& pass, passes) {
164 pass->resizeGLObjectBuffers(maxSize);
166 _contextMap.resize(maxSize);
169 void Technique::releaseGLObjects(osg::State* state) const
171 if (_shadowingStateSet.valid())
172 _shadowingStateSet->releaseGLObjects(state);
173 BOOST_FOREACH(const ref_ptr<Pass>& pass, passes)
175 pass->releaseGLObjects(state);
178 for (int i = 0; i < _contextMap.size(); ++i) {
179 ContextInfo& info = _contextMap[i];
180 Status oldVal = info.valid();
181 info.valid.compareAndSwap(oldVal, UNKNOWN);
184 ContextInfo& info = _contextMap[state->getContextID()];
185 Status oldVal = info.valid();
186 info.valid.compareAndSwap(oldVal, UNKNOWN);
190 bool Technique_writeLocalData(const Object& obj, osgDB::Output& fw)
192 const Technique& tniq = static_cast<const Technique&>(obj);
193 fw.indent() << "alwaysValid "
194 << (tniq.getAlwaysValid() ? "TRUE\n" : "FALSE\n");
195 fw.indent() << "glVersion " << tniq.getGLVersion() << "\n";
196 if (tniq.getShadowingStateSet()) {
197 fw.indent() << "shadowingStateSet\n";
198 fw.writeObject(*tniq.getShadowingStateSet());
200 fw.indent() << "passes\n";
201 BOOST_FOREACH(const ref_ptr<Pass>& pass, tniq.passes) {
202 fw.writeObject(*pass);
209 osgDB::RegisterDotOsgWrapperProxy TechniqueProxy
212 "simgear::Technique",
213 "Object simgear::Technique",
215 &Technique_writeLocalData