[vlc-commits] [Git][videolan/vlc][master] 4 commits: qt: add `RESET` to `textureSubRect` property in `TextureProviderItem`

Steve Lhomme (@robUx4) gitlab at videolan.org
Sun Aug 24 13:38:39 UTC 2025



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
aeb39ff8 by Fatih Uzunoglu at 2025-08-24T13:14:25+00:00
qt: add `RESET` to `textureSubRect` property in `TextureProviderItem`

This is useful because `MEMBER` does not seem to cover resetting.

- - - - -
baaefeca by Fatih Uzunoglu at 2025-08-24T13:14:25+00:00
qt: do not accept mipmap filtering if there are no mipmaps in `QSGTextureViewProvider::setMipmapFiltering()`

- - - - -
0e5200bc by Fatih Uzunoglu at 2025-08-24T13:14:25+00:00
qt: expose texture view state as properties in `TextureProviderItem`

This can be useful in certain situations, like tiling the source
texture without a layer (thanks to wrap mode).

It should be noted that these are the view states, we are not
modifying the source texture state here.

`ShaderEffectSource` already exposes these for the layer texture
it manages. Though, it seems more limited there, for example it
does not seem to allow disabling filtering completely, or allow
adjusting anisotropy level (which does not mean anything at the
moment but nevertheless).

- - - - -
3669f1e1 by Fatih Uzunoglu at 2025-08-24T13:14:25+00:00
qt: add a note to clarify having larger sub-size than the texture size in `TextureProviderItem`

- - - - -


2 changed files:

- modules/gui/qt/widgets/native/textureprovideritem.cpp
- modules/gui/qt/widgets/native/textureprovideritem.hpp


Changes:

=====================================
modules/gui/qt/widgets/native/textureprovideritem.cpp
=====================================
@@ -90,16 +90,44 @@ QSGTextureProvider *TextureProviderItem::textureProvider() const
                 provider->setRect(rect);
         };
 
+        const auto synchronizeState = [weakThis = QPointer(this), provider = m_textureProvider]() {
+            if (Q_UNLIKELY(!weakThis))
+                return;
+
+            provider->setFiltering(weakThis->m_filtering);
+            provider->setMipmapFiltering(weakThis->m_mipmapFiltering);
+            provider->setAnisotropyLevel(weakThis->m_anisotropyLevel);
+            provider->setHorizontalWrapMode(weakThis->m_horizontalWrapMode);
+            provider->setVerticalWrapMode(weakThis->m_verticalWrapMode);
+        };
+
+        // 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::filteringChanged, m_textureProvider, &QSGTextureViewProvider::setFiltering);
+        connect(this, &TextureProviderItem::mipmapFilteringChanged, m_textureProvider, &QSGTextureViewProvider::setMipmapFiltering);
+        connect(this, &TextureProviderItem::anisotropyLevelChanged, m_textureProvider, &QSGTextureViewProvider::setAnisotropyLevel);
+        connect(this, &TextureProviderItem::horizontalWrapModeChanged, m_textureProvider, &QSGTextureViewProvider::setHorizontalWrapMode);
+        connect(this, &TextureProviderItem::verticalWrapModeChanged, m_textureProvider, &QSGTextureViewProvider::setVerticalWrapMode);
+
+        // 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);
+        synchronizeState();
     }
     return m_textureProvider;
 }
 
+void TextureProviderItem::resetTextureSubRect()
+{
+    m_rect = {};
+    emit rectChanged({});
+}
+
 void TextureProviderItem::invalidateSceneGraph()
 {
     // https://doc.qt.io/qt-6/qquickitem.html#graphics-resource-handling
@@ -198,6 +226,20 @@ void QSGTextureViewProvider::setMipmapFiltering(QSGTexture::Filtering filter)
     if (m_textureView.mipmapFiltering() == filter)
         return;
 
+    if (filter != QSGTexture::Filtering::None)
+    {
+        const auto targetTexture = m_textureView.texture();
+        // If there is no target texture, we can accept mipmap filtering. When there becomes a target texture, `QSGTextureView` should
+        // consider this itself anyway if the new target texture has no mipmaps. Workarounds should probably not be over-conservative,
+        // we should not dismiss the case if there is no target texture now but the upcoming texture has mip maps.
+        if (targetTexture && !targetTexture->hasMipmaps())
+        {
+            // Having mip map filtering when there are no mip maps may be problematic with certain graphics backends (like OpenGL).
+            qWarning() << this << "Enabling mip map filtering is blocked if the target texture has no mip maps.";
+            return;
+        }
+    }
+
     m_textureView.setMipmapFiltering(filter);
     emit textureChanged();
 }


