Skip to content

Commit

Permalink
Made QSGNode flags togglable and added StaticSubtreeGeometry.
Browse files Browse the repository at this point in the history
The UsePreprocess and ChildrenDoNotOverlap flags could previously
only be set during node initialization. They can now be toggled.
This change also introduces the StaticSubtreeGeometry flag which is
meant to be used to indicate that all the nodes in the sub-tree
have static matrices and vertex data.

Change-Id: I3b182b81f7010aea636f8f654ef22dab19bc6b29
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com>
  • Loading branch information
Kim Motoyoshi Kalland authored and Qt by Nokia committed Dec 14, 2011
1 parent 5676c6c commit 9db4060
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 77 deletions.
5 changes: 5 additions & 0 deletions src/quick/items/qquickcanvas.cpp
Expand Up @@ -1610,6 +1610,11 @@ void QQuickCanvasPrivate::updateDirtyNode(QQuickItem *item)
}
}

if ((dirty & QQuickItemPrivate::PerformanceHints) && itemPriv->groupNode) {
itemPriv->groupNode->setFlag(QSGNode::ChildrenDoNotOverlap, itemPriv->childrenDoNotOverlap);
itemPriv->groupNode->setFlag(QSGNode::StaticSubtreeGeometry, itemPriv->staticSubtreeGeometry);
}

#ifndef QT_NO_DEBUG
// Check consistency.
const QSGNode *nodeChain[] = {
Expand Down
2 changes: 2 additions & 0 deletions src/quick/items/qquickitem.cpp
Expand Up @@ -2250,6 +2250,7 @@ QQuickItemPrivate::QQuickItemPrivate()
effectiveVisible(true), explicitEnable(true), effectiveEnable(true), polishScheduled(false),
inheritedLayoutMirror(false), effectiveLayoutMirror(false), isMirrorImplicit(true),
inheritMirrorFromParent(false), inheritMirrorFromItem(false), childrenDoNotOverlap(false),
staticSubtreeGeometry(false),

canvas(0), parentItem(0), sortedChildItems(&childItems),

Expand Down Expand Up @@ -3960,6 +3961,7 @@ QString QQuickItemPrivate::dirtyToString() const
DIRTY_TO_STRING(EffectReference);
DIRTY_TO_STRING(Visible);
DIRTY_TO_STRING(HideReference);
DIRTY_TO_STRING(PerformanceHints);

return rv;
}
Expand Down
3 changes: 3 additions & 0 deletions src/quick/items/qquickitem_p.h
Expand Up @@ -279,6 +279,7 @@ class Q_QUICK_EXPORT QQuickItemPrivate : public QObjectPrivate
bool inheritMirrorFromParent:1;
bool inheritMirrorFromItem:1;
bool childrenDoNotOverlap:1;
bool staticSubtreeGeometry:1;

QQuickCanvas *canvas;
QSGContext *sceneGraphContext() const { Q_ASSERT(canvas); return static_cast<QQuickCanvasPrivate *>(QObjectPrivate::get(canvas))->context; }
Expand Down Expand Up @@ -396,6 +397,7 @@ class Q_QUICK_EXPORT QQuickItemPrivate : public QObjectPrivate
EffectReference = 0x00008000,
Visible = 0x00010000,
HideReference = 0x00020000,
PerformanceHints = 0x00040000,
// When you add an attribute here, don't forget to update
// dirtyToString()

Expand Down Expand Up @@ -738,6 +740,7 @@ QSGNode *QQuickItemPrivate::childContainerNode()
else
itemNode()->appendChildNode(groupNode);
groupNode->setFlag(QSGNode::ChildrenDoNotOverlap, childrenDoNotOverlap);
groupNode->setFlag(QSGNode::StaticSubtreeGeometry, staticSubtreeGeometry);
#ifdef QML_RUNTIME_TESTING
groupNode->description = QLatin1String("group");
#endif
Expand Down
14 changes: 7 additions & 7 deletions src/quick/scenegraph/coreapi/qsgdefaultrenderer.cpp
Expand Up @@ -175,18 +175,18 @@ QSGDefaultRenderer::QSGDefaultRenderer(QSGContext *context)
#endif
}

void QSGDefaultRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags)
void QSGDefaultRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
{
QSGRenderer::nodeChanged(node, flags);
QSGRenderer::nodeChanged(node, state);

quint32 rebuildFlags = QSGNode::DirtyNodeAdded | QSGNode::DirtyNodeRemoved
| QSGNode::DirtyMaterial | QSGNode::DirtyOpacity
| QSGNode::DirtyForceUpdate;
const quint32 rebuildBits = QSGNode::DirtyNodeAdded | QSGNode::DirtyNodeRemoved
| QSGNode::DirtyMaterial | QSGNode::DirtyOpacity
| QSGNode::DirtyForceUpdate | QSGNode::DirtyChildrenDoNotOverlap;

if (flags & rebuildFlags)
if (state & rebuildBits)
m_rebuild_lists = true;

if (flags & (rebuildFlags | QSGNode::DirtyClipList))
if (state & (rebuildBits | QSGNode::DirtyClipList))
m_needs_sorting = true;
}

Expand Down
2 changes: 1 addition & 1 deletion src/quick/scenegraph/coreapi/qsgdefaultrenderer_p.h
Expand Up @@ -82,7 +82,7 @@ class QSGDefaultRenderer : public QSGRenderer

void render();

void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags);
void nodeChanged(QSGNode *node, QSGNode::DirtyState state);

void setSortFrontToBackEnabled(bool sort);
bool isSortFrontToBackEnabled() const;
Expand Down
57 changes: 35 additions & 22 deletions src/quick/scenegraph/coreapi/qsgnode.cpp
Expand Up @@ -92,7 +92,7 @@ QSGNode::QSGNode()
, m_previousSibling(0)
, m_subtreeGeometryCount(0)
, m_nodeFlags(OwnedByParent)
, m_flags(0)
, m_dirtyState(0)
{
init();
}
Expand All @@ -106,7 +106,7 @@ QSGNode::QSGNode(NodeType type)
, m_previousSibling(0)
, m_subtreeGeometryCount(type == GeometryNodeType ? 1 : 0)
, m_nodeFlags(OwnedByParent)
, m_flags(0)
, m_dirtyState(0)
{
init();
}
Expand Down Expand Up @@ -421,10 +421,15 @@ QSGNode *QSGNode::childAtIndex(int i) const

void QSGNode::setFlag(Flag f, bool enabled)
{
if (enabled)
m_nodeFlags |= f;
else
m_nodeFlags &= ~f;
if (bool(m_nodeFlags & f) == enabled)
return;
m_nodeFlags ^= f;
Q_ASSERT(int(UsePreprocess) == int(DirtyUsePreprocess));
Q_ASSERT(int(ChildrenDoNotOverlap) == int(DirtyChildrenDoNotOverlap));
Q_ASSERT(int(StaticSubtreeGeometry) == int(DirtyStaticSubtreeGeometry));
int changedFlag = f & (UsePreprocess | ChildrenDoNotOverlap | StaticSubtreeGeometry);
if (changedFlag)
markDirty(DirtyState(changedFlag));
}


Expand All @@ -437,10 +442,18 @@ void QSGNode::setFlag(Flag f, bool enabled)

void QSGNode::setFlags(Flags f, bool enabled)
{
Flags oldFlags = m_nodeFlags;
if (enabled)
m_nodeFlags |= f;
else
m_nodeFlags &= ~f;
Q_ASSERT(int(UsePreprocess) == int(DirtyUsePreprocess));
Q_ASSERT(int(ChildrenDoNotOverlap) == int(DirtyChildrenDoNotOverlap));
Q_ASSERT(int(StaticSubtreeGeometry) == int(DirtyStaticSubtreeGeometry));
int changedFlags = (oldFlags ^ m_nodeFlags)
& (UsePreprocess | ChildrenDoNotOverlap | StaticSubtreeGeometry);
if (changedFlags)
markDirty(DirtyState(changedFlags));
}


Expand All @@ -452,24 +465,24 @@ void QSGNode::setFlags(Flags f, bool enabled)
as dirty and notify all connected renderers that the has dirty states.
*/

