From ec559c38c349c38785bdcc265d7e0f852249cfb4 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 31 Jul 2014 11:40:03 +0200 Subject: [PATCH] Clean up Image and ShaderEffectSource properly. Change-Id: I9e3eb5f65ea5f46d30fb7905d0f9c479da367bf5 Reviewed-by: Laszlo Agocs --- src/quick/items/qquickimage.cpp | 35 ++++++++++++++++++-- src/quick/items/qquickimage_p.h | 4 +++ src/quick/items/qquickshadereffectsource.cpp | 49 ++++++++++++++++++++++------ src/quick/items/qquickshadereffectsource_p.h | 1 + 4 files changed, 77 insertions(+), 12 deletions(-) diff --git a/src/quick/items/qquickimage.cpp b/src/quick/items/qquickimage.cpp index 5df9e63..14dc6c3 100644 --- a/src/quick/items/qquickimage.cpp +++ b/src/quick/items/qquickimage.cpp @@ -49,6 +49,7 @@ #include #include +#include QT_BEGIN_NAMESPACE @@ -100,6 +101,14 @@ QQuickImagePrivate::QQuickImagePrivate() { } +class QQuickImageCleanup : public QRunnable +{ +public: + QQuickImageCleanup(QQuickImageTextureProvider *p) : provider(p) { } + void run() Q_DECL_OVERRIDE { delete provider; } + QQuickImageTextureProvider *provider; +}; + /*! \qmltype Image \instantiates QQuickImage @@ -159,18 +168,24 @@ QQuickImagePrivate::QQuickImagePrivate() QQuickImage::QQuickImage(QQuickItem *parent) : QQuickImageBase(*(new QQuickImagePrivate), parent) { + connect(this, SIGNAL(sceneGraphInvalidated()), this, SLOT(invalidateSG())); } QQuickImage::QQuickImage(QQuickImagePrivate &dd, QQuickItem *parent) : QQuickImageBase(dd, parent) { + connect(this, SIGNAL(sceneGraphInvalidated()), this, SLOT(invalidateSG())); } QQuickImage::~QQuickImage() { Q_D(QQuickImage); - if (d->provider) - d->provider->deleteLater(); + if (QQuickWindow *w = window()) { + w->scheduleRenderJob(new QQuickImageCleanup(d->provider), QQuickWindow::AfterSynchronizingStage); + } else { + // Should have been released already in releaseResources or in invalidateSG. + Q_ASSERT(!d->provider); + } } void QQuickImagePrivate::setImage(const QImage &image) @@ -571,6 +586,22 @@ QSGTextureProvider *QQuickImage::textureProvider() const return d->provider; } +void QQuickImage::invalidateSG() +{ + Q_D(QQuickImage); + delete d->provider; + d->provider = 0; +} + +void QQuickImage::releaseResources() +{ + Q_D(QQuickImage); + if (d->provider) { + window()->scheduleRenderJob(new QQuickImageCleanup(d->provider), QQuickWindow::AfterSynchronizingStage); + d->provider = 0; + } +} + QSGNode *QQuickImage::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { Q_D(QQuickImage); diff --git a/src/quick/items/qquickimage_p.h b/src/quick/items/qquickimage_p.h index 56b064f..82ac776 100644 --- a/src/quick/items/qquickimage_p.h +++ b/src/quick/items/qquickimage_p.h @@ -102,10 +102,14 @@ Q_SIGNALS: void verticalAlignmentChanged(VAlignment alignment); Q_REVISION(1) void mipmapChanged(bool); +private Q_SLOTS: + void invalidateSG(); + protected: QQuickImage(QQuickImagePrivate &dd, QQuickItem *parent); void pixmapChange(); void updatePaintedGeometry(); + void releaseResources() Q_DECL_OVERRIDE; virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry); virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); diff --git a/src/quick/items/qquickshadereffectsource.cpp b/src/quick/items/qquickshadereffectsource.cpp index 7603495..b727c11 100644 --- a/src/quick/items/qquickshadereffectsource.cpp +++ b/src/quick/items/qquickshadereffectsource.cpp @@ -50,6 +50,7 @@ #include "qopenglframebufferobject.h" #include "qmath.h" #include +#include QT_BEGIN_NAMESPACE @@ -485,6 +486,21 @@ QImage QQuickShaderEffectTexture::toImage() const return QImage(); } +class QQuickShaderEffectSourceCleanup : public QRunnable +{ +public: + QQuickShaderEffectSourceCleanup(QQuickShaderEffectTexture *t, QQuickShaderEffectSourceTextureProvider *p) + : texture(t) + , provider(p) + {} + void run() Q_DECL_OVERRIDE { + delete texture; + delete provider; + } + QQuickShaderEffectTexture *texture; + QQuickShaderEffectSourceTextureProvider *provider; +}; + /*! \qmltype ShaderEffectSource \instantiates QQuickShaderEffectSource @@ -586,15 +602,20 @@ QQuickShaderEffectSource::QQuickShaderEffectSource(QQuickItem *parent) , m_grab(true) { setFlag(ItemHasContents); + connect(this, SIGNAL(sceneGraphInvalidated()), this, SLOT(invalidateSG())); } QQuickShaderEffectSource::~QQuickShaderEffectSource() { - if (m_texture) - m_texture->deleteLater(); - - if (m_provider) - m_provider->deleteLater(); + if (window()) { + window()->scheduleRenderJob(new QQuickShaderEffectSourceCleanup(m_texture, m_provider), + QQuickWindow::AfterSynchronizingStage); + } else { + // If we don't have a window, these should already have been + // released in invalidateSG or in releaseResrouces() + Q_ASSERT(!m_texture); + Q_ASSERT(!m_provider); + } if (m_sourceItem) { QQuickItemPrivate *sd = QQuickItemPrivate::get(m_sourceItem); @@ -967,12 +988,10 @@ static void get_wrap_mode(QQuickShaderEffectSource::WrapMode mode, QSGTexture::W void QQuickShaderEffectSource::releaseResources() { - if (m_texture) { - m_texture->deleteLater(); + if (m_texture || m_provider) { + window()->scheduleRenderJob(new QQuickShaderEffectSourceCleanup(m_texture, m_provider), + QQuickWindow::AfterSynchronizingStage); m_texture = 0; - } - if (m_provider) { - m_provider->deleteLater(); m_provider = 0; } } @@ -1064,6 +1083,16 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint return node; } +void QQuickShaderEffectSource::invalidateSG() +{ + if (m_texture) + delete m_texture; + if (m_provider) + delete m_provider; + m_texture = 0; + m_provider = 0; +} + void QQuickShaderEffectSource::itemChange(ItemChange change, const ItemChangeData &value) { if (change == QQuickItem::ItemSceneChange && m_sourceItem) { diff --git a/src/quick/items/qquickshadereffectsource_p.h b/src/quick/items/qquickshadereffectsource_p.h index efa963f..13b81ce 100644 --- a/src/quick/items/qquickshadereffectsource_p.h +++ b/src/quick/items/qquickshadereffectsource_p.h @@ -235,6 +235,7 @@ Q_SIGNALS: private Q_SLOTS: void sourceItemDestroyed(QObject *item); + void invalidateSG(); protected: virtual void releaseResources(); -- 2.7.4