[vlc-commits] [Git][videolan/vlc][master] 7 commits: qml: make sure the layer is gone when it is not used in `ArtistTopBanner`

Steve Lhomme (@robUx4) gitlab at videolan.org
Sun Oct 5 10:14:54 UTC 2025



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
81af16b6 by Fatih Uzunoglu at 2025-10-05T09:59:24+00:00
qml: make sure the layer is gone when it is not used in `ArtistTopBanner`

This is for the switching case, once the layer is created it would remain,
so setting the `sourceItem` to null while `live` is enabled should help
with this.

Instead of creating the layer once and keeping it around, I believe it
makes more sense to destroy it when it is not used, and re-create when
necessary.

- - - - -
40049d8e by Fatih Uzunoglu at 2025-10-05T09:59:24+00:00
qt: use weak pointer for the target texture in `QSGTextureView`

This is useful for these situations:
- Target is gone for any reason.
- Target is gone, but its provider did not report it. This is
for the cases where the view is not driven by its default
provider counterpart, `QSGTextureViewProvider`.

- - - - -
b851692d by Fatih Uzunoglu at 2025-10-05T09:59:24+00:00
qt: fix unable to reset sub-rect in texture view

- - - - -
b4e36c5b by Fatih Uzunoglu at 2025-10-05T09:59:24+00:00
qt: introduce `QSGTextureView::requestDetachFromAtlas()`

This allows detaching from the atlas at appropriate time,
which is useful because calling `removedFromAtlas()`
directly may be problematic without an update batch.

- - - - -
abfe098d by Fatih Uzunoglu at 2025-10-05T09:59:24+00:00
qt: introduce property `detachAtlasTextures` in `TextureProviderItem`

This boolean property allows detaching the target textures from the
atlas when applicable. As the comment describes, this is useful in
certain situations, such as making use of wrapping.

- - - - -
afc55821 by Fatih Uzunoglu at 2025-10-05T09:59:24+00:00
qml: get rid of the layer used for tiling in `ArtistTopBanner`

Do tiling at sampler level than layer level, thanks to
the texture view. This allows us to save video memory.

- - - - -
fdcb6f07 by Fatih Uzunoglu at 2025-10-05T09:59:24+00:00
qml: do not display the effect during initialization in `ArtistTopBanner`

- - - - -


5 changed files:

- modules/gui/qt/medialibrary/qml/ArtistTopBanner.qml
- modules/gui/qt/util/qsgtextureview.cpp
- modules/gui/qt/util/qsgtextureview.hpp
- modules/gui/qt/widgets/native/textureprovideritem.cpp
- modules/gui/qt/widgets/native/textureprovideritem.hpp


Changes:

