From 73be6657ea379f08673f1616d6ba9264b66fad81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20H=C3=B6glund?= Date: Sat, 12 Feb 2011 01:36:21 +0100 Subject: [PATCH] kwin: Replace brightness and opacity with a modulation constant This makes it possible to adjust both brightness and opacity at the same time with one multiplication in the fragment shader. --- effects/invert/data/invert.frag | 9 ++-- effects/presentwindows/presentwindows.cpp | 6 ++- lanczosfilter.cpp | 21 ++++++-- lib/kwinglutils.cpp | 13 +++-- lib/kwinglutils.h | 9 +++- scene-fragment.glsl | 12 +++-- scene_opengl.cpp | 62 +++++++++++++++-------- 7 files changed, 89 insertions(+), 43 deletions(-) diff --git a/effects/invert/data/invert.frag b/effects/invert/data/invert.frag index a944e10152..cc3af1cb84 100644 --- a/effects/invert/data/invert.frag +++ b/effects/invert/data/invert.frag @@ -1,8 +1,7 @@ uniform sampler2D sample; +uniform vec4 modulation; uniform float textureWidth; uniform float textureHeight; -uniform float opacity; -uniform float brightness; uniform float saturation; uniform int u_forceAlpha; @@ -11,17 +10,19 @@ varying vec2 varyingTexCoords; void main() { vec4 tex = texture2D(sample, varyingTexCoords); + if (u_forceAlpha > 0) { tex.a = 1.0; } + if (saturation != 1.0) { vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 ); desaturated = vec3( dot( desaturated, tex.rgb )); tex.rgb = tex.rgb * vec3( saturation ) + desaturated * vec3( 1.0 - saturation ); } - tex.rgb = tex.rgb * opacity * vec3( brightness ); + + tex *= modulation; tex.rgb = vec3(1.0) - tex.rgb; - tex.a = tex.a * opacity; gl_FragColor = tex; } diff --git a/effects/presentwindows/presentwindows.cpp b/effects/presentwindows/presentwindows.cpp index 12a3f35cee..f84a70a216 100644 --- a/effects/presentwindows/presentwindows.cpp +++ b/effects/presentwindows/presentwindows.cpp @@ -324,9 +324,10 @@ void PresentWindowsEffect::paintWindow(EffectWindow *w, int mask, QRegion region m_windowData[w].iconFrame->setPosition(point); #ifdef KWIN_HAVE_OPENGL_COMPOSITING if (effects->compositingType() == KWin::OpenGLCompositing && data.shader) { + const float a = 0.9 * data.opacity * m_decalOpacity * 0.75; data.shader->setUniform(GLShader::TextureWidth, 1.0f); data.shader->setUniform(GLShader::TextureHeight, 1.0f); - data.shader->setUniform(GLShader::Opacity, 0.9 * data.opacity * m_decalOpacity * 0.75); + data.shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); } #endif m_windowData[w].iconFrame->render(region, 0.9 * data.opacity * m_decalOpacity, 0.75); @@ -337,9 +338,10 @@ void PresentWindowsEffect::paintWindow(EffectWindow *w, int mask, QRegion region m_windowData[w].textFrame->setPosition(point); #ifdef KWIN_HAVE_OPENGL_COMPOSITING if (effects->compositingType() == KWin::OpenGLCompositing && data.shader) { + const float a = 0.9 * data.opacity * m_decalOpacity * 0.75; data.shader->setUniform(GLShader::TextureWidth, 1.0f); data.shader->setUniform(GLShader::TextureHeight, 1.0f); - data.shader->setUniform(GLShader::Opacity, 0.9 * data.opacity * m_decalOpacity * 0.75); + data.shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); } #endif m_windowData[w].textFrame->render(region, 0.9 * data.opacity * m_decalOpacity, 0.75); diff --git a/lanczosfilter.cpp b/lanczosfilter.cpp index 44ec61fcc6..cbd4aa04be 100644 --- a/lanczosfilter.cpp +++ b/lanczosfilter.cpp @@ -207,6 +207,7 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region, int sw = width; int sh = height; + GLTexture *cachedTexture = static_cast< GLTexture*>(w->data(LanczosCacheRole).value()); if (cachedTexture) { if (cachedTexture->width() == tw && cachedTexture->height() == th) { @@ -214,13 +215,18 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region, if (ShaderManager::instance()->isValid()) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + const float rgb = data.brightness * data.opacity; + const float a = data.opacity; + GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); shader->setUniform(GLShader::Offset, QVector2D(0, 0)); - shader->setUniform(GLShader::Opacity, data.opacity); - shader->setUniform(GLShader::Brightness, data.brightness); + shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a)); shader->setUniform(GLShader::Saturation, data.saturation); shader->setUniform(GLShader::AlphaToOne, 0); + cachedTexture->render(textureRect, textureRect); + ShaderManager::instance()->popShader(); glDisable(GL_BLEND); } else { @@ -336,16 +342,22 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region, cache->bind(); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, m_offscreenTex->height() - th, tw, th); effects->popRenderTarget(); + if (ShaderManager::instance()->isValid()) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + const float rgb = data.brightness * data.opacity; + const float a = data.opacity; + GLShader *shader = ShaderManager::instance()->pushShader(ShaderManager::SimpleShader); shader->setUniform(GLShader::Offset, QVector2D(0, 0)); - shader->setUniform(GLShader::Opacity, data.opacity); - shader->setUniform(GLShader::Brightness, data.brightness); + shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a)); shader->setUniform(GLShader::Saturation, data.saturation); shader->setUniform(GLShader::AlphaToOne, 0); + cache->render(textureRect, textureRect); + ShaderManager::instance()->popShader(); glDisable(GL_BLEND); } else { @@ -353,6 +365,7 @@ void LanczosFilter::performPaint(EffectWindowImpl* w, int mask, QRegion region, cache->render(textureRect, textureRect); restoreRenderStates(cache, data.opacity, data.brightness, data.saturation); } + cache->unbind(); w->setData(LanczosCacheRole, QVariant::fromValue(static_cast(cache))); diff --git a/lib/kwinglutils.cpp b/lib/kwinglutils.cpp index dfba6c053a..9772d110bf 100644 --- a/lib/kwinglutils.cpp +++ b/lib/kwinglutils.cpp @@ -870,8 +870,8 @@ void GLShader::resolveLocations() mVec2Location[Offset] = uniformLocation("offset"); - mFloatLocation[Opacity] = uniformLocation("opacity"); - mFloatLocation[Brightness] = uniformLocation("brightness"); + mVec4Location[ModulationConstant] = uniformLocation("modulation"); + mFloatLocation[Saturation] = uniformLocation("saturation"); mFloatLocation[TextureWidth] = uniformLocation("textureWidth"); mFloatLocation[TextureHeight] = uniformLocation("textureHeight"); @@ -899,6 +899,12 @@ bool GLShader::setUniform(GLShader::Vec2Uniform uniform, const QVector2D &value) return setUniform(mVec2Location[uniform], value); } +bool GLShader::setUniform(GLShader::Vec4Uniform uniform, const QVector4D &value) +{ + resolveLocations(); + return setUniform(mVec4Location[uniform], value); +} + bool GLShader::setUniform(GLShader::FloatUniform uniform, float value) { resolveLocations(); @@ -1329,9 +1335,8 @@ void ShaderManager::resetShader(ShaderType type) shader->setUniform(GLShader::WindowTransformation, identity); shader->setUniform(GLShader::Offset, QVector2D(0, 0)); + shader->setUniform(GLShader::ModulationConstant, QVector4D(1.0, 1.0, 1.0, 1.0)); - shader->setUniform(GLShader::Opacity, 1.0f); - shader->setUniform(GLShader::Brightness, 1.0f); shader->setUniform(GLShader::Saturation, 1.0f); shader->setUniform(GLShader::AlphaToOne, 0); diff --git a/lib/kwinglutils.h b/lib/kwinglutils.h index 5c044e15e4..5f331ea269 100644 --- a/lib/kwinglutils.h +++ b/lib/kwinglutils.h @@ -297,9 +297,12 @@ public: Vec2UniformCount }; + enum Vec4Uniform { + ModulationConstant, + Vec4UniformCount + }; + enum FloatUniform { - Opacity, - Brightness, Saturation, TextureWidth, TextureHeight, @@ -313,6 +316,7 @@ public: bool setUniform(MatrixUniform uniform, const QMatrix4x4 &matrix); bool setUniform(Vec2Uniform uniform, const QVector2D &value); + bool setUniform(Vec4Uniform uniform, const QVector4D &value); bool setUniform(FloatUniform uniform, float value); bool setUniform(IntUniform uniform, int value); @@ -340,6 +344,7 @@ private: bool mLocationsResolved:1; int mMatrixLocation[MatrixCount]; int mVec2Location[Vec2UniformCount]; + int mVec4Location[Vec4UniformCount]; int mFloatLocation[FloatUniformCount]; int mIntLocation[IntUniformCount]; float mTextureWidth; diff --git a/scene-fragment.glsl b/scene-fragment.glsl index 33f1399fb9..d8b1be7816 100644 --- a/scene-fragment.glsl +++ b/scene-fragment.glsl @@ -1,6 +1,5 @@ uniform sampler2D sample; -uniform float opacity; -uniform float brightness; +uniform vec4 modulation; uniform float saturation; uniform int debug; uniform int u_forceAlpha; @@ -11,19 +10,22 @@ varying vec2 varyingTexCoords; void main() { vec4 tex = texture2D(sample, varyingTexCoords); + if (u_forceAlpha > 0) { tex.a = 1.0; } + if( saturation != 1.0 ) { vec3 desaturated = tex.rgb * vec3( 0.30, 0.59, 0.11 ); desaturated = vec3( dot( desaturated, tex.rgb )); tex.rgb = tex.rgb * vec3( saturation ) + desaturated * vec3( 1.0 - saturation ); } - tex.rgb = tex.rgb * opacity * brightness; - tex.a = tex.a * opacity; + + tex *= modulation; + /*if (debug != 0) { tex.g += 0.5; }*/ - + gl_FragColor = tex; } diff --git a/scene_opengl.cpp b/scene_opengl.cpp index d45829a932..ff95298f26 100644 --- a/scene_opengl.cpp +++ b/scene_opengl.cpp @@ -729,10 +729,13 @@ void SceneOpenGL::Window::prepareShaderRenderStates(TextureType type, double opa glBlendFunc(GL_ONE, GL_ONE_MINUS_CONSTANT_ALPHA); } } - shader->setUniform(GLShader::Opacity, opacity); - shader->setUniform(GLShader::Saturation, saturation); - shader->setUniform(GLShader::Brightness, brightness); - shader->setUniform(GLShader::AlphaToOne, opaque ? 1 : 0); + + const float rgb = brightness * opacity; + const float a = opacity; + + shader->setUniform(GLShader::ModulationConstant, QVector4D(rgb, rgb, rgb, a)); + shader->setUniform(GLShader::Saturation, saturation); + shader->setUniform(GLShader::AlphaToOne, opaque ? 1 : 0); const float texw = shader->textureWidth(); const float texh = shader->textureHeight(); @@ -1081,8 +1084,8 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra if (sceneShader) shader->setUniform(GLShader::Offset, QVector2D(0, 0)); + shader->setUniform(GLShader::ModulationConstant, QVector4D(1.0, 1.0, 1.0, 1.0)); shader->setUniform(GLShader::Saturation, 1.0f); - shader->setUniform(GLShader::Brightness, 1.0f); shader->setUniform(GLShader::AlphaToOne, 0); shader->setUniform(GLShader::TextureWidth, 1.0f); @@ -1210,8 +1213,10 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra m_unstyledVBO->setData(verts.count() / 2, 2, verts.data(), texCoords.data()); } - if (shader) - shader->setUniform(GLShader::Opacity, opacity * frameOpacity); + if (shader) { + const float a = opacity * frameOpacity; + shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); + } #ifndef KWIN_HAVE_OPENGLES else glColor4f(0.0, 0.0, 0.0, opacity * frameOpacity); @@ -1243,8 +1248,10 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra if (!m_texture) // Lazy creation updateTexture(); - if (shader) - shader->setUniform(GLShader::Opacity, opacity * frameOpacity); + if (shader) { + const float a = opacity * frameOpacity; + shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); + } #ifndef KWIN_HAVE_OPENGLES else glColor4f(1.0, 1.0, 1.0, opacity * frameOpacity); @@ -1275,9 +1282,10 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra m_effectFrame->geometry().center().y() - m_effectFrame->iconSize().height() / 2); if (m_effectFrame->isCrossFade() && m_oldIconTexture) { - if (shader) - shader->setUniform(GLShader::Opacity, - opacity * (1.0f - m_effectFrame->crossFadeProgress())); + if (shader) { + const float a = opacity * (1.0 - m_effectFrame->crossFadeProgress()); + shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); + } #ifndef KWIN_HAVE_OPENGLES else glColor4f(1.0, 1.0, 1.0, opacity * (1.0 - m_effectFrame->crossFadeProgress())); @@ -1286,15 +1294,19 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra m_oldIconTexture->bind(); m_oldIconTexture->render(region, QRect(topLeft, m_effectFrame->iconSize())); m_oldIconTexture->unbind(); - if (shader) - shader->setUniform(GLShader::Opacity, opacity * m_effectFrame->crossFadeProgress()); + if (shader) { + const float a = opacity * m_effectFrame->crossFadeProgress(); + shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); + } #ifndef KWIN_HAVE_OPENGLES else glColor4f(1.0, 1.0, 1.0, opacity * m_effectFrame->crossFadeProgress()); #endif } else { - if (shader) - shader->setUniform(GLShader::Opacity, opacity); + if (shader) { + const QVector4D constant(opacity, opacity, opacity, opacity); + shader->setUniform(GLShader::ModulationConstant, constant); + } #ifndef KWIN_HAVE_OPENGLES else glColor4f(1.0, 1.0, 1.0, opacity); @@ -1315,8 +1327,10 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra // Render text if (!m_effectFrame->text().isEmpty()) { if (m_effectFrame->isCrossFade() && m_oldTextTexture) { - if (shader) - shader->setUniform(GLShader::Opacity, opacity * (1.0f - m_effectFrame->crossFadeProgress())); + if (shader) { + const float a = opacity * (1.0 - m_effectFrame->crossFadeProgress()); + shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); + } #ifndef KWIN_HAVE_OPENGLES else glColor4f(1.0, 1.0, 1.0, opacity *(1.0 - m_effectFrame->crossFadeProgress())); @@ -1325,15 +1339,19 @@ void SceneOpenGL::EffectFrame::render(QRegion region, double opacity, double fra m_oldTextTexture->bind(); m_oldTextTexture->render(region, m_effectFrame->geometry()); m_oldTextTexture->unbind(); - if (shader) - shader->setUniform(GLShader::Opacity, opacity * m_effectFrame->crossFadeProgress()); + if (shader) { + const float a = opacity * m_effectFrame->crossFadeProgress(); + shader->setUniform(GLShader::ModulationConstant, QVector4D(a, a, a, a)); + } #ifndef KWIN_HAVE_OPENGLES else glColor4f(1.0, 1.0, 1.0, opacity * m_effectFrame->crossFadeProgress()); #endif } else { - if (shader) - shader->setUniform(GLShader::Opacity, opacity); + if (shader) { + const QVector4D constant(opacity, opacity, opacity, opacity); + shader->setUniform(GLShader::ModulationConstant, constant); + } #ifndef KWIN_HAVE_OPENGLES else glColor4f(1.0, 1.0, 1.0, opacity);