diff --git a/playground/parrots/Overlay.cpp b/playground/parrots/Overlay.cpp index b9b6a760..4f33e144 100644 --- a/playground/parrots/Overlay.cpp +++ b/playground/parrots/Overlay.cpp @@ -140,6 +140,8 @@ namespace if ( rootNode == nullptr ) return nullptr; + const auto rect = overlay->subControlRect( Overlay::Panel ); + auto textureNode = static_cast< FilterNode* >( node ); if ( textureNode == nullptr ) @@ -149,22 +151,22 @@ namespace overlay, &QQuickItem::update ); textureNode = new FilterNode( texture ); + texture->setTextureNode( textureNode ); } - { - auto texture = qobject_cast< QskSceneTexture* >( textureNode->texture() ); - Q_ASSERT( texture ); + textureNode->setRect( rect ); + auto texture = qobject_cast< QskSceneTexture* >( textureNode->texture() ); + Q_ASSERT( texture ); + + if ( texture->isDirty() ) + { texture->setFiltering( overlay->smooth() ? QSGTexture::Linear : QSGTexture::Nearest ); auto finalNode = const_cast< QSGTransformNode* >( qskItemNode( overlay ) ); texture->render( rootNode, finalNode, overlay->geometry() ); - } - - { - const auto rect = overlay->subControlRect( Overlay::Panel ); - textureNode->setRect( rect ); + textureNode->markDirty( QSGNode::DirtyMaterial ); } return textureNode; diff --git a/playground/parrots/TextureFilterMaterial.cpp b/playground/parrots/TextureFilterMaterial.cpp index 7a5e67e7..dccc1905 100644 --- a/playground/parrots/TextureFilterMaterial.cpp +++ b/playground/parrots/TextureFilterMaterial.cpp @@ -39,7 +39,7 @@ namespace } void updateState( const QSGMaterialShader::RenderState& state, - QSGMaterial* newMaterial, QSGMaterial* ) override + QSGMaterial* newMaterial, QSGMaterial* oldMaterial ) override { auto p = program(); @@ -50,8 +50,22 @@ namespace p->setUniformValue( m_opacityId, state.opacity() ); auto material = static_cast< TextureFilterMaterial* >( newMaterial ); - if ( material->texture() ) - material->texture()->bind(); + + if ( auto texture = material->texture() ) + { + auto textureId = -1; + + if ( auto oldMat = static_cast< TextureFilterMaterial* >( oldMaterial ) ) + { + if ( oldMat->texture() ) + textureId = oldMat->texture()->textureId(); + } + + if ( texture->textureId() != textureId ) + texture->bind(); + else + texture->updateBindOptions(); + } } private: diff --git a/src/nodes/QskSceneTexture.cpp b/src/nodes/QskSceneTexture.cpp index 7613d333..0441ea06 100644 --- a/src/nodes/QskSceneTexture.cpp +++ b/src/nodes/QskSceneTexture.cpp @@ -49,6 +49,8 @@ namespace inline QRhiTexture* texture() const { return m_rhiTexture; } #endif + inline bool isDirty() const { return m_dirty; } + void setFinalNode( QSGTransformNode* ); void setProjection( const QRectF& ); @@ -70,6 +72,8 @@ namespace #else QRhiTexture* m_rhiTexture = nullptr; #endif + + bool m_dirty = true; }; Renderer::Renderer( QskSceneTexture* texture, QSGDefaultRenderContext* context ) @@ -148,22 +152,32 @@ namespace void Renderer::render() { qskTryBlockTrailingNodes( m_finalNode, rootNode(), true, false ); + #if 0 + static int counter = 0; + qDebug() << ++counter; QSGNodeDumper::dump( rootNode() ); #endif Inherited::render(); qskTryBlockTrailingNodes( m_finalNode, rootNode(), false, false ); + + m_dirty = false; } void Renderer::nodeChanged( QSGNode* node, QSGNode::DirtyState state ) { - // do not forward nodes that are blocked while rendering + Inherited::nodeChanged( node, state ); - const bool isTrailingNode = false; // TODO ... + /* + We want to limit updates to nodes, that are actually rendered. TODO ... - if ( !isTrailingNode ) + 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. + */ + if ( ( state != QSGNode::DirtyMaterial ) + || ( node != m_texture->textureNode() ) ) { - Inherited::nodeChanged( node, state ); + m_dirty = true; Q_EMIT m_texture->updateRequested(); } } @@ -242,6 +256,8 @@ class QskSceneTexturePrivate final : public QSGTexturePrivate Renderer* renderer = nullptr; QSGDefaultRenderContext* context = nullptr; + + const QSGGeometryNode* textureNode = nullptr; }; QskSceneTexture::QskSceneTexture( const QQuickWindow* window ) @@ -255,6 +271,16 @@ 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 ); @@ -294,6 +320,12 @@ void QskSceneTexture::render( const QSGRootNode* rootNode, d->renderer->renderScene(); } +bool QskSceneTexture::isDirty() const +{ + Q_D( const QskSceneTexture ); + return d->renderer ? d->renderer->isDirty() : true; +} + QRectF QskSceneTexture::normalizedTextureSubRect() const { return QRectF( 0, 1, 1, -1 ); diff --git a/src/nodes/QskSceneTexture.h b/src/nodes/QskSceneTexture.h index c5d89d10..39e267a5 100644 --- a/src/nodes/QskSceneTexture.h +++ b/src/nodes/QskSceneTexture.h @@ -13,6 +13,7 @@ class QskSceneTexturePrivate; class QSGRootNode; class QSGTransformNode; +class QSGGeometryNode; class QQuickWindow; class QSK_EXPORT QskSceneTexture : public QSGTexture @@ -25,6 +26,12 @@ class QSK_EXPORT QskSceneTexture : public QSGTexture QskSceneTexture( const QQuickWindow* ); ~QskSceneTexture(); +#if 1 + // to avoid recursive update, need to find a better solution + void setTextureNode( const QSGGeometryNode* ); + const QSGGeometryNode* textureNode() const; +#endif + void render( const QSGRootNode*, const QSGTransformNode*, const QRectF& ); QSize textureSize() const override; @@ -43,6 +50,8 @@ class QSK_EXPORT QskSceneTexture : public QSGTexture bool hasAlphaChannel() const override; bool hasMipmaps() const override; + bool isDirty() const; + Q_SIGNALS: void updateRequested();