From 37e545e0f133ff6be9e9071e9419b0996e41fcdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 4 Jan 2019 17:08:15 +0100 Subject: Deduplicate QWidgetBackingStore::markDirty Now that MSVC (presumably) supports templates, we can merge the QRect and QRegion versions of the functions into one. Change-Id: Ia4264096c4988d9043444e604ebb133e4ff2ace9 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/widgets/kernel/qwidget_p.h | 5 + src/widgets/kernel/qwidgetbackingstore.cpp | 153 +++++++++-------------------- src/widgets/kernel/qwidgetbackingstore_p.h | 6 +- 3 files changed, 53 insertions(+), 111 deletions(-) diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 60612e9b52..e50d828775 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -607,6 +607,11 @@ public: return extra ? extra->nativeChildrenForced : false; } + inline QRect effectiveRectFor(const QRegion ®ion) const + { + return effectiveRectFor(region.boundingRect()); + } + inline QRect effectiveRectFor(const QRect &rect) const { #if QT_CONFIG(graphicseffect) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index f4d1dab84e..0481dffda8 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -507,6 +507,9 @@ void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTi } } +static inline QRect widgetRectFor(QWidget *, const QRect &r) { return r; } +static inline QRect widgetRectFor(QWidget *widget, const QRegion &) { return widget->rect(); } + /*! Marks the region of the widget as dirty (if not already marked as dirty) and posts an UpdateRequest event to the top-level widget (if not already posted). @@ -517,42 +520,44 @@ void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, UpdateTime updateTi If the widget paints directly on screen, the event is sent to the widget instead of the top-level widget, and bufferState is completely ignored. - - ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore). */ -void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, - UpdateTime updateTime, BufferState bufferState) +template +void QWidgetBackingStore::markDirty(const T &r, QWidget *widget, UpdateTime updateTime, BufferState bufferState) { Q_ASSERT(tlw->d_func()->extra); Q_ASSERT(tlw->d_func()->extra->topextra); Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize); Q_ASSERT(widget->isVisible() && widget->updatesEnabled()); Q_ASSERT(widget->window() == tlw); - Q_ASSERT(!rgn.isEmpty()); + Q_ASSERT(!r.isEmpty()); #if QT_CONFIG(graphicseffect) widget->d_func()->invalidateGraphicsEffectsRecursively(); -#endif // QT_CONFIG(graphicseffect) +#endif + + QRect widgetRect = widgetRectFor(widget, r); + + // --------------------------------------------------------------------------- if (widget->d_func()->paintOnScreen()) { if (widget->d_func()->dirty.isEmpty()) { - widget->d_func()->dirty = rgn; + widget->d_func()->dirty = r; sendUpdateRequest(widget, updateTime); return; - } else if (qt_region_strictContains(widget->d_func()->dirty, widget->rect())) { + } else if (qt_region_strictContains(widget->d_func()->dirty, widgetRect)) { if (updateTime == UpdateNow) sendUpdateRequest(widget, updateTime); - return; // Already dirty. + return; // Already dirty } const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty(); - widget->d_func()->dirty += rgn; + widget->d_func()->dirty += r; if (!eventAlreadyPosted || updateTime == UpdateNow) sendUpdateRequest(widget, updateTime); return; } - const QPoint offset = widget->mapTo(tlw, QPoint()); + // --------------------------------------------------------------------------- if (QWidgetPrivate::get(widget)->renderToTexture) { if (!widget->d_func()->inDirtyList) @@ -562,133 +567,67 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, return; } - const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect()); - if (qt_region_strictContains(dirty, widgetRect.translated(offset))) { + // --------------------------------------------------------------------------- + + QRect effectiveWidgetRect = widget->d_func()->effectiveRectFor(widgetRect); + const QPoint offset = widget->mapTo(tlw, QPoint()); + QRect translatedRect = effectiveWidgetRect.translated(offset); +#if QT_CONFIG(graphicseffect) + // Graphics effects may exceed window size, clamp + translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size())); +#endif + if (qt_region_strictContains(dirty, translatedRect)) { if (updateTime == UpdateNow) sendUpdateRequest(tlw, updateTime); - return; // Already dirty. + return; // Already dirty } + // --------------------------------------------------------------------------- + if (bufferState == BufferInvalid) { const bool eventAlreadyPosted = !dirty.isEmpty() || updateRequestSent; #if QT_CONFIG(graphicseffect) if (widget->d_func()->graphicsEffect) - dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset); + dirty += widget->d_func()->effectiveRectFor(r).translated(offset); else -#endif // QT_CONFIG(graphicseffect) - dirty += rgn.translated(offset); +#endif + dirty += r.translated(offset); + if (!eventAlreadyPosted || updateTime == UpdateNow) sendUpdateRequest(tlw, updateTime); return; } + // --------------------------------------------------------------------------- + if (dirtyWidgets.isEmpty()) { - addDirtyWidget(widget, rgn); + addDirtyWidget(widget, r); sendUpdateRequest(tlw, updateTime); return; } + // --------------------------------------------------------------------------- + if (widget->d_func()->inDirtyList) { - if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) { + if (!qt_region_strictContains(widget->d_func()->dirty, effectiveWidgetRect)) { #if QT_CONFIG(graphicseffect) if (widget->d_func()->graphicsEffect) - widget->d_func()->dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()); + widget->d_func()->dirty += widget->d_func()->effectiveRectFor(r); else -#endif // QT_CONFIG(graphicseffect) - widget->d_func()->dirty += rgn; +#endif + widget->d_func()->dirty += r; } } else { - addDirtyWidget(widget, rgn); - } - - if (updateTime == UpdateNow) - sendUpdateRequest(tlw, updateTime); -} - -/*! - This function is equivalent to calling markDirty(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 QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, - UpdateTime updateTime, BufferState bufferState) -{ - Q_ASSERT(tlw->d_func()->extra); - Q_ASSERT(tlw->d_func()->extra->topextra); - Q_ASSERT(!tlw->d_func()->extra->topextra->inTopLevelResize); - Q_ASSERT(widget->isVisible() && widget->updatesEnabled()); - Q_ASSERT(widget->window() == tlw); - Q_ASSERT(!rect.isEmpty()); - -#if QT_CONFIG(graphicseffect) - widget->d_func()->invalidateGraphicsEffectsRecursively(); -#endif // QT_CONFIG(graphicseffect) - - if (widget->d_func()->paintOnScreen()) { - if (widget->d_func()->dirty.isEmpty()) { - widget->d_func()->dirty = QRegion(rect); - sendUpdateRequest(widget, updateTime); - return; - } else if (qt_region_strictContains(widget->d_func()->dirty, rect)) { - if (updateTime == UpdateNow) - sendUpdateRequest(widget, updateTime); - return; // Already dirty. - } - - const bool eventAlreadyPosted = !widget->d_func()->dirty.isEmpty(); - widget->d_func()->dirty += rect; - if (!eventAlreadyPosted || updateTime == UpdateNow) - sendUpdateRequest(widget, updateTime); - return; + addDirtyWidget(widget, r); } - if (QWidgetPrivate::get(widget)->renderToTexture) { - if (!widget->d_func()->inDirtyList) - addDirtyRenderToTextureWidget(widget); - if (!updateRequestSent || updateTime == UpdateNow) - sendUpdateRequest(tlw, updateTime); - return; - } - - - const QRect widgetRect = widget->d_func()->effectiveRectFor(rect); - QRect translatedRect = widgetRect; - if (widget != tlw) - translatedRect.translate(widget->mapTo(tlw, QPoint())); - // Graphics effects may exceed window size, clamp. - translatedRect = translatedRect.intersected(QRect(QPoint(), tlw->size())); - if (qt_region_strictContains(dirty, translatedRect)) { - if (updateTime == UpdateNow) - sendUpdateRequest(tlw, updateTime); - return; // Already dirty - } - - if (bufferState == BufferInvalid) { - const bool eventAlreadyPosted = !dirty.isEmpty(); - dirty += translatedRect; - if (!eventAlreadyPosted || updateTime == UpdateNow) - sendUpdateRequest(tlw, updateTime); - return; - } - - if (dirtyWidgets.isEmpty()) { - addDirtyWidget(widget, rect); - sendUpdateRequest(tlw, updateTime); - return; - } - - if (widget->d_func()->inDirtyList) { - if (!qt_region_strictContains(widget->d_func()->dirty, widgetRect)) - widget->d_func()->dirty += widgetRect; - } else { - addDirtyWidget(widget, rect); - } + // --------------------------------------------------------------------------- if (updateTime == UpdateNow) sendUpdateRequest(tlw, updateTime); } +template void QWidgetBackingStore::markDirty(const QRect &, QWidget *, UpdateTime, BufferState); +template void QWidgetBackingStore::markDirty(const QRegion &, QWidget *, UpdateTime, BufferState); /*! Marks the \a region of the \a widget as dirty on screen. The \a region will be copied from diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h index 41469a04bb..4d15ab138e 100644 --- a/src/widgets/kernel/qwidgetbackingstore_p.h +++ b/src/widgets/kernel/qwidgetbackingstore_p.h @@ -118,10 +118,8 @@ public: return !(dirtyWidgets.isEmpty() && dirty.isEmpty() && dirtyRenderToTextureWidgets.isEmpty()); } - // ### Qt 4.6: Merge into a template function (after MSVC isn't supported anymore). - void markDirty(const QRegion &rgn, QWidget *widget, UpdateTime updateTime = UpdateLater, - BufferState bufferState = BufferValid); - void markDirty(const QRect &rect, QWidget *widget, UpdateTime updateTime = UpdateLater, + template + void markDirty(const T &r, QWidget *widget, UpdateTime updateTime = UpdateLater, BufferState bufferState = BufferValid); private: -- cgit v1.2.3