void QSGNode::markDirty(DirtyFlags flags)
void QSGNode::markDirty(DirtyState bits)
{
m_flags |= (flags & DirtyPropagationMask);
m_dirtyState |= (bits & DirtyPropagationMask);

DirtyFlags subtreeFlags = DirtyFlags((flags & DirtyPropagationMask) << 16);
DirtyState subtreeBits = DirtyState((bits & DirtyPropagationMask) << 16);

int geometryCountDiff = 0;
if (flags & DirtyNodeAdded)
if (bits & DirtyNodeAdded)
geometryCountDiff += m_subtreeGeometryCount;
if (flags & DirtyNodeRemoved)
if (bits & DirtyNodeRemoved)
geometryCountDiff -= m_subtreeGeometryCount;

QSGNode *p = m_parent;
while (p) {
p->m_flags |= subtreeFlags;
p->m_dirtyState |= subtreeBits;
p->m_subtreeGeometryCount += geometryCountDiff;
if (p->type() == RootNodeType)
static_cast<QSGRootNode *>(p)->notifyNodeChange(this, flags);
static_cast<QSGRootNode *>(p)->notifyNodeChange(this, bits);
p = p->m_parent;
}
}
Expand Down Expand Up @@ -685,7 +698,7 @@ void QSGGeometryNode::setOpaqueMaterial(QSGMaterial *material)
*/
QSGMaterial *QSGGeometryNode::activeMaterial() const
{
Q_ASSERT_X(dirtyFlags() == 0, "QSGGeometryNode::activeMaterial()", "function assumes that all dirty states are cleaned up");
Q_ASSERT_X(dirtyState() == 0, "QSGGeometryNode::activeMaterial()", "function assumes that all dirty states are cleaned up");
if (m_opaque_material && m_opacity > 0.999)
return m_opaque_material;
return m_material;
Expand Down Expand Up @@ -908,10 +921,10 @@ QSGRootNode::~QSGRootNode()
with \a flags.
*/

void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyFlags flags)
void QSGRootNode::notifyNodeChange(QSGNode *node, DirtyState state)
{
for (int i=0; i<m_renderers.size(); ++i) {
m_renderers.at(i)->nodeChanged(node, flags);
m_renderers.at(i)->nodeChanged(node, state);
}
}

Expand Down Expand Up @@ -1138,7 +1151,7 @@ QDebug operator<<(QDebug d, const QSGGeometryNode *n)
#ifdef QML_RUNTIME_TESTING
d << n->description;
#endif
d << "dirty=" << hex << (int) n->dirtyFlags() << dec;
d << "dirty=" << hex << (int) n->dirtyState() << dec;
return d;
}

Expand All @@ -1159,7 +1172,7 @@ QDebug operator<<(QDebug d, const QSGClipNode *n)
#ifdef QML_RUNTIME_TESTING
d << n->description;
#endif
d << "dirty=" << hex << (int) n->dirtyFlags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
d << "dirty=" << hex << (int) n->dirtyState() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
return d;
}

Expand All @@ -1181,7 +1194,7 @@ QDebug operator<<(QDebug d, const QSGTransformNode *n)
#ifdef QML_RUNTIME_TESTING
d << n->description;
#endif
d << "dirty=" << hex << (int) n->dirtyFlags() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
d << "dirty=" << hex << (int) n->dirtyState() << dec << (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
d << ")";
return d;
}
Expand All @@ -1200,7 +1213,7 @@ QDebug operator<<(QDebug d, const QSGOpacityNode *n)
#ifdef QML_RUNTIME_TESTING
d << n->description;
#endif
d << "dirty=" << hex << (int) n->dirtyFlags() << dec;
d << "dirty=" << hex << (int) n->dirtyState() << dec;
d << ")";
return d;
}
Expand All @@ -1212,7 +1225,7 @@ QDebug operator<<(QDebug d, const QSGRootNode *n)
d << "QSGRootNode(null)";
return d;
}
d << "QSGRootNode" << hex << (void *) n << "dirty=" << (int) n->dirtyFlags() << dec
d << "QSGRootNode" << hex << (void *) n << "dirty=" << (int) n->dirtyState() << dec
<< (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
#ifdef QML_RUNTIME_TESTING
d << n->description;
Expand Down Expand Up @@ -1247,7 +1260,7 @@ QDebug operator<<(QDebug d, const QSGNode *n)
break;
default:
d << "QSGNode(" << hex << (void *) n << dec
<< "dirty=" << hex << (int) n->dirtyFlags()
<< "dirty=" << hex << (int) n->dirtyState()
<< "flags=" << (int) n->flags() << dec
<< (n->isSubtreeBlocked() ? "*BLOCKED*" : "");
#ifdef QML_RUNTIME_TESTING
Expand Down
55 changes: 30 additions & 25 deletions src/quick/scenegraph/coreapi/qsgnode.h
Expand Up @@ -74,30 +74,12 @@ class Q_QUICK_EXPORT QSGNode
UserNodeType = 1024
};