=====================================
modules/gui/qt/widgets/native/textureprovideritem.hpp
=====================================
@@ -56,17 +56,59 @@ class TextureProviderItem : public QQuickItem
     Q_OBJECT
 
     Q_PROPERTY(const QQuickItem* source MEMBER m_source NOTIFY sourceChanged FINAL)
-    Q_PROPERTY(QRect textureSubRect MEMBER m_rect NOTIFY rectChanged FINAL)
+    // NOTE: Although this is named as `textureSubRect`, it is allowed to provide a larger size than
+    //       the texture size. In that case, the texture's wrap mode is going to be relevant, provided
+    //       that the graphics backend supports it. Do note that if the source texture is already a
+    //       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).
+    Q_PROPERTY(QRect textureSubRect MEMBER m_rect NOTIFY rectChanged RESET resetTextureSubRect FINAL)
+
+    Q_PROPERTY(QSGTexture::AnisotropyLevel anisotropyLevel MEMBER m_anisotropyLevel NOTIFY anisotropyLevelChanged FINAL)
+    Q_PROPERTY(QSGTexture::WrapMode horizontalWrapMode MEMBER m_horizontalWrapMode NOTIFY horizontalWrapModeChanged FINAL)
+    Q_PROPERTY(QSGTexture::WrapMode verticalWrapMode MEMBER m_verticalWrapMode NOTIFY verticalWrapModeChanged FINAL)
+    // Maybe we should use `Item::smooth` instead of these properties, or maybe not, as we should allow disabling filtering completely.
+    Q_PROPERTY(QSGTexture::Filtering filtering MEMBER m_filtering NOTIFY filteringChanged FINAL)
+    // WARNING: mipmap filtering is not respected if target texture has no mip maps:
+    Q_PROPERTY(QSGTexture::Filtering mipmapFiltering MEMBER m_mipmapFiltering NOTIFY mipmapFilteringChanged FINAL)
 
     QML_ELEMENT
 public:
     TextureProviderItem() = default;
     virtual ~TextureProviderItem();
 
+    // These enumerations must be in sync with `QSGTexture`:
+    // It appears that MOC is not clever enough to consider foreign enumerations with `Q_ENUM` (I tried)...
+    enum _WrapMode {
+        Repeat,
+        ClampToEdge,
+        MirroredRepeat
+    };
+    Q_ENUM(_WrapMode);
+
+    enum _Filtering {
+        None,
+        Nearest,
+        Linear
+    };
+    Q_ENUM(_Filtering);
+
+    enum _AnisotropyLevel {
+        AnisotropyNone,
+        Anisotropy2x,
+        Anisotropy4x,
+        Anisotropy8x,
+        Anisotropy16x
+    };
+    Q_ENUM(_AnisotropyLevel);
+
     bool isTextureProvider() const override;
 
     QSGTextureProvider *textureProvider() const override;
 
+    void resetTextureSubRect();
+
 public slots:
     void invalidateSceneGraph();
 
@@ -75,6 +117,12 @@ signals:
     void rectChanged(const QRect& rect);
     void dprChanged();
 
+    void anisotropyLevelChanged(QSGTexture::AnisotropyLevel);
+    void filteringChanged(QSGTexture::Filtering);
+    void mipmapFilteringChanged(QSGTexture::Filtering);
+    void horizontalWrapModeChanged(QSGTexture::WrapMode);
+    void verticalWrapModeChanged(QSGTexture::WrapMode);
+
 protected:
     void releaseResources() override;
     void itemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) override;
@@ -85,6 +133,13 @@ private:
 
     mutable QPointer<QSGTextureViewProvider> m_textureProvider;
     mutable QMutex m_textureProviderMutex; // I'm not sure if this mutex is necessary
+
+    std::atomic<QSGTexture::AnisotropyLevel> m_anisotropyLevel = QSGTexture::AnisotropyNone;
+    std::atomic<QSGTexture::Filtering> m_filtering = (smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
+    std::atomic<QSGTexture::WrapMode> m_horizontalWrapMode = QSGTexture::ClampToEdge;
+    std::atomic<QSGTexture::WrapMode> m_verticalWrapMode = QSGTexture::ClampToEdge;
+    // When there are mip maps, no mip map filtering should be fine (unlike no mip maps with mip map filtering):
+    std::atomic<QSGTexture::Filtering> m_mipmapFiltering = QSGTexture::None;
 };
 
 #endif // TEXTUREPROVIDERITEM_HPP



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/7b08af3d097c8dffb896f564360395025dfc4f48...3669f1e15315efce430c8882279f487f3b82fb40

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/7b08af3d097c8dffb896f564360395025dfc4f48...3669f1e15315efce430c8882279f487f3b82fb40
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