From 486d367e8086e63f51707e78c07ef77fa6240f0a Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Tue, 15 Oct 2013 09:12:09 +0200 Subject: Prevent badly formed texture nodes in the scene graph. A texture based node without a valid texture is not allowed, as the material and the renderer will only tolerate well-formed nodes. If a node is missing any part of its material state it should not be in the scene graph in the first place. Because of an "optimization" in QSGDefaultImageNode::setTexture and QSGSimpleTextureNode::setTexture, we must temporarily set the texture to 0 to ensure that it gets updated properly. This temporarily puts the node into an invalid state which can lead to crashes when QSGNode::markDirty() reaches the renderer. Task-number: QTBUG-34062 Change-Id: Ic1735c9b974b90b3684262de9589133c961bac6e Reviewed-by: Laszlo Agocs --- src/quick/items/qquickborderimage.cpp | 8 ++++++-- src/quick/items/qquickimage.cpp | 1 - src/quick/scenegraph/qsgdefaultimagenode.cpp | 8 +++----- src/quick/scenegraph/util/qsgsimpletexturenode.cpp | 3 +-- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index 3cbcf1937f..9fc9752707 100644 --- a/src/quick/items/qquickborderimage.cpp +++ b/src/quick/items/qquickborderimage.cpp @@ -560,10 +560,14 @@ QSGNode *QQuickBorderImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat QSGImageNode *node = static_cast(oldNode); - if (!node) + bool updatePixmap = d->pixmapChanged; + if (!node) { node = d->sceneGraphContext()->createImageNode(); + updatePixmap = true; + } - node->setTexture(texture); + if (updatePixmap) + node->setTexture(texture); // Don't implicitly create the scalegrid in the rendering thread... QRectF innerSourceRect(0, 0, 1, 1); diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index 3a8fd99a66..d6be13f3c0 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -666,7 +666,6 @@ QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) if (d->pixmapChanged) { // force update the texture in the node to trigger reconstruction of // geometry and the likes when a atlas segment has changed. - node->setTexture(0); if (texture->isAtlasTexture() && (hWrap == QSGTexture::Repeat || vWrap == QSGTexture::Repeat)) node->setTexture(texture->removedFromAtlas()); else diff --git a/src/quick/scenegraph/qsgdefaultimagenode.cpp b/src/quick/scenegraph/qsgdefaultimagenode.cpp index 349a92ac7f..11d0e5dbeb 100644 --- a/src/quick/scenegraph/qsgdefaultimagenode.cpp +++ b/src/quick/scenegraph/qsgdefaultimagenode.cpp @@ -298,15 +298,13 @@ void QSGDefaultImageNode::setHorizontalWrapMode(QSGTexture::WrapMode wrapMode) void QSGDefaultImageNode::setTexture(QSGTexture *texture) { - if (texture == m_material.texture()) - return; + Q_ASSERT(texture); m_material.setTexture(texture); m_materialO.setTexture(texture); m_smoothMaterial.setTexture(texture); - // Texture cleanup - if (texture) - m_material.setFlag(QSGMaterial::Blending, texture->hasAlphaChannel()); + m_material.setFlag(QSGMaterial::Blending, texture->hasAlphaChannel()); + markDirty(DirtyMaterial); // Because the texture can be a different part of the atlas, we need to update it... diff --git a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp index 5d9946a37b..fc1d6cecbc 100644 --- a/src/quick/scenegraph/util/qsgsimpletexturenode.cpp +++ b/src/quick/scenegraph/util/qsgsimpletexturenode.cpp @@ -173,8 +173,7 @@ QRectF QSGSimpleTextureNode::rect() const */ void QSGSimpleTextureNode::setTexture(QSGTexture *texture) { - if (m_material.texture() == texture) - return; + Q_ASSERT(texture); m_material.setTexture(texture); m_opaque_material.setTexture(texture); Q_D(QSGSimpleTextureNode); -- cgit v1.2.3