From f181228d4a3fe678df7c37fadfbbd912542e913b Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 30 Jun 2006 13:50:02 +0000 Subject: [PATCH] From Michael Platings, added support for glBlendFuncSeperate. --- include/osg/BlendFunc | 84 +++++++++++++++++++++++++++++++-- src/osg/BlendFunc.cpp | 105 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 183 insertions(+), 6 deletions(-) diff --git a/include/osg/BlendFunc b/include/osg/BlendFunc index 96a33e717..d87d1ca73 100644 --- a/include/osg/BlendFunc +++ b/include/osg/BlendFunc @@ -25,6 +25,12 @@ #define GL_BLEND_COLOR 0x8005 #endif +#ifndef GL_VERSION_1_4 +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#endif namespace osg { @@ -37,12 +43,15 @@ class OSG_EXPORT BlendFunc : public StateAttribute BlendFunc(); BlendFunc(GLenum source, GLenum destination); + BlendFunc(GLenum source, GLenum destination, GLenum source_alpha, GLenum destination_alpha); /** Copy constructor using CopyOp to manage deep vs shallow copy. */ BlendFunc(const BlendFunc& trans,const CopyOp& copyop=CopyOp::SHALLOW_COPY): StateAttribute(trans,copyop), _source_factor(trans._source_factor), - _destination_factor(trans._destination_factor) {} + _destination_factor(trans._destination_factor), + _source_factor_alpha(trans._source_factor_alpha), + _destination_factor_alpha(trans._destination_factor_alpha) {} META_StateAttribute(osg, BlendFunc,BLENDFUNC); @@ -56,6 +65,8 @@ class OSG_EXPORT BlendFunc : public StateAttribute // Compare each parameter in turn against the rhs. COMPARE_StateAttribute_Parameter(_source_factor) COMPARE_StateAttribute_Parameter(_destination_factor) + COMPARE_StateAttribute_Parameter(_source_factor_alpha) + COMPARE_StateAttribute_Parameter(_destination_factor_alpha) return 0; // Passed all the above comparison macros, so must be equal. } @@ -90,13 +101,78 @@ class OSG_EXPORT BlendFunc : public StateAttribute _destination_factor = destination; } - void setSource(GLenum source) { _source_factor = source; } + inline void setFunction( GLenum source_rgb, GLenum destination_rgb, GLenum source_alpha, GLenum destination_alpha ) + { + _source_factor = source_rgb; + _destination_factor = destination_rgb; + _source_factor_alpha = source_alpha; + _destination_factor_alpha = destination_alpha; + } + + void setSource(GLenum source) { _source_factor = _source_factor_alpha = source; } inline GLenum getSource() const { return _source_factor; } + + void setSourceRGB(GLenum source) { _source_factor = source; } + inline GLenum getSourceRGB() const { return _source_factor; } + + void setSourceAlpha(GLenum source) { _source_factor_alpha = source; } + inline GLenum getSourceAlpha() const { return _source_factor_alpha; } - void setDestination(GLenum destination) { _destination_factor = destination; } + void setDestination(GLenum destination) { _destination_factor = _destination_factor_alpha = destination; } inline GLenum getDestination() const { return _destination_factor; } + void setDestinationRGB(GLenum destination) { _destination_factor = destination; } + inline GLenum getDestinationRGB() const { return _destination_factor; } + + void setDestinationAlpha(GLenum destination) { _destination_factor_alpha = destination; } + inline GLenum getDestinationAlpha() const { return _destination_factor_alpha; } + virtual void apply(State& state) const; + /** Encapsulates queries of extension availability, obtains extension + * function pointers, and provides convenience wrappers for + * calling extension functions. */ + class OSG_EXPORT Extensions : public osg::Referenced + { + public: + Extensions(unsigned int contextID); + + Extensions(const Extensions& rhs); + + void lowestCommonDenominator(const Extensions& rhs); + + void setupGLExtensions(unsigned int contextID); + + void setBlendFuncSeparateSupported(bool flag) { _isBlendFuncSeparateSupported=flag; } + bool isBlendFuncSeparateSupported() const { return _isBlendFuncSeparateSupported; } + + void setBlendFuncSeparateProc(void* ptr) { _glBlendFuncSeparate = ptr; } + void glBlendFuncSeparate(GLenum sfactorRGB, + GLenum dfactorRGB, + GLenum sfactorAlpha, + GLenum dfactorAlpha) const; + + protected: + + ~Extensions() {} + + bool _isBlendFuncSeparateSupported; + + void* _glBlendFuncSeparate; + + }; + + /** 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 : @@ -104,6 +180,8 @@ class OSG_EXPORT BlendFunc : public StateAttribute GLenum _source_factor; GLenum _destination_factor; + GLenum _source_factor_alpha; + GLenum _destination_factor_alpha; }; } diff --git a/src/osg/BlendFunc.cpp b/src/osg/BlendFunc.cpp index 345fb091e..fe0cb5954 100644 --- a/src/osg/BlendFunc.cpp +++ b/src/osg/BlendFunc.cpp @@ -11,18 +11,33 @@ * OpenSceneGraph Public License for more details. */ #include +#include +#include +#include using namespace osg; BlendFunc::BlendFunc(): _source_factor(SRC_ALPHA), - _destination_factor(ONE_MINUS_SRC_ALPHA) + _destination_factor(ONE_MINUS_SRC_ALPHA), + _source_factor_alpha(SRC_ALPHA), + _destination_factor_alpha(ONE_MINUS_SRC_ALPHA) { } BlendFunc::BlendFunc(GLenum source, GLenum destination): _source_factor(source), - _destination_factor(destination) + _destination_factor(destination), + _source_factor_alpha(source), + _destination_factor_alpha(destination) +{ +} + +BlendFunc::BlendFunc(GLenum source, GLenum destination, GLenum source_alpha, GLenum destination_alpha): + _source_factor(source), + _destination_factor(destination), + _source_factor_alpha(source_alpha), + _destination_factor_alpha(destination_alpha) { } @@ -30,7 +45,91 @@ BlendFunc::~BlendFunc() { } -void BlendFunc::apply(State&) const +void BlendFunc::apply(State& state) const { + if (_source_factor != _source_factor_alpha || + _destination_factor != _destination_factor_alpha) + { + // 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->isBlendFuncSeparateSupported()) + { + notify(WARN)<<"Warning: BlendFunc::apply(..) failed, BlendFuncSeparate is not support by OpenGL driver, falling back to BlendFunc."<glBlendFuncSeparate(_source_factor, _destination_factor, _source_factor_alpha, _destination_factor_alpha); + return; + } + } + glBlendFunc( _source_factor, _destination_factor ); } + + +typedef buffered_value< ref_ptr > BufferedExtensions; +static BufferedExtensions s_extensions; + +BlendFunc::Extensions* BlendFunc::getExtensions(unsigned int contextID,bool createIfNotInitalized) +{ + if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Extensions(contextID); + return s_extensions[contextID].get(); +} + +void BlendFunc::setExtensions(unsigned int contextID,Extensions* extensions) +{ + s_extensions[contextID] = extensions; +} + + +BlendFunc::Extensions::Extensions(unsigned int contextID) +{ + setupGLExtensions(contextID); +} + +BlendFunc::Extensions::Extensions(const Extensions& rhs): + Referenced() +{ + _isBlendFuncSeparateSupported = rhs._isBlendFuncSeparateSupported; + _glBlendFuncSeparate = rhs._glBlendFuncSeparate; +} + +void BlendFunc::Extensions::lowestCommonDenominator(const Extensions& rhs) +{ + if (!rhs._isBlendFuncSeparateSupported) _isBlendFuncSeparateSupported = false; + if (!rhs._glBlendFuncSeparate) _glBlendFuncSeparate = 0; +} + +void BlendFunc::Extensions::setupGLExtensions(unsigned int contextID) +{ + _isBlendFuncSeparateSupported = isGLExtensionSupported(contextID, "GL_EXT_blend_func_separate") || + strncmp((const char*)glGetString(GL_VERSION), "1.4", 3) >= 0; + + _glBlendFuncSeparate = getGLExtensionFuncPtr("glBlendFuncSeparate", "glBlendFuncSeparateEXT"); +} + +void BlendFunc::Extensions::glBlendFuncSeparate(GLenum sfactorRGB, + GLenum dfactorRGB, + GLenum sfactorAlpha, + GLenum dfactorAlpha) const +{ + if (_glBlendFuncSeparate) + { + typedef void (APIENTRY * GLBlendFuncSeparateProc) (GLenum sfactorRGB, + GLenum dfactorRGB, + GLenum sfactorAlpha, + GLenum dfactorAlpha); + ((GLBlendFuncSeparateProc)_glBlendFuncSeparate)(sfactorRGB, + dfactorRGB, + sfactorAlpha, + dfactorAlpha); + } + else + { + notify(WARN)<<"Error: glBlendFuncSeparate not supported by OpenGL driver"<