165QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)
167 QGuiGLThreadContext *threadContext = qwindow_context_storage()->localData();
168 if (!threadContext) {
169 if (!QThread::currentThread()) {
170 qWarning(
"No QTLS available. currentContext won't work");
176 threadContext =
new QGuiGLThreadContext;
177 qwindow_context_storage()->setLocalData(threadContext);
179 QOpenGLContext *previous = threadContext->context;
180 threadContext->context = context;
184int QOpenGLContextPrivate::maxTextureSize()
186 if (max_texture_size != -1)
187 return max_texture_size;
190 QOpenGLFunctions *funcs = q->functions();
191 funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
193#if !QT_CONFIG(opengles2)
194 if (!q->isOpenGLES()) {
195 GLenum proxy = GL_PROXY_TEXTURE_2D;
199 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
201 QOpenGLExtraFunctions *extraFuncs = q->extraFunctions();
202 extraFuncs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
205 return max_texture_size;
211 if (next > max_texture_size)
213 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
214 extraFuncs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
215 }
while (next > size);
217 max_texture_size = size;
221 return max_texture_size;
312void QOpenGLContext::setScreen(QScreen *screen)
316 disconnect(d->screen, SIGNAL(destroyed(QObject*)),
this, SLOT(_q_screenDestroyed(QObject*)));
319 d->screen = QGuiApplication::primaryScreen();
321 connect(d->screen, SIGNAL(destroyed(QObject*)),
this, SLOT(_q_screenDestroyed(QObject*)));
387void QOpenGLContextPrivate::adopt(QPlatformOpenGLContext *context)
391 platformGLContext = context;
392 platformGLContext->setContext(q);
393 platformGLContext->initialize();
395 if (!platformGLContext->isSharing())
396 shareContext =
nullptr;
397 shareGroup = shareContext ? shareContext->shareGroup() :
new QOpenGLContextGroup;
398 shareGroup->d_func()->addContext(q);
657bool QOpenGLContext::makeCurrent(QSurface *surface)
663 if (Q_UNLIKELY(!qApp->testAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity)
664 && thread() != QThread::currentThread())) {
665 qFatal(
"Cannot make QOpenGLContext current in a different thread");
673 if (!surface->surfaceHandle())
675 if (!surface->supportsOpenGL()) {
676 qWarning() <<
"QOpenGLContext::makeCurrent() called with non-opengl surface" << surface;
680 if (!d->platformGLContext->makeCurrent(surface->surfaceHandle()))
683 QOpenGLContextPrivate::setCurrentContext(
this);
685 QOpenGLContextPrivate::toggleMakeCurrentTracker(
this,
true);
688 d->surface = surface;
690 static bool needsWorkaroundSet =
false;
691 static bool needsWorkaround =
false;
693 if (!needsWorkaroundSet) {
696 env = qgetenv(QByteArrayLiteral(
"QT_ANDROID_DISABLE_GLYPH_CACHE_WORKAROUND"));
697 needsWorkaround = env.isEmpty() || env == QByteArrayLiteral(
"0") || env == QByteArrayLiteral(
"false");
699 env = qgetenv(QByteArrayLiteral(
"QT_ENABLE_GLYPH_CACHE_WORKAROUND"));
700 if (env == QByteArrayLiteral(
"1") || env == QByteArrayLiteral(
"true"))
701 needsWorkaround =
true;
703 if (!needsWorkaround) {
704 const char *rendererString =
reinterpret_cast<
const char *>(functions()->glGetString(GL_RENDERER));
707 qstrncmp(rendererString,
"Mali-4xx", 6) == 0
708 || qstrcmp(rendererString,
"Mali-T880") == 0
709 || qstrncmp(rendererString,
"Adreno (TM) 2xx", 13) == 0
710 || qstrncmp(rendererString,
"Adreno 2xx", 8) == 0
711 || qstrncmp(rendererString,
"Adreno (TM) 3xx", 13) == 0
712 || qstrncmp(rendererString,
"Adreno 3xx", 8) == 0
713 || qstrncmp(rendererString,
"Adreno (TM) 4xx", 13) == 0
714 || qstrncmp(rendererString,
"Adreno 4xx", 8) == 0
715 || qstrncmp(rendererString,
"Adreno (TM) 5xx", 13) == 0
716 || qstrncmp(rendererString,
"Adreno 5xx", 8) == 0
717 || qstrncmp(rendererString,
"Adreno (TM) 6xx", 13) == 0
718 || qstrncmp(rendererString,
"Adreno 6xx", 8) == 0
719 || qstrcmp(rendererString,
"GC800 core") == 0
720 || qstrcmp(rendererString,
"GC1000 core") == 0
721 || strstr(rendererString,
"GC2000") !=
nullptr
722 || qstrcmp(rendererString,
"Immersion.16") == 0
723 || qstrncmp(rendererString,
"Apple Mx", 7) == 0;
725 needsWorkaroundSet =
true;
729 d->workaround_brokenFBOReadBack =
true;
731 d->shareGroup->d_func()->deletePendingResources(
this);
743void QOpenGLContext::doneCurrent()
748 if (QOpenGLContext::currentContext() ==
this)
749 d->shareGroup->d_func()->deletePendingResources(
this);
750 d->platformGLContext->doneCurrent();
753 QOpenGLContextPrivate::setCurrentContext(
nullptr);
755 d->surface =
nullptr;
777void QOpenGLContext::swapBuffers(QSurface *surface)
784 qWarning(
"QOpenGLContext::swapBuffers() called with null argument");
788 if (!surface->supportsOpenGL()) {
789 qWarning(
"QOpenGLContext::swapBuffers() called with non-opengl surface");
793 QPlatformSurface *surfaceHandle = surface->surfaceHandle();
797#if !defined(QT_NO_DEBUG)
798 if (!QOpenGLContextPrivate::toggleMakeCurrentTracker(
this,
false))
799 qWarning(
"QOpenGLContext::swapBuffers() called without corresponding makeCurrent()");
801 if (surface->format().swapBehavior() == QSurfaceFormat::SingleBuffer)
802 functions()->glFlush();
803 d->platformGLContext->swapBuffers(surfaceHandle);
1054void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx)
1056 Q_Q(QOpenGLContextGroup);
1058 bool deleteObject =
false;
1061 const auto locker = qt_scoped_lock(m_mutex);
1062 m_shares.removeOne(ctx);
1064 if (ctx == m_context && !m_shares.isEmpty())
1065 m_context = m_shares.constFirst();
1067 if (!m_refs.deref()) {
1069 deleteObject =
true;
1074 if (q->thread() == QThread::currentThread())
1081void QOpenGLContextGroupPrivate::cleanup()
1083 Q_Q(QOpenGLContextGroup);
1085 QHash<QOpenGLMultiGroupSharedResource *, QOpenGLSharedResource *>::const_iterator it, end;
1086 end = m_resources.constEnd();
1087 for (it = m_resources.constBegin(); it != end; ++it)
1088 it.key()->cleanup(q, it.value());
1089 m_resources.clear();
1092 QList<QOpenGLSharedResource *>::iterator it = m_sharedResources.begin();
1093 QList<QOpenGLSharedResource *>::iterator end = m_sharedResources.end();
1096 (*it)->invalidateResource();
1097 (*it)->m_group =
nullptr;
1101 m_sharedResources.clear();
1103 qDeleteAll(m_pendingDeletion.begin(), m_pendingDeletion.end());
1104 m_pendingDeletion.clear();
1107void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx)
1109 const auto locker = qt_scoped_lock(m_mutex);
1111 const QList<QOpenGLSharedResource *> pending = m_pendingDeletion;
1112 m_pendingDeletion.clear();
1114 QList<QOpenGLSharedResource *>::const_iterator it = pending.begin();
1115 QList<QOpenGLSharedResource *>::const_iterator end = pending.end();
1117 (*it)->freeResource(ctx);
1159void QOpenGLSharedResource::free()
1166 const auto locker = qt_scoped_lock(m_group->d_func()->m_mutex);
1167 m_group->d_func()->m_sharedResources.removeOne(
this);
1168 m_group->d_func()->m_pendingDeletion <<
this;
1171 QOpenGLContext *current = QOpenGLContext::currentContext();
1172 if (current && current->shareGroup() == m_group) {
1173 m_group->d_func()->deletePendingResources(current);
1225QOpenGLMultiGroupSharedResource::~QOpenGLMultiGroupSharedResource()
1227#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1228 qDebug(
"Deleting context group resource %p. Group size: %d.",
this, m_groups.size());
1230 for (
int i = 0; i < m_groups.size(); ++i) {
1231 if (!m_groups.at(i)->shares().isEmpty()) {
1232 QOpenGLContext *context = m_groups.at(i)->shares().constFirst();
1233 QOpenGLSharedResource *resource = value(context);
1237 m_groups.at(i)->d_func()->m_resources.remove(
this);
1241 if (active.loadRelaxed() != 0) {
1242 qWarning(
"QtGui: Resources are still available at program shutdown.\n"
1243 " This is possibly caused by a leaked QOpenGLWidget, \n"
1244 " QOpenGLFramebufferObject or QOpenGLPixelBuffer.");
1249void QOpenGLMultiGroupSharedResource::insert(QOpenGLContext *context, QOpenGLSharedResource *value)
1251#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1252 qDebug(
"Inserting context group resource %p for context %p, managed by %p.", value, context,
this);
1254 QOpenGLContextGroup *group = context->shareGroup();
1255 Q_ASSERT(!group->d_func()->m_resources.contains(
this));
1256 group->d_func()->m_resources.insert(
this, value);
1257 m_groups.append(group);
1267QList<QOpenGLSharedResource *> QOpenGLMultiGroupSharedResource::resources()
const
1269 QList<QOpenGLSharedResource *> result;
1270 for (QList<QOpenGLContextGroup *>::const_iterator it = m_groups.constBegin(); it != m_groups.constEnd(); ++it) {
1271 QOpenGLSharedResource *resource = (*it)->d_func()->m_resources.value(
const_cast<QOpenGLMultiGroupSharedResource *>(
this),
nullptr);
1278void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContextGroup *group, QOpenGLSharedResource *value)
1280#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1281 qDebug(
"Cleaning up context group resource %p, for group %p in thread %p.",
this, group, QThread::currentThread());
1283 value->invalidateResource();
1287 Q_ASSERT(m_groups.contains(group));
1288 m_groups.removeOne(group);
QOpenGLContext * qt_gl_global_share_context()
void qt_gl_set_global_share_context(QOpenGLContext *context)
static QOpenGLContext * global_share_context