#include <boost/bind.hpp>
#include <boost/foreach.hpp>
+#include <vector>
#include <string>
#include <osg/GLExtensions>
}
Technique::Technique(bool alwaysValid)
- : _alwaysValid(alwaysValid), _glVersion(1.1f)
+ : _alwaysValid(alwaysValid), _contextIdLocation(-1)
{
}
Technique::Technique(const Technique& rhs, const osg::CopyOp& copyop) :
_contextMap(rhs._contextMap), _alwaysValid(rhs._alwaysValid),
- _shadowingStateSet(rhs._shadowingStateSet), _glVersion(rhs._glVersion)
+ _shadowingStateSet(rhs._shadowingStateSet),
+ _validExpression(rhs._validExpression),
+ _contextIdLocation(rhs._contextIdLocation)
{
using namespace std;
using namespace boost;
return contextInfo.valid();
}
ref_ptr<ValidateOperation> validOp = new ValidateOperation(this);
- renderInfo->getState()->getGraphicsContext()->getGraphicsThread()
- ->add(validOp.get());
+ GraphicsContext* context = renderInfo->getState()->getGraphicsContext();
+ GraphicsThread* thread = context->getGraphicsThread();
+ if (thread)
+ thread->add(validOp.get());
+ else
+ context->add(validOp.get());
return newStatus;
}
void Technique::validateInContext(GraphicsContext* gc)
{
- ContextInfo& contextInfo = _contextMap[gc->getState()->getContextID()];
+ unsigned int contextId = gc->getState()->getContextID();
+ ContextInfo& contextInfo = _contextMap[contextId];
Status oldVal = contextInfo.valid();
Status newVal = INVALID;
- if (getGLVersionNumber() >= _glVersion)
+ expression::FixedLengthBinding<1> binding;
+ binding.getBindings()[_contextIdLocation].val.intVal = contextId;
+ if (_validExpression->getValue(&binding))
newVal = VALID;
contextInfo.valid.compareAndSwap(oldVal, newVal);
}
}
}
+void Technique::setValidExpression(SGExpressionb* exp,
+ const simgear::expression
+ ::BindingLayout& layout)
+{
+ using namespace simgear::expression;
+ _validExpression = exp;
+ VariableBinding binding;
+ if (layout.findBinding("__contextId", binding))
+ _contextIdLocation = binding.location;
+}
+
+class GLVersionExpression : public SGExpression<float>
+{
+public:
+ void eval(float& value, const expression::Binding*) const
+ {
+ value = getGLVersionNumber();
+ }
+};
+
+class ExtensionSupportedExpression
+ : public GeneralNaryExpression<bool, int>
+{
+public:
+ ExtensionSupportedExpression() {}
+ ExtensionSupportedExpression(const string& extString)
+ : _extString(extString)
+ {
+ }
+ const string& getExtensionString() { return _extString; }
+ void setExtensionString(const string& extString) { _extString = extString; }
+ void eval(bool&value, const expression::Binding* b) const
+ {
+ int contextId = getOperand(0)->getValue(b);
+ value = isGLExtensionSupported((unsigned)contextId, _extString.c_str());
+ }
+protected:
+ string _extString;
+};
+
+void Technique::setGLExtensionsPred(float glVersion,
+ const std::vector<std::string>& extensions)
+{
+ using namespace std;
+ using namespace expression;
+ BindingLayout layout;
+ int contextLoc = layout.addBinding("__contextId", INT);
+ VariableExpression<int>* contextExp
+ = new VariableExpression<int>(contextLoc);
+ LessEqualExpression<float>* versionTest
+ = new LessEqualExpression<float>(new SGConstExpression<float>(glVersion),
+ new GLVersionExpression);
+ AndExpression* extensionsExp = 0;
+ for (vector<string>::const_iterator itr = extensions.begin(),
+ e = extensions.end();
+ itr != e;
+ ++itr) {
+ if (!extensionsExp)
+ extensionsExp = new AndExpression;
+ ExtensionSupportedExpression* supported
+ = new ExtensionSupportedExpression(*itr);
+ supported->addOperand(contextExp);
+ extensionsExp->addOperand(supported);
+ }
+ SGExpressionb* predicate = 0;
+ if (extensionsExp) {
+ OrExpression* orExp = new OrExpression;
+ orExp->addOperand(versionTest);
+ orExp->addOperand(extensionsExp);
+ predicate = orExp;
+ } else {
+ predicate = versionTest;
+ }
+ setValidExpression(predicate, layout);
+}
+
bool Technique_writeLocalData(const Object& obj, osgDB::Output& fw)
{
const Technique& tniq = static_cast<const Technique&>(obj);
fw.indent() << "alwaysValid "
<< (tniq.getAlwaysValid() ? "TRUE\n" : "FALSE\n");
+#if 0
fw.indent() << "glVersion " << tniq.getGLVersion() << "\n";
+#endif
if (tniq.getShadowingStateSet()) {
fw.indent() << "shadowingStateSet\n";
fw.writeObject(*tniq.getShadowingStateSet());
#include "EffectGeode.hxx"
#include <simgear/structure/SGAtomic.hxx>
+#include <simgear/structure/SGExpression.hxx>
#include <map>
#include <vector>
void setShadowingStateSet(osg::StateSet* ss) { _shadowingStateSet = ss; }
virtual void resizeGLObjectBuffers(unsigned int maxSize);
virtual void releaseGLObjects(osg::State* state = 0) const;
- // Initial validity testing. Either the minimum OpenGL version
- // must be supported, or the list of extensions must be supported.
- float getGLVersion() const { return _glVersion; }
- void setGLVersion(float glVersion) { _glVersion = glVersion; }
- std::vector<std::string> glExtensions;
bool getAlwaysValid() const { return _alwaysValid; }
void setAlwaysValid(bool val) { _alwaysValid = val; }
+ void setValidExpression(SGExpressionb* exp,
+ const simgear::expression::BindingLayout&);
+ void setGLExtensionsPred(float glVersion,
+ const std::vector<std::string>& extensions);
protected:
// Validity of technique in a graphics context.
struct ContextInfo : public osg::Referenced
mutable ContextMap _contextMap;
bool _alwaysValid;
osg::ref_ptr<osg::StateSet> _shadowingStateSet;
- float _glVersion;
+ SGSharedPtr<SGExpressionb> _validExpression;
+ int _contextIdLocation;
};
}
#endif