166QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)
168 QGuiGLThreadContext *threadContext = qwindow_context_storage()->localData();
169 if (!threadContext) {
170 if (!QThread::currentThread()) {
171 qWarning(
"No QTLS available. currentContext won't work");
177 threadContext =
new QGuiGLThreadContext;
178 qwindow_context_storage()->setLocalData(threadContext);
180 QOpenGLContext *previous = threadContext->context;
181 threadContext->context = context;
185int QOpenGLContextPrivate::maxTextureSize()
187 if (max_texture_size != -1)
188 return max_texture_size;
191 QOpenGLFunctions *funcs = q->functions();
192 funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
194#if !QT_CONFIG(opengles2)
195 if (!q->isOpenGLES()) {
196 GLenum proxy = GL_PROXY_TEXTURE_2D;
200 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
202 QOpenGLExtraFunctions *extraFuncs = q->extraFunctions();
203 extraFuncs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
206 return max_texture_size;
212 if (next > max_texture_size)
214 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
215 extraFuncs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
216 }
while (next > size);
218 max_texture_size = size;
222 return max_texture_size;
313void QOpenGLContext::setScreen(QScreen *screen)
317 disconnect(d->screen, SIGNAL(destroyed(QObject*)),
this, SLOT(_q_screenDestroyed(QObject*)));
320 d->screen = QGuiApplication::primaryScreen();
322 connect(d->screen, SIGNAL(destroyed(QObject*)),
this, SLOT(_q_screenDestroyed(QObject*)));
388void QOpenGLContextPrivate::adopt(QPlatformOpenGLContext *context)
392 platformGLContext = context;
393 platformGLContext->setContext(q);
394 platformGLContext->initialize();
396 if (!platformGLContext->isSharing())
397 shareContext =
nullptr;
398 shareGroup = shareContext ? shareContext->shareGroup() :
new QOpenGLContextGroup;
399 shareGroup->d_func()->addContext(q);
658bool QOpenGLContext::makeCurrent(QSurface *surface)
664 if (Q_UNLIKELY(!qApp->testAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity)
665 && thread() != QThread::currentThread())) {
666 qFatal(
"Cannot make QOpenGLContext current in a different thread");
674 if (!surface->surfaceHandle())
676 if (!surface->supportsOpenGL()) {
677 qWarning() <<
"QOpenGLContext::makeCurrent() called with non-opengl surface" << surface;
681 if (!d->platformGLContext->makeCurrent(surface->surfaceHandle()))
684 QOpenGLContextPrivate::setCurrentContext(
this);
686 QOpenGLContextPrivate::toggleMakeCurrentTracker(
this,
true);
689 d->surface = surface;
691 static bool needsWorkaroundSet =
false;
692 static bool needsWorkaround =
false;
694 if (!needsWorkaroundSet) {
697 env = qgetenv(QByteArrayLiteral(
"QT_ANDROID_DISABLE_GLYPH_CACHE_WORKAROUND"));
698 needsWorkaround = env.isEmpty() || env == QByteArrayLiteral(
"0") || env == QByteArrayLiteral(
"false");
700 env = qgetenv(QByteArrayLiteral(
"QT_ENABLE_GLYPH_CACHE_WORKAROUND"));
701 if (env == QByteArrayLiteral(
"1") || env == QByteArrayLiteral(
"true"))
702 needsWorkaround =
true;
704 if (!needsWorkaround) {
705 const char *rendererString =
reinterpret_cast<
const char *>(functions()->glGetString(GL_RENDERER));
708 qstrncmp(rendererString,
"Mali-4xx", 6) == 0
709 || qstrcmp(rendererString,
"Mali-T880") == 0
710 || qstrncmp(rendererString,
"Adreno (TM) 2xx", 13) == 0
711 || qstrncmp(rendererString,
"Adreno 2xx", 8) == 0
712 || qstrncmp(rendererString,
"Adreno (TM) 3xx", 13) == 0
713 || qstrncmp(rendererString,
"Adreno 3xx", 8) == 0
714 || qstrncmp(rendererString,
"Adreno (TM) 4xx", 13) == 0
715 || qstrncmp(rendererString,
"Adreno 4xx", 8) == 0
716 || qstrncmp(rendererString,
"Adreno (TM) 5xx", 13) == 0
717 || qstrncmp(rendererString,
"Adreno 5xx", 8) == 0
718 || qstrncmp(rendererString,
"Adreno (TM) 6xx", 13) == 0
719 || qstrncmp(rendererString,
"Adreno 6xx", 8) == 0
720 || qstrcmp(rendererString,
"GC800 core") == 0
721 || qstrcmp(rendererString,
"GC1000 core") == 0
722 || strstr(rendererString,
"GC2000") !=
nullptr
723 || qstrcmp(rendererString,
"Immersion.16") == 0
724 || qstrncmp(rendererString,
"Apple Mx", 7) == 0;
726 needsWorkaroundSet =
true;
730 d->workaround_brokenFBOReadBack =
true;
732 d->shareGroup->d_func()->deletePendingResources(
this);
744void QOpenGLContext::doneCurrent()
749 if (QOpenGLContext::currentContext() ==
this)
750 d->shareGroup->d_func()->deletePendingResources(
this);
751 d->platformGLContext->doneCurrent();
754 QOpenGLContextPrivate::setCurrentContext(
nullptr);
756 d->surface =
nullptr;
778void QOpenGLContext::swapBuffers(QSurface *surface)
785 qWarning(
"QOpenGLContext::swapBuffers() called with null argument");
789 if (!surface->supportsOpenGL()) {
790 qWarning(
"QOpenGLContext::swapBuffers() called with non-opengl surface");
794 QPlatformSurface *surfaceHandle = surface->surfaceHandle();
798#if !defined(QT_NO_DEBUG)
799 if (!QOpenGLContextPrivate::toggleMakeCurrentTracker(
this,
false))
800 qWarning(
"QOpenGLContext::swapBuffers() called without corresponding makeCurrent()");
802 if (surface->format().swapBehavior() == QSurfaceFormat::SingleBuffer)
803 functions()->glFlush();
804 d->platformGLContext->swapBuffers(surfaceHandle);
969QOpenGLContext *QOpenGLContext::globalShareContext()
974 QMutexLocker locker(&mutex);
977 if (!qt_gl_global_share_context() && qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts)) {
978 QOpenGLContext *ctx =
new QOpenGLContext;
979 ctx->setFormat(QSurfaceFormat::defaultFormat());
981 ctx->moveToThread(qGuiApp->thread());
982 qt_gl_set_global_share_context(ctx);
983 QGuiApplicationPrivate::instance()->ownGlobalShareContext =
true;
985 return qt_gl_global_share_context();
1064void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx)
1066 Q_Q(QOpenGLContextGroup);
1068 bool deleteObject =
false;
1071 const auto locker = qt_scoped_lock(m_mutex);
1072 m_shares.removeOne(ctx);
1074 if (ctx == m_context && !m_shares.isEmpty())
1075 m_context = m_shares.constFirst();
1077 if (!m_refs.deref()) {
1079 deleteObject =
true;
1084 if (q->thread() == QThread::currentThread())
1091void QOpenGLContextGroupPrivate::cleanup()
1093 Q_Q(QOpenGLContextGroup);
1095 QHash<QOpenGLMultiGroupSharedResource *, QOpenGLSharedResource *>::const_iterator it, end;
1096 end = m_resources.constEnd();
1097 for (it = m_resources.constBegin(); it != end; ++it)
1098 it.key()->cleanup(q, it.value());
1099 m_resources.clear();
1102 QList<QOpenGLSharedResource *>::iterator it = m_sharedResources.begin();
1103 QList<QOpenGLSharedResource *>::iterator end = m_sharedResources.end();
1106 (*it)->invalidateResource();
1107 (*it)->m_group =
nullptr;
1111 m_sharedResources.clear();
1113 qDeleteAll(m_pendingDeletion.begin(), m_pendingDeletion.end());
1114 m_pendingDeletion.clear();
1117void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx)
1119 const auto locker = qt_scoped_lock(m_mutex);
1121 const QList<QOpenGLSharedResource *> pending = m_pendingDeletion;
1122 m_pendingDeletion.clear();
1124 QList<QOpenGLSharedResource *>::const_iterator it = pending.begin();
1125 QList<QOpenGLSharedResource *>::const_iterator end = pending.end();
1127 (*it)->freeResource(ctx);
1169void QOpenGLSharedResource::free()
1176 const auto locker = qt_scoped_lock(m_group->d_func()->m_mutex);
1177 m_group->d_func()->m_sharedResources.removeOne(
this);
1178 m_group->d_func()->m_pendingDeletion <<
this;
1181 QOpenGLContext *current = QOpenGLContext::currentContext();
1182 if (current && current->shareGroup() == m_group) {
1183 m_group->d_func()->deletePendingResources(current);
1235QOpenGLMultiGroupSharedResource::~QOpenGLMultiGroupSharedResource()
1237#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1238 qDebug(
"Deleting context group resource %p. Group size: %d.",
this, m_groups.size());
1240 for (
int i = 0; i < m_groups.size(); ++i) {
1241 if (!m_groups.at(i)->shares().isEmpty()) {
1242 QOpenGLContext *context = m_groups.at(i)->shares().constFirst();
1243 QOpenGLSharedResource *resource = value(context);
1247 m_groups.at(i)->d_func()->m_resources.remove(
this);
1251 if (active.loadRelaxed() != 0) {
1252 qWarning(
"QtGui: Resources are still available at program shutdown.\n"
1253 " This is possibly caused by a leaked QOpenGLWidget, \n"
1254 " QOpenGLFramebufferObject or QOpenGLPixelBuffer.");
1259void QOpenGLMultiGroupSharedResource::insert(QOpenGLContext *context, QOpenGLSharedResource *value)
1261#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1262 qDebug(
"Inserting context group resource %p for context %p, managed by %p.", value, context,
this);
1264 QOpenGLContextGroup *group = context->shareGroup();
1265 Q_ASSERT(!group->d_func()->m_resources.contains(
this));
1266 group->d_func()->m_resources.insert(
this, value);
1267 m_groups.append(group);
1277QList<QOpenGLSharedResource *> QOpenGLMultiGroupSharedResource::resources()
const
1279 QList<QOpenGLSharedResource *> result;
1280 for (QList<QOpenGLContextGroup *>::const_iterator it = m_groups.constBegin(); it != m_groups.constEnd(); ++it) {
1281 QOpenGLSharedResource *resource = (*it)->d_func()->m_resources.value(
const_cast<QOpenGLMultiGroupSharedResource *>(
this),
nullptr);
1288void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContextGroup *group, QOpenGLSharedResource *value)
1290#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1291 qDebug(
"Cleaning up context group resource %p, for group %p in thread %p.",
this, group, QThread::currentThread());
1293 value->invalidateResource();
1297 Q_ASSERT(m_groups.contains(group));
1298 m_groups.removeOne(group);
QOpenGLContext * qt_gl_global_share_context()
void qt_gl_set_global_share_context(QOpenGLContext *context)
static QOpenGLContext * global_share_context