enum DirtyFlag {
DirtyMatrix = 0x0001,
DirtyClipList = 0x0002,
DirtyNodeAdded = 0x0004,
DirtyNodeRemoved = 0x0008,
DirtyGeometry = 0x0010,
DirtyMaterial = 0x0040,
DirtyOpacity = 0x0080,
DirtyForceUpdate = 0x0100,

DirtyPropagationMask = DirtyMatrix
| DirtyClipList
| DirtyNodeAdded
| DirtyOpacity
| DirtyForceUpdate

};
Q_DECLARE_FLAGS(DirtyFlags, DirtyFlag)

enum Flag {
// Lower 16 bites reserved for general node
OwnedByParent = 0x0001,
UsePreprocess = 0x0002,
ChildrenDoNotOverlap = 0x0004,
StaticSubtreeGeometry = 0x0008, // Subtree nodes have fixed matrix and vertex data.

// Upper 16 bits reserved for node subclasses

Expand All @@ -108,6 +90,29 @@ class Q_QUICK_EXPORT QSGNode
};
Q_DECLARE_FLAGS(Flags, Flag)

enum DirtyStateBit {
DirtyUsePreprocess = UsePreprocess,
DirtyChildrenDoNotOverlap = ChildrenDoNotOverlap,
DirtyStaticSubtreeGeometry = StaticSubtreeGeometry,

DirtyMatrix = 0x0100,
DirtyClipList = 0x0200,
DirtyNodeAdded = 0x0400,
DirtyNodeRemoved = 0x0800,
DirtyGeometry = 0x1000,
DirtyMaterial = 0x2000,
DirtyOpacity = 0x4000,
DirtyForceUpdate = 0x8000,

DirtyPropagationMask = DirtyMatrix
| DirtyClipList
| DirtyNodeAdded
| DirtyOpacity
| DirtyForceUpdate

};
Q_DECLARE_FLAGS(DirtyState, DirtyStateBit)

QSGNode();
virtual ~QSGNode();

Expand All @@ -129,9 +134,9 @@ class Q_QUICK_EXPORT QSGNode

inline NodeType type() const { return m_type; }

void clearDirty() { m_flags = 0; }
void markDirty(DirtyFlags flags);
DirtyFlags dirtyFlags() const { return m_flags; }
void clearDirty() { m_dirtyState = 0; }
void markDirty(DirtyState bits);
DirtyState dirtyState() const { return m_dirtyState; }

virtual bool isSubtreeBlocked() const;

Expand Down Expand Up @@ -163,12 +168,12 @@ class Q_QUICK_EXPORT QSGNode
int m_subtreeGeometryCount;

Flags m_nodeFlags;
DirtyFlags m_flags;
DirtyState m_dirtyState;

void *m_reserved;
};

Q_DECLARE_OPERATORS_FOR_FLAGS(QSGNode::DirtyFlags)
Q_DECLARE_OPERATORS_FOR_FLAGS(QSGNode::DirtyState)
Q_DECLARE_OPERATORS_FOR_FLAGS(QSGNode::Flags)

class Q_QUICK_EXPORT QSGBasicGeometryNode : public QSGNode
Expand Down Expand Up @@ -284,7 +289,7 @@ class Q_QUICK_EXPORT QSGRootNode : public QSGNode
~QSGRootNode();

private:
void notifyNodeChange(QSGNode *node, DirtyFlags flags);
void notifyNodeChange(QSGNode *node, DirtyState state);

friend class QSGRenderer;
friend class QSGNode;
Expand Down

0 comments on commit 9db4060

Please sign in to comment.