diff --git a/effects/blur/blur.cpp b/effects/blur/blur.cpp index eef3857d6e..1b318bef99 100644 --- a/effects/blur/blur.cpp +++ b/effects/blur/blur.cpp @@ -116,8 +116,7 @@ void BlurEffect::propertyNotify(EffectWindow *w, long atom) bool BlurEffect::supported() { return GLRenderTarget::supported() && GLTexture::NPOTTextureSupported() && - ((GLShader::vertexShaderSupported() && GLShader::fragmentShaderSupported()) || - hasGLExtension("GL_ARB_fragment_program")); + (GLSLBlurShader::supported() || ARBBlurShader::supported()); } QRect BlurEffect::expand(const QRect &rect) const diff --git a/effects/blur/blurshader.cpp b/effects/blur/blurshader.cpp index d441bc7d77..23734fc9aa 100644 --- a/effects/blur/blurshader.cpp +++ b/effects/blur/blurshader.cpp @@ -39,7 +39,7 @@ BlurShader::~BlurShader() BlurShader *BlurShader::create() { - if (GLShader::vertexShaderSupported() && GLShader::fragmentShaderSupported()) + if (GLSLBlurShader::supported()) return new GLSLBlurShader(); return new ARBBlurShader(); @@ -122,6 +122,34 @@ void GLSLBlurShader::reset() setIsValid(false); } +bool GLSLBlurShader::supported() +{ + if (!GLShader::fragmentShaderSupported() || !GLShader::vertexShaderSupported()) + return false; + + (void) glGetError(); // Clear the error state + + // These are the minimum values the implementation is required to support + int value = 0; + + glGetIntegerv(GL_MAX_VARYING_FLOATS, &value); + if (value < 32) + return false; + + glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, &value); + if (value < 64) + return false; + + glGetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, &value); + if (value < 512) + return false; + + if (glGetError() != GL_NO_ERROR) + return false; + + return true; +} + void GLSLBlurShader::setPixelDistance(float val) { if (!isValid()) @@ -312,6 +340,42 @@ void ARBBlurShader::reset() setIsValid(false); } +bool ARBBlurShader::supported() +{ + if (!hasGLExtension("GL_ARB_fragment_program")) + return false; + + (void) glGetError(); // Clear the error state + + // These are the minimum values the implementation is required to support + int value = 0; + + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_PARAMETERS_ARB, &value); + if (value < 24) + return false; + + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEMPORARIES_ARB, &value); + if (value < 16) + return false; + + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_INSTRUCTIONS_ARB, &value); + if (value < 72) + return false; + + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, &value); + if (value < 24) + return false; + + glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_MAX_PROGRAM_TEX_INDIRECTIONS_ARB, &value); + if (value < 4) + return false; + + if (glGetError() != GL_NO_ERROR) + return false; + + return true; +} + void ARBBlurShader::setPixelDistance(float val) { float firstStep = val * 1.5; diff --git a/effects/blur/blurshader.h b/effects/blur/blurshader.h index 2b36cfa43a..75b32eface 100644 --- a/effects/blur/blurshader.h +++ b/effects/blur/blurshader.h @@ -78,6 +78,8 @@ public: void bind(); void unbind(); + static bool supported(); + protected: void init(); void reset(); @@ -108,6 +110,8 @@ public: void bind(); void unbind(); + static bool supported(); + protected: void init(); void reset();