Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
d2110b64 by Fatih Uzunoglu at 2026-01-22T15:18:24+00:00
qt: fix undefined behavior if there is no rounding in `SDFAARoundedTexture.frag`
This also prevents doing additional calculations when there is no need.
When there is no rounding custom soft edge may end up being 0.0 since it may be
derived from radius, because of that `smoothstep()` is called with the same
edge values, which is undefined behavior. This is interesting, because the
expectation was `smoothstep()` converging to `step()` if the edges are the
same.
This does not really matter though, because we should not be calling
`smoothstep()` at all, provided that there is no rounding.
It is the responsibility of the consumer to not provide invalid soft edges
when `CUSTOM_SOFTEDGE` is defined. No additional checks are added beside
whether to apply rounding or not (depending on the radius values).
This patch introduces new branches, but since the branches depend on
the uniform buffer, it is not expected to cause performance penalty.
- - - - -
b44736d9 by Fatih Uzunoglu at 2026-01-22T15:18:24+00:00
qml: expose `blending` in `ImageExt`
- - - - -
267d92c1 by Fatih Uzunoglu at 2026-01-22T15:18:24+00:00
qml: adjust default blending in `ImageExt`
If there is no rounding, and background color is opaque,
there is no need for blending.
Unlike `EnhancedImageExt`, we can not check if the
texture is opaque because `TextureProviderObserver` is
not available. Introducing an observer just for adjusting
blending is not considered a good idea, even though the
observer is not a heavy itself.
- - - - -
2c20e402 by Fatih Uzunoglu at 2026-01-22T15:18:24+00:00
qml: adjust default blending in `EnhancedImageExt.qml`
Unlike `ImageExt`, since observer is available here,
we can disable blending if the texture is opaque.
- - - - -
ad56aa72 by Fatih Uzunoglu at 2026-01-22T15:18:24+00:00
qml: define the background color property in root in `ImageExt`
So that the reader does not need to inspect
the shader effect to see the default color.
No behavioral change is intended.
Akin to dcb834f7.
- - - - -
4 changed files:
- modules/gui/qt/shaders/SDFAARoundedTexture.frag
- modules/gui/qt/shaders/SDFAARoundedTexture_cropsupport_bordersupport.frag
- modules/gui/qt/widgets/qml/EnhancedImageExt.qml
- modules/gui/qt/widgets/qml/ImageExt.qml
Changes:
=====================================
modules/gui/qt/shaders/SDFAARoundedTexture.frag
=====================================
@@ -86,16 +86,27 @@ float sdRoundBox( in vec2 p, in vec2 b, in vec4 r )
void main()
{
- // The signed distance function works when the primitive is centered.
- // If the texture is in the atlas, this condition is not satisfied.
- // Therefore, we have to normalize the coordinate for the distance
- // function to [0, 1]:
- vec2 normalCoord = vec2(1.0, 1.0) / (qt_SubRect_source.zw) * (qt_TexCoord0
- (qt_SubRect_source.zw + qt_SubRect_source.xy)) + vec2(1.0, 1.0);
- normalCoord.y = (1.0 - normalCoord.y); // invert y-axis because texture
coordinates have origin at the top
+ // Depends on uniform values, this is considered acceptable:
+ bool rounding = (radiusTopLeft > 0.0 || radiusTopRight > 0.0 ||
radiusBottomLeft > 0.0 || radiusBottomRight > 0.0);
- vec2 p = (size.xy * ((2.0 * normalCoord) - 1)) / size.y;
- // Signed distance:
- float dist = sdRoundBox(p, vec2(size.x / size.y, 1.0),
vec4(radiusTopRight, radiusBottomRight, radiusTopLeft, radiusBottomLeft));
+ float dist;
+#ifdef BORDER_SUPPORT
+ if (rounding || borderRange > 0.0) // border requires sdf, even if there
is no rounding wanted for the texture
+#else
+ if (rounding)
+#endif
+ {
+ // The signed distance function works when the primitive is centered.
+ // If the texture is in the atlas, this condition is not satisfied.
+ // Therefore, we have to normalize the coordinate for the distance
+ // function to [0, 1]:
+ vec2 normalCoord = vec2(1.0, 1.0) / (qt_SubRect_source.zw) *
(qt_TexCoord0 - (qt_SubRect_source.zw + qt_SubRect_source.xy)) + vec2(1.0, 1.0);
+ normalCoord.y = (1.0 - normalCoord.y); // invert y-axis because
texture coordinates have origin at the top
+
+ vec2 p = (size.xy * ((2.0 * normalCoord) - 1)) / size.y;
+ // Signed distance:
+ dist = sdRoundBox(p, vec2(size.x / size.y, 1.0), vec4(radiusTopRight,
radiusBottomRight, radiusTopLeft, radiusBottomLeft));
+ }
#ifdef CROP_SUPPORT
vec2 texCoord;
@@ -157,29 +168,32 @@ void main()
}
#endif
- float factor;
-#ifdef ANTIALIASING
- if (antialiasing != 0)
+ if (rounding)
{
+ float factor;
+#ifdef ANTIALIASING
+ if (antialiasing != 0)
+ {
#ifndef CUSTOM_SOFTEDGE
- float softEdgeMax = fwidth(dist) * 0.75;
- float softEdgeMin = -softEdgeMax;
+ float softEdgeMax = fwidth(dist) * 0.75;
+ float softEdgeMin = -softEdgeMax;
#endif
- // Breathing room (shrink):
- dist += softEdgeMax;
+ // Breathing room (shrink):
+ dist += softEdgeMax;
- // Soften the outline, as recommended by the Valve paper, using
smoothstep:
- // "Improved Alpha-Tested Magnification for Vector Textures and
Special Effects"
- // NOTE: The whole texel is multiplied, because of premultiplied alpha.
- factor = smoothstep(softEdgeMin, softEdgeMax, dist);
- }
- else
+ // Soften the outline, as recommended by the Valve paper, using
smoothstep:
+ // "Improved Alpha-Tested Magnification for Vector Textures and
Special Effects"
+ // NOTE: The whole texel is multiplied, because of premultiplied
alpha.
+ factor = smoothstep(softEdgeMin, softEdgeMax, dist);
+ }
+ else
#endif
- {
- factor = step(0.0, dist);
- }
+ {
+ factor = step(0.0, dist);
+ }
- texel *= 1.0 - factor;
+ texel *= 1.0 - factor;
+ }
fragColor = texel * qt_Opacity;
}
=====================================
modules/gui/qt/shaders/SDFAARoundedTexture_cropsupport_bordersupport.frag
=====================================
@@ -99,16 +99,27 @@ float sdRoundBox( in vec2 p, in vec2 b, in vec4 r )
void main()
{
- // The signed distance function works when the primitive is centered.
- // If the texture is in the atlas, this condition is not satisfied.
- // Therefore, we have to normalize the coordinate for the distance
- // function to [0, 1]:
- vec2 normalCoord = vec2(1.0, 1.0) / (qt_SubRect_source.zw) * (qt_TexCoord0
- (qt_SubRect_source.zw + qt_SubRect_source.xy)) + vec2(1.0, 1.0);
- normalCoord.y = (1.0 - normalCoord.y); // invert y-axis because texture
coordinates have origin at the top
+ // Depends on uniform values, this is considered acceptable:
+ bool rounding = (radiusTopLeft > 0.0 || radiusTopRight > 0.0 ||
radiusBottomLeft > 0.0 || radiusBottomRight > 0.0);
- vec2 p = (size.xy * ((2.0 * normalCoord) - 1)) / size.y;
- // Signed distance:
- float dist = sdRoundBox(p, vec2(size.x / size.y, 1.0),
vec4(radiusTopRight, radiusBottomRight, radiusTopLeft, radiusBottomLeft));
+ float dist;
+#ifdef BORDER_SUPPORT
+ if (rounding || borderRange > 0.0) // border requires sdf, even if there
is no rounding wanted for the texture
+#else
+ if (rounding)
+#endif
+ {
+ // The signed distance function works when the primitive is centered.
+ // If the texture is in the atlas, this condition is not satisfied.
+ // Therefore, we have to normalize the coordinate for the distance
+ // function to [0, 1]:
+ vec2 normalCoord = vec2(1.0, 1.0) / (qt_SubRect_source.zw) *
(qt_TexCoord0 - (qt_SubRect_source.zw + qt_SubRect_source.xy)) + vec2(1.0, 1.0);
+ normalCoord.y = (1.0 - normalCoord.y); // invert y-axis because
texture coordinates have origin at the top
+
+ vec2 p = (size.xy * ((2.0 * normalCoord) - 1)) / size.y;
+ // Signed distance:
+ dist = sdRoundBox(p, vec2(size.x / size.y, 1.0), vec4(radiusTopRight,
radiusBottomRight, radiusTopLeft, radiusBottomLeft));
+ }
#ifdef CROP_SUPPORT
vec2 texCoord;
@@ -170,29 +181,32 @@ void main()
}
#endif
- float factor;
-#ifdef ANTIALIASING
- if (antialiasing != 0)
+ if (rounding)
{
+ float factor;
+#ifdef ANTIALIASING
+ if (antialiasing != 0)
+ {
#ifndef CUSTOM_SOFTEDGE
- float softEdgeMax = fwidth(dist) * 0.75;
- float softEdgeMin = -softEdgeMax;
+ float softEdgeMax = fwidth(dist) * 0.75;
+ float softEdgeMin = -softEdgeMax;
#endif
- // Breathing room (shrink):
- dist += softEdgeMax;
+ // Breathing room (shrink):
+ dist += softEdgeMax;
- // Soften the outline, as recommended by the Valve paper, using
smoothstep:
- // "Improved Alpha-Tested Magnification for Vector Textures and
Special Effects"
- // NOTE: The whole texel is multiplied, because of premultiplied alpha.
- factor = smoothstep(softEdgeMin, softEdgeMax, dist);
- }
- else
+ // Soften the outline, as recommended by the Valve paper, using
smoothstep:
+ // "Improved Alpha-Tested Magnification for Vector Textures and
Special Effects"
+ // NOTE: The whole texel is multiplied, because of premultiplied
alpha.
+ factor = smoothstep(softEdgeMin, softEdgeMax, dist);
+ }
+ else
#endif
- {
- factor = step(0.0, dist);
- }
+ {
+ factor = step(0.0, dist);
+ }
- texel *= 1.0 - factor;
+ texel *= 1.0 - factor;
+ }
fragColor = texel * qt_Opacity;
}
=====================================
modules/gui/qt/widgets/qml/EnhancedImageExt.qml
=====================================
@@ -45,6 +45,22 @@ ImageExt {
// No need to load images in this case:
loadImages: (targetTextureProvider === root.sourceTextureProviderItem)
+ blending: {
+ if (effectiveRadius > 0.0)
+ return true // Outside the radius is always transparent, need
blending
+
+ if (effectiveBackgroundColor.a > (1.0 - Number.EPSILON))
+ return false // If background color is opaque, no need for blending
+
+ if (textureProviderItem === textureProvider) {
+ console.assert(observer.source === textureProvider)
+ if (!observer.hasAlphaChannel)
+ return false // If the texture is opaque, no need for blending
+ }
+
+ return true
+ }
+
TextureProviderItem {
id: textureProvider
=====================================
modules/gui/qt/widgets/qml/ImageExt.qml
=====================================
@@ -115,11 +115,14 @@ Item {
property real radiusTopLeft: radius
property real radiusBottomRight: radius
property real radiusBottomLeft: radius
-
- property alias backgroundColor: shaderEffect.backgroundColor
readonly property real effectiveRadius: shaderEffect.readyForVisibility ?
Math.max(radiusTopRight, radiusTopLeft, radiusBottomRight, radiusBottomLeft) :
0.0
+
+ property color backgroundColor: "transparent"
readonly property color effectiveBackgroundColor:
shaderEffect.readyForVisibility ? backgroundColor : "transparent"
+ property alias blending: shaderEffect.blending
+ blending: (effectiveRadius > 0.0) || (effectiveBackgroundColor.a < 1.0)
+
// Border:
// NOTE: The border is an overlay for the texture (the
// texture does not shrink).
@@ -163,8 +166,6 @@ Item {
supportsAtlasTextures: true
- blending: true
-
antialiasing: root.antialiasing
// cullMode: ShaderEffect.BackFaceCulling // QTBUG-136611 (Layering
breaks culling with OpenGL)
@@ -178,7 +179,7 @@ Item {
readonly property real radiusTopLeft:
normalizeRadius(root.radiusTopLeft)
readonly property real radiusBottomLeft:
normalizeRadius(root.radiusBottomLeft)
- property color backgroundColor: "transparent"
+ property alias backgroundColor: root.backgroundColor
readonly property size size: Qt.size(width, height)
View it on GitLab:
https://code.videolan.org/videolan/vlc/-/compare/b5f1d577fdb625782011458ac5d12d9d5b1af7d0...ad56aa72ebc4cd35ad1167d74ecbd7c06056f420
--
View it on GitLab:
https://code.videolan.org/videolan/vlc/-/compare/b5f1d577fdb625782011458ac5d12d9d5b1af7d0...ad56aa72ebc4cd35ad1167d74ecbd7c06056f420
You're receiving this email because of your account on code.videolan.org.
VideoLAN code repository instance_______________________________________________
vlc-commits mailing list
[email protected]
https://mailman.videolan.org/listinfo/vlc-commits