X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fscene%2Fmaterial%2FTechnique.cxx;h=aeab9cf365b9b3057c70701b82e6d9165fd02397;hb=9f9c4cf32c2cf774c7febd7fe2b4e65a7d205294;hp=d800f0cc6cd6a750119d1b6637eb2920f5a409bb;hpb=c6b2124129e908d95ccfdf9d11a51cd257e55e55;p=simgear.git diff --git a/simgear/scene/material/Technique.cxx b/simgear/scene/material/Technique.cxx index d800f0cc..aeab9cf3 100644 --- a/simgear/scene/material/Technique.cxx +++ b/simgear/scene/material/Technique.cxx @@ -1,12 +1,19 @@ + +#ifdef HAVE_CONFIG_H +# include +#endif + #include "Technique.hxx" #include "Pass.hxx" -#include #include +#include +#include #include #include +#include #include #include @@ -14,6 +21,7 @@ #include #include +#include #include namespace simgear @@ -45,20 +53,21 @@ void ValidateOperation::operator() (GraphicsContext* gc) } 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(copyop(rhs._shadowingStateSet.get())), + _validExpression(rhs._validExpression), + _contextIdLocation(rhs._contextIdLocation) { - using namespace std; - using namespace boost; - transform(rhs.passes.begin(), rhs.passes.end(), - backRefInsertIterator(passes), - bind(simgear::clone_ref, _1, copyop)); - + for (std::vector >::const_iterator itr = rhs.passes.begin(), + end = rhs.passes.end(); + itr != end; + ++itr) + passes.push_back(static_cast(copyop(itr->get()))); } Technique::~Technique() @@ -81,8 +90,12 @@ Technique::Status Technique::valid(osg::RenderInfo* renderInfo) return contextInfo.valid(); } ref_ptr 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; } @@ -96,10 +109,13 @@ Technique::Status Technique::getValidStatus(const RenderInfo* renderInfo) const 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); } @@ -145,7 +161,7 @@ Technique::processDrawables(const EffectGeode::DrawablesIterator& begin, EffectGeode::DrawablesIterator drawablesEnd = itr; BOOST_FOREACH(ref_ptr& pass, passes) { - cv->pushStateSet(pass->getStateSet()); + cv->pushStateSet(pass.get()); int i = 0; for (itr = begin; itr != drawablesEnd; ++itr, ++i) { if (depth[i] != FLT_MAX) @@ -175,7 +191,7 @@ void Technique::releaseGLObjects(osg::State* state) const pass->releaseGLObjects(state); } if (state == 0) { - for (int i = 0; i < _contextMap.size(); ++i) { + for (int i = 0; i < (int)_contextMap.size(); ++i) { ContextInfo& info = _contextMap[i]; Status oldVal = info.valid(); info.valid.compareAndSwap(oldVal, UNKNOWN); @@ -187,17 +203,169 @@ void Technique::releaseGLObjects(osg::State* state) const } } +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 +{ +public: + void eval(float& value, const expression::Binding*) const + { +#ifdef TECHNIQUE_TEST_EXTENSIONS + value = 1.1; +#else + value = getGLVersionNumber(); +#endif + } +}; + +Expression* glVersionParser(const SGPropertyNode* exp, + expression::Parser* parser) +{ + return new GLVersionExpression(); +} + +expression::ExpParserRegistrar glVersionRegistrar("glversion", glVersionParser); + +class ExtensionSupportedExpression + : public GeneralNaryExpression +{ +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; +}; + +Expression* extensionSupportedParser(const SGPropertyNode* exp, + expression::Parser* parser) +{ + if (exp->getType() == props::STRING + || exp->getType() == props::UNSPECIFIED) { + ExtensionSupportedExpression* esp + = new ExtensionSupportedExpression(exp->getStringValue()); + int location = parser->getBindingLayout().addBinding("__contextId", + expression::INT); + VariableExpression* contextExp + = new VariableExpression(location); + esp->addOperand(contextExp); + return esp; + } + throw expression::ParseError("extension-supported expression has wrong type"); +} + +expression::ExpParserRegistrar +extensionSupportedRegistrar("extension-supported", extensionSupportedParser); + +class GLShaderLanguageExpression : public GeneralNaryExpression +{ +public: + void eval(float& value, const expression::Binding* b) const + { + value = 0.0f; + int contextId = getOperand(0)->getValue(b); + GL2Extensions* extensions + = GL2Extensions::Get(static_cast(contextId), true); + if (!extensions) + return; + if (!extensions->isGlslSupported()) + return; + value = extensions->getLanguageVersion(); + } +}; + +Expression* shaderLanguageParser(const SGPropertyNode* exp, + expression::Parser* parser) +{ + GLShaderLanguageExpression* slexp = new GLShaderLanguageExpression; + int location = parser->getBindingLayout().addBinding("__contextId", + expression::INT); + VariableExpression* contextExp = new VariableExpression(location); + slexp->addOperand(contextExp); + return slexp; +} + +expression::ExpParserRegistrar shaderLanguageRegistrar("shader-language", + glVersionParser); + + +void Technique::setGLExtensionsPred(float glVersion, + const std::vector& extensions) +{ + using namespace std; + using namespace expression; + BindingLayout layout; + int contextLoc = layout.addBinding("__contextId", INT); + VariableExpression* contextExp + = new VariableExpression(contextLoc); + SGExpression* versionTest + = makePredicate(new SGConstExpression(glVersion), + new GLVersionExpression); + AndExpression* extensionsExp = 0; + for (vector::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); +} + +void Technique::refreshValidity() +{ + for (int i = 0; i < (int)_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(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()); } - fw.indent() << "passes\n"; + fw.indent() << "num_passes " << tniq.passes.size() << "\n"; BOOST_FOREACH(const ref_ptr& pass, tniq.passes) { fw.writeObject(*pass); }