195QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context)
197 QGuiGLThreadContext *threadContext = qwindow_context_storage()->localData();
198 if (!threadContext) {
202 threadContext =
new QGuiGLThreadContext;
203 qwindow_context_storage()->setLocalData(threadContext);
205 QOpenGLContext *previous = threadContext->context;
206 threadContext->context = context;
210int QOpenGLContextPrivate::maxTextureSize()
212 if (max_texture_size != -1)
213 return max_texture_size;
216 QOpenGLFunctions *funcs = q->functions();
217 funcs->glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
219#if !QT_CONFIG(opengles2)
220 if (!q->isOpenGLES()) {
221 GLenum proxy = GL_PROXY_TEXTURE_2D;
225 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
227 QOpenGLExtraFunctions *extraFuncs = q->extraFunctions();
228 extraFuncs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
231 return max_texture_size;
237 if (next > max_texture_size)
239 funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE,
nullptr);
240 extraFuncs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
241 }
while (next > size);
243 max_texture_size = size;
247 return max_texture_size;
338void QOpenGLContext::setScreen(QScreen *screen)
342 disconnect(d->screen, SIGNAL(destroyed(QObject*)),
this, SLOT(_q_screenDestroyed(QObject*)));
345 d->screen = QGuiApplication::primaryScreen();
347 connect(d->screen, SIGNAL(destroyed(QObject*)),
this, SLOT(_q_screenDestroyed(QObject*)));
413void QOpenGLContextPrivate::adopt(QPlatformOpenGLContext *context)
417 platformGLContext = context;
418 platformGLContext->setContext(q);
419 platformGLContext->initialize();
421 if (!platformGLContext->isSharing())
422 shareContext =
nullptr;
423 shareGroup = shareContext ? shareContext->shareGroup() :
new QOpenGLContextGroup;
424 shareGroup->d_func()->addContext(q);
683bool QOpenGLContext::makeCurrent(QSurface *surface)
689 if (Q_UNLIKELY(!qApp->testAttribute(Qt::AA_DontCheckOpenGLContextThreadAffinity))) {
690 QThread *thr = thread();
691 if (thr && !thr->isCurrentThread())
692 qFatal(
"Cannot make QOpenGLContext current in a different thread");
700 if (!surface->surfaceHandle())
702 if (!surface->supportsOpenGL()) {
703 qWarning() <<
"QOpenGLContext::makeCurrent() called with non-opengl surface" << surface;
707 if (!d->platformGLContext->makeCurrent(surface->surfaceHandle()))
710 QOpenGLContextPrivate::setCurrentContext(
this);
712 QOpenGLContextPrivate::toggleMakeCurrentTracker(
this,
true);
715 d->surface = surface;
717 static bool needsWorkaroundSet =
false;
718 static bool needsWorkaround =
false;
720 if (!needsWorkaroundSet) {
723 env = qgetenv(QByteArrayLiteral(
"QT_ANDROID_DISABLE_GLYPH_CACHE_WORKAROUND"));
724 needsWorkaround = env.isEmpty() || env == QByteArrayLiteral(
"0") || env == QByteArrayLiteral(
"false");
726 env = qgetenv(QByteArrayLiteral(
"QT_ENABLE_GLYPH_CACHE_WORKAROUND"));
727 if (env == QByteArrayLiteral(
"1") || env == QByteArrayLiteral(
"true"))
728 needsWorkaround =
true;
730 if (!needsWorkaround) {
731 const char *rendererString =
reinterpret_cast<
const char *>(functions()->glGetString(GL_RENDERER));
734 qstrncmp(rendererString,
"Mali-4xx", 6) == 0
735 || qstrcmp(rendererString,
"Mali-T880") == 0
736 || qstrncmp(rendererString,
"Adreno (TM) 2xx", 13) == 0
737 || qstrncmp(rendererString,
"Adreno 2xx", 8) == 0
738 || qstrncmp(rendererString,
"Adreno (TM) 3xx", 13) == 0
739 || qstrncmp(rendererString,
"Adreno 3xx", 8) == 0
740 || qstrncmp(rendererString,
"Adreno (TM) 4xx", 13) == 0
741 || qstrncmp(rendererString,
"Adreno 4xx", 8) == 0
742 || qstrncmp(rendererString,
"Adreno (TM) 5xx", 13) == 0
743 || qstrncmp(rendererString,
"Adreno 5xx", 8) == 0
744 || qstrncmp(rendererString,
"Adreno (TM) 6xx", 13) == 0
745 || qstrncmp(rendererString,
"Adreno 6xx", 8) == 0
746 || qstrcmp(rendererString,
"GC800 core") == 0
747 || qstrcmp(rendererString,
"GC1000 core") == 0
748 || strstr(rendererString,
"GC2000") !=
nullptr
749 || qstrcmp(rendererString,
"Immersion.16") == 0
750 || qstrncmp(rendererString,
"Apple Mx", 7) == 0;
752 needsWorkaroundSet =
true;
756 d->workaround_brokenFBOReadBack =
true;
758 d->shareGroup->d_func()->deletePendingResources(
this);
770void QOpenGLContext::doneCurrent()
775 if (QOpenGLContext::currentContext() ==
this)
776 d->shareGroup->d_func()->deletePendingResources(
this);
777 d->platformGLContext->doneCurrent();
780 QOpenGLContextPrivate::setCurrentContext(
nullptr);
782 d->surface =
nullptr;
804void QOpenGLContext::swapBuffers(QSurface *surface)
811 qWarning(
"QOpenGLContext::swapBuffers() called with null argument");
815 if (!surface->supportsOpenGL()) {
816 qWarning(
"QOpenGLContext::swapBuffers() called with non-opengl surface");
820 QPlatformSurface *surfaceHandle = surface->surfaceHandle();
824#if !defined(QT_NO_DEBUG)
825 if (!QOpenGLContextPrivate::toggleMakeCurrentTracker(
this,
false))
826 qWarning(
"QOpenGLContext::swapBuffers() called without corresponding makeCurrent()");
828 if (surface->format().swapBehavior() == QSurfaceFormat::SingleBuffer)
829 functions()->glFlush();
830 d->platformGLContext->swapBuffers(surfaceHandle);
1004QOpenGLContext *QOpenGLContext::globalShareContext()
1008 static QMutex mutex;
1009 QMutexLocker locker(&mutex);
1012 if (!qt_gl_global_share_context() && qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts)) {
1013 QOpenGLContext *ctx =
new QOpenGLContext;
1014 ctx->setFormat(QSurfaceFormat::defaultFormat());
1016 ctx->moveToThread(qGuiApp->thread());
1017 qt_gl_set_global_share_context(ctx);
1018 QGuiApplicationPrivate::instance()->ownGlobalShareContext =
true;
1020 return qt_gl_global_share_context();
1099void QOpenGLContextGroupPrivate::removeContext(QOpenGLContext *ctx)
1101 Q_Q(QOpenGLContextGroup);
1103 bool deleteObject =
false;
1106 const auto locker = qt_scoped_lock(m_mutex);
1107 m_shares.removeOne(ctx);
1109 if (ctx == m_context && !m_shares.isEmpty())
1110 m_context = m_shares.constFirst();
1112 if (!m_refs.deref()) {
1114 deleteObject =
true;
1119 QObjectPrivate::deleteInOwnThread(q);
1122void QOpenGLContextGroupPrivate::cleanup()
1124 Q_Q(QOpenGLContextGroup);
1126 QHash<QOpenGLMultiGroupSharedResource *, QOpenGLSharedResource *>::const_iterator it, end;
1127 end = m_resources.constEnd();
1128 for (it = m_resources.constBegin(); it != end; ++it)
1129 it.key()->cleanup(q, it.value());
1130 m_resources.clear();
1133 QList<QOpenGLSharedResource *>::iterator it = m_sharedResources.begin();
1134 QList<QOpenGLSharedResource *>::iterator end = m_sharedResources.end();
1137 (*it)->invalidateResource();
1138 (*it)->m_group =
nullptr;
1142 m_sharedResources.clear();
1144 qDeleteAll(m_pendingDeletion.begin(), m_pendingDeletion.end());
1145 m_pendingDeletion.clear();
1148void QOpenGLContextGroupPrivate::deletePendingResources(QOpenGLContext *ctx)
1150 const auto locker = qt_scoped_lock(m_mutex);
1152 const QList<QOpenGLSharedResource *> pending = m_pendingDeletion;
1153 m_pendingDeletion.clear();
1155 QList<QOpenGLSharedResource *>::const_iterator it = pending.begin();
1156 QList<QOpenGLSharedResource *>::const_iterator end = pending.end();
1158 (*it)->freeResource(ctx);
1200void QOpenGLSharedResource::free()
1207 const auto locker = qt_scoped_lock(m_group->d_func()->m_mutex);
1208 m_group->d_func()->m_sharedResources.removeOne(
this);
1209 m_group->d_func()->m_pendingDeletion <<
this;
1212 QOpenGLContext *current = QOpenGLContext::currentContext();
1213 if (current && current->shareGroup() == m_group) {
1214 m_group->d_func()->deletePendingResources(current);
1266QOpenGLMultiGroupSharedResource::~QOpenGLMultiGroupSharedResource()
1268#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1269 qDebug(
"Deleting context group resource %p. Group size: %d.",
this, m_groups.size());
1271 for (
int i = 0; i < m_groups.size(); ++i) {
1272 if (!m_groups.at(i)->shares().isEmpty()) {
1273 QOpenGLContext *context = m_groups.at(i)->shares().constFirst();
1274 QOpenGLSharedResource *resource = value(context);
1278 m_groups.at(i)->d_func()->m_resources.remove(
this);
1282 if (active.loadRelaxed() != 0) {
1283 qWarning(
"QtGui: Resources are still available at program shutdown.\n"
1284 " This is possibly caused by a leaked QOpenGLWidget, \n"
1285 " QOpenGLFramebufferObject or QOpenGLPixelBuffer.");
1290void QOpenGLMultiGroupSharedResource::insert(QOpenGLContext *context, QOpenGLSharedResource *value)
1292#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1293 qDebug(
"Inserting context group resource %p for context %p, managed by %p.", value, context,
this);
1295 QOpenGLContextGroup *group = context->shareGroup();
1296 Q_ASSERT(!group->d_func()->m_resources.contains(
this));
1297 group->d_func()->m_resources.insert(
this, value);
1298 m_groups.append(group);
1308QList<QOpenGLSharedResource *> QOpenGLMultiGroupSharedResource::resources()
const
1310 QList<QOpenGLSharedResource *> result;
1311 for (QList<QOpenGLContextGroup *>::const_iterator it = m_groups.constBegin(); it != m_groups.constEnd(); ++it) {
1312 QOpenGLSharedResource *resource = (*it)->d_func()->m_resources.value(
const_cast<QOpenGLMultiGroupSharedResource *>(
this),
nullptr);
1319void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContextGroup *group, QOpenGLSharedResource *value)
1321#ifdef QT_GL_CONTEXT_RESOURCE_DEBUG
1322 qDebug(
"Cleaning up context group resource %p, for group %p in thread %p.",
this, group, QThread::currentThread());
1324 value->invalidateResource();
1328 Q_ASSERT(m_groups.contains(group));
1329 m_groups.removeOne(group);
QOpenGLContext * qt_gl_global_share_context()
void qt_gl_set_global_share_context(QOpenGLContext *context)
static QOpenGLContext * global_share_context