Reduce QQuickItemPrivate memory usage
- Avoid mixed type bitfields: There are compilers which generally support bitfields, but will not combine members if the type is different. Requires explicitly casting bitfield members to bool in a few places to avoid ambiguous overloads. - Move all containment mask members into extraData: extraData will be allocated anyway to store the contains meta-method, so we might as well move the mask pointer there. - Do not store quickMask separately; instead, cast mask to QQuickItem on demand. qobject_cast<QQuickItem *> is fast, as it only has to check a single flag. - Do not store a QMetaMethod for the mask's contains method. Instead store only the index, and retrieve the metaObject on demand. Change-Id: Ib2120c3b01ea037eb17c6c903a2977c38cd6c40c Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
parent
b51ad14bc6
commit
3edebbb764
|
@ -6373,7 +6373,7 @@ bool QQuickItemPrivate::setEffectiveVisibleRecur(bool newEffectiveVisible)
|
|||
for (int ii = 0; ii < childItems.count(); ++ii)
|
||||
childVisibilityChanged |= QQuickItemPrivate::get(childItems.at(ii))->setEffectiveVisibleRecur(newEffectiveVisible);
|
||||
|
||||
itemChange(QQuickItem::ItemVisibleHasChanged, effectiveVisible);
|
||||
itemChange(QQuickItem::ItemVisibleHasChanged, bool(effectiveVisible));
|
||||
#if QT_CONFIG(accessibility)
|
||||
if (isAccessible) {
|
||||
QAccessibleEvent ev(q, effectiveVisible ? QAccessible::ObjectShow : QAccessible::ObjectHide);
|
||||
|
@ -6432,7 +6432,7 @@ void QQuickItemPrivate::setEffectiveEnableRecur(QQuickItem *scope, bool newEffec
|
|||
QQuickDeliveryAgentPrivate::DontChangeSubFocusItem);
|
||||
}
|
||||
|
||||
itemChange(QQuickItem::ItemEnabledHasChanged, effectiveEnable);
|
||||
itemChange(QQuickItem::ItemEnabledHasChanged, bool(effectiveEnable));
|
||||
emit q->enabledChanged();
|
||||
}
|
||||
|
||||
|
@ -6764,7 +6764,7 @@ void QQuickItem::setAntialiasing(bool aa)
|
|||
d->antialiasing = aa;
|
||||
d->dirty(QQuickItemPrivate::Antialiasing);
|
||||
|
||||
d->itemChange(ItemAntialiasingHasChanged, d->antialiasing);
|
||||
d->itemChange(ItemAntialiasingHasChanged, bool(d->antialiasing));
|
||||
|
||||
emit antialiasingChanged(antialiasing());
|
||||
}
|
||||
|
@ -8217,12 +8217,13 @@ void QQuickItem::setKeepTouchGrab(bool keep)
|
|||
bool QQuickItem::contains(const QPointF &point) const
|
||||
{
|
||||
Q_D(const QQuickItem);
|
||||
if (d->mask) {
|
||||
if (d->quickMask)
|
||||
return d->quickMask->contains(point - d->quickMask->position());
|
||||
if (d->extra.isAllocated() && d->extra->mask) {
|
||||
if (auto quickMask = qobject_cast<QQuickItem *>(d->extra->mask))
|
||||
return quickMask->contains(point - quickMask->position());
|
||||
|
||||
bool res = false;
|
||||
d->extra->maskContains.invoke(d->mask,
|
||||
QMetaMethod maskContains = d->extra->mask->metaObject()->method(d->extra->maskContainsIndex);
|
||||
maskContains.invoke(d->extra->mask,
|
||||
Qt::DirectConnection,
|
||||
Q_RETURN_ARG(bool, res),
|
||||
Q_ARG(QPointF, point));
|
||||
|
@ -8300,33 +8301,44 @@ bool QQuickItem::contains(const QPointF &point) const
|
|||
QObject *QQuickItem::containmentMask() const
|
||||
{
|
||||
Q_D(const QQuickItem);
|
||||
return d->mask.data();
|
||||
if (!d->extra.isAllocated())
|
||||
return nullptr;
|
||||
return d->extra->mask.data();
|
||||
}
|
||||
|
||||
void QQuickItem::setContainmentMask(QObject *mask)
|
||||
{
|
||||
Q_D(QQuickItem);
|
||||
const bool extraDataExists = d->extra.isAllocated();
|
||||
// an Item can't mask itself (to prevent infinite loop in contains())
|
||||
if (d->mask.data() == mask || mask == static_cast<QObject *>(this))
|
||||
if (mask == static_cast<QObject *>(this))
|
||||
return;
|
||||
// mask is null, and we had no mask
|
||||
if (!extraDataExists && !mask)
|
||||
return;
|
||||
// mask is non-null and the same
|
||||
if (extraDataExists && d->extra->mask == mask)
|
||||
return;
|
||||
|
||||
QQuickItem *quickMask = qobject_cast<QQuickItem *>(d->mask);
|
||||
QQuickItem *quickMask = d->extra.isAllocated() ? qobject_cast<QQuickItem *>(d->extra->mask)
|
||||
: nullptr;
|
||||
if (quickMask) {
|
||||
QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(quickMask);
|
||||
maskPrivate->registerAsContainmentMask(this, false); // removed from use as my mask
|
||||
}
|
||||
|
||||
if (!extraDataExists)
|
||||
d->extra.value(); // ensure extra exists
|
||||
if (mask) {
|
||||
int methodIndex = mask->metaObject()->indexOfMethod(QByteArrayLiteral("contains(QPointF)"));
|
||||
if (methodIndex < 0) {
|
||||
qmlWarning(this) << QStringLiteral("QQuickItem: Object set as mask does not have an invokable contains method, ignoring it.");
|
||||
return;
|
||||
}
|
||||
d->extra.value().maskContains = mask->metaObject()->method(methodIndex);
|
||||
d->extra->maskContainsIndex = methodIndex;
|
||||
}
|
||||
d->mask = mask;
|
||||
d->extra->mask = mask;
|
||||
quickMask = qobject_cast<QQuickItem *>(mask);
|
||||
d->quickMask = quickMask;
|
||||
if (quickMask) {
|
||||
QQuickItemPrivate *maskPrivate = QQuickItemPrivate::get(quickMask);
|
||||
maskPrivate->registerAsContainmentMask(this, true); // telling maskPrivate that "this" is using it as mask
|
||||
|
|
|
@ -378,6 +378,11 @@ public:
|
|||
int hideRefCount;
|
||||
// updated recursively for child items as well
|
||||
int recursiveEffectRefCount;
|
||||
// Mask contains() method index
|
||||
int maskContainsIndex;
|
||||
|
||||
// Contains mask
|
||||
QPointer<QObject> mask;
|
||||
|
||||
QSGOpacityNode *opacityNode;
|
||||
QQuickDefaultClipNode *clipNode;
|
||||
|
@ -385,9 +390,6 @@ public:
|
|||
// subsceneDeliveryAgent is set only if this item is the root of a subscene, not on all items within.
|
||||
QQuickDeliveryAgent *subsceneDeliveryAgent = nullptr;
|
||||
|
||||
// Mask contains() method
|
||||
QMetaMethod maskContains;
|
||||
|
||||
QObjectList resourcesList;
|
||||
|
||||
// Although acceptedMouseButtons is inside ExtraData, we actually store
|
||||
|
@ -397,7 +399,7 @@ public:
|
|||
Qt::MouseButtons acceptedMouseButtons;
|
||||
Qt::MouseButtons acceptedMouseButtonsWithoutHandlers;
|
||||
|
||||
QQuickItem::TransformOrigin origin:5;
|
||||
uint origin:5; // QQuickItem::TransformOrigin
|
||||
uint transparentForPositioner : 1;
|
||||
|
||||
// 26 bits padding
|
||||
|
@ -410,9 +412,6 @@ public:
|
|||
Q_DECLARE_FLAGS(ExtraDataTags, ExtraDataTag)
|
||||
|
||||
QLazilyAllocated<ExtraData, ExtraDataTags> extra;
|
||||
// Contains mask
|
||||
QPointer<QObject> mask;
|
||||
QPointer<QQuickItem> quickMask;
|
||||
// If the mask is an Item, inform it that it's being used as a mask (true) or is no longer being used (false)
|
||||
virtual void registerAsContainmentMask(QQuickItem * /* maskedItem */, bool /* set */) { }
|
||||
|
||||
|
@ -436,53 +435,53 @@ public:
|
|||
|
||||
// Bit 0
|
||||
quint32 flags:7;
|
||||
bool widthValidFlag:1;
|
||||
bool heightValidFlag:1;
|
||||
bool componentComplete:1;
|
||||
bool keepMouse:1;
|
||||
bool keepTouch:1;
|
||||
bool hoverEnabled:1;
|
||||
bool smooth:1;
|
||||
bool antialiasing:1;
|
||||
bool focus:1;
|
||||
quint32 widthValidFlag:1;
|
||||
quint32 heightValidFlag:1;
|
||||
quint32 componentComplete:1;
|
||||
quint32 keepMouse:1;
|
||||
quint32 keepTouch:1;
|
||||
quint32 hoverEnabled:1;
|
||||
quint32 smooth:1;
|
||||
quint32 antialiasing:1;
|
||||
quint32 focus:1;
|
||||
// Bit 16
|
||||
bool activeFocus:1;
|
||||
bool notifiedFocus:1;
|
||||
bool notifiedActiveFocus:1;
|
||||
bool filtersChildMouseEvents:1;
|
||||
bool explicitVisible:1;
|
||||
bool effectiveVisible:1;
|
||||
bool explicitEnable:1;
|
||||
bool effectiveEnable:1;
|
||||
bool polishScheduled:1;
|
||||
bool inheritedLayoutMirror:1;
|
||||
bool effectiveLayoutMirror:1;
|
||||
bool isMirrorImplicit:1;
|
||||
bool inheritMirrorFromParent:1;
|
||||
bool inheritMirrorFromItem:1;
|
||||
bool isAccessible:1;
|
||||
bool culled:1;
|
||||
quint32 activeFocus:1;
|
||||
quint32 notifiedFocus:1;
|
||||
quint32 notifiedActiveFocus:1;
|
||||
quint32 filtersChildMouseEvents:1;
|
||||
quint32 explicitVisible:1;
|
||||
quint32 effectiveVisible:1;
|
||||
quint32 explicitEnable:1;
|
||||
quint32 effectiveEnable:1;
|
||||
quint32 polishScheduled:1;
|
||||
quint32 inheritedLayoutMirror:1;
|
||||
quint32 effectiveLayoutMirror:1;
|
||||
quint32 isMirrorImplicit:1;
|
||||
quint32 inheritMirrorFromParent:1;
|
||||
quint32 inheritMirrorFromItem:1;
|
||||
quint32 isAccessible:1;
|
||||
quint32 culled:1;
|
||||
// Bit 32
|
||||
bool hasCursor:1;
|
||||
bool subtreeCursorEnabled:1;
|
||||
bool subtreeHoverEnabled:1;
|
||||
bool activeFocusOnTab:1;
|
||||
bool implicitAntialiasing:1;
|
||||
bool antialiasingValid:1;
|
||||
quint32 hasCursor:1;
|
||||
quint32 subtreeCursorEnabled:1;
|
||||
quint32 subtreeHoverEnabled:1;
|
||||
quint32 activeFocusOnTab:1;
|
||||
quint32 implicitAntialiasing:1;
|
||||
quint32 antialiasingValid:1;
|
||||
// isTabFence: When true, the item acts as a fence within the tab focus chain.
|
||||
// This means that the item and its children will be skipped from the tab focus
|
||||
// chain when navigating from its parent or any of its siblings. Similarly,
|
||||
// when any of the item's descendants gets focus, the item constrains the tab
|
||||
// focus chain and prevents tabbing outside.
|
||||
bool isTabFence:1;
|
||||
bool replayingPressEvent:1;
|
||||
bool touchEnabled:1;
|
||||
bool hasCursorHandler:1;
|
||||
quint32 isTabFence:1;
|
||||
quint32 replayingPressEvent:1;
|
||||
quint32 touchEnabled:1;
|
||||
quint32 hasCursorHandler:1;
|
||||
// set true when this item does not expect events via a subscene delivery agent; false otherwise
|
||||
bool maybeHasSubsceneDeliveryAgent:1;
|
||||
quint32 maybeHasSubsceneDeliveryAgent:1;
|
||||
// set true if this item or any child wants QQuickItemPrivate::transformChanged() to visit all children
|
||||
// (e.g. when parent has ItemIsViewport and child has ItemObservesViewport)
|
||||
bool subtreeTransformChangedEnabled:1;
|
||||
quint32 subtreeTransformChangedEnabled:1;
|
||||
|
||||
enum DirtyType {
|
||||
TransformOrigin = 0x00000001,
|
||||
|
@ -1002,7 +1001,8 @@ void QQuickItemPrivate::markSortedChildrenDirty(QQuickItem *child)
|
|||
|
||||
QQuickItem::TransformOrigin QQuickItemPrivate::origin() const
|
||||
{
|
||||
return extra.isAllocated()?extra->origin:QQuickItem::Center;
|
||||
return extra.isAllocated() ? QQuickItem::TransformOrigin(extra->origin)
|
||||
: QQuickItem::Center;
|
||||
}
|
||||
|
||||
QSGTransformNode *QQuickItemPrivate::itemNode()
|
||||
|
|
|
@ -555,7 +555,7 @@ void QQuickDeliveryAgentPrivate::notifyFocusChangesRecur(QQuickItem **items, int
|
|||
|
||||
if (item && itemPrivate->notifiedActiveFocus != itemPrivate->activeFocus) {
|
||||
itemPrivate->notifiedActiveFocus = itemPrivate->activeFocus;
|
||||
itemPrivate->itemChange(QQuickItem::ItemActiveFocusHasChanged, itemPrivate->activeFocus);
|
||||
itemPrivate->itemChange(QQuickItem::ItemActiveFocusHasChanged, bool(itemPrivate->activeFocus));
|
||||
itemPrivate->notifyChangeListeners(QQuickItemPrivate::Focus, &QQuickItemChangeListener::itemFocusChanged, item, reason);
|
||||
emit item->activeFocusChanged(itemPrivate->activeFocus);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue