]> git.mxchange.org Git - simgear.git/blobdiff - simgear/scene/material/Technique.cxx
Compile even if OSG_USE_REF_PTR_IMPLICIT_OUTPUT_CONVERSION is not set.
[simgear.git] / simgear / scene / material / Technique.cxx
index d800f0cc6cd6a750119d1b6637eb2920f5a409bb..aeab9cf365b9b3057c70701b82e6d9165fd02397 100644 (file)
@@ -1,12 +1,19 @@
+
+#ifdef HAVE_CONFIG_H
+#  include <simgear_config.h>
+#endif
+
 #include "Technique.hxx"
 #include "Pass.hxx"
 
-#include <boost/bind.hpp>
 #include <boost/foreach.hpp>
 
+#include <iterator>
+#include <vector>
 #include <string>
 
 #include <osg/GLExtensions>
+#include <osg/GL2Extensions>
 #include <osg/Math>
 #include <osgUtil/CullVisitor>
 
@@ -14,6 +21,7 @@
 #include <osgDB/Input>
 #include <osgDB/ParameterOutput>
 
+#include <simgear/props/props.hxx>
 #include <simgear/structure/OSGUtils.hxx>
 
 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<Pass>, _1, copyop));
-
+    for (std::vector<ref_ptr<Pass> >::const_iterator itr = rhs.passes.begin(),
+             end = rhs.passes.end();
+         itr != end;
+         ++itr)
+        passes.push_back(static_cast<Pass*>(copyop(itr->get())));
 }
 
 Technique::~Technique()
@@ -81,8 +90,12 @@ Technique::Status Technique::valid(osg::RenderInfo* renderInfo)
         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;
 }
 
@@ -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>& 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<float>
+{
+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<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;
+};
+
+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<int>* contextExp
+            = new VariableExpression<int>(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<float, int>
+{
+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<unsigned>(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<int>* contextExp = new VariableExpression<int>(location);
+    slexp->addOperand(contextExp);
+    return slexp;
+}
+
+expression::ExpParserRegistrar shaderLanguageRegistrar("shader-language",
+                                                       glVersionParser);
+
+    
+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);
+    SGExpression<bool>* versionTest
+        = makePredicate<std::less_equal>(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);
+}
+
+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<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());
     }
-    fw.indent() << "passes\n";
+    fw.indent() << "num_passes " << tniq.passes.size() << "\n";
     BOOST_FOREACH(const ref_ptr<Pass>& pass, tniq.passes) {
         fw.writeObject(*pass);
     }