Get tests based on properties and OpenGL extensions working.
tniq->setAlwaysValid(true);
} else {
try {
- expression::BindingLayout layout;
+ TechniquePredParser parser;
+ parser.setTechnique(tniq);
+ expression::BindingLayout& layout = parser.getBindingLayout();
int contextLoc = layout.addBinding("__contextId", expression::INT);
SGExpressionb* validExp
- = dynamic_cast<SGExpressionb*>(expression::read(predProp
- ->getChild(0)));
+ = dynamic_cast<SGExpressionb*>(parser.read(predProp
+ ->getChild(0)));
if (validExp)
tniq->setValidExpression(validExp, layout);
else
public:
void eval(float& value, const expression::Binding*) const
{
+#ifdef TECHNIQUE_TEST_EXTENSIONS
+ value = 1.1;
+#else
value = getGLVersionNumber();
+#endif
}
};
expression::Parser* parser)
{
if (exp->getType() == props::STRING
- || exp->getType() == props::UNSPECIFIED)
- return new ExtensionSupportedExpression(exp->getStringValue());
+ || exp->getType() == props::UNSPECIFIED) {
+ ExtensionSupportedExpression* esp
+ = new ExtensionSupportedExpression(exp->getStringValue());
+ int location = parser->getBindingLayout().addBinding("__contextId",
+ expression::INT);
+ VariableExpression<int>* contextExp
+ = new VariableExpression<int>(location);
+ esp->addOperand(contextExp);
+ return esp;
+ }
throw expression::ParseError("extension-supported expression has wrong type");
}
SGExpression<bool>* versionTest
= makePredicate<std::less_equal>(new SGConstExpression<float>(glVersion),
new GLVersionExpression);
-#if 0
- LessEqualExpression<float>* versionTest
- = new LessEqualExpression<float>(new SGConstExpression<float>(glVersion),
- new GLVersionExpression);
-#endif
AndExpression* extensionsExp = 0;
for (vector<string>::const_iterator itr = extensions.begin(),
e = extensions.end();
setValidExpression(predicate, layout);
}
+void Technique::refreshValidity()
+{
+ for (int i = 0; i < _contextMap.size(); ++i) {
+ ContextInfo& info = _contextMap[i];
+ Status oldVal = info.valid();
+ // What happens if we lose the race here?
+ info.valid.compareAndSwap(oldVal, UNKNOWN);
+ }
+}
+
bool Technique_writeLocalData(const Object& obj, osgDB::Output& fw)
{
const Technique& tniq = static_cast<const Technique&>(obj);
const simgear::expression::BindingLayout&);
void setGLExtensionsPred(float glVersion,
const std::vector<std::string>& extensions);
+ void refreshValidity();
protected:
// Validity of technique in a graphics context.
struct ContextInfo : public osg::Referenced
SGSharedPtr<SGExpressionb> _validExpression;
int _contextIdLocation;
};
+
+class TechniquePredParser : public expression::ExpressionParser
+{
+public:
+ void setTechnique(Technique* tniq) { _tniq = tniq; }
+ Technique* getTechnique() { return _tniq.get(); }
+// void setEffect(Effect* effect) { _effect = effect; }
+// Effect* getEffect() { return _effect.get(); }
+protected:
+ osg::ref_ptr<Technique> _tniq;
+ // osg::ref_ptr<Effect> _effect;
+};
}
#endif
namespace expression
{
-class Parser {
-public:
- void addParser(const std::string& name, exp_parser parser)
- {
- _parserTable.insert(std::make_pair(name, parser));
- }
- Expression* read(const SGPropertyNode* exp)
- {
- ParserMap::iterator itr = _parserTable.find(exp->getName());
- if (itr == _parserTable.end())
- throw ParseError(string("unknown expression ") + exp->getName());
- exp_parser parser = itr->second;
- return (*parser)(exp, this);
- }
- // XXX vector of SGSharedPtr?
- bool readChildren(const SGPropertyNode* exp,
- vector<Expression*>& result);
-protected:
- typedef std::map<const std::string, exp_parser> ParserMap;
- ParserMap _parserTable;
-};
-
-class ExpressionParser : public Parser, public Singleton<ExpressionParser>
-{
-};
-
-void addExpParser(const string& token, exp_parser parsefn)
-{
- ExpressionParser::instance()->addParser(token, parsefn);
-}
-
-Expression* read(const SGPropertyNode* exp, Parser* parser)
-{
- if (!parser)
- parser = ExpressionParser::instance();
- return parser->read(exp);
-}
-
bool Parser::readChildren(const SGPropertyNode* exp,
vector<Expression*>& result)
{
return true;
}
+Parser::ParserMap ExpressionParser::_parserTable;
+
+void ExpressionParser::addExpParser(const string& token, exp_parser parsefn)
+{
+ _parserTable.insert(std::make_pair(token, parsefn));
+}
+
Expression* valueParser(const SGPropertyNode* exp, Parser* parser)
{
switch (exp->getType()) {
ExpParserRegistrar andRegistrar("and", logicopParser<AndExpression>);
ExpParserRegistrar orRegistrar("or", logicopParser<OrExpression>);
-
int BindingLayout::addBinding(const string& name, Type type)
{
//XXX error checkint
+ vector<VariableBinding>::iterator itr
+ = find_if(bindings.begin(), bindings.end(),
+ bind(&VariableBinding::name, _1) == name);
+ if (itr != bindings.end())
+ return itr->location;
int result = bindings.size();
bindings.push_back(VariableBinding(name, type, bindings.size()));
return result;
{
namespace expression
{
- class Parser;
- /**
- * Function that parses a property tree, producing an expression.
- */
- typedef Expression* (*exp_parser)(const SGPropertyNode* exp,
- Parser* parser);
- void addExpParser(const std::string&, exp_parser);
- Expression* read(const SGPropertyNode* exp, Parser* parser = 0);
- /**
- * Constructor for registering parser functions.
- */
- struct ExpParserRegistrar
- {
- ExpParserRegistrar(const std::string& token, exp_parser parser)
- {
- addExpParser(token, parser);
- }
- };
-
- struct ParseError : public sg_exception
- {
+ struct ParseError : public sg_exception
+ {
ParseError(const string& message = std::string())
- : sg_exception(message) {}
- };
+ : sg_exception(message) {}
+ };
- // Support for binding variables around an expression.
- class Binding
- {
- public:
+ // Support for binding variables around an expression.
+ class Binding
+ {
+ public:
virtual ~Binding() {}
const virtual Value* getBindings() const = 0;
virtual Value* getBindings() = 0;
- };
+ };
- class VariableLengthBinding : public Binding
- {
- public:
+ class VariableLengthBinding : public Binding
+ {
+ public:
const Value* getBindings() const
{
- if (_bindings.empty())
- return 0;
- else
- return &_bindings[0];
+ if (_bindings.empty())
+ return 0;
+ else
+ return &_bindings[0];
}
Value* getBindings()
{
- if (_bindings.empty())
- return 0;
- else
- return &_bindings[0];
+ if (_bindings.empty())
+ return 0;
+ else
+ return &_bindings[0];
}
std::vector<Value> _bindings;
- };
+ };
- template<int Size> class FixedLengthBinding : public Binding
- {
- public:
+ template<int Size> class FixedLengthBinding : public Binding
+ {
+ public:
Value* getBindings()
{
- return &_bindings[0];
+ return &_bindings[0];
}
const Value* getBindings() const
{
- return &_bindings[0];
+ return &_bindings[0];
}
Value _bindings[Size];
- };
+ };
- struct VariableBinding
- {
+ struct VariableBinding
+ {
VariableBinding() : type(expression::DOUBLE), location(-1) {}
VariableBinding(const std::string& name_, expression::Type type_,
int location_)
- : name(name_), type(type_), location(location_)
+ : name(name_), type(type_), location(location_)
{
}
std::string name;
expression::Type type;
int location;
- };
+ };
- class BindingLayout
- {
- public:
+ class BindingLayout
+ {
+ public:
int addBinding(const std::string& name, expression::Type type);
bool findBinding(const string& name, VariableBinding& result) const;
- protected:
std::vector<VariableBinding> bindings;
- };
+ };
+
+ class Parser {
+ public:
+ typedef Expression* (*exp_parser)(const SGPropertyNode* exp,
+ Parser* parser);
+ void addParser(const std::string& name, exp_parser parser)
+ {
+ getParserMap().insert(std::make_pair(name, parser));
+ }
+ Expression* read(const SGPropertyNode* exp)
+ {
+ ParserMap& map = getParserMap();
+ ParserMap::iterator itr = map.find(exp->getName());
+ if (itr == map.end())
+ throw ParseError(string("unknown expression ") + exp->getName());
+ exp_parser parser = itr->second;
+ return (*parser)(exp, this);
+ }
+ // XXX vector of SGSharedPtr?
+ bool readChildren(const SGPropertyNode* exp,
+ std::vector<Expression*>& result);
+ /**
+ * Function that parses a property tree, producing an expression.
+ */
+ typedef std::map<const std::string, exp_parser> ParserMap;
+ virtual ParserMap& getParserMap() = 0;
+ /**
+ * After an expression is parsed, the binding layout may contain
+ * references that need to be bound during evaluation.
+ */
+ BindingLayout& getBindingLayout() { return _bindingLayout; }
+ protected:
+ BindingLayout _bindingLayout;
+ };
+
+ class ExpressionParser : public Parser
+ {
+ public:
+ ParserMap& getParserMap() { return _parserTable; }
+ static void addExpParser(const std::string&, exp_parser);
+ protected:
+ static ParserMap _parserTable;
+ };
+
+ /**
+ * Constructor for registering parser functions.
+ */
+ struct ExpParserRegistrar
+ {
+ ExpParserRegistrar(const std::string& token, Parser::exp_parser parser)
+ {
+ ExpressionParser::addExpParser(token, parser);
+ }
+ };
+
}
/**