diff --git a/include/osg/BlendEquation b/include/osg/BlendEquation index bead41515..617603377 100644 --- a/include/osg/BlendEquation +++ b/include/osg/BlendEquation @@ -18,11 +18,11 @@ #ifndef GL_VERSION_1_2 /* Logic Ops */ -#define GL_MIN_EXT 0x8007 -#define GL_MAX_EXT 0x8008 -#define GL_FUNC_ADD_EXT 0x8006 -#define GL_FUNC_SUBTRACT_EXT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT_EXT 0x800B +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B #define GL_ALPHA_MIN_SGIX 0x8320 #define GL_ALPHA_MAX_SGIX 0x8321 #define GL_LOGIC_OP 0x0BF1 @@ -86,11 +86,54 @@ class SG_EXPORT BlendEquation : public StateAttribute inline GLenum getEquation() const { return _equation; } virtual void apply(State& state) const; + /** Encapsulates queries of extension availability, obtains extension + * function pointers, and provides convinience wrappers for + * calling extension functions. */ + class SG_EXPORT Extensions : public osg::Referenced + { + public: + Extensions(); + + Extensions(const Extensions& rhs); + + void lowestCommonDenominator(const Extensions& rhs); + + void setupGLExtenions(); + + void setBlendEquationSupported(bool flag) { _isBlendEquationSupported=flag; } + bool isBlendEquationSupported() const { return _isBlendEquationSupported; } + + void setBlendEquationProc(void* ptr) { _glBlendEquation = ptr; } + void glBlendEquation(GLenum mode) const; + + protected: + + ~Extensions() {} + + bool _isBlendEquationSupported; + + void* _glBlendEquation; + + }; + + /** Returns the Extensions object for the given context. + * If createIfNotInitalized is true and the Exentsions object doesn't + * exist, getExtensions() creates it on the given context. + * Returns NULL if createIfNotInitalized is false and the Extensions + * object doesn't exist. */ + static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized); + + /** setExtensions() allows users to override the extensions across graphics contexts. + * Typically used when you have different extensions supported across graphics pipes, + * but need to ensure that they all use the same low common denominator extensions. */ + static void setExtensions(unsigned int contextID,Extensions* extensions); + protected : virtual ~BlendEquation(); + GLenum _equation; }; diff --git a/src/osg/BlendEquation.cpp b/src/osg/BlendEquation.cpp index d3536cc6b..36c486e98 100644 --- a/src/osg/BlendEquation.cpp +++ b/src/osg/BlendEquation.cpp @@ -11,6 +11,11 @@ * OpenSceneGraph Public License for more details. */ #include +#include +#include +#include +#include + using namespace osg; @@ -28,8 +33,77 @@ BlendEquation::~BlendEquation() { } -void BlendEquation::apply(State&) const +void BlendEquation::apply(State& state) const { - glBlendEquation(_equation); + + // get the contextID (user defined ID of 0 upwards) for the + // current OpenGL context. + const unsigned int contextID = state.getContextID(); + + const Extensions* extensions = getExtensions(contextID,true); + + if (!extensions->isBlendEquationSupported()) + { + notify(WARN)<<"Warning: BlendEquation::apply(..) failed, BlendEquation is not support by OpenGL driver."<glBlendEquation(_equation); + } + +typedef buffered_value< ref_ptr > BufferedExtensions; +static BufferedExtensions s_extensions; + +BlendEquation::Extensions* BlendEquation::getExtensions(unsigned int contextID,bool createIfNotInitalized) +{ + if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Extensions; + return s_extensions[contextID].get(); +} + +void BlendEquation::setExtensions(unsigned int contextID,Extensions* extensions) +{ + s_extensions[contextID] = extensions; +} + + +BlendEquation::Extensions::Extensions() +{ + setupGLExtenions(); +} + +BlendEquation::Extensions::Extensions(const Extensions& rhs): + Referenced() +{ + _isBlendEquationSupported = rhs._isBlendEquationSupported; +} + +void BlendEquation::Extensions::lowestCommonDenominator(const Extensions& rhs) +{ + if (!rhs._isBlendEquationSupported) _isBlendEquationSupported = false; + if (!rhs._glBlendEquation) _glBlendEquation = 0; +} + +void BlendEquation::Extensions::setupGLExtenions() +{ + _isBlendEquationSupported = isGLExtensionSupported("GL_EXT_blend_equation") || + strncmp((const char*)glGetString(GL_VERSION),"1.2",3)>=0; + + _glBlendEquation = getGLExtensionFuncPtr("glBlendEquation", "glBlendEquationEXT"); +} + +void BlendEquation::Extensions::glBlendEquation(GLenum mode) const +{ + if (_glBlendEquation) + { + typedef void (APIENTRY * GLBlendEquationProc) (GLenum mode); + ((GLBlendEquationProc)_glBlendEquation)(mode); + } + else + { + notify(WARN)<<"Error: glBlendEquation not supported by OpenGL driver"<