Fixes for technique predicates

Get tests based on properties and OpenGL extensions working.
This commit is contained in:
timoore
2009-07-15 23:11:55 +00:00
committed by Tim Moore
parent e3646d4d4a
commit efec9070e1
5 changed files with 144 additions and 104 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}
};
}
/**