Skip to content

Commit

Permalink
Don't re-parent ShaderEffect source items.
Browse files Browse the repository at this point in the history
ShaderEffect and ShaderEffectSource used to set themselves as
parent of and hide source items that don't already have a parent.
This was done in order to make sure the source items got a canvas.
This patch sets the canvas of the source items without re-parenting.

Task-number: QTBUG-23069
Change-Id: I24d56e6eb970590bca3adff7a61459d25e4983a0
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
  • Loading branch information
Kim Motoyoshi Kalland authored and Qt by Nokia committed Jan 2, 2012
1 parent 27a497b commit 6aa535e
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 21 deletions.
4 changes: 3 additions & 1 deletion src/quick/items/qquickcanvas.cpp
Expand Up @@ -1415,8 +1415,10 @@ void QQuickCanvasPrivate::cleanupNodesOnShutdown(QQuickItem *item)
void QQuickCanvasPrivate::cleanupNodesOnShutdown()
{
cleanupNodes();

cleanupNodesOnShutdown(rootItem);
QSet<QQuickItem *>::const_iterator it = parentlessItems.begin();
for (; it != parentlessItems.end(); ++it)
cleanupNodesOnShutdown(*it);
}

void QQuickCanvasPrivate::updateDirtyNodes()
Expand Down
1 change: 1 addition & 0 deletions src/quick/items/qquickcanvas_p.h
Expand Up @@ -107,6 +107,7 @@ class QQuickCanvasPrivate : public QWindowPrivate
void initRootItem();//Currently only used if items added in QML

QQuickRootItem *rootItem;
QSet<QQuickItem *> parentlessItems;
QDeclarativeListProperty<QObject> data();

QQuickItem *activeFocusItem;
Expand Down
7 changes: 7 additions & 0 deletions src/quick/items/qquickitem.cpp
Expand Up @@ -1892,6 +1892,8 @@ void QQuickItem::setParentItem(QQuickItem *parentItem)
QQuickCanvasPrivate::DontChangeFocusProperty);

op->removeChild(this);
} else if (d->canvas) {
QQuickCanvasPrivate::get(d->canvas)->parentlessItems.remove(this);
}

d->parentItem = parentItem;
Expand Down Expand Up @@ -2119,6 +2121,8 @@ void QQuickItemPrivate::initCanvas(InitializationState *state, QQuickCanvas *c)
c->hoverItems.removeAll(q);
if (itemNodeInstance)
c->cleanup(itemNodeInstance);
if (!parentItem)
c->parentlessItems.remove(q);
}

canvas = c;
Expand All @@ -2142,6 +2146,9 @@ void QQuickItemPrivate::initCanvas(InitializationState *state, QQuickCanvas *c)
childState = &_dummy;
}

if (!parentItem && canvas)
QQuickCanvasPrivate::get(canvas)->parentlessItems.insert(q);

for (int ii = 0; ii < childItems.count(); ++ii) {
QQuickItem *child = childItems.at(ii);
QQuickItemPrivate::get(child)->initCanvas(childState, c);
Expand Down
39 changes: 28 additions & 11 deletions src/quick/items/qquickshadereffect.cpp
Expand Up @@ -388,14 +388,17 @@ void QQuickShaderEffect::setSource(const QVariant &var, int index)

source.sourceObject = item;


// TODO: Find better solution.
// 'item' needs a canvas to get a scenegraph node.
// The easiest way to make sure it gets a canvas is to
// make it a part of the same item tree as 'this'.
if (item && item->parentItem() == 0) {
item->setParentItem(this);
item->setVisible(false);
if (item) {
QQuickItemPrivate *d = QQuickItemPrivate::get(item);
// 'item' needs a canvas to get a scene graph node. It usually gets one through its
// parent, but if the source item is "inline" rather than a reference -- i.e.
// "property variant source: Image { }" instead of "property variant source: foo" -- it
// will not get a parent. In those cases, 'item' should get the canvas from 'this'.
if (!d->parentItem && canvas() && !d->canvas) {
QQuickItemPrivate::InitializationState initState;
initState.clear();
d->initCanvas(&initState, canvas());
}
}
}

Expand Down Expand Up @@ -454,9 +457,6 @@ void QQuickShaderEffect::reset()
for (int i = 0; i < m_sources.size(); ++i) {
const SourceData &source = m_sources.at(i);
delete source.mapper;
QQuickItem *item = qobject_cast<QQuickItem *>(source.sourceObject);
if (item && item->parentItem() == this)
item->setParentItem(0);
}
m_sources.clear();

Expand Down Expand Up @@ -760,4 +760,21 @@ QSGNode *QQuickShaderEffect::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
return node;
}

