From 6e28e8441b698c3397c2c78125c877f2e9867cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 22 Aug 2011 10:49:28 +0200 Subject: Copy core GL functionality to QtGui with QGL -> QOpenGL naming. Change-Id: Ibc989afa4a30dd184d41d1a1cd89f97196e48855 Reviewed-on: http://codereview.qt.nokia.com/3710 Reviewed-by: Gunnar Sletta --- src/gui/kernel/qopenglcontext.cpp | 531 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 531 insertions(+) create mode 100644 src/gui/kernel/qopenglcontext.cpp (limited to 'src/gui/kernel/qopenglcontext.cpp') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp new file mode 100644 index 0000000000..92a651ddf4 --- /dev/null +++ b/src/gui/kernel/qopenglcontext.cpp @@ -0,0 +1,531 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qplatformopenglcontext_qpa.h" +#include "qopenglcontext.h" +#include "qopenglcontext_p.h" +#include "qwindow.h" + +#include +#include + +#include +#include + +#include + +#include + +class QGuiGLThreadContext +{ +public: + ~QGuiGLThreadContext() { + if (context) + context->doneCurrent(); + } + QOpenGLContext *context; +}; + +static QThreadStorage qwindow_context_storage; + +void QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context) +{ + QGuiGLThreadContext *threadContext = qwindow_context_storage.localData(); + if (!threadContext) { + if (!QThread::currentThread()) { + qWarning("No QTLS available. currentContext wont work"); + return; + } + threadContext = new QGuiGLThreadContext; + qwindow_context_storage.setLocalData(threadContext); + } + threadContext->context = context; +} + +/*! + Returns the last context which called makeCurrent. This function is thread aware. +*/ +QOpenGLContext* QOpenGLContext::currentContext() +{ + QGuiGLThreadContext *threadContext = qwindow_context_storage.localData(); + if(threadContext) { + return threadContext->context; + } + return 0; +} + +bool QOpenGLContext::areSharing(QOpenGLContext *first, QOpenGLContext *second) +{ + return first->shareGroup() == second->shareGroup(); +} + +QPlatformOpenGLContext *QOpenGLContext::handle() const +{ + Q_D(const QOpenGLContext); + return d->platformGLContext; +} + +QPlatformOpenGLContext *QOpenGLContext::shareHandle() const +{ + Q_D(const QOpenGLContext); + if (d->shareContext) + return d->shareContext->handle(); + return 0; +} + +/*! + Creates a new GL context instance, you need to call create() before it can be used. +*/ +QOpenGLContext::QOpenGLContext(QObject *parent) + : QObject(*new QOpenGLContextPrivate(), parent) +{ + Q_D(QOpenGLContext); + d->screen = QGuiApplication::primaryScreen(); +} + +/*! + Sets the format the GL context should be compatible with. You need to call create() before it takes effect. +*/ +void QOpenGLContext::setFormat(const QSurfaceFormat &format) +{ + Q_D(QOpenGLContext); + d->requestedFormat = format; +} + +/*! + Sets the context to share textures, shaders, and other GL resources with. You need to call create() before it takes effect. +*/ +void QOpenGLContext::setShareContext(QOpenGLContext *shareContext) +{ + Q_D(QOpenGLContext); + d->shareContext = shareContext; +} + +/*! + Sets the screen the GL context should be valid for. You need to call create() before it takes effect. +*/ +void QOpenGLContext::setScreen(QScreen *screen) +{ + Q_D(QOpenGLContext); + d->screen = screen; + if (!d->screen) + d->screen = QGuiApplication::primaryScreen(); +} + +/*! + Attempts to create the GL context with the desired parameters. + + Returns true if the native context was successfully created and is ready to be used. +*/ +bool QOpenGLContext::create() +{ + destroy(); + + Q_D(QOpenGLContext); + d->platformGLContext = QGuiApplicationPrivate::platformIntegration()->createPlatformOpenGLContext(this); + d->platformGLContext->setContext(this); + d->shareGroup = d->shareContext ? d->shareContext->shareGroup() : new QOpenGLContextGroup; + d->shareGroup->d_func()->addContext(this); + return d->platformGLContext; +} + +void QOpenGLContext::destroy() +{ + Q_D(QOpenGLContext); + if (QOpenGLContext::currentContext() == this) + doneCurrent(); + if (d->shareGroup) + d->shareGroup->d_func()->removeContext(this); + d->shareGroup = 0; + delete d->platformGLContext; + d->platformGLContext = 0; + delete d->functions; + d->functions = 0; +} + +/*! + If this is the current context for the thread, doneCurrent is called +*/ +QOpenGLContext::~QOpenGLContext() +{ + destroy(); +} + +/*! + Returns if this context is valid, i.e. has been successfully created. +*/ +bool QOpenGLContext::isValid() const +{ + Q_D(const QOpenGLContext); + return d->platformGLContext != 0; +} + +/*! + Get the QOpenGLFunctions instance for this context. + + The context or a sharing context must be current. +*/ + +QOpenGLFunctions *QOpenGLContext::functions() const +{ + Q_D(const QOpenGLContext); + if (!d->functions) + const_cast(d->functions) = new QOpenGLExtensions(QOpenGLContext::currentContext()); + return d->functions; +} + +/*! + If surface is 0 this is equivalent to calling doneCurrent(). +*/ +bool QOpenGLContext::makeCurrent(QSurface *surface) +{ + Q_D(QOpenGLContext); + if (!d->platformGLContext) + return false; + + if (!surface) { + doneCurrent(); + return true; + } + + if (!surface->surfaceHandle()) + return false; + + if (d->platformGLContext->makeCurrent(surface->surfaceHandle())) { + QOpenGLContextPrivate::setCurrentContext(this); + d->surface = surface; + + d->shareGroup->d_func()->deletePendingResources(this); + + return true; + } + + return false; +} + +/*! + Convenience function for calling makeCurrent with a 0 surface. +*/ +void QOpenGLContext::doneCurrent() +{ + Q_D(QOpenGLContext); + if (!d->platformGLContext) + return; + + if (QOpenGLContext::currentContext() == this) + d->shareGroup->d_func()->deletePendingResources(this); + + d->platformGLContext->doneCurrent(); + QOpenGLContextPrivate::setCurrentContext(0); + + d->surface = 0; +} + +/*! + Returns the surface the context is current for. +*/ +QSurface *QOpenGLContext::surface() const +{ + Q_D(const QOpenGLContext); + return d->surface; +} + + +void QOpenGLContext::swapBuffers(QSurface *surface) +{ + Q_D(QOpenGLContext); + if (!d->platformGLContext) + return; + + if (!surface) { + qWarning() << "QOpenGLContext::swapBuffers() called with null argument"; + return; + } + + d->platformGLContext->swapBuffers(surface->surfaceHandle()); +} + +void (*QOpenGLContext::getProcAddress(const QByteArray &procName)) () +{ + Q_D(QOpenGLContext); + if (!d->platformGLContext) + return 0; + return d->platformGLContext->getProcAddress(procName); +} + +QSurfaceFormat QOpenGLContext::format() const +{ + Q_D(const QOpenGLContext); + if (!d->platformGLContext) + return d->requestedFormat; + return d->platformGLContext->format(); +} + +QOpenGLContextGroup *QOpenGLContext::shareGroup() const +{ + Q_D(const QOpenGLContext); + return d->shareGroup; +} + +QOpenGLContext *QOpenGLContext::shareContext() const +{ + Q_D(const QOpenGLContext); + return d->shareContext; +} + +QScreen *QOpenGLContext::screen() const +{ + Q_D(const QOpenGLContext); + return d->screen; +} + +/* + internal: Needs to have a pointer to qGLContext. But since this is in QtGui we cant + have any type information. +*/ +void *QOpenGLContext::qGLContextHandle() const +{ + Q_D(const QOpenGLContext); + return d->qGLContextHandle; +} + +void QOpenGLContext::setQGLContextHandle(void *handle,void (*qGLContextDeleteFunction)(void *)) +{ + Q_D(QOpenGLContext); + d->qGLContextHandle = handle; + d->qGLContextDeleteFunction = qGLContextDeleteFunction; +} + +void QOpenGLContext::deleteQGLContext() +{ + Q_D(QOpenGLContext); + if (d->qGLContextDeleteFunction && d->qGLContextHandle) { + d->qGLContextDeleteFunction(d->qGLContextHandle); + d->qGLContextDeleteFunction = 0; + d->qGLContextHandle = 0; + } +} + +QOpenGLContextGroup::QOpenGLContextGroup() + : QObject(*new QOpenGLContextGroupPrivate()) +{ +} + +QOpenGLContextGroup::~QOpenGLContextGroup() +{ + Q_D(QOpenGLContextGroup); + + QList::iterator it = d->m_sharedResources.begin(); + QList::iterator end = d->m_sharedResources.end(); + + while (it != end) { + (*it)->invalidateResource(); + (*it)->m_group = 0; + ++it; + } + + qDeleteAll(d->m_pendingDeletion.begin(), d->m_pendingDeletion.end()); +} + +QList QOpenGLContextGroup::shares() const +{ + Q_D(const QOpenGLContextGroup); + return d->m_shares; +} + +QOpenGLContextGroup *QOpenGLContextGroup::currentContextGroup() +{ + QOpenGLContext *current = QOpenGLContext::currentContext(); + return current ? current->shareGroup() : 0; +} + +void QOpenGLContextGroupPrivate::addContext(QOpenGLContext *ctx) +{ + QMutexLocker locker(&m_mutex); + m_refs.ref(); + m_shares << ctx; +} + +void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx) +{ + Q_Q(QOpenGLContextGroup); + + QMutexLocker locker(&m_mutex); + m_shares.removeOne(ctx); + + if (ctx == m_context && !m_shares.isEmpty()) + m_context = m_shares.first(); + + if (!m_refs.deref()) + q->deleteLater(); +} + +void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx) +{ + QMutexLocker locker(&m_mutex); + + QList pending = m_pendingDeletion; + m_pendingDeletion.clear(); + + QList::iterator it = pending.begin(); + QList::iterator end = pending.end(); + while (it != end) { + (*it)->freeResource(ctx); + delete *it; + ++it; + } +} + +QOpenGLSharedResource::QOpenGLSharedResource(QOpenGLContextGroup *group) + : m_group(group) +{ + QMutexLocker locker(&m_group->d_func()->m_mutex); + m_group->d_func()->m_sharedResources << this; +} + +QOpenGLSharedResource::~QOpenGLSharedResource() +{ +} + +// schedule the resource for deletion at an appropriate time +void QOpenGLSharedResource::free() +{ + if (!m_group) { + delete this; + return; + } + + QMutexLocker locker(&m_group->d_func()->m_mutex); + m_group->d_func()->m_sharedResources.removeOne(this); + m_group->d_func()->m_pendingDeletion << this; + + // can we delete right away? + QOpenGLContext *current = QOpenGLContext::currentContext(); + if (current && current->shareGroup() == m_group) { + m_group->d_func()->deletePendingResources(current); + } +} + +void QOpenGLSharedResourceGuard::freeResource(QOpenGLContext *context) +{ + if (m_id) { + QOpenGLFunctions functions(context); + m_func(&functions, m_id); + m_id = 0; + } +} + +QOpenGLMultiGroupSharedResource::QOpenGLMultiGroupSharedResource() + : active(0) +{ +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Creating context group resource object %p.", this); +#endif +} + +QOpenGLMultiGroupSharedResource::~QOpenGLMultiGroupSharedResource() +{ +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Deleting context group resource %p. Group size: %d.", this, m_groups.size()); +#endif + for (int i = 0; i < m_groups.size(); ++i) { + if (!m_groups.at(i)->shares().isEmpty()) { + QOpenGLContext *context = m_groups.at(i)->shares().first(); + QOpenGLSharedResource *resource = value(context); + if (resource) + resource->free(); + } + m_groups.at(i)->d_func()->m_resources.remove(this); + active.deref(); + } +#ifndef QT_NO_DEBUG + if (active != 0) { + qWarning("QtGui: Resources are still available at program shutdown.\n" + " This is possibly caused by a leaked QOpenGLWidget, \n" + " QOpenGLFramebufferObject or QOpenGLPixelBuffer."); + } +#endif +} + +void QOpenGLMultiGroupSharedResource::insert(QOpenGLContext *context, QOpenGLSharedResource *value) +{ +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Inserting context group resource %p for context %p, managed by %p.", value, context, this); +#endif + QOpenGLContextGroup *group = context->shareGroup(); + Q_ASSERT(!group->d_func()->m_resources.contains(this)); + group->d_func()->m_resources.insert(this, value); + m_groups.append(group); + active.ref(); +} + +QOpenGLSharedResource *QOpenGLMultiGroupSharedResource::value(QOpenGLContext *context) +{ + QOpenGLContextGroup *group = context->shareGroup(); + return group->d_func()->m_resources.value(this, 0); +} + +void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContext *ctx) +{ + QOpenGLSharedResource *resource = value(ctx); + + if (resource != 0) { + resource->free(); + + QOpenGLContextGroup *group = ctx->shareGroup(); + group->d_func()->m_resources.remove(this); + m_groups.removeOne(group); + active.deref(); + } +} + +void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContext *ctx, QOpenGLSharedResource *value) +{ +#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG + qDebug("Cleaning up context group resource %p, for context %p in thread %p.", this, ctx, QThread::currentThread()); +#endif + value->free(); + active.deref(); + + QOpenGLContextGroup *group = ctx->shareGroup(); + m_groups.removeOne(group); +} + -- cgit v1.2.3 From 19a0048d1755d127607f66266ab4868191647b3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 30 Aug 2011 10:14:39 +0200 Subject: Added some documentation for internal OpenGL resource handling classes. Change-Id: Ib9a9442199a29d5781013155190ad0f20741198e Reviewed-on: http://codereview.qt.nokia.com/3859 Reviewed-by: Qt Sanity Bot Reviewed-by: Gunnar Sletta --- src/gui/kernel/qopenglcontext.cpp | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'src/gui/kernel/qopenglcontext.cpp') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 92a651ddf4..883b60961e 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -214,6 +214,11 @@ QOpenGLFunctions *QOpenGLContext::functions() const /*! If surface is 0 this is equivalent to calling doneCurrent(). + + Do not call this function from a different thread than the one the QOpenGLContext instance lives in. If + you wish to use QOpenGLContext from a different thread you should first call make sure it's not current + in the current thread, by calling doneCurrent() if necessary. Then call moveToThread(otherThread) + before using it in the other thread. */ bool QOpenGLContext::makeCurrent(QSurface *surface) { @@ -414,6 +419,28 @@ void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx) } } +/*! + \class QOpenGLSharedResource + \internal + \since 5.0 + \brief The QOpenGLSharedResource class is used to keep track of resources that + are shared between OpenGL contexts (like textures, framebuffer objects, shader + programs, etc), and clean them up in a safe way when they're no longer needed. + + The QOpenGLSharedResource instance should never be deleted, instead free() + should be called when it's no longer needed. Thus it will be put on a queue + and freed at an appropriate time (when a context in the share group becomes + current). + + The sub-class needs to implement two pure virtual functions. The first, + freeResource() must be implemented to actually do the freeing, for example + call glDeleteTextures() on a texture id. Qt makes sure a valid context in + the resource's share group is current at the time. The other, invalidateResource(), + is called by Qt in the circumstance when the last context in the share group is + destroyed before free() has been called. The implementation of invalidateResource() + should set any identifiers to 0 or set a flag to prevent them from being used + later on. +*/ QOpenGLSharedResource::QOpenGLSharedResource(QOpenGLContextGroup *group) : m_group(group) { @@ -444,6 +471,15 @@ void QOpenGLSharedResource::free() } } +/*! + \class QOpenGLSharedResourceGuard + \internal + \since 5.0 + \brief The QOpenGLSharedResourceGuard class is a convenience sub-class of + QOpenGLSharedResource to be used to track a single OpenGL object with a + GLuint identifier. The constructor takes a function pointer to a function + that will be used to free the resource if and when necessary. +*/ void QOpenGLSharedResourceGuard::freeResource(QOpenGLContext *context) { if (m_id) { @@ -453,6 +489,21 @@ void QOpenGLSharedResourceGuard::freeResource(QOpenGLContext *context) } } +/*! + \class QOpenGLMultiGroupSharedResource + \internal + \since 5.0 + \brief The QOpenGLMultiGroupSharedResource keeps track of a shared resource + that might be needed from multiple contexts, like a glyph cache or gradient + cache. One instance of the object is created for each group when + necessary. The shared resource instance should have a constructor that + takes a QOpenGLContext *. To get an instance for a given context one calls + T *QOpenGLMultiGroupSharedResource::value(context), where T is a sub-class + of QOpenGLSharedResource. + + You should not call free() on QOpenGLSharedResources owned by a + QOpenGLMultiGroupSharedResource instance. +*/ QOpenGLMultiGroupSharedResource::QOpenGLMultiGroupSharedResource() : active(0) { -- cgit v1.2.3 From 1056d02ee07ab9bba3a4dd9f5fd483d45773e665 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Tue, 30 Aug 2011 10:12:46 +0200 Subject: Cause fatal error when trying to make a context current in wrong thread. Since QOpenGLContext is now a QObject, it needs to be moved to, or created in, the thread where it's going to be used. Change-Id: I7ed12b25e75c84bb12be8c7102e46e9a242fc2df Reviewed-on: http://codereview.qt.nokia.com/3858 Reviewed-by: Qt Sanity Bot Reviewed-by: Gunnar Sletta --- src/gui/kernel/qopenglcontext.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/gui/kernel/qopenglcontext.cpp') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index 883b60961e..e61c117bfa 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -226,6 +226,9 @@ bool QOpenGLContext::makeCurrent(QSurface *surface) if (!d->platformGLContext) return false; + if (thread() != QThread::currentThread()) + qFatal("Cannot make QOpenGLContext current in a different thread"); + if (!surface) { doneCurrent(); return true; -- cgit v1.2.3 From a3b026475483f9377248b2a00e55da28d17258d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 29 Aug 2011 12:45:39 +0200 Subject: Clean up shared resources immediately as the last context is destroyed. By not waiting until deleteLater() kicks in it's easier to auto-test. We can now add a test case for what happens when a shared resource is still valid while the last context is destroyed. Change-Id: I72963928e6a921e49ed59a79e2579b497ba37ccf Reviewed-on: http://codereview.qt.nokia.com/3732 Reviewed-by: Qt Sanity Bot Reviewed-by: Gunnar Sletta --- src/gui/kernel/qopenglcontext.cpp | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'src/gui/kernel/qopenglcontext.cpp') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index e61c117bfa..d5b34c2f9b 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -360,17 +360,7 @@ QOpenGLContextGroup::QOpenGLContextGroup() QOpenGLContextGroup::~QOpenGLContextGroup() { Q_D(QOpenGLContextGroup); - - QList::iterator it = d->m_sharedResources.begin(); - QList::iterator end = d->m_sharedResources.end(); - - while (it != end) { - (*it)->invalidateResource(); - (*it)->m_group = 0; - ++it; - } - - qDeleteAll(d->m_pendingDeletion.begin(), d->m_pendingDeletion.end()); + d->cleanup(); } QList QOpenGLContextGroup::shares() const @@ -402,8 +392,27 @@ void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx) if (ctx == m_context && !m_shares.isEmpty()) m_context = m_shares.first(); - if (!m_refs.deref()) + if (!m_refs.deref()) { + cleanup(); q->deleteLater(); + } +} + +void QOpenGLContextGroupPrivate::cleanup() +{ + QList::iterator it = m_sharedResources.begin(); + QList::iterator end = m_sharedResources.end(); + + while (it != end) { + (*it)->invalidateResource(); + (*it)->m_group = 0; + ++it; + } + + m_sharedResources.clear(); + + qDeleteAll(m_pendingDeletion.begin(), m_pendingDeletion.end()); + m_pendingDeletion.clear(); } void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx) -- cgit v1.2.3 From fa42faaee527b9822500cd9a69023be817083d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 12 Sep 2011 14:53:20 +0200 Subject: Implemented texture cache for GL paint engine in QtGui. This is simpler than the existing texture cache in QtOpenGL, as it only serves the GL paint engine. There's one per context group, to simplify the design and to prevent performance degradations. Change-Id: I61e3c9a444d8e246a8b38da019a56f2c0a533c0c Reviewed-on: http://codereview.qt-project.org/4674 Reviewed-by: Qt Sanity Bot Reviewed-by: Kim M. Kalland --- src/gui/kernel/qopenglcontext.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/gui/kernel/qopenglcontext.cpp') diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp index d5b34c2f9b..22d003d4e9 100644 --- a/src/gui/kernel/qopenglcontext.cpp +++ b/src/gui/kernel/qopenglcontext.cpp @@ -566,6 +566,17 @@ QOpenGLSharedResource *QOpenGLMultiGroupSharedResource::value(QOpenGLContext *co return group->d_func()->m_resources.value(this, 0); } +QList QOpenGLMultiGroupSharedResource::resources() const +{ + QList result; + for (QList::const_iterator it = m_groups.constBegin(); it != m_groups.constEnd(); ++it) { + QOpenGLSharedResource *resource = (*it)->d_func()->m_resources.value(const_cast(this), 0); + if (resource) + result << resource; + } + return result; +} + void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContext *ctx) { QOpenGLSharedResource *resource = value(ctx); -- cgit v1.2.3