=====================================
modules/gui/qt/medialibrary/qml/ArtistTopBanner.qml
=====================================
@@ -77,7 +77,7 @@ FocusScope {
     Item {
         anchors.fill: background
 
-        visible: (GraphicsInfo.shaderType === GraphicsInfo.RhiShader)
+        visible: (GraphicsInfo.shaderType === GraphicsInfo.RhiShader) && (root.artist.id) // do not display the effect during initialization
 
         // This blur effect does not create an implicit layer that is updated
         // each time the size changes. The source texture is static, so the blur
@@ -92,15 +92,19 @@ FocusScope {
 
             // NOTE: No need to disable `live`, as this uses two pass mode so there is no video memory saving benefit.
 
-            // If source image is tiled, layering is necessary:
-            readonly property bool sourceNeedsLayering: (background.fillMode === Image.Tile)
+            readonly property bool sourceNeedsTiling: (background.fillMode === Image.Tile)
 
             readonly property real aspectRatio: (background.implicitHeight / background.implicitWidth)
 
-            height: sourceNeedsLayering ? background.height : (aspectRatio * width)
+            height: sourceNeedsTiling ? background.height : (aspectRatio * width)
 
             source: textureProviderItem
 
+            // Instead of clipping in the parent, denote the viewport here so we both
+            // do not need to clip the excess, and also save significant video memory:
+            viewportRect: !blurEffect.sourceNeedsLayering ? Qt.rect((width - parent.width) / 2, (height - parent.height) / 2, parent.width, parent.height)
+                                                          : Qt.rect(0, 0, 0, 0)
+
             Widgets.TextureProviderItem {
                 id: textureProviderItem
 
@@ -110,23 +114,17 @@ FocusScope {
                 // we can have an indirection here through `TextureProviderItem`.
                 // This is totally acceptable as there is virtually no overhead.
 
-                source: blurEffect.sourceNeedsLayering ? backgroundLayer : background
-            }
-
-            // Instead of clipping in the parent, denote the viewport here so we both
-            // do not need to clip the excess, and also save significant video memory:
-            viewportRect: !blurEffect.sourceNeedsLayering ? Qt.rect((width - parent.width) / 2, (height - parent.height) / 2, parent.width, parent.height)
-                                                          : Qt.rect(0, 0, 0, 0)
+                source: background
 
-            ShaderEffectSource {
-                id: backgroundLayer
+                detachAtlasTextures: blurEffect.sourceNeedsTiling
 
-                sourceItem: background
+                horizontalWrapMode: blurEffect.sourceNeedsTiling ? Widgets.TextureProviderItem.Repeat : Widgets.TextureProviderItem.ClampToEdge
+                verticalWrapMode: blurEffect.sourceNeedsTiling ? Widgets.TextureProviderItem.Repeat : Widgets.TextureProviderItem.ClampToEdge
 
-                // We hope that Qt does not create the layer unless this is actually used as
-                // texture provider (it is already invisible). GammaRay tells that this is
-                // already the case (I can not access the texture).
-                visible: false
+                textureSubRect: blurEffect.sourceNeedsTiling ? Qt.rect(blurEffect.width / 8,
+                                                                       blurEffect.height / 8,
+                                                                       blurEffect.width * 1.25,
+                                                                       blurEffect.height * 1.25) : undefined
             }
 
             // Strong blurring is not wanted here:


=====================================
modules/gui/qt/util/qsgtextureview.cpp
=====================================
@@ -112,9 +112,6 @@ void QSGTextureView::setRect(const QRect &rect)
     if (m_rect == rect)
         return;
 
-    if (!rect.isValid())
-        return;
-
     m_rect = rect;
 
     // We need the source texture in order to calculate the normal rect.
@@ -122,7 +119,10 @@ void QSGTextureView::setRect(const QRect &rect)
     // later in `normalizedTextureSubRect()`.
     if (m_texture)
     {
-        adjustNormalRect();
+        if (m_rect.isValid())
+            adjustNormalRect();
+        else
+            m_normalRect.reset();
         emit updateRequested();
     }
     else
@@ -284,7 +284,20 @@ QSGTexture *QSGTextureView::removedFromAtlas(QRhiResourceUpdateBatch *batch) con
 void QSGTextureView::commitTextureOperations(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
 {
     if (m_texture)
+    {
+        if (m_detachFromAtlasPending)
+        {
+            if (isAtlasTexture())
+            {
+                const auto oldTexture = m_texture;
+                if (removedFromAtlas(resourceUpdates))
+                    qDebug() << this << ": Detached" << oldTexture << "from the atlas, and re-targeted to" << m_texture;
+            }
+            m_detachFromAtlasPending = false;
+        }
+
         m_texture->commitTextureOperations(rhi, resourceUpdates);
+    }
 }
 
 bool QSGTextureView::updateTexture()
@@ -306,3 +319,7 @@ bool QSGTextureView::updateTexture()
     return ret;
 }
 
+void QSGTextureView::requestDetachFromAtlas()
+{
+    m_detachFromAtlasPending = true;
+}


=====================================
modules/gui/qt/util/qsgtextureview.hpp
=====================================
@@ -26,10 +26,11 @@ class QSGTextureView : public QSGDynamicTexture
 {
     Q_OBJECT
 
-    QSGTexture* m_texture = nullptr;
+    QPointer<QSGTexture> m_texture;
     QRect m_rect;
     mutable std::optional<QRectF> m_normalRect;
     mutable bool m_normalRectChanged = false;
+    bool m_detachFromAtlasPending = false;
 
 private slots:
     bool adjustNormalRect() const;
@@ -75,6 +76,9 @@ public:
 
     bool updateTexture() override;
 
+    // Detaches from atlas (when applicable) upon the next `commitTextureOperations()` call:
+    void requestDetachFromAtlas();
+
 signals:
     void updateRequested();
 };


=====================================
modules/gui/qt/widgets/native/textureprovideritem.cpp
=====================================
@@ -83,11 +83,6 @@ QSGTextureProvider *TextureProviderItem::textureProvider() const
             }
         };
 
-        const auto adjustRect = [provider = m_textureProvider](const QRect& rect) {
-            if (rect.isValid())
-                provider->setRect(rect);
-        };
-
         const auto synchronizeState = [weakThis = QPointer(this), provider = m_textureProvider]() {
             if (Q_UNLIKELY(!weakThis))
                 return;
@@ -97,11 +92,14 @@ QSGTextureProvider *TextureProviderItem::textureProvider() const
             provider->setAnisotropyLevel(weakThis->m_anisotropyLevel);
             provider->setHorizontalWrapMode(weakThis->m_horizontalWrapMode);
             provider->setVerticalWrapMode(weakThis->m_verticalWrapMode);
+
+            if (weakThis->m_detachAtlasTextures)
+                provider->requestDetachFromAtlas();
         };
 
         // These are going to be queued when necessary:
         connect(this, &TextureProviderItem::sourceChanged, m_textureProvider, adjustSource);
-        connect(this, &TextureProviderItem::rectChanged, m_textureProvider, adjustRect);
+        connect(this, &TextureProviderItem::rectChanged, m_textureProvider, &QSGTextureViewProvider::setRect);
 
         connect(this, &TextureProviderItem::filteringChanged, m_textureProvider, &QSGTextureViewProvider::setFiltering);
         connect(this, &TextureProviderItem::mipmapFilteringChanged, m_textureProvider, &QSGTextureViewProvider::setMipmapFiltering);
@@ -109,12 +107,18 @@ QSGTextureProvider *TextureProviderItem::textureProvider() const
         connect(this, &TextureProviderItem::horizontalWrapModeChanged, m_textureProvider, &QSGTextureViewProvider::setHorizontalWrapMode);
         connect(this, &TextureProviderItem::verticalWrapModeChanged, m_textureProvider, &QSGTextureViewProvider::setVerticalWrapMode);
 
+        connect(this, &TextureProviderItem::detachAtlasTexturesChanged, m_textureProvider, [provider = m_textureProvider](bool detach) {
+            if (detach)
+                provider->requestDetachFromAtlas();
+        });
+
         // When the target texture changes, the texture view may reset its state, so we need to synchronize in that case:
         connect(m_textureProvider, &QSGTextureProvider::textureChanged, m_textureProvider, synchronizeState); // Executed in texture provider's thread
 
         // Initial adjustments:
         adjustSource(m_source);
-        adjustRect(m_rect);
+        if (m_rect.isValid())
+            m_textureProvider->setRect(m_rect);
         synchronizeState();
     }
     return m_textureProvider;
@@ -264,3 +268,8 @@ void QSGTextureViewProvider::setVerticalWrapMode(QSGTexture::WrapMode vwrap)
     m_textureView.setVerticalWrapMode(vwrap);
     emit textureChanged();
 }
