Deduplicate QWidgetPrivate::invalidateBuffer

Now that MSVC (presumably) supports templates, we can merge the QRect
and QRegion versions of the functions into one.

The function has been renamed to invalidateBackingStore to better
reflect what it's doing.

Change-Id: I0e94a0cabd286cf97f2ba718a42ee0425f59d3ec
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Tor Arne Vestbø 2019-01-04 15:18:39 +01:00
parent a3c3330b6f
commit 1a36cf5ea1
4 changed files with 73 additions and 101 deletions

View File

@ -5317,7 +5317,7 @@ void QWidget::setGraphicsEffect(QGraphicsEffect *effect)
return;
if (d->graphicsEffect) {
d->invalidateBuffer(rect());
d->invalidateBackingStore(rect());
delete d->graphicsEffect;
d->graphicsEffect = 0;
}
@ -7340,11 +7340,11 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
if (renderToTexture) {
QRegion updateRegion(q->geometry());
updateRegion += QRect(oldPos, olds);
q->parentWidget()->d_func()->invalidateBuffer(updateRegion);
q->parentWidget()->d_func()->invalidateBackingStore(updateRegion);
} else if (isMove && !isResize) {
moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y());
} else {
invalidateBuffer_resizeHelper(oldPos, olds);
invalidateBackingStore_resizeHelper(oldPos, olds);
}
}
}
@ -8106,7 +8106,7 @@ void QWidgetPrivate::show_sys()
QWidgetWindow *window = windowHandle();
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
invalidateBuffer(q->rect());
invalidateBackingStore(q->rect());
q->setAttribute(Qt::WA_Mapped);
// add our window the modal window list (native dialogs)
if (window && q->isWindow()
@ -8149,7 +8149,7 @@ void QWidgetPrivate::show_sys()
#ifndef QT_NO_CURSOR
qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
#endif
invalidateBuffer(q->rect());
invalidateBackingStore(q->rect());
window->setNativeWindowVisibility(true);
// Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
if (window->isTopLevel()) {
@ -8263,12 +8263,12 @@ void QWidgetPrivate::hide_sys()
QWidget *p = q->parentWidget();
if (p &&p->isVisible()) {
if (renderToTexture)
p->d_func()->invalidateBuffer(q->geometry());
p->d_func()->invalidateBackingStore(q->geometry());
else
invalidateBuffer(q->rect());
invalidateBackingStore(q->rect());
}
} else {
invalidateBuffer(q->rect());
invalidateBackingStore(q->rect());
}
if (window)
@ -11901,7 +11901,7 @@ void QWidget::raise()
QRegion region(rect());
d->subtractOpaqueSiblings(region);
d->invalidateBuffer(region);
d->invalidateBackingStore(region);
}
if (testAttribute(Qt::WA_WState_Created))
d->raise_sys();
@ -11921,7 +11921,7 @@ void QWidgetPrivate::raise_sys()
} else if (renderToTexture) {
if (QWidget *p = q->parentWidget()) {
setDirtyOpaqueRegion();
p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
}
}
}
@ -11971,7 +11971,7 @@ void QWidgetPrivate::lower_sys()
q->windowHandle()->lower();
} else if (QWidget *p = q->parentWidget()) {
setDirtyOpaqueRegion();
p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
}
}
@ -12015,7 +12015,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget*)
Q_Q(QWidget);
if (QWidget *p = q->parentWidget()) {
setDirtyOpaqueRegion();
p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry()));
p->d_func()->invalidateBackingStore(effectiveRectFor(q->geometry()));
}
}
@ -12457,7 +12457,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
d->aboutToDestroy();
if (!isWindow() && parentWidget())
parentWidget()->d_func()->invalidateBuffer(d->effectiveRectFor(geometry()));
parentWidget()->d_func()->invalidateBackingStore(d->effectiveRectFor(geometry()));
d->deactivateWidgetCleanup();
if ((windowType() == Qt::Popup) && qApp)

View File

@ -452,10 +452,11 @@ public:
void scrollChildren(int dx, int dy);
void moveRect(const QRect &, int dx, int dy);
void scrollRect(const QRect &, int dx, int dy);
void invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize);
// ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
void invalidateBuffer(const QRegion &);
void invalidateBuffer(const QRect &);
void invalidateBackingStore_resizeHelper(const QPoint &oldPos, const QSize &oldSize);
template <class T>
void invalidateBackingStore(const T &);
QRegion overlappedRegion(const QRect &rect, bool breakAfterFirst = false) const;
void syncBackingStore();
void syncBackingStore(const QRegion &region);

View File

