diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 90c54c4039..7fc9cceb60 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -636,12 +636,21 @@ void QOpenGLContext::destroy() d->platformGLContext = 0; delete d->functions; d->functions = 0; + + foreach (QAbstractOpenGLFunctions *func, d->externalVersionFunctions) { + QAbstractOpenGLFunctionsPrivate *func_d = QAbstractOpenGLFunctionsPrivate::get(func); + func_d->owningContext = 0; + func_d->initialized = false; + } + d->externalVersionFunctions.clear(); qDeleteAll(d->versionFunctions); d->versionFunctions.clear(); qDeleteAll(d->versionFunctionsBackend); d->versionFunctionsBackend.clear(); + delete d->textureFunctions; d->textureFunctions = 0; + d->nativeHandle = QVariant(); } @@ -719,7 +728,7 @@ QOpenGLFunctions *QOpenGLContext::functions() const QAbstractOpenGLFunctions::initializeOpenGLFunctions() as long as this context is current. It is also possible to call this function when the context is not current, but in that case it is the caller's responsibility to ensure proper - intiialization by calling QAbstractOpenGLFunctions::initializeOpenGLFunctions() + initialization by calling QAbstractOpenGLFunctions::initializeOpenGLFunctions() afterwards. Usually one would use the template version of this function to automatically @@ -1257,6 +1266,24 @@ void QOpenGLContext::removeFunctionsBackend(const QOpenGLVersionStatus &v) d->versionFunctionsBackend.remove(v); } +/*! + \internal + */ +void QOpenGLContext::insertExternalFunctions(QAbstractOpenGLFunctions *f) +{ + Q_D(QOpenGLContext); + d->externalVersionFunctions.insert(f); +} + +/*! + \internal + */ +void QOpenGLContext::removeExternalFunctions(QAbstractOpenGLFunctions *f) +{ + Q_D(QOpenGLContext); + d->externalVersionFunctions.remove(f); +} + /*! \internal */ diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h index 30a9bc3ad9..a529957ad6 100644 --- a/src/gui/kernel/qopenglcontext.h +++ b/src/gui/kernel/qopenglcontext.h @@ -229,6 +229,8 @@ private: void insertFunctionsBackend(const QOpenGLVersionStatus &v, QOpenGLVersionFunctionsBackend *backend); void removeFunctionsBackend(const QOpenGLVersionStatus &v); + void insertExternalFunctions(QAbstractOpenGLFunctions *f); + void removeExternalFunctions(QAbstractOpenGLFunctions *f); QOpenGLTextureHelper* textureFunctions() const; void setTextureFunctions(QOpenGLTextureHelper* textureFuncs); diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h index 446efa369c..5004ed6a8e 100644 --- a/src/gui/kernel/qopenglcontext_p.h +++ b/src/gui/kernel/qopenglcontext_p.h @@ -216,6 +216,7 @@ public: mutable QHash versionFunctions; mutable QHash versionFunctionsBackend; + mutable QSet externalVersionFunctions; void *qGLContextHandle; void (*qGLContextDeleteFunction)(void *handle); diff --git a/src/gui/opengl/qopenglversionfunctions.cpp b/src/gui/opengl/qopenglversionfunctions.cpp index f3f709c3f0..346a526054 100644 --- a/src/gui/opengl/qopenglversionfunctions.cpp +++ b/src/gui/opengl/qopenglversionfunctions.cpp @@ -67,6 +67,17 @@ void QAbstractOpenGLFunctionsPrivate::removeFunctionsBackend(QOpenGLContext *con context->removeFunctionsBackend(v); } +void QAbstractOpenGLFunctionsPrivate::insertExternalFunctions(QOpenGLContext *context, QAbstractOpenGLFunctions *f) +{ + Q_ASSERT(context); + context->insertExternalFunctions(f); +} + +void QAbstractOpenGLFunctionsPrivate::removeExternalFunctions(QOpenGLContext *context, QAbstractOpenGLFunctions *f) +{ + Q_ASSERT(context); + context->removeExternalFunctions(f); +} /*! \class QAbstractOpenGLFunctions @@ -182,6 +193,9 @@ QAbstractOpenGLFunctions::QAbstractOpenGLFunctions() QAbstractOpenGLFunctions::~QAbstractOpenGLFunctions() { + Q_D(QAbstractOpenGLFunctions); + if (d->owningContext) + d->removeExternalFunctions(d->owningContext, this); delete d_ptr; } @@ -191,6 +205,18 @@ bool QAbstractOpenGLFunctions::initializeOpenGLFunctions() { Q_D(QAbstractOpenGLFunctions); d->initialized = true; + + // For a subclass whose instance is not created via + // QOpenGLContext::versionFunctions() owningContext is not set. Set it now + // and register such instances to the context as external ones. These are + // not owned by the context but still need certain cleanup when the context + // is destroyed. + if (!d->owningContext) { + d->owningContext = QOpenGLContext::currentContext(); + if (d->owningContext) + d->insertExternalFunctions(d->owningContext, this); + } + return true; } diff --git a/src/gui/opengl/qopenglversionfunctions.h b/src/gui/opengl/qopenglversionfunctions.h index 2ae0f429e5..fcf665f97e 100644 --- a/src/gui/opengl/qopenglversionfunctions.h +++ b/src/gui/opengl/qopenglversionfunctions.h @@ -114,6 +114,8 @@ public: QAtomicInt refs; }; +class QAbstractOpenGLFunctions; + class QAbstractOpenGLFunctionsPrivate { public: @@ -128,12 +130,16 @@ public: const QOpenGLVersionStatus &v, QOpenGLVersionFunctionsBackend *backend); static void removeFunctionsBackend(QOpenGLContext *context, const QOpenGLVersionStatus &v); + static void insertExternalFunctions(QOpenGLContext *context, QAbstractOpenGLFunctions *f); + static void removeExternalFunctions(QOpenGLContext *context, QAbstractOpenGLFunctions *f); + + static QAbstractOpenGLFunctionsPrivate *get(QAbstractOpenGLFunctions *q); QOpenGLContext *owningContext; bool initialized; }; -class QAbstractOpenGLFunctions +class Q_GUI_EXPORT QAbstractOpenGLFunctions { public: virtual ~QAbstractOpenGLFunctions(); @@ -154,6 +160,11 @@ protected: friend class QOpenGLContext; }; +inline QAbstractOpenGLFunctionsPrivate *QAbstractOpenGLFunctionsPrivate::get(QAbstractOpenGLFunctions *q) +{ + return q->d_func(); +} + #if !defined(QT_OPENGL_ES_2) class QOpenGLFunctions_1_0_CoreBackend : public QOpenGLVersionFunctionsBackend