diff options
Diffstat (limited to 'src/widgets/kernel/qwidgetbackingstore.cpp')
-rw-r--r-- | src/widgets/kernel/qwidgetbackingstore.cpp | 87 |
1 files changed, 77 insertions, 10 deletions
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index d373400623..c8d5440999 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -57,6 +57,8 @@ #include <private/qpaintengine_raster_p.h> #include <private/qgraphicseffect_p.h> +#include <qpa/qplatformbackingstore.h> + #if defined(Q_OS_WIN) && !defined(QT_NO_PAINT_DEBUG) # include <QtCore/qt_windows.h> # include <qpa/qplatformnativeinterface.h> @@ -72,10 +74,15 @@ extern QRegion qt_dirtyRegion(QWidget *); * \a region is the region to be updated in \a widget coordinates. */ static inline void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStore *backingStore, - QWidget *tlw, const QPoint &tlwOffset) + QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures = 0, + QOpenGLContext *context = 0) { +#ifdef QT_NO_OPENGL + Q_UNUSED(widgetTextures); + Q_UNUSED(context); +#endif Q_ASSERT(widget); - Q_ASSERT(!region.isEmpty()); + Q_ASSERT(!region.isEmpty() || (context && widgetTextures && widgetTextures->count())); Q_ASSERT(backingStore); Q_ASSERT(tlw); @@ -104,10 +111,16 @@ static inline void qt_flush(QWidget *widget, const QRegion ®ion, QBackingStor if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen)) return; + QPoint offset = tlwOffset; if (widget != tlw) - backingStore->flush(region, widget->windowHandle(), tlwOffset + widget->mapTo(tlw, QPoint())); + offset += widget->mapTo(tlw, QPoint()); + +#ifndef QT_NO_OPENGL + if (widgetTextures) + backingStore->handle()->composeAndFlush(widget->windowHandle(), region, offset, widgetTextures, context); else - backingStore->flush(region, widget->windowHandle(), tlwOffset); +#endif + backingStore->flush(region, widget->windowHandle(), offset); } #ifndef QT_NO_PAINT_DEBUG @@ -430,7 +443,7 @@ QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &within return region; } -static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately) +void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, bool updateImmediately) { if (!widget) return; @@ -439,6 +452,7 @@ static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately) QEvent event(QEvent::UpdateRequest); QApplication::sendEvent(widget, &event); } else { + updateRequestSent = true; QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority); } } @@ -488,6 +502,7 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up return; } + //### FIXME fullUpdatePending seems to be always false???? if (fullUpdatePending) { if (updateImmediately) sendUpdateRequest(tlw, updateImmediately); @@ -495,6 +510,13 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up } const QPoint offset = widget->mapTo(tlw, QPoint()); + + if (QWidgetPrivate::get(widget)->renderToTexture) { + if (!updateRequestSent || updateImmediately) + sendUpdateRequest(tlw, updateImmediately); + return; + } + const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect()); if (qt_region_strictContains(dirty, widgetRect.translated(offset))) { if (updateImmediately) @@ -503,7 +525,7 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up } if (invalidateBuffer) { - const bool eventAlreadyPosted = !dirty.isEmpty(); + const bool eventAlreadyPosted = !dirty.isEmpty() || updateRequestSent; #ifndef QT_NO_GRAPHICSEFFECT if (widget->d_func()->graphicsEffect) dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset); @@ -583,6 +605,13 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd return; } + if (QWidgetPrivate::get(widget)->renderToTexture) { + if (!updateRequestSent || updateImmediately) + sendUpdateRequest(tlw, updateImmediately); + return; + } + + const QRect widgetRect = widget->d_func()->effectiveRectFor(rect); const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint()))); if (qt_region_strictContains(dirty, translatedRect)) { @@ -703,7 +732,11 @@ void QWidgetBackingStore::updateLists(QWidget *cur) } QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel) - : tlw(topLevel), dirtyOnScreenWidgets(0), fullUpdatePending(0) + : tlw(topLevel), + dirtyOnScreenWidgets(0), + widgetTextures(0), + fullUpdatePending(0), + updateRequestSent(0) { store = tlw->backingStore(); Q_ASSERT(store); @@ -902,7 +935,7 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg // Nothing to repaint. if (!isDirty()) { - qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset); + qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext()); return; } @@ -914,11 +947,27 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg doSync(); } +#ifndef QT_NO_OPENGL +static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures) +{ + QWidgetPrivate *wd = QWidgetPrivate::get(widget); + if (wd->renderToTexture) + widgetTextures->appendTexture(wd->textureId(), QRect(widget->mapTo(tlw, QPoint()), widget->size())); + + for (int i = 0; i < wd->children.size(); ++i) { + QWidget *w = qobject_cast<QWidget *>(wd->children.at(i)); + if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen) + findTextureWidgetsRecursively(tlw, w, widgetTextures); + } +} +#endif + /*! Synchronizes the backing store, i.e. dirty areas are repainted and flushed. */ void QWidgetBackingStore::sync() { + updateRequestSent = false; QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData(); if (discardSyncRequest(tlw, tlwExtra)) { // If the top-level is minimized, it's not visible on the screen so we can delay the @@ -1024,7 +1073,15 @@ void QWidgetBackingStore::doSync() } dirtyWidgets.clear(); +#ifndef QT_NO_OPENGL + delete widgetTextures; + widgetTextures = 0; + if (tlw->d_func()->textureChildSeen) { + widgetTextures = new QPlatformTextureList; // TODO: implement support for locking + findTextureWidgetsRecursively(tlw, tlw, widgetTextures); + } fullUpdatePending = false; +#endif if (toClean.isEmpty()) { // Nothing to repaint. However, we might have newly exposed areas on the @@ -1038,6 +1095,7 @@ void QWidgetBackingStore::doSync() if (tlw->d_func()->extra->proxyWidget) { updateStaticContentsSize(); dirty = QRegion(); + updateRequestSent = false; const QVector<QRect> rects(toClean.rects()); for (int i = 0; i < rects.size(); ++i) tlw->d_func()->extra->proxyWidget->update(rects.at(i)); @@ -1051,6 +1109,7 @@ void QWidgetBackingStore::doSync() for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) resetWidget(opaqueNonOverlappedWidgets[i]); dirty = QRegion(); + updateRequestSent = false; return; } @@ -1059,6 +1118,7 @@ void QWidgetBackingStore::doSync() updateStaticContentsSize(); const QRegion dirtyCopy(dirty); dirty = QRegion(); + updateRequestSent = false; // Paint opaque non overlapped widgets. for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) { @@ -1099,12 +1159,19 @@ void QWidgetBackingStore::flush(QWidget *widget) { if (!dirtyOnScreen.isEmpty()) { QWidget *target = widget ? widget : tlw; - qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset); + qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext()); dirtyOnScreen = QRegion(); } - if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) + if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) { +#ifndef QT_NO_OPENGL + if (widgetTextures && widgetTextures->count()) { + QWidget *target = widget ? widget : tlw; + qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext()); + } +#endif return; + } for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) { QWidget *w = dirtyOnScreenWidgets->at(i); |