@ -859,11 +859,11 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
if (!extra || !extra->hasMask) {
parentR -= newRect;
} else {
// invalidateBuffer() excludes anything outside the mask
// invalidateBackingStore() excludes anything outside the mask
parentR += newRect & clipR;
}
pd->invalidateBuffer(parentR);
invalidateBuffer((newRect & clipR).translated(-data.crect.topLeft()));
pd->invalidateBackingStore(parentR);
invalidateBackingStore((newRect & clipR).translated(-data.crect.topLeft()));
} else {
QWidgetBackingStore *wbs = x->backingStoreTracker.data();
@ -894,7 +894,7 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy)
if (childUpdatesEnabled) {
if (!overlappedExpose.isEmpty()) {
overlappedExpose.translate(-data.crect.topLeft());
invalidateBuffer(overlappedExpose);
invalidateBackingStore(overlappedExpose);
}
if (!childExpose.isEmpty()) {
childExpose.translate(-data.crect.topLeft());
@ -944,9 +944,9 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
if (!overlappedRegion(scrollRect.translated(data.crect.topLeft()), true).isEmpty()) {
QRegion region(scrollRect);
subtractOpaqueSiblings(region);
invalidateBuffer(region);
invalidateBackingStore(region);
}else {
invalidateBuffer(scrollRect);
invalidateBackingStore(scrollRect);
}
} else {
const QPoint toplevelOffset = q->mapTo(tlw, QPoint());
@ -987,7 +987,7 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy)
return;
if (!overlappedExpose.isEmpty())
invalidateBuffer(overlappedExpose);
invalidateBackingStore(overlappedExpose);
if (!childExpose.isEmpty()) {
wbs->markDirty(childExpose, q);
isScrolled = true;
@ -1471,26 +1471,11 @@ void QWidgetBackingStore::flush(QWidget *widget)
dirtyOnScreenWidgets->clear();
}
static inline bool discardInvalidateBufferRequest(QWidget *widget, QTLWExtra *tlwExtra)
{
Q_ASSERT(widget);
if (QApplication::closingDown())
return true;
if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore)
return true;
if (!widget->isVisible() || !widget->updatesEnabled())
return true;
return false;
}
/*!
Invalidates the buffer when the widget is resized.
Invalidates the backing store when the widget is resized.
Static areas are never invalidated unless absolutely needed.
*/
void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize)
void QWidgetPrivate::invalidateBackingStore_resizeHelper(const QPoint &oldPos, const QSize &oldSize)
{
Q_Q(QWidget);
Q_ASSERT(!q->isWindow());
@ -1515,10 +1500,10 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q
if (hasStaticChildren) {
QRegion dirty(newWidgetRect);
dirty -= staticChildren;
invalidateBuffer(dirty);
invalidateBackingStore(dirty);
} else {
// Entire widget needs repaint.
invalidateBuffer(newWidgetRect);
invalidateBackingStore(newWidgetRect);
}
if (!parentAreaExposed)
@ -1530,14 +1515,14 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q
parentExpose &= QRect(oldPos, oldSize);
if (hasStaticChildren)
parentExpose -= data.crect; // Offset is unchanged, safe to do this.
q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
q->parentWidget()->d_func()->invalidateBackingStore(parentExpose);
} else {
if (hasStaticChildren && !graphicsEffect) {
QRegion parentExpose(QRect(oldPos, oldSize));
parentExpose -= data.crect; // Offset is unchanged, safe to do this.
q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
q->parentWidget()->d_func()->invalidateBackingStore(parentExpose);
} else {
q->parentWidget()->d_func()->invalidateBuffer(effectiveRectFor(QRect(oldPos, oldSize)));
q->parentWidget()->d_func()->invalidateBackingStore(effectiveRectFor(QRect(oldPos, oldSize)));
}
}
return;
@ -1558,7 +1543,7 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q
if (!sizeDecreased || !oldWidgetRect.contains(newWidgetRect)) {
QRegion newVisible(newWidgetRect);
newVisible -= oldWidgetRect;
invalidateBuffer(newVisible);
invalidateBackingStore(newVisible);
}
if (!parentAreaExposed)
@ -1570,74 +1555,56 @@ void QWidgetPrivate::invalidateBuffer_resizeHelper(const QPoint &oldPos, const Q
QRegion parentExpose(oldRect);
parentExpose &= extra->mask.translated(oldPos);
parentExpose -= (extra->mask.translated(data.crect.topLeft()) & data.crect);
q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
q->parentWidget()->d_func()->invalidateBackingStore(parentExpose);
} else {
QRegion parentExpose(oldRect);
parentExpose -= data.crect;
q->parentWidget()->d_func()->invalidateBuffer(parentExpose);
q->parentWidget()->d_func()->invalidateBackingStore(parentExpose);
}
}
/*!
Invalidates the \a rgn (in widget's coordinates) of the backing store, i.e.
all widgets intersecting with the region will be repainted when the backing store
is synced.
### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
Invalidates the \a r (in widget's coordinates) of the backing store, i.e.
all widgets intersecting with the region will be repainted when the backing
store is synced.
*/
void QWidgetPrivate::invalidateBuffer(const QRegion &rgn)
template <class T>
void QWidgetPrivate::invalidateBackingStore(const T &r)
{
if (r.isEmpty())
return;
if (QApplication::closingDown())
return;
Q_Q(QWidget);
if (!q->isVisible() || !q->updatesEnabled())
return;
QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
if (discardInvalidateBufferRequest(q, tlwExtra) || rgn.isEmpty())
if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore)
return;
QRegion wrgn(rgn);
wrgn &= clipRect();
if (!graphicsEffect && extra && extra->hasMask)
wrgn &= extra->mask;
if (wrgn.isEmpty())
T clipped(r);
clipped &= clipRect();
if (clipped.isEmpty())
return;
tlwExtra->backingStoreTracker->markDirty(wrgn, q,
if (!graphicsEffect && extra && extra->hasMask) {
QRegion masked(extra->mask);
masked &= clipped;
if (masked.isEmpty())
return;
tlwExtra->backingStoreTracker->markDirty(masked, q,
QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
} else {
tlwExtra->backingStoreTracker->markDirty(clipped, q,
QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
}
/*!
This function is equivalent to calling invalidateBuffer(QRegion(rect), ...), but
is more efficient as it eliminates QRegion operations/allocations and can
use the rect more precisely for additional cut-offs.
### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore).
*/
void QWidgetPrivate::invalidateBuffer(const QRect &rect)
{
Q_Q(QWidget);
QTLWExtra *tlwExtra = q->window()->d_func()->maybeTopData();
if (discardInvalidateBufferRequest(q, tlwExtra) || rect.isEmpty())
return;
QRect wRect(rect);
wRect &= clipRect();
if (wRect.isEmpty())
return;
if (graphicsEffect || !extra || !extra->hasMask) {
tlwExtra->backingStoreTracker->markDirty(wRect, q,
QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
return;
}
QRegion wRgn(extra->mask);
wRgn &= wRect;
if (wRgn.isEmpty())
return;
tlwExtra->backingStoreTracker->markDirty(wRgn, q,
QWidgetBackingStore::UpdateLater, QWidgetBackingStore::BufferInvalid);
}
// Needed by tst_QWidget
template Q_AUTOTEST_EXPORT void QWidgetPrivate::invalidateBackingStore<QRect>(const QRect &r);
void QWidgetPrivate::repaint_sys(const QRegion &rgn)
{

View File

@ -321,7 +321,9 @@ private slots:
void setMaskInResizeEvent();
void moveInResizeEvent();
void immediateRepaintAfterInvalidateBuffer();
#ifdef QT_BUILD_INTERNAL
void immediateRepaintAfterInvalidateBackingStore();
#endif
void effectiveWinId();
void effectiveWinId2();
@ -8215,7 +8217,7 @@ void tst_QWidget::resizeInPaintEvent()
widget.resizeInPaintEvent = true;
// This will call resize in the paintEvent, which in turn will call
// invalidateBuffer() and a new update request should be posted.
// invalidateBackingStore() and a new update request should be posted.
widget.repaint();
QCOMPARE(widget.numPaintEvents, 1);
widget.numPaintEvents = 0;
@ -8370,7 +8372,8 @@ void tst_QWidget::moveInResizeEvent()
QTRY_COMPARE(testWidget.geometry(), expectedGeometry);
}
void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
#ifdef QT_BUILD_INTERNAL
void tst_QWidget::immediateRepaintAfterInvalidateBackingStore()
{
if (m_platform != QStringLiteral("xcb") && m_platform != QStringLiteral("windows"))
QSKIP("We don't support immediate repaint right after show on other platforms.");
@ -8384,7 +8387,7 @@ void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
// Marks the area covered by the widget as dirty in the backing store and
// posts an UpdateRequest event.
qt_widget_private(widget.data())->invalidateBuffer(widget->rect());
qt_widget_private(widget.data())->invalidateBackingStore(widget->rect());
QCOMPARE(widget->numPaintEvents, 0);
// The entire widget is already dirty, but this time we want to update immediately
@ -8393,6 +8396,7 @@ void tst_QWidget::immediateRepaintAfterInvalidateBuffer()
widget->repaint();
QCOMPARE(widget->numPaintEvents, 1);
}
#endif
void tst_QWidget::effectiveWinId()
{
@ -9628,7 +9632,7 @@ public:
{
if (!static_cast<QWidgetPrivate*>(d_ptr.data())->maybeBackingStore()) {
static_cast<QWidgetPrivate*>(d_ptr.data())->topData()->backingStoreTracker.create(this);
static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBuffer(this->rect());
static_cast<QWidgetPrivate*>(d_ptr.data())->invalidateBackingStore(this->rect());
repaint();
}
}