+
+void QSGTextureViewProvider::requestDetachFromAtlas()
+{
+    m_textureView.requestDetachFromAtlas();
+}


=====================================
modules/gui/qt/widgets/native/textureprovideritem.hpp
=====================================
@@ -49,6 +49,8 @@ public:
     void setAnisotropyLevel(QSGTexture::AnisotropyLevel level);
     void setHorizontalWrapMode(QSGTexture::WrapMode hwrap);
     void setVerticalWrapMode(QSGTexture::WrapMode vwrap);
+
+    void requestDetachFromAtlas();
 };
 
 class TextureProviderItem : public QQuickItem
@@ -62,8 +64,9 @@ class TextureProviderItem : public QQuickItem
     //       sub-texture (such as a texture in the atlas), wrapping would only be applicable outside
     //       the boundaries of the whole texture and not the source sub-texture, and not considering
     //       this may expose irrelevant parts of the atlas (this means that wrap mode is effectively
-    //       useless for sub- or atlas textures).
+    //       useless for sub- or atlas textures). In such a case, `detachAtlasTextures` can be used.
     Q_PROPERTY(QRect textureSubRect MEMBER m_rect NOTIFY rectChanged RESET resetTextureSubRect FINAL)
+    Q_PROPERTY(bool detachAtlasTextures MEMBER m_detachAtlasTextures NOTIFY detachAtlasTexturesChanged FINAL)
 
     Q_PROPERTY(QSGTexture::AnisotropyLevel anisotropyLevel MEMBER m_anisotropyLevel NOTIFY anisotropyLevelChanged FINAL)
     Q_PROPERTY(QSGTexture::WrapMode horizontalWrapMode MEMBER m_horizontalWrapMode NOTIFY horizontalWrapModeChanged FINAL)
@@ -122,6 +125,8 @@ signals:
     void horizontalWrapModeChanged(QSGTexture::WrapMode);
     void verticalWrapModeChanged(QSGTexture::WrapMode);
 
+    void detachAtlasTexturesChanged(bool);
+
 protected:
     void releaseResources() override;
 
@@ -138,6 +143,7 @@ private:
     // When there are mip maps, no mip map filtering should be fine (unlike no mip maps with mip map filtering):
     // But we want to have mip map filtering by default if the texture has mip maps (if not, it won't be respected):
     std::atomic<QSGTexture::Filtering> m_mipmapFiltering = QSGTexture::Linear;
+    std::atomic<bool> m_detachAtlasTextures = false;
 };
 
 #endif // TEXTUREPROVIDERITEM_HPP



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/8be3f74f504f7e782f43e8215f38ff1dd034e6ac...fdcb6f07789b6873594c2fd736dcb06e0e184370

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/8be3f74f504f7e782f43e8215f38ff1dd034e6ac...fdcb6f07789b6873594c2fd736dcb06e0e184370
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list