1 #include "Technique.hxx"
4 #include <boost/bind.hpp>
5 #include <boost/foreach.hpp>
9 #include <osg/GLExtensions>
11 #include <osgUtil/CullVisitor>
13 #include <simgear/structure/OSGUtils.hxx>
18 using namespace osgUtil;
23 struct ValidateOperation : GraphicsOperation
25 ValidateOperation(Technique* technique_)
26 : GraphicsOperation(opName, false), technique(technique_)
29 virtual void operator() (GraphicsContext* gc);
30 osg::ref_ptr<Technique> technique;
31 static const std::string opName;
34 const std::string ValidateOperation::opName("ValidateOperation");
37 void ValidateOperation::operator() (GraphicsContext* gc)
39 technique->validateInContext(gc);
43 Technique::Technique() : _glVersion(1.1f)
47 Technique::Technique(const Technique& rhs, const osg::CopyOp& copyop) :
48 _contextMap(rhs._contextMap), _shadowingStateSet(rhs._shadowingStateSet),
49 _glVersion(rhs._glVersion)
52 using namespace boost;
53 transform(rhs.passes.begin(), rhs.passes.end(),
54 backRefInsertIterator(passes),
55 bind(simgear::clone_ref<Pass>, _1, copyop));
59 Technique::~Technique()
63 Technique::Status Technique::valid(osg::RenderInfo* renderInfo)
65 unsigned contextID = renderInfo->getContextID();
66 ContextInfo& contextInfo = _contextMap[contextID];
67 Status status = contextInfo.valid();
68 if (status != UNKNOWN)
70 Status newStatus = QUERY_IN_PROGRESS;
71 // lock and spawn validity check.
72 if (!contextInfo.valid.compareAndSwap(status, newStatus)) {
73 // Lost the race with another thread spawning a request
74 return contextInfo.valid();
76 ref_ptr<ValidateOperation> validOp = new ValidateOperation(this);
77 renderInfo->getState()->getGraphicsContext()->getGraphicsThread()
82 Technique::Status Technique::getValidStatus(const RenderInfo* renderInfo) const
84 ContextInfo& contextInfo = _contextMap[renderInfo->getContextID()];
85 return contextInfo.valid();
88 void Technique::validateInContext(GraphicsContext* gc)
90 ContextInfo& contextInfo = _contextMap[gc->getState()->getContextID()];
91 Status oldVal = contextInfo.valid();
92 Status newVal = INVALID;
93 if (getGLVersionNumber() >= _glVersion)
95 contextInfo.valid.compareAndSwap(oldVal, newVal);
100 enum NumDrawables {NUM_DRAWABLES = 128};
103 EffectGeode::DrawablesIterator
104 Technique::processDrawables(const EffectGeode::DrawablesIterator& begin,
105 const EffectGeode::DrawablesIterator& end,
107 bool isCullingActive)
109 RefMatrix& matrix = *cv->getModelViewMatrix();
110 float depth[NUM_DRAWABLES];
111 EffectGeode::DrawablesIterator itr = begin;
113 = cv->getComputeNearFarMode() != CullVisitor::DO_NOT_COMPUTE_NEAR_FAR;
114 for (int i = 0; i < NUM_DRAWABLES && itr != end; ++itr, ++i) {
115 Drawable* drawable = itr->get();
116 const BoundingBox& bb = drawable->getBound();
117 if ((drawable->getCullCallback()
118 && drawable->getCullCallback()->cull(cv, drawable,
119 &cv->getRenderInfo()))
120 || (isCullingActive && cv->isCulled(bb))) {
124 if (computeNearFar && bb.valid()) {
125 if (!cv->updateCalculatedNearFar(matrix, *drawable, false)) {
130 depth[i] = (bb.valid()
131 ? cv->getDistanceFromEyePoint(bb.center(), false)
136 EffectGeode::DrawablesIterator drawablesEnd = itr;
137 BOOST_FOREACH(ref_ptr<Pass>& pass, passes)
139 cv->pushStateSet(pass->getStateSet());
141 for (itr = begin; itr != drawablesEnd; ++itr, ++i) {
142 if (depth[i] != FLT_MAX)
143 cv->addDrawableAndDepth(itr->get(), &matrix, depth[i]);
150 void Technique::resizeGLObjectBuffers(unsigned int maxSize)
152 if (_shadowingStateSet.valid())
153 _shadowingStateSet->resizeGLObjectBuffers(maxSize);
154 BOOST_FOREACH(ref_ptr<Pass>& pass, passes) {
155 pass->resizeGLObjectBuffers(maxSize);
157 _contextMap.resize(maxSize);
160 void Technique::releaseGLObjects(osg::State* state) const
162 if (_shadowingStateSet.valid())
163 _shadowingStateSet->releaseGLObjects(state);
164 BOOST_FOREACH(const ref_ptr<Pass>& pass, passes)
166 pass->releaseGLObjects(state);
169 for (int i = 0; i < _contextMap.size(); ++i) {
170 ContextInfo& info = _contextMap[i];
171 Status oldVal = info.valid();
172 info.valid.compareAndSwap(oldVal, UNKNOWN);
175 ContextInfo& info = _contextMap[state->getContextID()];
176 Status oldVal = info.valid();
177 info.valid.compareAndSwap(oldVal, UNKNOWN);