diff --git a/playground/parrots/Overlay.cpp b/playground/parrots/Overlay.cpp index 4f02563e..b6d0f9a7 100644 --- a/playground/parrots/Overlay.cpp +++ b/playground/parrots/Overlay.cpp @@ -152,7 +152,6 @@ namespace const bool useRhi = qskRenderingHardwareInterface( window ); textureNode = new FilterNode( useRhi, texture ); - texture->setTextureNode( textureNode ); } auto texture = qobject_cast< QskSceneTexture* >( textureNode->texture() ); diff --git a/src/nodes/QskSceneTexture.cpp b/src/nodes/QskSceneTexture.cpp index 7252a170..4ec93575 100644 --- a/src/nodes/QskSceneTexture.cpp +++ b/src/nodes/QskSceneTexture.cpp @@ -29,6 +29,26 @@ QSK_QT_PRIVATE_END #include #endif +static int qskRenderOrderCompare( const QSGNode* rootNode, + const QSGNode* node1, const QSGNode* node2 ) +{ + if ( rootNode == node1 ) + return 1; + + if ( rootNode == node2 ) + return -1; + + for ( auto node = rootNode->firstChild(); + node != nullptr; node = node->nextSibling() ) + { + const auto ret = qskRenderOrderCompare( node, node1, node2 ); + if ( ret ) + return ret; + } + + return 0; +} + namespace { #if QT_VERSION >= QT_VERSION_CHECK( 6, 0, 0 ) @@ -84,6 +104,7 @@ namespace private: void createTarget( const QSize& ); void clearTarget(); + void markDirty(); QSGTransformNode* m_finalNode = nullptr; QskSceneTexture* m_texture = nullptr; @@ -114,6 +135,9 @@ namespace , m_texture( texture ) { setClearColor( Qt::transparent ); + + connect( this, &QSGRenderer::sceneGraphChanged, + this, &Renderer::markDirty ); } Renderer::~Renderer() @@ -126,6 +150,7 @@ namespace if ( node != m_finalNode ) { m_finalNode = node; + markDirty(); } } @@ -205,16 +230,25 @@ namespace void Renderer::nodeChanged( QSGNode* node, QSGNode::DirtyState state ) { - Inherited::nodeChanged( node, state ); - /* - We want to limit updates to nodes, that are actually rendered. TODO ... + No need to update the texture for changes of nodes behind + the final node. - In any case we need to block update requests, when the textureNode reports - that it has been updated by us to the renderer of the window. + Unfortunately QQuickWindow does not update the scene graph in + rendering order and we might be called for relevant nodes after + the texture has already been updated. In these situations we + update the texture twice. Not so good ... */ - if ( ( state != QSGNode::DirtyMaterial ) - || ( node != m_texture->textureNode() ) ) + if ( qskRenderOrderCompare( rootNode(), node, m_finalNode ) > 0 ) + { + // triggering QSGRenderer::sceneGraphChanged signals + Inherited::nodeChanged( node, state ); + } + } + + void Renderer::markDirty() + { + if ( !m_dirty ) { m_dirty = true; Q_EMIT m_texture->updateRequested(); @@ -352,8 +386,6 @@ class QskSceneTexturePrivate final : public QSGTexturePrivate Renderer* renderer = nullptr; QSGDefaultRenderContext* context = nullptr; - - const QSGGeometryNode* textureNode = nullptr; }; QskSceneTexture::QskSceneTexture( const QQuickWindow* window ) @@ -367,16 +399,6 @@ QskSceneTexture::~QskSceneTexture() delete d_func()->renderer; } -void QskSceneTexture::setTextureNode( const QSGGeometryNode* node ) -{ - d_func()->textureNode = node; -} - -const QSGGeometryNode* QskSceneTexture::textureNode() const -{ - return d_func()->textureNode; -} - QSize QskSceneTexture::textureSize() const { Q_D( const QskSceneTexture ); diff --git a/src/nodes/QskSceneTexture.h b/src/nodes/QskSceneTexture.h index 56acdb3e..eff6727f 100644 --- a/src/nodes/QskSceneTexture.h +++ b/src/nodes/QskSceneTexture.h @@ -13,7 +13,6 @@ class QskSceneTexturePrivate; class QSGRootNode; class QSGTransformNode; -class QSGGeometryNode; class QQuickWindow; class QSK_EXPORT QskSceneTexture : public QSGTexture @@ -26,12 +25,6 @@ class QSK_EXPORT QskSceneTexture : public QSGTexture QskSceneTexture( const QQuickWindow* ); ~QskSceneTexture(); -#if 1 - // to avoid recursive update - need to find a better solution TODO - void setTextureNode( const QSGGeometryNode* ); - const QSGGeometryNode* textureNode() const; -#endif - void render( const QSGRootNode*, const QSGTransformNode*, const QRectF& ); QSize textureSize() const override;