[plasma/kwin] src: opengl: Pre-multiply RGB values in QColor uniforms

Vlad Zahorodnii <[email protected]>
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit c908a326186e0e0dfddb03b1b314126a632be513 by Vlad Zahorodnii.
Committed on 21/07/2026 at 07:31.
Pushed by vladz into branch 'master'.

opengl: Pre-multiply RGB values in QColor uniforms

The blend equation that we often use assumes that the RGB values are
pre-multiplied by the alpha value. So perform the pre-multiplication
step when the uniform is set.

We could require that the input QColor needs to have the RGB values
pre-multiplied but that'll be inconvenient and easy to forget.

This should fix QColor::alpha() not doing anything with border outlines.

M  +8    -1    src/opengl/glshader.cpp
M  +8    -0    src/opengl/glshader.h
M  +1    -1    src/plugins/mouseclick/mouseclick.cpp
M  +1    -1    src/plugins/showpaint/showpaint.cpp
M  +1    -1    src/plugins/touchpoints/touchpoints.cpp

https://invent.kde.org/plasma/kwin/-/commit/c908a326186e0e0dfddb03b1b314126a632be513

diff --git a/src/opengl/glshader.cpp b/src/opengl/glshader.cpp
index 8518d1b5f1b..399902cb0b8 100644
--- a/src/opengl/glshader.cpp
+++ b/src/opengl/glshader.cpp
@@ -461,7 +461,14 @@ bool GLShader::setUniform(int location, const QMatrix4x4 &value)
 bool GLShader::setUniform(int location, const QColor &color)
 {
     if (location >= 0) {
-        glUniform4f(location, color.redF(), color.greenF(), color.blueF(), color.alphaF());
+        // Pre-multiply RGB values with the alpha channel. The blend equation that we often
+        // use assumes that colors are pre-multiplied by the alpha value.
+        const float alpha = color.alphaF();
+        const float red = color.redF() * alpha;
+        const float green = color.greenF() * alpha;
+        const float blue = color.blueF() * alpha;
+
+        glUniform4f(location, red, green, blue, alpha);
     }
     return (location >= 0);
 }
diff --git a/src/opengl/glshader.h b/src/opengl/glshader.h
index 7efc35314a9..124c6f0bbf2 100644
--- a/src/opengl/glshader.h
+++ b/src/opengl/glshader.h
@@ -55,6 +55,10 @@ public:
     bool setUniform(int location, const QVector4D &value);
     bool setUniform(int location, const QMatrix3x3 &value);
     bool setUniform(int location, const QMatrix4x4 &value);
+
+    /**
+     * The RGB values will be pre-multiplied with the alpha value.
+     */
     bool setUniform(int location, const QColor &value);
 
     int attributeLocation(const char *name);
@@ -134,6 +138,10 @@ public:
     bool setUniform(FloatUniform uniform, float value);
     bool setUniform(IntUniform uniform, int value);
     bool setUniform(ColorUniform uniform, const QVector4D &value);
+
+    /**
+     * The RGB values will be pre-multiplied with the alpha value.
+     */
     bool setUniform(ColorUniform uniform, const QColor &value);
 
     void setColorspaceUniforms(const std::shared_ptr<ColorDescription> &src, const std::shared_ptr<ColorDescription> &dst, RenderingIntent intent);
diff --git a/src/plugins/mouseclick/mouseclick.cpp b/src/plugins/mouseclick/mouseclick.cpp
index f2e783e62c4..2e02c1af7ba 100644
--- a/src/plugins/mouseclick/mouseclick.cpp
+++ b/src/plugins/mouseclick/mouseclick.cpp
@@ -290,7 +290,7 @@ void MouseClickEffect::paintScreenSetupGl(const RenderTarget &renderTarget, cons
 
     glLineWidth(m_lineWidth);
     glEnable(GL_BLEND);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 }
 
 void MouseClickEffect::paintScreenFinishGl()
diff --git a/src/plugins/showpaint/showpaint.cpp b/src/plugins/showpaint/showpaint.cpp
index e99c0432d96..1687bf47877 100644
--- a/src/plugins/showpaint/showpaint.cpp
+++ b/src/plugins/showpaint/showpaint.cpp
@@ -52,7 +52,7 @@ void ShowPaintEffect::paintGL(const RenderTarget &renderTarget, const RenderView
     binder.shader()->setUniform(GLShader::Mat4Uniform::ModelViewProjectionMatrix, viewport.projectionMatrix());
     binder.shader()->setColorspaceUniforms(ColorDescription::sRGB, renderTarget.colorDescription(), RenderingIntent::Perceptual);
     glEnable(GL_BLEND);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
     QColor color = s_colors[m_colorIndex];
     color.setAlphaF(s_alpha);
     binder.shader()->setUniform(GLShader::ColorUniform::Color, color);
diff --git a/src/plugins/touchpoints/touchpoints.cpp b/src/plugins/touchpoints/touchpoints.cpp
index 63e5b5f290c..cf8d7ad0e3b 100644
--- a/src/plugins/touchpoints/touchpoints.cpp
+++ b/src/plugins/touchpoints/touchpoints.cpp
@@ -218,7 +218,7 @@ void TouchPointsEffect::paintScreenSetupGl(const RenderTarget &renderTarget, con
 
     glLineWidth(m_lineWidth);
     glEnable(GL_BLEND);
-    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 }
 
 void TouchPointsEffect::paintScreenFinishGl()
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.