[vlc-commits] [Git][videolan/vlc][master] qt: reset texture state in `QSGTextureView` on source texture update
Steve Lhomme (@robUx4)
gitlab at videolan.org
Sun Aug 24 10:30:04 UTC 2025
Steve Lhomme pushed to branch master at VideoLAN / VLC
Commits:
35401cd1 by Fatih Uzunoglu at 2025-08-24T10:14:34+00:00
qt: reset texture state in `QSGTextureView` on source texture update
This is important because if the source texture has no
mipmaps, but the view has mipmap filtering enabled,
depending on the graphics backend the texture might not
be rendered at all (reproduced with OpenGL, not with Vulkan).
Currently we are not accounting for the case when the source
texture is the same*, but it starts having mipmaps or no longer
has mipmaps after the initial `QSGTextureView::setTexture()`
call. At the same time, the workaround for the Qt bug where
the source texture has mipmap filtering but no mipmaps should
be considered better with `hasMipmaps()` rather than
`isAtlasTexture()` (maybe we should check both, but only
`hasMipmaps()` seemed fine to me), where I also changed in this
merge request. In the future, if Qt still has this bug, we can
test `QRhiTexture::flags()` with `QRhiTexture::MipMapped` for
a better check if the underlying/native texture actually has
mipmaps.
The rest of the parameters, such as wrap mode, or anisotropy
level should be independent of the source texture. We do not
need to reset them in this case, but for consistency I reset
the whole state altogether. If the view wants to have a
different state than the source texture, they should be set
again after reset.
- state is reset regardless of if the texture pointer changes in
`::setTexture()`. I was hesitant before about what the signal
`QSGTextureProvider::textureChanged()` actually meant, because
it was not obvious to me if it was referring only to the whole
texture changes (residing in different address), or also if
it meant the properties of the provided texture. But I can now
tell that there is at least one case it is signalled even if the
provider's texture is the same*, but states change (`QQuickImage`).
This makes sense, as there is no other signal that indicates state
changes in `QSGTextureProvider`. Though, I would name the signal
`QSGTextureProvider::textureUpdated()`, or better, have a separate
signal for that.
- state is reset if the source texture is a layer and it signals
update request (`QSGLayer::updateRequested()`), whether or not
`::setTexture()` is called. We are already re-adjusting the normal
coordinates in this case, I just added a new connection.
(*) as in, the same pointer, not meaning deep compare
- - - - -
2 changed files:
- modules/gui/qt/util/qsgtextureview.cpp
- modules/gui/qt/util/qsgtextureview.hpp
Changes:
=====================================
modules/gui/qt/util/qsgtextureview.cpp
=====================================
@@ -30,7 +30,15 @@ QSGTexture *QSGTextureView::texture() const
void QSGTextureView::setTexture(QSGTexture *texture)
{
if (m_texture == texture)
+ {
+ if (m_texture)
+ {
+ if (resetState())
+ emit updateRequested();
+ }
+
return;
+ }
if (m_texture)
{
@@ -41,21 +49,14 @@ void QSGTextureView::setTexture(QSGTexture *texture)
if (texture)
{
- setFiltering(texture->filtering());
- if (!texture->isAtlasTexture())
- {
- // Atlas textures are not rendered if they have mipmap filtering.
- // Normally it should not happen because atlas textures are not
- // mipmapped, mipmap filtering should not change anything.
- setMipmapFiltering(texture->mipmapFiltering());
- }
-
- setAnisotropyLevel(texture->anisotropyLevel());
- setHorizontalWrapMode(texture->horizontalWrapMode());
- setVerticalWrapMode(texture->verticalWrapMode());
+ resetState();
if (texture->inherits("QSGLayer"))
{
+ // Since Qt 5, it is guaranteed that slots are executed in the order they
+ // are connected. The order is important here, we want to emit `updateRequested()`
+ // only after necessary adjustments:
+ connect(texture, SIGNAL(updateRequested()), this, SLOT(resetState()));
connect(texture, SIGNAL(updateRequested()), this, SLOT(adjustNormalRect()));
connect(texture, SIGNAL(updateRequested()), this, SIGNAL(updateRequested()));
}
@@ -131,6 +132,62 @@ void QSGTextureView::setRect(const QRect &rect)
}
}
+bool QSGTextureView::resetState()
+{
+ assert(m_texture); // This method must not be called when there is no target texture.
+
+ bool changeMade = false;
+
+ if (const auto newFiltering = m_texture->filtering(); filtering() != newFiltering)
+ {
+ setFiltering(newFiltering);
+ changeMade = true;
+ }
+
+ {
+ // Qt bug: source `QSGTexture` has mipmap filtering, but has no mipmaps. Depending on the graphics backend,
+ // this may cause the texture to be not rendered (OpenGL case). As a workaround, we must disable
+ // mipmap filtering here.
+
+ // Testing `QRhiTexture::flags()` with `QRhiTexture::MipMapped` would make more sense, as that is expected to
+ // actually reflect if the underlying native texture actually has mip maps. But this should be okay also as
+ // RHI stuff are still semi-public as of Qt 6.9, and private before Qt 6.6 (we are supporting Qt 6.2).
+ if (m_texture->hasMipmaps())
+ {
+ if (const auto newMipmapFiltering = m_texture->mipmapFiltering(); mipmapFiltering() != newMipmapFiltering)
+ {
+ setMipmapFiltering(newMipmapFiltering);
+ changeMade = true;
+ }
+ }
+ else if (mipmapFiltering() != QSGTexture::Filtering::None)
+ {
+ setMipmapFiltering(QSGTexture::Filtering::None);
+ changeMade = true;
+ }
+ }
+
+ if (const auto newAnisotropyLevel = m_texture->anisotropyLevel(); anisotropyLevel() != newAnisotropyLevel)
+ {
+ setAnisotropyLevel(newAnisotropyLevel);
+ changeMade = true;
+ }
+
+ if (const auto newHWrapMode = m_texture->horizontalWrapMode(); horizontalWrapMode() != newHWrapMode)
+ {
+ setHorizontalWrapMode(newHWrapMode);
+ changeMade = true;
+ }
+
+ if (const auto newVWrapMode = m_texture->verticalWrapMode(); verticalWrapMode() != newVWrapMode)
+ {
+ setHorizontalWrapMode(newVWrapMode);
+ changeMade = true;
+ }
+
+ return changeMade;
+}
+
qint64 QSGTextureView::comparisonKey() const
{
assert(m_texture);
=====================================
modules/gui/qt/util/qsgtextureview.hpp
=====================================
@@ -34,6 +34,20 @@ class QSGTextureView : public QSGDynamicTexture
private slots:
bool adjustNormalRect() const;
+public slots:
+ // Reset the view texture state to the target texture state.
+ // NOTE: When `setTexture()` is called (regardless of if the texture pointer changes), this is called implicitly.
+ // The reason for that is, some states such as mipmap filtering, is only applicable when the target texture
+ // has mipmaps. Therefore it only makes sense to reset the state when the texture changes, because we do not
+ // know if the new texture has mipmaps or not. At the same time, it is observed that `QSGTextureProvider::textureChanged()`
+ // is also emitted when the texture pointer is the same but some states change (`QQuickImage` case), so for
+ // convenience reasons this is also called when the texture pointer does not change upon `setTexture()` call,
+ // as it is expected that if a texture provider uses this class, it would connect source texture change signal
+ // to `setTexture()` here (as done in `QSGTextureViewProvider` at the moment).
+ // NOTE: This slot returns `true` if a state changes, and `false` otherwise.
+ // NOTE: This slot does not emit `updateRequested()` itself if a state changes.
+ bool resetState();
+
public:
QSGTextureView() = default;
explicit QSGTextureView(QSGTexture* texture);
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/35401cd15fa70124eccbc6f6b51d9e50011f4be1
--
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/35401cd15fa70124eccbc6f6b51d9e50011f4be1
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