195QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)
197 QGuiGLThreadContext *threadContext = qwindow_context_storage()->localData();
198 if (!threadContext) {
199 if (!QThread::currentThread()) {
200 qWarning(
"No QTLS available. currentContext won't work");
206 threadContext =
new QGuiGLThreadContext;
207 qwindow_context_storage()->setLocalData(threadContext);
209 QOpenGLContext *previous = threadContext->context;
210 threadContext->context = context;
214int QOpenGLContextPrivate::maxTextureSize()
216 if (max_texture_size != -1)
217 return max_texture_size;
220 QOpenGLFunctions *funcs = q->functions();
221 funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
223#if !QT_CONFIG(opengles2)
224 if (!q->isOpenGLES()) {
225 GLenum proxy = GL_PROXY_TEXTURE_2D;
229 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
231 QOpenGLExtraFunctions *extraFuncs = q->extraFunctions();
232 extraFuncs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
235 return max_texture_size;
241 if (next > max_texture_size)
243 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
244 extraFuncs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
245 }
while (next > size);
247 max_texture_size = size;
251 return max_texture_size;
342void QOpenGLContext::setScreen(QScreen *screen)
346 disconnect(d->screen, SIGNAL(destroyed(QObject*)),
this, SLOT(_q_screenDestroyed(QObject*)));
349 d->screen = QGuiApplication::primaryScreen();
351 connect(d->screen, SIGNAL(destroyed(QObject*)),
this, SLOT(_q_screenDestroyed(QObject*)));
417void QOpenGLContextPrivate::adopt(QPlatformOpenGLContext *context)
421 platformGLContext = context;
422 platformGLContext->setContext(q);
423 platformGLContext->initialize();
425 if (!platformGLContext->isSharing())
426 shareContext =
nullptr;
427 shareGroup = shareContext ? shareContext->shareGroup() :
new QOpenGLContextGroup;
428 shareGroup->d_func()->addContext(q);
687bool QOpenGLContext::makeCurrent(QSurface *surface)
693 if (Q_UNLIKELY(!qApp->testAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity)
694 && thread() != QThread::currentThread())) {
695 qFatal(
"Cannot make QOpenGLContext current in a different thread");
703 if (!surface->surfaceHandle())
705 if (!surface->supportsOpenGL()) {
706 qWarning() <<
"QOpenGLContext::makeCurrent() called with non-opengl surface" << surface;
710 if (!d->platformGLContext->makeCurrent(surface->surfaceHandle()))
713 QOpenGLContextPrivate::setCurrentContext(
this);
715 QOpenGLContextPrivate::toggleMakeCurrentTracker(
this,
true);
718 d->surface = surface;
720 static bool needsWorkaroundSet =
false;
721 static bool needsWorkaround =
false;
723 if (!needsWorkaroundSet) {
726 env = qgetenv(QByteArrayLiteral(
"QT_ANDROID_DISABLE_GLYPH_CACHE_WORKAROUND"));
727 needsWorkaround = env.isEmpty() || env == QByteArrayLiteral(
"0") || env == QByteArrayLiteral(
"false");
729 env = qgetenv(QByteArrayLiteral(
"QT_ENABLE_GLYPH_CACHE_WORKAROUND"));
730 if (env == QByteArrayLiteral(
"1") || env == QByteArrayLiteral(
"true"))
731 needsWorkaround =
true;
733 if (!needsWorkaround) {
734 const char *rendererString =
reinterpret_cast<
const char *>(functions()->glGetString(GL_RENDERER));
737 qstrncmp(rendererString,
"Mali-4xx", 6) == 0
738 || qstrcmp(rendererString,
"Mali-T880") == 0
739 || qstrncmp(rendererString,
"Adreno (TM) 2xx", 13) == 0
740 || qstrncmp(rendererString,
"Adreno 2xx", 8) == 0
741 || qstrncmp(rendererString,
"Adreno (TM) 3xx", 13) == 0
742 || qstrncmp(rendererString,
"Adreno 3xx", 8) == 0
743 || qstrncmp(rendererString,
"Adreno (TM) 4xx", 13) == 0
744 || qstrncmp(rendererString,
"Adreno 4xx", 8) == 0
745 || qstrncmp(rendererString,
"Adreno (TM) 5xx", 13) == 0
746 || qstrncmp(rendererString,
"Adreno 5xx", 8) == 0
747 || qstrncmp(rendererString,
"Adreno (TM) 6xx", 13) == 0
748 || qstrncmp(rendererString,
"Adreno 6xx", 8) == 0
749 || qstrcmp(rendererString,
"GC800 core") == 0
750 || qstrcmp(rendererString,
"GC1000 core") == 0
751 || strstr(rendererString,
"GC2000") !=
nullptr
752 || qstrcmp(rendererString,
"Immersion.16") == 0
753 || qstrncmp(rendererString,
"Apple Mx", 7) == 0;
755 needsWorkaroundSet =
true;
759 d->workaround_brokenFBOReadBack =
true;
761 d->shareGroup->d_func()->deletePendingResources(
this);
773void QOpenGLContext::doneCurrent()
778 if (QOpenGLContext::currentContext() ==
this)
779 d->shareGroup->d_func()->deletePendingResources(
this);
780 d->platformGLContext->doneCurrent();
783 QOpenGLContextPrivate::setCurrentContext(
nullptr);
785 d->surface =
nullptr;
807void QOpenGLContext::swapBuffers(QSurface *surface)
814 qWarning(
"QOpenGLContext::swapBuffers() called with null argument");
818 if (!surface->supportsOpenGL()) {
819 qWarning(
"QOpenGLContext::swapBuffers() called with non-opengl surface");
823 QPlatformSurface *surfaceHandle = surface->surfaceHandle();
827#if !defined(QT_NO_DEBUG)
828 if (!QOpenGLContextPrivate::toggleMakeCurrentTracker(
this,
false))
829 qWarning(
"QOpenGLContext::swapBuffers() called without corresponding makeCurrent()");
831 if (surface->format().swapBehavior() == QSurfaceFormat::SingleBuffer)
832 functions()->glFlush();
833 d->platformGLContext->swapBuffers(surfaceHandle);
1007QOpenGLContext *QOpenGLContext::globalShareContext()
1011 static QMutex mutex;
1012 QMutexLocker locker(&mutex);
1015 if (!qt_gl_global_share_context() && qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts)) {
1016 QOpenGLContext *ctx =
new QOpenGLContext;
1017 ctx->setFormat(QSurfaceFormat::defaultFormat());
1019 ctx->moveToThread(qGuiApp->thread());
1020 qt_gl_set_global_share_context(ctx);
1021 QGuiApplicationPrivate::instance()->ownGlobalShareContext =
true;
1023 return qt_gl_global_share_context();
1102void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx)
1104 Q_Q(QOpenGLContextGroup);
1106 bool deleteObject =
false;
1109 const auto locker = qt_scoped_lock(m_mutex);
1110 m_shares.removeOne(ctx);
1112 if (ctx == m_context && !m_shares.isEmpty())
1113 m_context = m_shares.constFirst();
1115 if (!m_refs.deref()) {
1117 deleteObject =
true;
1122 if (q->thread() == QThread::currentThread())
1129void QOpenGLContextGroupPrivate::cleanup()
1131 Q_Q(QOpenGLContextGroup);
1133 QHash<QOpenGLMultiGroupSharedResource *, QOpenGLSharedResource *>::const_iterator it, end;
1134 end = m_resources.constEnd();
1135 for (it = m_resources.constBegin(); it != end; ++it)
1136 it.key()->cleanup(q, it.value());
1137 m_resources.clear();
1140 QList<QOpenGLSharedResource *>::iterator it = m_sharedResources.begin();
1141 QList<QOpenGLSharedResource *>::iterator end = m_sharedResources.end();
1144 (*it)->invalidateResource();
1145 (*it)->m_group =
nullptr;
1149 m_sharedResources.clear();
1151 qDeleteAll(m_pendingDeletion.begin(), m_pendingDeletion.end());
1152 m_pendingDeletion.clear();
1155void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx)
1157 const auto locker = qt_scoped_lock(m_mutex);
1159 const QList<QOpenGLSharedResource *> pending = m_pendingDeletion;
1160 m_pendingDeletion.clear();
1162 QList<QOpenGLSharedResource *>::const_iterator it = pending.begin();
1163 QList<QOpenGLSharedResource *>::const_iterator end = pending.end();
1165 (*it)->freeResource(ctx);
1207void QOpenGLSharedResource::free()
1214 const auto locker = qt_scoped_lock(m_group->d_func()->m_mutex);
1215 m_group->d_func()->m_sharedResources.removeOne(
this);
1216 m_group->d_func()->m_pendingDeletion <<
this;
1219 QOpenGLContext *current = QOpenGLContext::currentContext();
1220 if (current && current->shareGroup() == m_group) {
1221 m_group->d_func()->deletePendingResources(current);
1273QOpenGLMultiGroupSharedResource::~QOpenGLMultiGroupSharedResource()
1275#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1276 qDebug(
"Deleting context group resource %p. Group size: %d.",
this, m_groups.size());
1278 for (
int i = 0; i < m_groups.size(); ++i) {
1279 if (!m_groups.at(i)->shares().isEmpty()) {
1280 QOpenGLContext *context = m_groups.at(i)->shares().constFirst();
1281 QOpenGLSharedResource *resource = value(context);
1285 m_groups.at(i)->d_func()->m_resources.remove(
this);
1289 if (active.loadRelaxed() != 0) {
1290 qWarning(
"QtGui: Resources are still available at program shutdown.\n"
1291 " This is possibly caused by a leaked QOpenGLWidget, \n"
1292 " QOpenGLFramebufferObject or QOpenGLPixelBuffer.");
1297void QOpenGLMultiGroupSharedResource::insert(QOpenGLContext *context, QOpenGLSharedResource *value)
1299#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1300 qDebug(
"Inserting context group resource %p for context %p, managed by %p.", value, context,
this);
1302 QOpenGLContextGroup *group = context->shareGroup();
1303 Q_ASSERT(!group->d_func()->m_resources.contains(
this));
1304 group->d_func()->m_resources.insert(
this, value);
1305 m_groups.append(group);
1315QList<QOpenGLSharedResource *> QOpenGLMultiGroupSharedResource::resources()
const
1317 QList<QOpenGLSharedResource *> result;
1318 for (QList<QOpenGLContextGroup *>::const_iterator it = m_groups.constBegin(); it != m_groups.constEnd(); ++it) {
1319 QOpenGLSharedResource *resource = (*it)->d_func()->m_resources.value(
const_cast<QOpenGLMultiGroupSharedResource *>(
this),
nullptr);
1326void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContextGroup *group, QOpenGLSharedResource *value)
1328#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1329 qDebug(
"Cleaning up context group resource %p, for group %p in thread %p.",
this, group, QThread::currentThread());
1331 value->invalidateResource();
1335 Q_ASSERT(m_groups.contains(group));
1336 m_groups.removeOne(group);
QOpenGLContext * qt_gl_global_share_context()
void qt_gl_set_global_share_context(QOpenGLContext *context)
static QOpenGLContext * global_share_context