}
}
+ 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[] = {
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),
DIRTY_TO_STRING(EffectReference);
DIRTY_TO_STRING(Visible);
DIRTY_TO_STRING(HideReference);
+ DIRTY_TO_STRING(PerformanceHints);
return rv;
}
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; }
EffectReference = 0x00008000,
Visible = 0x00010000,
HideReference = 0x00020000,
+ PerformanceHints = 0x00040000,
// When you add an attribute here, don't forget to update
// dirtyToString()
else
itemNode()->appendChildNode(groupNode);
groupNode->setFlag(QSGNode::ChildrenDoNotOverlap, childrenDoNotOverlap);
+ groupNode->setFlag(QSGNode::StaticSubtreeGeometry, staticSubtreeGeometry);
#ifdef QML_RUNTIME_TESTING
groupNode->description = QLatin1String("group");
#endif
#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;
}
void render();
- void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags);
+ void nodeChanged(QSGNode *node, QSGNode::DirtyState state);
void setSortFrontToBackEnabled(bool sort);
bool isSortFrontToBackEnabled() const;
, m_previousSibling(0)
, m_subtreeGeometryCount(0)
, m_nodeFlags(OwnedByParent)
- , m_flags(0)
+ , m_dirtyState(0)
{
init();
}
, m_previousSibling(0)
, m_subtreeGeometryCount(type == GeometryNodeType ? 1 : 0)
, m_nodeFlags(OwnedByParent)
- , m_flags(0)
+ , m_dirtyState(0)
{
init();
}
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));
}
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));
}
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;
}
}
*/
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;
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);
}
}
#ifdef QML_RUNTIME_TESTING
d << n->description;
#endif
- d << "dirty=" << hex << (int) n->dirtyFlags() << dec;
+ d << "dirty=" << hex << (int) n->dirtyState() << dec;
return d;
}
#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;
}
#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;
}
#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;
}
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;
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
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
};
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();
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;
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
~QSGRootNode();
private:
- void notifyNodeChange(QSGNode *node, DirtyFlags flags);
+ void notifyNodeChange(QSGNode *node, DirtyState state);
friend class QSGRenderer;
friend class QSGNode;
void QSGNodeUpdater::enterTransformNode(QSGTransformNode *t)
{
- if (t->dirtyFlags() & QSGNode::DirtyMatrix)
+ if (t->dirtyState() & QSGNode::DirtyMatrix)
++m_force_update;
#ifdef QSG_UPDATER_DEBUG
qDebug() << "leave transform:" << t;
#endif
- if (t->dirtyFlags() & QSGNode::DirtyMatrix)
+ if (t->dirtyState() & QSGNode::DirtyMatrix)
--m_force_update;
if (!t->matrix().isIdentity()) {
qDebug() << "enter clip:" << c;
#endif
- if (c->dirtyFlags() & QSGNode::DirtyClipList)
+ if (c->dirtyState() & QSGNode::DirtyClipList)
++m_force_update;
c->m_matrix = m_combined_matrix_stack.isEmpty() ? 0 : m_combined_matrix_stack.last();
qDebug() << "leave clip:" << c;
#endif
- if (c->dirtyFlags() & QSGNode::DirtyClipList)
+ if (c->dirtyState() & QSGNode::DirtyClipList)
--m_force_update;
m_current_clip = c->m_clip_list;
void QSGNodeUpdater::enterOpacityNode(QSGOpacityNode *o)
{
- if (o->dirtyFlags() & QSGNode::DirtyOpacity)
+ if (o->dirtyState() & QSGNode::DirtyOpacity)
++m_force_update;
qreal opacity = m_opacity_stack.last() * o->opacity();
qDebug() << "enter:" << n;
#endif
- if (!n->dirtyFlags() && !m_force_update)
+ if (!n->dirtyState() && !m_force_update)
return;
if (n->isSubtreeBlocked())
return;
- bool forceUpdate = n->dirtyFlags() & (QSGNode::DirtyNodeAdded | QSGNode::DirtyForceUpdate);
+ bool forceUpdate = n->dirtyState() & (QSGNode::DirtyNodeAdded | QSGNode::DirtyForceUpdate);
if (forceUpdate)
++m_force_update;
pointer.
*/
-void QSGRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags)
+void QSGRenderer::nodeChanged(QSGNode *node, QSGNode::DirtyState state)
{
- Q_UNUSED(node);
- Q_UNUSED(flags);
-
- if (flags & QSGNode::DirtyNodeAdded)
+ if (state & QSGNode::DirtyNodeAdded)
addNodesToPreprocess(node);
- if (flags & QSGNode::DirtyNodeRemoved)
+ if (state & QSGNode::DirtyNodeRemoved)
removeNodesToPreprocess(node);
+ if (state & QSGNode::DirtyUsePreprocess) {
+ if (node->flags() & QSGNode::UsePreprocess)
+ m_nodes_to_preprocess.insert(node);
+ else
+ m_nodes_to_preprocess.remove(node);
+ }
if (!m_changed_emitted && !m_is_rendering) {
// Premature overoptimization to avoid excessive signal emissions
void renderScene();
void renderScene(const QSGBindable &bindable);
- virtual void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags);
+ virtual void nodeChanged(QSGNode *node, QSGNode::DirtyState state);
virtual void materialChanged(QSGGeometryNode *node, QSGMaterial *from, QSGMaterial *to);
QSGNodeUpdater *nodeUpdater() const;
DummyRenderer(QSGRootNode *root)
: QSGRenderer(QSGContext::createDefaultContext())
, changedNode(0)
- , changedFlags(0)
+ , changedState(0)
, renderCount(0)
{
setRootNode(root);
renderingOrder = ++globalRendereringOrder;
}
- void nodeChanged(QSGNode *node, QSGNode::DirtyFlags flags) {
+ void nodeChanged(QSGNode *node, QSGNode::DirtyState state) {
changedNode = node;
- changedFlags = flags;
- QSGRenderer::nodeChanged(node, flags);
+ changedState = state;
+ QSGRenderer::nodeChanged(node, state);
}
QSGNode *changedNode;
- QSGNode::DirtyFlags changedFlags;
+ QSGNode::DirtyState changedState;
int renderCount;
int renderingOrder;
child.markDirty(QSGNode::DirtyGeometry);
QCOMPARE(&child, renderer.changedNode);
- QCOMPARE((int) renderer.changedFlags, (int) QSGNode::DirtyGeometry);
+ QCOMPARE((int) renderer.changedState, (int) QSGNode::DirtyGeometry);
}
QCOMPARE(ren1.changedNode, &child4);
QCOMPARE(ren2.changedNode, &child4);
- QCOMPARE((int) ren1.changedFlags, (int) QSGNode::DirtyGeometry);
- QCOMPARE((int) ren2.changedFlags, (int) QSGNode::DirtyGeometry);
+ QCOMPARE((int) ren1.changedState, (int) QSGNode::DirtyGeometry);
+ QCOMPARE((int) ren2.changedState, (int) QSGNode::DirtyGeometry);
}