From dc1f843c89ca233783771c747380ab96d63e20d8 Mon Sep 17 00:00:00 2001 From: Martin Andersson Date: Thu, 17 Nov 2022 14:37:05 +0100 Subject: Handle nullptr returned from the shader manager Sometimes the shader manager returns a nullptr when fetching the shader from a handle, so the return value needs to be checked before it is accessed. Change-Id: Ia021cd8f22ceb2626a7a2734b7e346fbcc8e0301 Reviewed-by: Paul Lemire (cherry picked from commit bffdaabaa5cd9d7fdc64e4124817b504319708e1) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/renderers/opengl/renderer/renderer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/renderers/opengl/renderer/renderer.cpp b/src/plugins/renderers/opengl/renderer/renderer.cpp index d8d24204d..7dcbbf184 100644 --- a/src/plugins/renderers/opengl/renderer/renderer.cpp +++ b/src/plugins/renderers/opengl/renderer/renderer.cpp @@ -1180,6 +1180,9 @@ void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager) const std::vector &activeShaders = m_nodesManager->shaderManager()->activeHandles(); for (const HShader &handle :activeShaders) { Shader *s = m_nodesManager->shaderManager()->data(handle); + if (!s) + continue; + if (s->requiresFrontendSync()) { QShaderProgram *frontend = static_cast(manager->lookupNode(s->peerId())); // Could happen as a backend shader might live beyong the frontend -- cgit v1.2.3 From 7671dec2f30b94f62b52f7490f1496713b1ed589 Mon Sep 17 00:00:00 2001 From: Tarja Sundqvist Date: Thu, 22 Dec 2022 11:11:29 +0200 Subject: Bump version to 5.15.13 Change-Id: I52fedcbdeff645e4958a19d786402865a6b54f68 Reviewed-by: Tarja Sundqvist --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index 8ece08892..74ed94e7c 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -6,4 +6,4 @@ load(qt_build_config) DEFINES += QT_NO_FOREACH DEFINES += QT_NO_JAVA_STYLE_ITERATORS -MODULE_VERSION = 5.15.12 +MODULE_VERSION = 5.15.13 -- cgit v1.2.3 From a7e1118103b367e4e5738104afdc7885536c7a1b Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 10 Feb 2023 06:52:03 +0100 Subject: QPaintedTextureImage: fill image with transparency by default Avoids having junk in the texture on the first paint call if not filling a rectangle with a QPainter. Change-Id: Icb65b6f994a9edea5132a2c54406fa0dd817bcb2 Reviewed-by: Mike Krus (cherry picked from commit 20d36f07fa7815fb7a05018c93602932e600397b) Reviewed-by: Qt Cherry-pick Bot Reviewed-by: Paul Lemire --- src/render/texture/qpaintedtextureimage.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/render/texture/qpaintedtextureimage.cpp b/src/render/texture/qpaintedtextureimage.cpp index c03588886..3c64b3bb4 100644 --- a/src/render/texture/qpaintedtextureimage.cpp +++ b/src/render/texture/qpaintedtextureimage.cpp @@ -87,6 +87,7 @@ void QPaintedTextureImagePrivate::repaint() { m_image.reset(new QImage(m_imageSize, QImage::Format_RGBA8888)); m_image->setDevicePixelRatio(m_devicePixelRatio); + m_image->fill(Qt::transparent); } QPainter painter(m_image.data()); -- cgit v1.2.3 From 9f2d212416c3c718a5661a09438fb413f9cc53b6 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Fri, 10 Feb 2023 09:47:50 +0100 Subject: QText2DEntity: fix QTextureAtlas parenting that could lead to crashes We rely on a DistanceFieldFont object to manage QTextureAtlas that hold the glyphs. The DistanceFieldFont/QTextureAtlas are supposed to be parented by the scene root to ensure that a QTextureAtlas lives as long as possible. DistanceFieldFont/QTextureAtlas are stored in a cache global to the scene to minimize the use of resources. When adding text elements, we can reuse atlases since the cache is global to the scene and only destroy an atlas (and remove it from the cache) when we know no more glyphs are referencing it. However we were mistakenly passing a null parenty to DistanceFieldFont instace of the scene root. This resulted on the QTextureAtlas not being parented by the scene root but rather by the first DistanceFieldRenderer to use the atlas. This meants that if the DistanceFieldRenderer were to be destroyed, so would the atlas (yet it would still be referenced by the glyph cache leading to crashes). Change-Id: Id84f6a651b162a4bb3c571b11388fd2429b231de Reviewed-by: Mike Krus (cherry picked from commit b1a135c547f38db0b2ce6b7bc4c4cccc43ef87d3) Reviewed-by: Paul Lemire --- src/extras/text/qdistancefieldglyphcache.cpp | 23 ++++++++++++++-------- src/extras/text/qtext2dentity.cpp | 3 ++- .../extras/qtext2dentity/tst_qtext2dentity.cpp | 2 +- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/extras/text/qdistancefieldglyphcache.cpp b/src/extras/text/qdistancefieldglyphcache.cpp index a65e7fc63..85591e680 100644 --- a/src/extras/text/qdistancefieldglyphcache.cpp +++ b/src/extras/text/qdistancefieldglyphcache.cpp @@ -161,6 +161,7 @@ DistanceFieldFont::DistanceFieldFont(const QRawFont &font, bool doubleRes, Qt3DC , m_doubleGlyphResolution(doubleRes) , m_parentNode(parent) { + Q_ASSERT(m_parentNode); } DistanceFieldFont::~DistanceFieldFont() @@ -197,13 +198,14 @@ StoredGlyph DistanceFieldFont::refGlyph(quint32 glyph) // scenarios const int size = m_doubleGlyphResolution ? 512 : 256; - QTextureAtlas *atlas = new QTextureAtlas(m_parentNode); + QTextureAtlas *atlas = new QTextureAtlas(); atlas->setWidth(size); atlas->setHeight(size); atlas->setFormat(Qt3DRender::QAbstractTexture::R8_UNorm); atlas->setPixelFormat(QOpenGLTexture::Red); atlas->setMinificationFilter(Qt3DRender::QAbstractTexture::Linear); atlas->setMagnificationFilter(Qt3DRender::QAbstractTexture::Linear); + atlas->setParent(m_parentNode); m_atlasses << atlas; if (!storedGlyph.addToTextureAtlas(atlas)) @@ -236,7 +238,12 @@ void DistanceFieldFont::derefGlyph(quint32 glyph) Q_ASSERT(m_atlasses.contains(atlas)); m_atlasses.removeAll(atlas); - delete atlas; + + // This function might have been called as a result of destroying + // the scene root which traverses the entire scene tree. Calling + // delete on the atlas here could lead to dangling pointers in the + // least of children being traversed for destruction. + atlas->deleteLater(); } m_glyphs.erase(it); @@ -287,7 +294,8 @@ DistanceFieldFont* QDistanceFieldGlyphCache::getOrCreateDistanceFieldFont(const // create new font cache // we set the parent node to nullptr, since the parent node of QTextureAtlasses // will be set when we pass them to QText2DMaterial later - DistanceFieldFont *dff = new DistanceFieldFont(actualFont, useDoubleRes, nullptr); + Q_ASSERT(m_rootNode); + DistanceFieldFont *dff = new DistanceFieldFont(actualFont, useDoubleRes, m_rootNode); m_fonts.insert(key, dff); return dff; } @@ -324,11 +332,10 @@ QDistanceFieldGlyphCache::Glyph refAndGetGlyph(DistanceFieldFont *dff, quint32 g if (dff) { const auto entry = dff->refGlyph(glyph); - if (entry.atlas()) { - ret.glyphPathBoundingRect = entry.glyphPathBoundingRect(); - ret.texCoords = entry.texCoords(); - ret.texture = entry.atlas(); - } + Q_ASSERT(entry.atlas()); + ret.glyphPathBoundingRect = entry.glyphPathBoundingRect(); + ret.texCoords = entry.texCoords(); + ret.texture = entry.atlas(); } return ret; diff --git a/src/extras/text/qtext2dentity.cpp b/src/extras/text/qtext2dentity.cpp index 59e8284e1..e3d3dad2e 100644 --- a/src/extras/text/qtext2dentity.cpp +++ b/src/extras/text/qtext2dentity.cpp @@ -304,8 +304,9 @@ void QText2DEntityPrivate::setCurrentGlyphRuns(const QVector &runs) delete m_renderers.takeLast(); while (m_renderers.size() < renderData.size()) { - DistanceFieldTextRenderer *renderer = new DistanceFieldTextRenderer(q_func()); + DistanceFieldTextRenderer *renderer = new DistanceFieldTextRenderer(); renderer->setColor(m_color); + renderer->setParent(q_func()); m_renderers << renderer; } diff --git a/tests/auto/extras/qtext2dentity/tst_qtext2dentity.cpp b/tests/auto/extras/qtext2dentity/tst_qtext2dentity.cpp index 6fcc2e637..35e241839 100644 --- a/tests/auto/extras/qtext2dentity/tst_qtext2dentity.cpp +++ b/tests/auto/extras/qtext2dentity/tst_qtext2dentity.cpp @@ -90,7 +90,7 @@ void tst_qtext2dentity::checkChangeArbiter() auto atlases = lookupNodeByClassName(rootEntity.data(), "Qt3DExtras::QTextureAtlas"); QVERIFY(atlases.length() == 1); auto atlas = atlases[0]; - QTRY_VERIFY(Qt3DCore::QNodePrivate::get(atlas)->m_changeArbiter); + QVERIFY(Qt3DCore::QNodePrivate::get(atlas)->m_changeArbiter); #endif } -- cgit v1.2.3