Fixes for technique predicates
Get tests based on properties and OpenGL extensions working.
This commit is contained in:
@@ -828,11 +828,13 @@ void buildTechnique(Effect* effect, const SGPropertyNode* prop,
|
||||
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
|
||||
|
||||
@@ -214,7 +214,11 @@ class GLVersionExpression : public SGExpression<float>
|
||||
public:
|
||||
void eval(float& value, const expression::Binding*) const
|
||||
{
|
||||
#ifdef TECHNIQUE_TEST_EXTENSIONS
|
||||
value = 1.1;
|
||||
#else
|
||||
value = getGLVersionNumber();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -250,8 +254,16 @@ Expression* extensionSupportedParser(const SGPropertyNode* exp,
|
||||
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");
|
||||
}
|
||||
|
||||
@@ -270,11 +282,6 @@ void Technique::setGLExtensionsPred(float glVersion,
|
||||
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();
|
||||
@@ -299,6 +306,16 @@ void Technique::setGLExtensionsPred(float glVersion,
|
||||
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);
|
||||
|
||||
@@ -97,6 +97,7 @@ public:
|
||||
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
|
||||
@@ -116,5 +117,17 @@ protected:
|
||||
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
|
||||
|
||||
@@ -682,44 +682,6 @@ namespace simgear
|
||||
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)
|
||||
{
|
||||
@@ -728,6 +690,13 @@ bool Parser::readChildren(const SGPropertyNode* exp,
|
||||
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()) {
|
||||
@@ -867,10 +836,14 @@ Expression* logicopParser(const SGPropertyNode* exp, Parser* parser)
|
||||
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;
|
||||
|
||||
@@ -901,96 +901,131 @@ namespace simgear
|
||||
{
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user