diff --git a/effects/blur/blur.cpp b/effects/blur/blur.cpp --- a/effects/blur/blur.cpp +++ b/effects/blur/blur.cpp @@ -46,7 +46,7 @@ BlurEffect::BlurEffect() { initConfig(); - m_shader = BlurShader::create(); + m_shader = new BlurShader(this); initBlurStrengthValues(); reconfigure(ReconfigureAll); @@ -84,9 +84,6 @@ BlurEffect::~BlurEffect() { deleteFBOs(); - - delete m_shader; - m_shader = nullptr; } void BlurEffect::slotScreenGeometryChanged() diff --git a/effects/blur/blurshader.h b/effects/blur/blurshader.h --- a/effects/blur/blurshader.h +++ b/effects/blur/blurshader.h @@ -22,84 +22,48 @@ #define BLURSHADER_H #include + +#include +#include +#include #include #include - -class QMatrix4x4; - namespace KWin { -class BlurShader +class BlurShader : public QObject { -public: - BlurShader(); - virtual ~BlurShader(); - - static BlurShader *create(); + Q_OBJECT - bool isValid() const { - return mValid; - } +public: + BlurShader(QObject *parent = nullptr); + ~BlurShader() override; - virtual void setModelViewProjectionMatrix(const QMatrix4x4 &matrix) = 0; - virtual void setOffset(float offset) = 0; - virtual void setTargetTextureSize(QSize renderTextureSize) = 0; - virtual void setNoiseTextureSize(QSize noiseTextureSize) = 0; - virtual void setTexturePosition(QPoint texPos) = 0; - virtual void setBlurRect(QRect blurRect, QSize screenSize) = 0; + bool isValid() const; enum SampleType { DownSampleType, UpSampleType, CopySampleType, NoiseSampleType }; - virtual void bind(SampleType sampleType) = 0; - virtual void unbind() = 0; - -protected: - void setIsValid(bool value) { - mValid = value; - } - virtual void init() = 0; - virtual void reset() = 0; - -private: - bool mValid; -}; - - -// ---------------------------------------------------------------------------- - + void bind(SampleType sampleType); + void unbind(); - -class GLSLBlurShader : public BlurShader -{ -public: - GLSLBlurShader(); - ~GLSLBlurShader(); - - void bind(SampleType sampleType) override final; - void unbind() override final; - void setModelViewProjectionMatrix(const QMatrix4x4 &matrix) override final; - void setOffset(float offset) override final; - void setTargetTextureSize(QSize renderTextureSize) override final; - void setNoiseTextureSize(QSize noiseTextureSize) override final; - void setTexturePosition(QPoint texPos) override final; - void setBlurRect(QRect blurRect, QSize screenSize) override final; - -protected: - void init() override final; - void reset() override final; + void setModelViewProjectionMatrix(const QMatrix4x4 &matrix); + void setOffset(float offset); + void setTargetTextureSize(const QSize &renderTextureSize); + void setNoiseTextureSize(const QSize &noiseTextureSize); + void setTexturePosition(const QPoint &texPos); + void setBlurRect(const QRect &blurRect, const QSize &screenSize); private: - GLShader *m_shaderDownsample = nullptr; - GLShader *m_shaderUpsample = nullptr; - GLShader *m_shaderCopysample = nullptr; - GLShader *m_shaderNoisesample = nullptr; + QScopedPointer m_shaderDownsample; + QScopedPointer m_shaderUpsample; + QScopedPointer m_shaderCopysample; + QScopedPointer m_shaderNoisesample; int m_mvpMatrixLocationDownsample; int m_offsetLocationDownsample; @@ -122,24 +86,31 @@ int m_texStartPosLocationNoisesample; int m_halfpixelLocationNoisesample; - //Caching uniform values to aviod unnecessary setUniform calls - int m_activeSampleType; + int m_activeSampleType = -1; - float m_offsetDownsample; + float m_offsetDownsample = 0.0; QMatrix4x4 m_matrixDownsample; - float m_offsetUpsample; + float m_offsetUpsample = 0.0; QMatrix4x4 m_matrixUpsample; QMatrix4x4 m_matrixCopysample; - float m_offsetNoisesample; + float m_offsetNoisesample = 0.0; QVector2D m_noiseTextureSizeNoisesample; QMatrix4x4 m_matrixNoisesample; + bool m_valid = false; + + Q_DISABLE_COPY(BlurShader); }; +inline bool BlurShader::isValid() const +{ + return m_valid; +} + } // namespace KWin #endif diff --git a/effects/blur/blurshader.cpp b/effects/blur/blurshader.cpp --- a/effects/blur/blurshader.cpp +++ b/effects/blur/blurshader.cpp @@ -21,227 +21,17 @@ #include "blurshader.h" #include -#include "kwinglutils.h" #include +#include #include -#include #include -#include -#include - -using namespace KWin; - - -BlurShader::BlurShader() - : mValid(false) -{ -} - -BlurShader::~BlurShader() -{ -} - -BlurShader *BlurShader::create() -{ - return new GLSLBlurShader(); -} - -// ---------------------------------------------------------------------------- - - - -GLSLBlurShader::GLSLBlurShader() -{ - init(); -} - -GLSLBlurShader::~GLSLBlurShader() -{ - reset(); -} - -void GLSLBlurShader::reset() -{ - delete m_shaderDownsample; - m_shaderDownsample = nullptr; - - delete m_shaderUpsample; - m_shaderUpsample = nullptr; - - delete m_shaderCopysample; - m_shaderCopysample = nullptr; - - delete m_shaderNoisesample; - m_shaderNoisesample = nullptr; - - setIsValid(false); -} - -void GLSLBlurShader::setModelViewProjectionMatrix(const QMatrix4x4 &matrix) -{ - if (!isValid()) - return; - - switch (m_activeSampleType) { - case CopySampleType: - if (matrix == m_matrixCopysample) - return; - - m_matrixCopysample = matrix; - m_shaderCopysample->setUniform(m_mvpMatrixLocationCopysample, matrix); - break; - - case UpSampleType: - if (matrix == m_matrixUpsample) - return; - - m_matrixUpsample = matrix; - m_shaderUpsample->setUniform(m_mvpMatrixLocationUpsample, matrix); - break; - - case DownSampleType: - if (matrix == m_matrixDownsample) - return; - - m_matrixDownsample = matrix; - m_shaderDownsample->setUniform(m_mvpMatrixLocationDownsample, matrix); - break; - - case NoiseSampleType: - if (matrix == m_matrixNoisesample) - return; - - m_matrixNoisesample = matrix; - m_shaderNoisesample->setUniform(m_mvpMatrixLocationNoisesample, matrix); - break; - } -} - -void GLSLBlurShader::setOffset(float offset) -{ - if (!isValid()) - return; - - switch (m_activeSampleType) { - case UpSampleType: - if (offset == m_offsetUpsample) - return; - - m_offsetUpsample = offset; - m_shaderUpsample->setUniform(m_offsetLocationUpsample, offset); - break; - - case DownSampleType: - if (offset == m_offsetDownsample) - return; - - m_offsetDownsample = offset; - m_shaderDownsample->setUniform(m_offsetLocationDownsample, offset); - break; - - case NoiseSampleType: - if (offset == m_offsetNoisesample) - return; - - m_offsetNoisesample = offset; - m_shaderNoisesample->setUniform(m_offsetLocationNoisesample, offset); - break; - } -} - -void GLSLBlurShader::setTargetTextureSize(QSize renderTextureSize) -{ - if (!isValid()) - return; - - QVector2D texSize = QVector2D(renderTextureSize.width(), renderTextureSize.height()); - - switch (m_activeSampleType) { - case CopySampleType: - m_shaderCopysample->setUniform(m_renderTextureSizeLocationCopysample, texSize); - break; - - case UpSampleType: - m_shaderUpsample->setUniform(m_renderTextureSizeLocationUpsample, texSize); - m_shaderUpsample->setUniform(m_halfpixelLocationUpsample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); - break; - - case DownSampleType: - m_shaderDownsample->setUniform(m_renderTextureSizeLocationDownsample, texSize); - m_shaderDownsample->setUniform(m_halfpixelLocationDownsample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); - break; - - case NoiseSampleType: - m_shaderNoisesample->setUniform(m_renderTextureSizeLocationNoisesample, texSize); - m_shaderNoisesample->setUniform(m_halfpixelLocationNoisesample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); - break; - } -} - -void GLSLBlurShader::setNoiseTextureSize(QSize noiseTextureSize) -{ - QVector2D noiseTexSize = QVector2D(noiseTextureSize.width(), noiseTextureSize.height()); - - if (noiseTexSize != m_noiseTextureSizeNoisesample) { - m_noiseTextureSizeNoisesample = noiseTexSize; - m_shaderNoisesample->setUniform(m_noiseTextureSizeLocationNoisesample, noiseTexSize); - } -} - -void GLSLBlurShader::setTexturePosition(QPoint texPos) -{ - m_shaderNoisesample->setUniform(m_texStartPosLocationNoisesample, QVector2D(-texPos.x(), texPos.y())); -} - -void GLSLBlurShader::setBlurRect(QRect blurRect, QSize screenSize) -{ - if (!isValid()) - return; - - QVector4D rect = QVector4D( - blurRect.bottomLeft().x() / float(screenSize.width()), - 1.0 - blurRect.bottomLeft().y() / float(screenSize.height()), - blurRect.topRight().x() / float(screenSize.width()), - 1.0 - blurRect.topRight().y() / float(screenSize.height()) - ); - - m_shaderCopysample->setUniform(m_blurRectLocationCopysample, rect); -} - -void GLSLBlurShader::bind(SampleType sampleType) -{ - if (!isValid()) - return; - - switch (sampleType) { - case CopySampleType: - ShaderManager::instance()->pushShader(m_shaderCopysample); - break; - - case UpSampleType: - ShaderManager::instance()->pushShader(m_shaderUpsample); - break; - - case DownSampleType: - ShaderManager::instance()->pushShader(m_shaderDownsample); - break; - - case NoiseSampleType: - ShaderManager::instance()->pushShader(m_shaderNoisesample); - break; - } - - m_activeSampleType = sampleType; -} - -void GLSLBlurShader::unbind() +namespace KWin { - ShaderManager::instance()->popShader(); -} -void GLSLBlurShader::init() +BlurShader::BlurShader(QObject *parent) + : QObject(parent) { const bool gles = GLPlatform::instance()->isGLES(); const bool glsl_140 = !gles && GLPlatform::instance()->glslVersion() >= kVersionNumber(1, 40); @@ -278,9 +68,7 @@ glUniformString += "out vec4 fragColor;\n\n"; } - // Vertex shader - // =================================================================== QTextStream streamVert(&vertexSource); streamVert << glHeaderString; @@ -296,7 +84,6 @@ streamVert.flush(); // Fragment shader (Dual Kawase Blur) - Downsample - // =================================================================== QTextStream streamFragDown(&fragmentDownSource); streamFragDown << glHeaderString << glUniformString; @@ -317,7 +104,6 @@ streamFragDown.flush(); // Fragment shader (Dual Kawase Blur) - Upsample - // =================================================================== QTextStream streamFragUp(&fragmentUpSource); streamFragUp << glHeaderString << glUniformString; @@ -341,17 +127,17 @@ streamFragUp.flush(); // Fragment shader - Copy texture - // =================================================================== QTextStream streamFragCopy(&fragmentCopySource); streamFragCopy << glHeaderString; streamFragCopy << "uniform sampler2D texUnit;\n"; streamFragCopy << "uniform vec2 renderTextureSize;\n"; streamFragCopy << "uniform vec4 blurRect;\n"; - if (core) + if (core) { streamFragCopy << "out vec4 fragColor;\n\n"; + } streamFragCopy << "void main(void)\n"; streamFragCopy << "{\n"; @@ -362,7 +148,6 @@ streamFragCopy.flush(); // Fragment shader - Noise texture - // =================================================================== QTextStream streamFragNoise(&fragmentNoiseSource); streamFragNoise << glHeaderString << glUniformString; @@ -391,19 +176,17 @@ streamFragNoise.flush(); + m_shaderDownsample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentDownSource)); + m_shaderUpsample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentUpSource)); + m_shaderCopysample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentCopySource)); + m_shaderNoisesample.reset(ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentNoiseSource)); - m_shaderDownsample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentDownSource); - m_shaderUpsample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentUpSource); - m_shaderCopysample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentCopySource); - m_shaderNoisesample = ShaderManager::instance()->loadShaderFromCode(vertexSource, fragmentNoiseSource); - - bool areShadersValid = m_shaderDownsample->isValid() && + m_valid = m_shaderDownsample->isValid() && m_shaderUpsample->isValid() && m_shaderCopysample->isValid() && m_shaderNoisesample->isValid(); - setIsValid(areShadersValid); - if (areShadersValid) { + if (m_valid) { m_mvpMatrixLocationDownsample = m_shaderDownsample->uniformLocation("modelViewProjectionMatrix"); m_offsetLocationDownsample = m_shaderDownsample->uniformLocation("offset"); m_renderTextureSizeLocationDownsample = m_shaderDownsample->uniformLocation("renderTextureSize"); @@ -430,27 +213,27 @@ modelViewProjection.ortho(0, screenSize.width(), screenSize.height(), 0, 0, 65535); //Add default values to the uniforms of the shaders - ShaderManager::instance()->pushShader(m_shaderDownsample); + ShaderManager::instance()->pushShader(m_shaderDownsample.data()); m_shaderDownsample->setUniform(m_mvpMatrixLocationDownsample, modelViewProjection); m_shaderDownsample->setUniform(m_offsetLocationDownsample, float(1.0)); m_shaderDownsample->setUniform(m_renderTextureSizeLocationDownsample, QVector2D(1.0, 1.0)); m_shaderDownsample->setUniform(m_halfpixelLocationDownsample, QVector2D(1.0, 1.0)); ShaderManager::instance()->popShader(); - ShaderManager::instance()->pushShader(m_shaderUpsample); + ShaderManager::instance()->pushShader(m_shaderUpsample.data()); m_shaderUpsample->setUniform(m_mvpMatrixLocationUpsample, modelViewProjection); m_shaderUpsample->setUniform(m_offsetLocationUpsample, float(1.0)); m_shaderUpsample->setUniform(m_renderTextureSizeLocationUpsample, QVector2D(1.0, 1.0)); m_shaderUpsample->setUniform(m_halfpixelLocationUpsample, QVector2D(1.0, 1.0)); ShaderManager::instance()->popShader(); - ShaderManager::instance()->pushShader(m_shaderCopysample); + ShaderManager::instance()->pushShader(m_shaderCopysample.data()); m_shaderCopysample->setUniform(m_mvpMatrixLocationCopysample, modelViewProjection); m_shaderCopysample->setUniform(m_renderTextureSizeLocationCopysample, QVector2D(1.0, 1.0)); m_shaderCopysample->setUniform(m_blurRectLocationCopysample, QVector4D(1.0, 1.0, 1.0, 1.0)); ShaderManager::instance()->popShader(); - ShaderManager::instance()->pushShader(m_shaderNoisesample); + ShaderManager::instance()->pushShader(m_shaderNoisesample.data()); m_shaderNoisesample->setUniform(m_mvpMatrixLocationNoisesample, modelViewProjection); m_shaderNoisesample->setUniform(m_offsetLocationNoisesample, float(1.0)); m_shaderNoisesample->setUniform(m_renderTextureSizeLocationNoisesample, QVector2D(1.0, 1.0)); @@ -462,19 +245,201 @@ glUniform1i(m_shaderNoisesample->uniformLocation("noiseTexUnit"), 1); ShaderManager::instance()->popShader(); + } +} + +BlurShader::~BlurShader() +{ +} + +void BlurShader::setModelViewProjectionMatrix(const QMatrix4x4 &matrix) +{ + if (!isValid()) { + return; + } - m_activeSampleType = -1; + switch (m_activeSampleType) { + case CopySampleType: + if (matrix == m_matrixCopysample) { + return; + } + + m_matrixCopysample = matrix; + m_shaderCopysample->setUniform(m_mvpMatrixLocationCopysample, matrix); + break; - m_offsetDownsample = 0.0; - m_matrixDownsample = QMatrix4x4(); + case UpSampleType: + if (matrix == m_matrixUpsample) { + return; + } + + m_matrixUpsample = matrix; + m_shaderUpsample->setUniform(m_mvpMatrixLocationUpsample, matrix); + break; - m_offsetUpsample = 0.0; - m_matrixUpsample = QMatrix4x4(); + case DownSampleType: + if (matrix == m_matrixDownsample) { + return; + } - m_matrixCopysample = QMatrix4x4(); + m_matrixDownsample = matrix; + m_shaderDownsample->setUniform(m_mvpMatrixLocationDownsample, matrix); + break; - m_offsetNoisesample = 0.0; - m_noiseTextureSizeNoisesample = QVector2D(); - m_matrixNoisesample = QMatrix4x4(); + case NoiseSampleType: + if (matrix == m_matrixNoisesample) { + return; + } + + m_matrixNoisesample = matrix; + m_shaderNoisesample->setUniform(m_mvpMatrixLocationNoisesample, matrix); + break; + + default: + Q_UNREACHABLE(); + break; } } + +void BlurShader::setOffset(float offset) +{ + if (!isValid()) { + return; + } + + switch (m_activeSampleType) { + case UpSampleType: + if (offset == m_offsetUpsample) { + return; + } + + m_offsetUpsample = offset; + m_shaderUpsample->setUniform(m_offsetLocationUpsample, offset); + break; + + case DownSampleType: + if (offset == m_offsetDownsample) { + return; + } + + m_offsetDownsample = offset; + m_shaderDownsample->setUniform(m_offsetLocationDownsample, offset); + break; + + case NoiseSampleType: + if (offset == m_offsetNoisesample) { + return; + } + + m_offsetNoisesample = offset; + m_shaderNoisesample->setUniform(m_offsetLocationNoisesample, offset); + break; + + default: + Q_UNREACHABLE(); + break; + } +} + +void BlurShader::setTargetTextureSize(const QSize &renderTextureSize) +{ + if (!isValid()) { + return; + } + + const QVector2D texSize(renderTextureSize.width(), renderTextureSize.height()); + + switch (m_activeSampleType) { + case CopySampleType: + m_shaderCopysample->setUniform(m_renderTextureSizeLocationCopysample, texSize); + break; + + case UpSampleType: + m_shaderUpsample->setUniform(m_renderTextureSizeLocationUpsample, texSize); + m_shaderUpsample->setUniform(m_halfpixelLocationUpsample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); + break; + + case DownSampleType: + m_shaderDownsample->setUniform(m_renderTextureSizeLocationDownsample, texSize); + m_shaderDownsample->setUniform(m_halfpixelLocationDownsample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); + break; + + case NoiseSampleType: + m_shaderNoisesample->setUniform(m_renderTextureSizeLocationNoisesample, texSize); + m_shaderNoisesample->setUniform(m_halfpixelLocationNoisesample, QVector2D(0.5 / texSize.x(), 0.5 / texSize.y())); + break; + + default: + Q_UNREACHABLE(); + break; + } +} + +void BlurShader::setNoiseTextureSize(const QSize &noiseTextureSize) +{ + const QVector2D noiseTexSize(noiseTextureSize.width(), noiseTextureSize.height()); + + if (noiseTexSize != m_noiseTextureSizeNoisesample) { + m_noiseTextureSizeNoisesample = noiseTexSize; + m_shaderNoisesample->setUniform(m_noiseTextureSizeLocationNoisesample, noiseTexSize); + } +} + +void BlurShader::setTexturePosition(const QPoint &texPos) +{ + m_shaderNoisesample->setUniform(m_texStartPosLocationNoisesample, QVector2D(-texPos.x(), texPos.y())); +} + +void BlurShader::setBlurRect(const QRect &blurRect, const QSize &screenSize) +{ + if (!isValid()) { + return; + } + + const QVector4D rect( + blurRect.left() / float(screenSize.width()), + 1.0 - blurRect.bottom() / float(screenSize.height()), + blurRect.right() / float(screenSize.width()), + 1.0 - blurRect.top() / float(screenSize.height()) + ); + + m_shaderCopysample->setUniform(m_blurRectLocationCopysample, rect); +} + +void BlurShader::bind(SampleType sampleType) +{ + if (!isValid()) { + return; + } + + switch (sampleType) { + case CopySampleType: + ShaderManager::instance()->pushShader(m_shaderCopysample.data()); + break; + + case UpSampleType: + ShaderManager::instance()->pushShader(m_shaderUpsample.data()); + break; + + case DownSampleType: + ShaderManager::instance()->pushShader(m_shaderDownsample.data()); + break; + + case NoiseSampleType: + ShaderManager::instance()->pushShader(m_shaderNoisesample.data()); + break; + + default: + Q_UNREACHABLE(); + break; + } + + m_activeSampleType = sampleType; +} + +void BlurShader::unbind() +{ + ShaderManager::instance()->popShader(); +} + +} // namespace KWin