[vlc-commits] [Git][videolan/vlc][master] 4 commits: qml: fix blur effect may not update on current item change in `Player`

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Fri May 29 11:48:06 UTC 2026



Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
824e88c4 by Fatih Uzunoglu at 2026-05-29T13:25:22+02:00
qml: fix blur effect may not update on current item change in `Player`

If the texture is updated, it is not guaranteed that the comparison
key changes. The old comparison key can be kept, because the old
texture content is no more.

Note that in this case we would not know if the texture is updated,
considering that the sub-rect also remains the same, but there is
not much we can do about that here besides expecting the texture
to be ready until we turn `live` back off (which takes `interval`
time). That is handled in the subsequent patch by introducing
`textureChanged()` signal in `TextureProviderObserver`.

- - - - -
42a70057 by Fatih Uzunoglu at 2026-05-29T13:25:22+02:00
qt: add signal `textureChanged()` in `TextureProviderObserver`

We can have this signal now, thanks to c6f45663.

This signal is necessary, because comparison key may not change
if the texture content changes, provided that the old content
is no more (such as updating an existing texture).

- - - - -
5cfec5a9 by Fatih Uzunoglu at 2026-05-29T13:25:22+02:00
qml: transient turn on `live` for blur effect also on texture change in `Player`

We still need keep doing the same in source changed signal in
order to not rely on the behavior of `Image`'s texture provider
that it signals `QSGTextureProvider::textureChanged()`.

- - - - -
1f78f377 by Fatih Uzunoglu at 2026-05-29T13:25:22+02:00
qml: get rid of `onNextEffectiveTextureChange` in `DualKawaseBlur::scheduleUpdate()`

The source texture provider observer that is exposed
now provides the `textureChanged()` signal, so this
is not necessary anymore.

As noted in the previous patches, relying on comparison
key is not enough anyway, so in hindsight this was not
really a concrete solution.

- - - - -


4 changed files:

- modules/gui/qt/player/qml/Player.qml
- modules/gui/qt/util/textureproviderobserver.cpp
- modules/gui/qt/util/textureproviderobserver.hpp
- modules/gui/qt/widgets/qml/DualKawaseBlur.qml


Changes:

=====================================
modules/gui/qt/player/qml/Player.qml
=====================================
@@ -323,7 +323,9 @@ FocusScope {
                     // video memory, depending on the excess content in the last layer:
                     viewportRect: Qt.rect((width - parent.width) / 2, (height - parent.height) / 2, parent.width, parent.height)
 
-                    funcOnNextEffectureTextureChange: liveTimer.transientTurnOnLive
+                    sourceTextureProviderObserver.onTextureChanged: {
+                        liveTimer.transientTurnOnLive()
+                    }
 
                     TextureProviderIndirection {
                         id: textureProviderIndirection
@@ -431,7 +433,7 @@ FocusScope {
                                 }
 
                                 onSourceChanged: {
-                                    blurredBackground.scheduleUpdate(true) // onNextTextureChange
+                                    liveTimer.transientTurnOnLive()
                                 }
 
                                 onStatusChanged: {


=====================================
modules/gui/qt/util/textureproviderobserver.cpp
=====================================
@@ -340,6 +340,12 @@ void TextureProviderObserver::updateProperties()
                 m_oldNativeTextureSize.store(nativeTextureSize, memoryOrder);
                 m_oldNormalizedTextureSubRect.store(normalizedTextureSubRect, memoryOrder);
                 m_oldComparisonKey.store(comparisonKey, memoryOrder);
+
+                emit textureChanged();
+            }
+            else
+            {
+                m_pendingNotifyTextureChange.store(true, memoryOrder);
             }
 
             return;
@@ -382,6 +388,9 @@ void TextureProviderObserver::resetProperties(std::memory_order memoryOrder)
     m_oldNativeTextureSize.store({}, memoryOrder);
     m_oldNormalizedTextureSubRect.store({}, memoryOrder);
     m_oldComparisonKey.store(-1, memoryOrder);
+
+    m_pendingNotifyTextureChange.store(false, memoryOrder);
+    emit textureChanged();
 }
 
 void TextureProviderObserver::adjustSampleAndNotifyConnection()
@@ -443,4 +452,7 @@ void TextureProviderObserver::sampleAndNotifyProperties()
         if (m_oldNormalizedTextureSubRect.exchange(normalizedTextureSubRect, memoryOrder) != normalizedTextureSubRect)
             emit normalizedTextureSubRectChanged(normalizedTextureSubRect);
     }
