summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@theqtcompany.com>2015-11-12 17:26:21 +0100
committerLaszlo Agocs <laszlo.agocs@theqtcompany.com>2015-11-23 08:31:53 +0000
commit5a48d1d164ba507469ee1a8a682a3c194d733890 (patch)
treea2ccfb485a17b63fccf777cb81bb755f7361f631 /src/widgets/kernel
parentfe4ab7edce3863a23d5871634d93f0b855aa93ac (diff)
Do not leak textures from the backing stores
Neither the default nor the eglfs-specific backingstore release the OpenGL textures that are in use when render-to-texture widgets are involved. The result can be fatal on embedded devices that run out of GPU memory at after showing and closing dialogs and popups a certain number of times. Task-number: QTBUG-49363 Task-number: QTBUG-49399 Change-Id: Ia7471b037f147bcca0a4f1db5808ca348e230547 Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com> Reviewed-by: Andy Nichols <andy.nichols@theqtcompany.com>
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r--src/widgets/kernel/qwidget.cpp46
1 files changed, 35 insertions, 11 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 2d7c03116b..7c3c4fe8da 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -72,6 +72,7 @@
#include <QtGui/qinputmethod.h>
#include <QtGui/qopenglcontext.h>
#include <QtGui/private/qopenglcontext_p.h>
+#include <QtGui/qoffscreensurface.h>
#include <private/qgraphicseffect_p.h>
#include <qbackingstore.h>
@@ -1817,24 +1818,47 @@ void QWidgetPrivate::deleteSysExtra()
{
}
+static void deleteBackingStore(QWidgetPrivate *d)
+{
+ QTLWExtra *topData = d->topData();
+
+ // The context must be current when destroying the backing store as it may attempt to
+ // release resources like textures and shader programs. The window may not be suitable
+ // anymore as there will often not be a platform window underneath at this stage. Fall
+ // back to a QOffscreenSurface in this case.
+ QScopedPointer<QOffscreenSurface> tempSurface;
+#ifndef QT_NO_OPENGL
+ if (d->textureChildSeen && topData->shareContext) {
+ if (topData->window->handle()) {
+ topData->shareContext->makeCurrent(topData->window);
+ } else {
+ tempSurface.reset(new QOffscreenSurface);
+ tempSurface->setFormat(topData->shareContext->format());
+ tempSurface->create();
+ topData->shareContext->makeCurrent(tempSurface.data());
+ }
+ }
+#endif
+
+ delete topData->backingStore;
+ topData->backingStore = 0;
+
+#ifndef QT_NO_OPENGL
+ if (d->textureChildSeen && topData->shareContext)
+ topData->shareContext->doneCurrent();
+#endif
+}
+
void QWidgetPrivate::deleteTLSysExtra()
{
if (extra && extra->topextra) {
//the qplatformbackingstore may hold a reference to the window, so the backingstore
//needs to be deleted first. If the backingstore holds GL resources, we need to
- // make the context current here, since the platform bs does not have a reference
- // to the widget.
+ // make the context current here. This is taken care of by deleteBackingStore().
-#ifndef QT_NO_OPENGL
- if (textureChildSeen && extra->topextra->shareContext)
- extra->topextra->shareContext->makeCurrent(extra->topextra->window);
-#endif
extra->topextra->backingStoreTracker.destroy();
- delete extra->topextra->backingStore;
- extra->topextra->backingStore = 0;
+ deleteBackingStore(this);
#ifndef QT_NO_OPENGL
- if (textureChildSeen && extra->topextra->shareContext)
- extra->topextra->shareContext->doneCurrent();
delete extra->topextra->shareContext;
extra->topextra->shareContext = 0;
#endif
@@ -11980,7 +12004,7 @@ void QWidget::setBackingStore(QBackingStore *store)
return;
QBackingStore *oldStore = topData->backingStore;
- delete topData->backingStore;
+ deleteBackingStore(d);
topData->backingStore = store;
QWidgetBackingStore *bs = d->maybeBackingStore();