Avoid artifacts when hiding or closing a QOpenGLWidget or QQuickWidget child

windows and xcb enables SwitchableWidgetComposition meaning that widget
backing stores will fall back to the normal flush path when no render-to-texture
widgets are visible anymore in the window. This switch however can lead to
artifacts with the image of the rtt widget remaining visible until the next
full bacinkgstore sync. The safe and simple way around this is to do the
switch only in the next flush, keeping the flush where the switch is
discovered on the OpenGL-based composition path still.

Task-number: QTBUG-54241
Change-Id: I1d3f10999f69c58efa791dd724891add56949dee
Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
This commit is contained in:
Laszlo Agocs 2016-06-22 10:08:28 +02:00
parent fe9ca6ede8
commit 2a7cee47e5
3 changed files with 18 additions and 2 deletions

View File

@ -274,6 +274,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
#endif
#ifndef QT_NO_OPENGL
, renderToTextureReallyDirty(1)
, renderToTextureComposeActive(0)
#endif
#if defined(Q_OS_WIN)
, noPaintOnScreen(0)

View File

@ -744,6 +744,7 @@ public:
#endif
#ifndef QT_NO_OPENGL
uint renderToTextureReallyDirty : 1;
uint renderToTextureComposeActive : 1;
#endif
// *************************** Platform specific ************************************

View File

@ -61,6 +61,8 @@ QT_BEGIN_NAMESPACE
extern QRegion qt_dirtyRegion(QWidget *);
Q_GLOBAL_STATIC(QPlatformTextureList, qt_dummy_platformTextureList)
/**
* Flushes the contents of the \a backingStore into the screen area of \a widget.
* \a tlwOffset is the position of the top level widget relative to the window surface.
@ -103,6 +105,20 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBack
offset += widget->mapTo(tlw, QPoint());
#ifndef QT_NO_OPENGL
const bool compositionWasActive = widget->d_func()->renderToTextureComposeActive;
if (!widgetTextures) {
widget->d_func()->renderToTextureComposeActive = false;
// Detect the case of falling back to the normal flush path when no
// render-to-texture widgets are visible anymore. We will force one
// last flush to go through the OpenGL-based composition to prevent
// artifacts. The next flush after this one will use the normal path.
if (compositionWasActive)
widgetTextures = qt_dummy_platformTextureList;
} else {
widget->d_func()->renderToTextureComposeActive = true;
}
// re-test since we may have been forced to this path via the dummy texture list above
if (widgetTextures) {
qt_window_private(tlw->windowHandle())->compositing = true;
widget->window()->d_func()->sendComposeStatus(widget->window(), false);
@ -978,8 +994,6 @@ static void findAllTextureWidgetsRecursively(QWidget *tlw, QWidget *widget)
}
}
Q_GLOBAL_STATIC(QPlatformTextureList, qt_dummy_platformTextureList)
static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget)
{
foreach (QPlatformTextureList *tl, QWidgetPrivate::get(tlw)->topData()->widgetTextures) {