Fix crash when combining QOpenGLWidget, QStaticText and Qt Quick
Under certain circumstances, if you had a widget with a QOpenGLPaintEngine, and drew QStaticText into this, and then later had Qt Quick access the same cache and try to resize it, we would get a crash because the resize function would have a pointer to the paint engine and try to access its shader manager (which would now be null, since this is outside the begin()/end() phase of the paint engine. The solution is to reset the paint engine pointer to null on the cache once it has been populated and it is no longer needed. [ChangeLog][QtGui][Text] Fixed a possible crash when combining QStaticText, QOpenGLWidget and Qt Quick in the same application. Task-number: QTBUG-70096 Change-Id: I7383ad7456d1a72499cfcd2da09a5a808d4b3eff Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
parent
981b16d9ba
commit
f71048a531
@ -1741,6 +1741,7 @@ void QOpenGL2PaintEngineExPrivate::drawCachedGlyphs(QFontEngine::GlyphFormat gly
|
||||
// we may have to re-bind brush textures after filling in the cache.
|
||||
brushTextureDirty = (QT_BRUSH_TEXTURE_UNIT == glypchCacheTextureUnit);
|
||||
}
|
||||
cache->setPaintEnginePrivate(nullptr);
|
||||
}
|
||||
|
||||
if (cache->width() == 0 || cache->height() == 0)
|
||||
|
@ -152,6 +152,11 @@ public:
|
||||
|
||||
void clear();
|
||||
|
||||
QOpenGL2PaintEngineExPrivate *paintEnginePrivate() const
|
||||
{
|
||||
return pex;
|
||||
}
|
||||
|
||||
private:
|
||||
void setupVertexAttribs();
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <QtGui/QOpenGLFunctions>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QScreen>
|
||||
#include <QtGui/QStaticText>
|
||||
#include <QtWidgets/QDesktopWidget>
|
||||
#include <QtWidgets/QGraphicsView>
|
||||
#include <QtWidgets/QGraphicsScene>
|
||||
@ -40,6 +41,8 @@
|
||||
#include <QtTest/QtTest>
|
||||
#include <QSignalSpy>
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <private/qstatictext_p.h>
|
||||
#include <private/qopengltextureglyphcache_p.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
|
||||
class tst_QOpenGLWidget : public QObject
|
||||
@ -64,6 +67,10 @@ private slots:
|
||||
void stackWidgetOpaqueChildIsVisible();
|
||||
void offscreen();
|
||||
void offscreenThenOnscreen();
|
||||
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
void staticTextDanglingPointer();
|
||||
#endif
|
||||
};
|
||||
|
||||
void tst_QOpenGLWidget::initTestCase()
|
||||
@ -675,6 +682,53 @@ void tst_QOpenGLWidget::offscreenThenOnscreen()
|
||||
QVERIFY(image.pixel(30, 40) == qRgb(0, 0, 255));
|
||||
}
|
||||
|
||||
class StaticTextPainterWidget : public QOpenGLWidget
|
||||
{
|
||||
public:
|
||||
StaticTextPainterWidget(QWidget *parent = nullptr)
|
||||
: QOpenGLWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void paintEvent(QPaintEvent *)
|
||||
{
|
||||
QPainter p(this);
|
||||
text.setText(QStringLiteral("test"));
|
||||
p.drawStaticText(0, 0, text);
|
||||
|
||||
ctx = QOpenGLContext::currentContext();
|
||||
}
|
||||
|
||||
QStaticText text;
|
||||
QOpenGLContext *ctx;
|
||||
};
|
||||
|
||||
#ifdef QT_BUILD_INTERNAL
|
||||
void tst_QOpenGLWidget::staticTextDanglingPointer()
|
||||
{
|
||||
QWidget w;
|
||||
StaticTextPainterWidget *glw = new StaticTextPainterWidget(&w);
|
||||
w.resize(640, 480);
|
||||
glw->resize(320, 200);
|
||||
w.show();
|
||||
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&w));
|
||||
QStaticTextPrivate *d = QStaticTextPrivate::get(&glw->text);
|
||||
|
||||
QCOMPARE(d->itemCount, 1);
|
||||
QFontEngine *fe = d->items->fontEngine();
|
||||
|
||||
for (int i = QFontEngine::Format_None; i <= QFontEngine::Format_ARGB; ++i) {
|
||||
QOpenGLTextureGlyphCache *cache =
|
||||
(QOpenGLTextureGlyphCache *) fe->glyphCache(glw->ctx,
|
||||
QFontEngine::GlyphFormat(i),
|
||||
QTransform());
|
||||
if (cache != nullptr)
|
||||
QCOMPARE(cache->paintEnginePrivate(), nullptr);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QTEST_MAIN(tst_QOpenGLWidget)
|
||||
|
||||
#include "tst_qopenglwidget.moc"
|
||||
|
Loading…
x
Reference in New Issue
Block a user