diff options
| author | Inho Lee <inho.lee@qt.io> | 2025-09-15 08:58:21 +0200 |
|---|---|---|
| committer | Inho Lee <inho.lee@qt.io> | 2025-10-13 13:23:52 +0200 |
| commit | 640948c05ce2463e85d4059eea082daaea71c44f (patch) | |
| tree | ae90905c2eb5e779d90754727c51c3a20d67b1af /src/quickcontrols/material/impl/qquickmaterialripple.cpp | |
| parent | 27dc9f3b8ad2ab019400d03ac9c0e5856445ff9d (diff) | |
quickcontrols - material style: postpone updating qsgnodes
QQuickAnimatedNode uses beforeRendering and this connection
can conflict with Quick3D render prep.
Updating qsgnodes will be delayed for now to prevent
the crash.
Fixes: QTBUG-126193
Pick-to: 6.10 6.8
Change-Id: I29aa09fb6a52a4446818699bebf42eabf613c43f
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Diffstat (limited to 'src/quickcontrols/material/impl/qquickmaterialripple.cpp')
| -rw-r--r-- | src/quickcontrols/material/impl/qquickmaterialripple.cpp | 86 |
1 files changed, 63 insertions, 23 deletions
diff --git a/src/quickcontrols/material/impl/qquickmaterialripple.cpp b/src/quickcontrols/material/impl/qquickmaterialripple.cpp index 0379d41e43..647e4ccbe3 100644 --- a/src/quickcontrols/material/impl/qquickmaterialripple.cpp +++ b/src/quickcontrols/material/impl/qquickmaterialripple.cpp @@ -30,12 +30,19 @@ public: void sync(QQuickItem *item) override; private: + void updateWaveNode(); + qreal m_from = 0; qreal m_to = 0; qreal m_value = 0; + qreal m_newValue = 0; + WavePhase m_phase = WaveEnter; QPointF m_anchor; QRectF m_bounds; + + qreal m_opacity = -1.0; + qreal m_newOpacity = 1.0; }; QQuickMaterialRippleWaveNode::QQuickMaterialRippleWaveNode(QQuickMaterialRipple *ripple) @@ -50,6 +57,9 @@ QQuickMaterialRippleWaveNode::QQuickMaterialRippleWaveNode(QQuickMaterialRipple QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode(); rectNode->setAntialiasing(true); opacityNode->appendChildNode(rectNode); + + auto window = ripple->window(); + connect(window, &QQuickWindow::beforeFrameBegin, this, &QQuickMaterialRippleWaveNode::updateWaveNode, Qt::DirectConnection); } void QQuickMaterialRippleWaveNode::exit() @@ -67,29 +77,10 @@ void QQuickMaterialRippleWaveNode::updateCurrentTime(int time) if (duration() > 0) p = time / static_cast<qreal>(duration()); - m_value = m_from + (m_to - m_from) * p; - p = m_value / m_to; - - const qreal dx = (1.0 - p) * (m_anchor.x() - m_bounds.width() / 2); - const qreal dy = (1.0 - p) * (m_anchor.y() - m_bounds.height() / 2); - - QMatrix4x4 m; - m.translate(qRound((m_bounds.width() - m_value) / 2 + dx), - qRound((m_bounds.height() - m_value) / 2 + dy)); - setMatrix(m); + m_newValue = m_from + (m_to - m_from) * p; - QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild()); - Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType); - qreal opacity = 1.0; if (m_phase == WaveExit) - opacity -= static_cast<qreal>(time) / WAVE_OPACITY_DECAY_DURATION; - opacityNode->setOpacity(opacity); - - QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild()); - Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType); - rectNode->setRect(QRectF(0, 0, m_value, m_value)); - rectNode->setRadius(m_value / 2); - rectNode->update(); + m_newOpacity = 1.0 - static_cast<qreal>(time) / WAVE_OPACITY_DECAY_DURATION; } void QQuickMaterialRippleWaveNode::sync(QQuickItem *item) @@ -107,6 +98,37 @@ void QQuickMaterialRippleWaveNode::sync(QQuickItem *item) rectNode->setColor(ripple->color()); } +void QQuickMaterialRippleWaveNode::updateWaveNode() +{ + QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild()); + Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType); + if (!qFuzzyCompare(m_opacity, m_newOpacity)) { + m_opacity = m_newOpacity; + opacityNode->setOpacity(m_opacity); + } + + if (qFuzzyCompare(m_value, m_newValue)) + return; + + m_value = m_newValue; + + qreal p = m_value / m_to; + + const qreal dx = (1.0 - p) * (m_anchor.x() - m_bounds.width() / 2); + const qreal dy = (1.0 - p) * (m_anchor.y() - m_bounds.height() / 2); + + QMatrix4x4 m; + m.translate(qRound((m_bounds.width() - m_value) / 2 + dx), + qRound((m_bounds.height() - m_value) / 2 + dy)); + setMatrix(m); + + QSGInternalRectangleNode *rectNode = static_cast<QSGInternalRectangleNode *>(opacityNode->firstChild()); + Q_ASSERT(rectNode->type() == QSGNode::GeometryNodeType); + rectNode->setRect(QRectF(0, 0, m_value, m_value)); + rectNode->setRadius(m_value / 2); + rectNode->update(); +} + class QQuickMaterialRippleBackgroundNode : public QQuickAnimatedNode { Q_OBJECT @@ -118,7 +140,12 @@ public: void sync(QQuickItem *item) override; private: + void updateBackgroundNode(); + bool m_active = false; + + qreal m_opacity = -1.0; + qreal m_newOpacity = 0.0; }; QQuickMaterialRippleBackgroundNode::QQuickMaterialRippleBackgroundNode(QQuickMaterialRipple *ripple) @@ -127,13 +154,15 @@ QQuickMaterialRippleBackgroundNode::QQuickMaterialRippleBackgroundNode(QQuickMat setDuration(OPACITY_ENTER_DURATION_FAST); QSGOpacityNode *opacityNode = new QSGOpacityNode; - opacityNode->setOpacity(0.0); appendChildNode(opacityNode); QQuickItemPrivate *d = QQuickItemPrivate::get(ripple); QSGInternalRectangleNode *rectNode = d->sceneGraphContext()->createInternalRectangleNode(); rectNode->setAntialiasing(true); opacityNode->appendChildNode(rectNode); + + auto window = ripple->window(); + connect(window, &QQuickWindow::beforeFrameBegin, this, &QQuickMaterialRippleBackgroundNode::updateBackgroundNode, Qt::DirectConnection); } void QQuickMaterialRippleBackgroundNode::updateCurrentTime(int time) @@ -144,7 +173,7 @@ void QQuickMaterialRippleBackgroundNode::updateCurrentTime(int time) QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild()); Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType); - opacityNode->setOpacity(opacity); + m_newOpacity = opacity; } void QQuickMaterialRippleBackgroundNode::sync(QQuickItem *item) @@ -181,6 +210,17 @@ void QQuickMaterialRippleBackgroundNode::sync(QQuickItem *item) rectNode->update(); } +void QQuickMaterialRippleBackgroundNode::updateBackgroundNode() +{ + if (m_opacity == m_newOpacity) + return; + + m_opacity = m_newOpacity; + QSGOpacityNode *opacityNode = static_cast<QSGOpacityNode *>(firstChild()); + Q_ASSERT(opacityNode->type() == QSGNode::OpacityNodeType); + opacityNode->setOpacity(m_opacity); +} + QQuickMaterialRipple::QQuickMaterialRipple(QQuickItem *parent) : QQuickItem(parent) { |
