Fix QSGshaderEffectTexture cleanup
authorGunnar Sletta <gunnar.sletta@nokia.com>
Wed, 7 Sep 2011 09:46:12 +0000 (11:46 +0200)
committerKim M. Kalland <kim.kalland@nokia.com>
Wed, 7 Sep 2011 10:22:12 +0000 (12:22 +0200)
Because we often created it too early it did not have a QSGContext
and would thus not clean up properly, causing crashes.

Change-Id: I1f5c82c87326254885ec217aaab4f1e79d18a243
Reviewed-on: http://codereview.qt.nokia.com/4329
Reviewed-by: Kim M. Kalland <kim.kalland@nokia.com>
src/declarative/items/qsgitem_p.h
src/declarative/items/qsgshadereffectsource.cpp
src/declarative/items/qsgshadereffectsource_p.h

index 294edc0..513aba2 100644 (file)
@@ -258,7 +258,7 @@ public:
     quint32 dummy:1;
 
     QSGCanvas *canvas;
-    QSGContext *sceneGraphContext() const { return static_cast<QSGCanvasPrivate *>(QObjectPrivate::get(canvas))->context; }
+    QSGContext *sceneGraphContext() const { Q_ASSERT(canvas); return static_cast<QSGCanvasPrivate *>(QObjectPrivate::get(canvas))->context; }
 
     QSGItem *parentItem;
     QList<QSGItem *> childItems;
index bb55af5..3b09838 100644 (file)
@@ -103,7 +103,7 @@ QSGShaderEffectTexture::QSGShaderEffectTexture(QSGItem *shaderSource)
 #ifdef QSG_DEBUG_FBO_OVERLAY
     , m_debugOverlay(0)
 #endif
-    , m_context(0)
+    , m_context(QSGItemPrivate::get(shaderSource)->sceneGraphContext())
     , m_mipmap(false)
     , m_live(true)
     , m_recursive(false)
@@ -124,18 +124,6 @@ QSGShaderEffectTexture::~QSGShaderEffectTexture()
 #endif
 }
 
-void QSGShaderEffectTexture::scheduleForCleanup()
-{
-    if (m_context)
-        m_context->scheduleTextureForCleanup(this);
-    else {
-        // Never really been used, hence we can delete it right away..
-        Q_ASSERT(!m_fbo);
-        delete this;
-    }
-}
-
-
 int QSGShaderEffectTexture::textureId() const
 {
     return m_fbo ? m_fbo->texture() : 0;
@@ -265,10 +253,6 @@ void QSGShaderEffectTexture::grab()
         return;
     }
 
-    if (!m_context)
-        m_context = QSGItemPrivate::get(m_shaderSource)->sceneGraphContext();
-    Q_ASSERT(QSGItemPrivate::get(m_shaderSource)->sceneGraphContext() == m_context);
-
     if (!m_renderer) {
         m_renderer = m_context->createRenderer();
         connect(m_renderer, SIGNAL(sceneGraphChanged()), this, SLOT(markDirtyTexture()), Qt::DirectConnection);
@@ -494,6 +478,7 @@ QImage QSGShaderEffectTexture::toImage() const
 QSGShaderEffectSource::QSGShaderEffectSource(QSGItem *parent)
     : QSGItem(parent)
     , m_provider(0)
+    , m_texture(0)
     , m_wrapMode(ClampToEdge)
     , m_sourceItem(0)
     , m_textureSize(0, 0)
@@ -505,13 +490,12 @@ QSGShaderEffectSource::QSGShaderEffectSource(QSGItem *parent)
     , m_grab(true)
 {
     setFlag(ItemHasContents);
-    m_texture = new QSGShaderEffectTexture(this);
-    connect(m_texture, SIGNAL(textureChanged()), this, SLOT(update()));
 }
 
 QSGShaderEffectSource::~QSGShaderEffectSource()
 {
-    m_texture->scheduleForCleanup();
+    if (m_texture)
+        m_texture->deleteLater();
 
     if (m_provider)
         m_provider->deleteLater();
@@ -520,6 +504,21 @@ QSGShaderEffectSource::~QSGShaderEffectSource()
         QSGItemPrivate::get(m_sourceItem)->derefFromEffectItem(m_hideSource);
 }
 
+void QSGShaderEffectSource::ensureTexture()
+{
+    if (m_texture)
+        return;
+
+    Q_ASSERT_X(QSGItemPrivate::get(this)->canvas
+               && QSGItemPrivate::get(this)->sceneGraphContext()
+               && QThread::currentThread() == QSGItemPrivate::get(this)->sceneGraphContext()->thread(),
+               "QSGShaderEffectSource::ensureTexture",
+               "Cannot be used outside the rendering thread");
+
+    m_texture = new QSGShaderEffectTexture(this);
+    connect(m_texture, SIGNAL(textureChanged()), this, SLOT(update()));
+}
+
 QSGTextureProvider *QSGShaderEffectSource::textureProvider() const
 {
     if (!m_provider) {
@@ -528,8 +527,10 @@ QSGTextureProvider *QSGShaderEffectSource::textureProvider() const
                    && QSGItemPrivate::get(this)->sceneGraphContext()
                    && QThread::currentThread() == QSGItemPrivate::get(this)->sceneGraphContext()->thread(),
                    "QSGShaderEffectSource::textureProvider",
-                   "Cannot be used outside the GUI thread");
+                   "Cannot be used outside the rendering thread");
         const_cast<QSGShaderEffectSource *>(this)->m_provider = new QSGShaderEffectSourceTextureProvider();
+
+        const_cast<QSGShaderEffectSource *>(this)->ensureTexture();
         connect(m_texture, SIGNAL(textureChanged()), m_provider, SIGNAL(textureChanged()), Qt::DirectConnection);
         m_provider->sourceTexture = m_texture;
     }
@@ -829,6 +830,8 @@ QSGNode *QSGShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNod
         return 0;
     }
 
+    ensureTexture();
+
     QSGShaderEffectTexture *tex = qobject_cast<QSGShaderEffectTexture *>(m_texture);
     tex->setLive(m_live);
     tex->setItem(QSGItemPrivate::get(m_sourceItem)->itemNode());
index 77cb412..6662412 100644 (file)
@@ -116,7 +116,6 @@ public:
 
     void scheduleUpdate();
 
-    void scheduleForCleanup();
     QImage toImage() const;
 
 Q_SIGNALS:
@@ -233,6 +232,8 @@ protected:
     virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
 
 private:
+    void ensureTexture();
+
     QSGShaderEffectSourceTextureProvider *m_provider;
     QSGShaderEffectTexture *m_texture;
     WrapMode m_wrapMode;