+
+    if (m_pendingNotifyTextureChange.exchange(false, memoryOrder))
+        emit textureChanged();
 }


=====================================
modules/gui/qt/util/textureproviderobserver.hpp
=====================================
@@ -105,6 +105,14 @@ public slots:
     void sampleAndNotifyProperties();
 
 signals:
+    // Similar to property notify signals, if the texture is dynamic, this
+    // signal is compressed and emitted at once once per frame from the GUI
+    // thread. If the texture is not dynamic, it is not compressed and emitted
+    // from the sg/rendering thread. You may use auto connection to connect
+    // to this signal, because there is no risk for backlogging (static
+    // textures are not expected to change rapidly).
+    void textureChanged();
+
     void notifyAllChangesChanged();
     void sourceChanged();
     void textureSizeChanged(const QSize&);
@@ -152,6 +160,7 @@ private:
     std::atomic<bool> m_hasMipmaps = false;
     std::atomic<bool> m_isAtlasTexture = false;
     std::atomic<bool> m_isValid = false;
+    std::atomic<bool> m_pendingNotifyTextureChange = false;
 };
 
 #endif // TEXTUREPROVIDEROBSERVER_HPP


=====================================
modules/gui/qt/widgets/qml/DualKawaseBlur.qml
=====================================
@@ -164,36 +164,9 @@ Item {
 
     property bool _queuedScheduledUpdate: false
 
-    readonly property var _comparisonVar: ({key: sourceTextureProviderObserver.comparisonKey,
-                                            subRect: sourceTextureProviderObserver.normalizedTextureSubRect})
-    property var _oldComparisonVar
-
-    on_ComparisonVarChanged: {
-        if (_comparisonVar.key >= 0) {
-            if (_oldComparisonVar !== undefined && _oldComparisonVar !== _comparisonVar) {
-                _oldComparisonVar = undefined
-
-                // If source texture is not valid, update will be requeued in `scheduleUpdate()`.
-                // That being said, a non-valid source texture should have (-1) as comparison key,
-                // which we already checked here.
-
-                if (root.funcOnNextEffectureTextureChange) {
-                    root.funcOnNextEffectureTextureChange()
-                }
-            }
-        }
-    }
-
-    // This is not respected when `live` is true, it is only for the `scheduleUpdate(true)` calls.
-    property var funcOnNextEffectureTextureChange: function() {
-        root.scheduleUpdate()
-    }
-
-    // When `onNextEffectiveTextureChange` is set, the update is scheduled automatically when the effective
-    // texture changes, which is when the texture itself changes or the texture remains the same but
-    // the sub-rect changes (such as, the new texture is a different part of the same atlas texture).
-    // This behavior can be fine-tuned with the property `funcOnNextEffectureTextureChange`.
-    function scheduleUpdate(onNextEffectiveTextureChange /* : bool */ = false) {
+    // NOTE: You can use the `sourceTextureProviderObserver.textureChanged()` signal to schedule an update
+    //       on source texture change at appropriate time.
+    function scheduleUpdate() {
         if (live)
             return // no-op
 
@@ -205,11 +178,6 @@ Item {
             return
         }
 
-        if (onNextEffectiveTextureChange) {
-            root._oldComparisonVar = root._comparisonVar
-            return
-        }
-
         if (root._window) {
             // One possible case for this is that the mipmaps for the source texture were generated too fast, and
             // the consumer wants to update the blur to make use of the mipmaps before the blur finished chained



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/860c6bbdb35a4d4d0dfcc1fd38dc8726e9715f3e...1f78f3778c2b0b646ac521c07a0d84e64cd19595

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/860c6bbdb35a4d4d0dfcc1fd38dc8726e9715f3e...1f78f3778c2b0b646ac521c07a0d84e64cd19595
You're receiving this email because of your account on code.videolan.org. Manage all notifications: https://code.videolan.org/-/profile/notifications | Help: https://code.videolan.org/help




More information about the vlc-commits mailing list