Reduce the number of paint events for QOpenGLWidget

Changes to other widgets in the window, especially special cases like
moving dock widgets around, trigger an unfortunately high number of
paint events and calls to paintGL(). Let's try to avoid this.

There is no need to send out a paint event to a texture-backed widget
when it was not explicitly dirtied. Overlaps won't matter since such
widgets are not part of the backingstore. Everything else has to work
like ordinary widgets, though, it is only the QPaintEvent sending we
can optimize away, nothing else.

Task-number: QTBUG-49466
Change-Id: I8ef294ba0a6c305d0002a80e85c06db2c2501cf8
Reviewed-by: Paul Olav Tvete <paul.tvete@theqtcompany.com>
bb10
Laszlo Agocs 2015-11-18 15:20:14 +01:00
parent a69c0bb38e
commit 5c7f000cd4
3 changed files with 16 additions and 3 deletions

View File

@ -271,6 +271,9 @@ QWidgetPrivate::QWidgetPrivate(int version)
#ifndef QT_NO_IM
, inheritsInputMethodHints(0)
#endif
#ifndef QT_NO_OPENGL
, renderToTextureReallyDirty(1)
#endif
#if defined(Q_OS_WIN)
, noPaintOnScreen(0)
#endif
@ -5547,7 +5550,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
<< "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
#endif
bool grabbed = false;
bool skipPaintEvent = false;
#ifndef QT_NO_OPENGL
if (renderToTexture) {
// This widget renders into a texture which is composed later. We just need to
@ -5561,14 +5564,18 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
} else {
// We are not drawing to a backingstore: fall back to QImage
p.drawImage(q->rect(), grabFramebuffer());
grabbed = true;
skipPaintEvent = true;
}
endBackingStorePainting();
}
if (renderToTextureReallyDirty)
renderToTextureReallyDirty = 0;
else
skipPaintEvent = true;
}
#endif // QT_NO_OPENGL
if (!grabbed) {
if (!skipPaintEvent) {
//actually send the paint event
sendPaintEvent(toBePainted);
}

View File

@ -743,6 +743,9 @@ public:
#ifndef QT_NO_IM
uint inheritsInputMethodHints : 1;
#endif
#ifndef QT_NO_OPENGL
uint renderToTextureReallyDirty : 1;
#endif
// *************************** Platform specific ************************************
#if defined(Q_OS_WIN)

View File

@ -1230,6 +1230,9 @@ void QWidgetBackingStore::doSync()
QWidget *w = static_cast<QWidget *>(tl->source(i));
if (dirtyRenderToTextureWidgets.contains(w)) {
const QRect rect = tl->geometry(i); // mapped to the tlw already
// Set a flag to indicate that the paint event for this
// render-to-texture widget must not to be optimized away.
w->d_func()->renderToTextureReallyDirty = 1;
dirty += rect;
toClean += rect;
}