void QQuickShaderEffect::itemChange(ItemChange change, const ItemChangeData &value)
{
if (change == QQuickItem::ItemSceneChange) {
// See comment in QQuickShaderEffect::setSource().
for (int i = 0; i < m_sources.size(); ++i) {
QQuickItemPrivate *d = QQuickItemPrivate::get(m_sources.at(i).sourceObject);
if (!d->parentItem && value.canvas != d->canvas) {
QQuickItemPrivate::InitializationState initState;
initState.clear();
d->initCanvas(&initState, value.canvas);
}
}
}
QQuickItem::itemChange(change, value);
}


QT_END_NAMESPACE
1 change: 1 addition & 0 deletions src/quick/items/qquickshadereffect_p.h
Expand Up @@ -110,6 +110,7 @@ class Q_AUTOTEST_EXPORT QQuickShaderEffect : public QQuickItem
protected:
virtual void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry);
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);
virtual void itemChange(ItemChange change, const ItemChangeData &value);

private Q_SLOTS:
void changeSource(int index);
Expand Down
34 changes: 25 additions & 9 deletions src/quick/items/qquickshadereffectsource.cpp
Expand Up @@ -601,16 +601,18 @@ void QQuickShaderEffectSource::setSourceItem(QQuickItem *item)
d->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
}
m_sourceItem = item;
if (m_sourceItem) {
// TODO: Find better solution.
// 'm_sourceItem' needs a canvas to get a scenegraph node.
// The easiest way to make sure it gets a canvas is to
// make it a part of the same item tree as 'this'.
if (m_sourceItem->parentItem() == 0) {
m_sourceItem->setParentItem(this);
m_sourceItem->setVisible(false);

if (item) {
QQuickItemPrivate *d = QQuickItemPrivate::get(item);
// 'item' needs a canvas to get a scene graph node. It usually gets one through its
// parent, but if the source item is "inline" rather than a reference -- i.e.
// "sourceItem: Item { }" instead of "sourceItem: foo" -- it will not get a parent.
// In those cases, 'item' should get the canvas from 'this'.
if (!d->parentItem && canvas() && !d->canvas) {
QQuickItemPrivate::InitializationState initState;
initState.clear();
d->initCanvas(&initState, canvas());
}
QQuickItemPrivate *d = QQuickItemPrivate::get(m_sourceItem);
d->refFromEffectItem(m_hideSource);
d->addItemChangeListener(this, QQuickItemPrivate::Geometry);
}
Expand Down Expand Up @@ -918,4 +920,18 @@ QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaint
return node;
}

void QQuickShaderEffectSource::itemChange(ItemChange change, const ItemChangeData &value)
{
if (change == QQuickItem::ItemSceneChange && m_sourceItem) {
// See comment in QQuickShaderEffectSource::setSourceItem().
QQuickItemPrivate *d = QQuickItemPrivate::get(m_sourceItem);
if (!d->parentItem && value.canvas != d->canvas) {
QQuickItemPrivate::InitializationState initState;
initState.clear();
d->initCanvas(&initState, value.canvas);
}
}
QQuickItem::itemChange(change, value);
}

QT_END_NAMESPACE
1 change: 1 addition & 0 deletions src/quick/items/qquickshadereffectsource_p.h
Expand Up @@ -232,6 +232,7 @@ class Q_QUICK_EXPORT QQuickShaderEffectSource : public QQuickItem, public QQuick
virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *);

virtual void itemGeometryChanged(QQuickItem *item, const QRectF &newRect, const QRectF &oldRect);
virtual void itemChange(ItemChange change, const ItemChangeData &value);

private:
void ensureTexture();
Expand Down

0 comments on commit 6aa535e

Please sign in to comment.