[ChangeLog][QPA][eglfs] Fix crash when using cursors and multiple GL contexts

The hash from QOpenGLContext* to cursor texture/shader data can
accumulate dangling pointers if the program uses multiple contexts on
the same screen. This is fixed by moving the cursor data into the
platform context. The code for deleting the texture and shader program
is omitted as it is tied to the life time of the context and the GL
context deletes its resources automatically upon destruction.

Task-number: QTBUG-65119
Change-Id: Ic3b8e5669d14949af811bdf047e7d47000216180
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
This commit is contained in:
Simon Hausmann 2017-12-11 15:50:21 +01:00
parent 06e903cf68
commit 495833b796
3 changed files with 17 additions and 23 deletions

View File

@ -52,6 +52,7 @@
//
#include "qeglfsglobal_p.h"
#include "qeglfscursor_p.h"
#include <QtEglSupport/private/qeglplatformcontext_p.h>
#include <QtCore/QVariant>
@ -68,6 +69,8 @@ public:
void runGLChecks() override;
void swapBuffers(QPlatformSurface *surface) override;
QEglFSCursorData cursorData;
private:
EGLNativeWindowType m_tempWindow;
};

View File

@ -40,10 +40,10 @@
#include "qeglfscursor_p.h"
#include "qeglfsintegration_p.h"
#include "qeglfsscreen_p.h"
#include "qeglfscontext_p.h"
#include <qpa/qwindowsysteminterface.h>
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLShaderProgram>
#include <QtCore/QFile>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonArray>
@ -115,13 +115,6 @@ void QEglFSCursorDeviceListener::onDeviceListChanged(QInputDeviceManager::Device
void QEglFSCursor::resetResources()
{
if (QOpenGLContext *ctx = QOpenGLContext::currentContext()) {
GraphicsContextData &gfx(m_gfx[ctx]);
delete gfx.program;
glDeleteTextures(1, &gfx.customCursorTexture);
glDeleteTextures(1, &gfx.atlasTexture);
gfx = GraphicsContextData();
}
m_cursor.customCursorPending = !m_cursor.customCursorImage.isNull();
}
@ -144,8 +137,8 @@ void QEglFSCursor::createShaderPrograms()
" gl_FragColor = texture2D(texture, textureCoord).bgra;\n"
"}\n";
GraphicsContextData &gfx(m_gfx[QOpenGLContext::currentContext()]);
gfx.program = new QOpenGLShaderProgram;
QEglFSCursorData &gfx = static_cast<QEglFSContext*>(QOpenGLContext::currentContext()->handle())->cursorData;
gfx.program.reset(new QOpenGLShaderProgram);
gfx.program->addCacheableShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
gfx.program->addCacheableShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
gfx.program->bindAttributeLocation("vertexCoordEntry", 0);
@ -475,7 +468,7 @@ void QEglFSCursor::draw(const QRectF &r)
{
StateSaver stateSaver;
GraphicsContextData &gfx(m_gfx[QOpenGLContext::currentContext()]);
QEglFSCursorData &gfx = static_cast<QEglFSContext*>(QOpenGLContext::currentContext()->handle())->cursorData;
if (!gfx.program) {
// one time initialization
initializeOpenGLFunctions();

View File

@ -56,6 +56,7 @@
#include <qpa/qplatformscreen.h>
#include <QtGui/QMatrix4x4>
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/private/qinputdevicemanager_p.h>
QT_BEGIN_NAMESPACE
@ -81,6 +82,15 @@ private:
#if QT_CONFIG(opengl)
struct QEglFSCursorData {
QScopedPointer<QOpenGLShaderProgram> program;
int textureEntry = 0;
int matEntry = 0;
uint customCursorTexture = 0;
uint atlasTexture = 0;
qint64 customCursorKey = 0;
};
class Q_EGLFS_EXPORT QEglFSCursor : public QPlatformCursor
, protected QOpenGLFunctions
{
@ -143,18 +153,6 @@ private:
QEglFSCursorDeviceListener *m_deviceListener;
bool m_updateRequested;
QMatrix4x4 m_rotationMatrix;
struct GraphicsContextData {
GraphicsContextData() : program(nullptr), textureEntry(0), matEntry(0),
customCursorTexture(0), atlasTexture(0), customCursorKey(0) { }
QOpenGLShaderProgram *program;
int textureEntry;
int matEntry;
uint customCursorTexture;
uint atlasTexture;
qint64 customCursorKey;
};
QHash<QOpenGLContext *, GraphicsContextData> m_gfx;
};
#endif // QT_CONFIG(opengl)