187QGLXContext::QGLXContext(Display *display, QXcbScreen *screen,
const QSurfaceFormat &format, QPlatformOpenGLContext *share)
188 : QPlatformOpenGLContext()
191 , m_ownsContext(
true)
193 if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
194 m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL
195 ? QSurfaceFormat::OpenGL : QSurfaceFormat::OpenGLES);
196 if (m_format.renderableType() != QSurfaceFormat::OpenGL && m_format.renderableType() != QSurfaceFormat::OpenGLES)
200 m_shareContext =
static_cast<
const QGLXContext*>(share)->glxContext();
202 GLXFBConfig config = qglx_findConfig(m_display, screen->screenNumber(), m_format);
204 XVisualInfo *visualInfo =
nullptr;
208 const QByteArrayList glxExt = QByteArray(glXQueryExtensionsString(m_display, screen->screenNumber())).split(
' ');
211 glXCreateContextAttribsARBProc glXCreateContextAttribsARB =
nullptr;
212 if (glxExt.contains(
"GLX_ARB_create_context"))
213 glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((
const GLubyte*)
"glXCreateContextAttribsARB");
215 const bool supportsProfiles = glxExt.contains(
"GLX_ARB_create_context_profile");
216 const bool supportsRobustness = glxExt.contains(
"GLX_ARB_create_context_robustness");
217 const bool supportsVideoMemoryPurge = glxExt.contains(
"GLX_NV_robustness_video_memory_purge");
221 if (glXCreateContextAttribsARB !=
nullptr
222 && (m_format.renderableType() != QSurfaceFormat::OpenGLES || (supportsProfiles && glxExt.contains(
"GLX_EXT_create_context_es2_profile")))) {
225 const int requestedVersion = m_format.majorVersion() * 10 + qMin(m_format.minorVersion(), 9);
227 QList<
int> glVersions;
228 if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
229 if (requestedVersion > 46)
230 glVersions << requestedVersion;
233 glVersions << 46 << 45 << 44 << 43 << 42 << 41 << 40 << 33 << 32 << 31 << 30 << 21 << 20;
234 }
else if (m_format.renderableType() == QSurfaceFormat::OpenGLES) {
235 if (requestedVersion > 32)
236 glVersions << requestedVersion;
239 glVersions << 32 << 31 << 30 << 20;
241 m_format.setOptions(QSurfaceFormat::FormatOptions());
244 if (share && share->format().testOption(QSurfaceFormat::ResetNotification))
245 m_format.setOption(QSurfaceFormat::ResetNotification);
246 Q_ASSERT(glVersions.size() > 0);
248 for (
int i = 0; !m_context && i < glVersions.size(); i++) {
249 const int version = glVersions[i];
250 if (version > requestedVersion)
253 const int majorVersion = version / 10;
254 const int minorVersion = version % 10;
256 QList<
int> contextAttributes;
257 contextAttributes << GLX_CONTEXT_MAJOR_VERSION_ARB << majorVersion
258 << GLX_CONTEXT_MINOR_VERSION_ARB << minorVersion;
261 if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
263 if (version >= 32 && supportsProfiles) {
264 if (m_format.profile() == QSurfaceFormat::CoreProfile)
272 if (supportsRobustness)
275 if (m_format.testOption(QSurfaceFormat::DebugContext))
276 flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
279 if (version >= 30 && !m_format.testOption(QSurfaceFormat::DeprecatedFunctions))
280 flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
283 contextAttributes << GLX_CONTEXT_FLAGS_ARB << flags;
284 }
else if (m_format.renderableType() == QSurfaceFormat::OpenGLES) {
288 if (supportsRobustness && m_format.testOption(QSurfaceFormat::ResetNotification)) {
289 QList<
int> contextAttributesWithRobustness = contextAttributes;
291 if (supportsVideoMemoryPurge)
294 contextAttributesWithRobustness << None;
295 m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext,
true,
296 contextAttributesWithRobustness.data());
302 m_getGraphicsResetStatus =
reinterpret_cast<GLenum (QOPENGLF_APIENTRYP)()>(getProcAddress(
"glGetGraphicsResetStatusARB"));
304 contextAttributes << None;
305 m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext,
true, contextAttributes.data());
306 if (!m_context && m_shareContext) {
308 m_context = glXCreateContextAttribsARB(m_display, config,
nullptr,
true, contextAttributes.data());
310 m_shareContext =
nullptr;
319 if (m_format.renderableType() == QSurfaceFormat::OpenGLES)
322 m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, m_shareContext,
true);
323 if (!m_context && m_shareContext) {
325 m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE,
nullptr,
true);
327 m_shareContext =
nullptr;
333 qglx_surfaceFormatFromGLXFBConfig(&m_format, m_display, config);
336 window = createDummyWindow(m_display, config, screen->screenNumber(), screen->root());
339 if (m_format.renderableType() == QSurfaceFormat::OpenGLES)
343 visualInfo = qglx_findVisualInfo(m_display, screen->screenNumber(), &m_format);
344 if (Q_UNLIKELY(!visualInfo))
345 qFatal(
"Could not initialize GLX");
346 m_context = glXCreateContext(m_display, visualInfo, m_shareContext,
true);
347 if (!m_context && m_shareContext) {
349 m_shareContext =
nullptr;
350 m_context = glXCreateContext(m_display, visualInfo,
nullptr,
true);
354 window = createDummyWindow(m_display, visualInfo, screen->screenNumber(), screen->root());
359 if (m_context && window) {
360 GLXContext prevContext = glXGetCurrentContext();
361 GLXDrawable prevDrawable = glXGetCurrentDrawable();
362 glXMakeCurrent(m_display, window, m_context);
363 updateFormatFromContext(m_format);
366 glXMakeCurrent(m_display, prevDrawable, prevContext);
370 XDestroyWindow(m_display, window);
373QGLXContext::QGLXContext(Display *display, GLXContext context,
void *visualInfo, QPlatformOpenGLContext *share)
374 : QPlatformOpenGLContext()
379 XVisualInfo *vinfo =
static_cast<XVisualInfo*>(visualInfo);
384 if (glXQueryContext(m_display, context, GLX_FBCONFIG_ID, &configId) != Success) {
385 qWarning(
"QGLXContext: Failed to query config from the provided context");
389 int screenNumber = 0;
390 if (glXQueryContext(m_display, context, GLX_SCREEN, &screenNumber) != Success) {
391 qWarning(
"QGLXContext: Failed to query screen from the provided context");
392 screenNumber = DefaultScreen(m_display);
395 GLXFBConfig *configs;
397 static const int attribs[] = { GLX_FBCONFIG_ID, configId, None };
398 configs = glXChooseFBConfig(m_display, screenNumber, attribs, &numConfigs);
400 qWarning(
"QGLXContext: Failed to find config(invalid arguments for glXChooseFBConfig)");
402 }
else if (numConfigs < 1) {
403 qWarning(
"QGLXContext: Failed to find config");
407 if (configs && numConfigs > 1)
408 qWarning(
"QGLXContext: Multiple configs for FBConfig ID %d", configId);
410 m_config = configs[0];
414 Q_ASSERT(vinfo || m_config);
416 int screenNumber = DefaultScreen(m_display);
423 qWarning(
"QGLXContext: Failed to create dummy window");
428 GLXContext prevContext = glXGetCurrentContext();
429 GLXDrawable prevDrawable = glXGetCurrentDrawable();
430 if (!glXMakeCurrent(m_display, window, context)) {
431 qWarning(
"QGLXContext: Failed to make provided context current");
434 m_format = QSurfaceFormat();
435 m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL
436 ? QSurfaceFormat::OpenGL : QSurfaceFormat::OpenGLES);
437 updateFormatFromContext(m_format);
439 qglx_surfaceFormatFromVisualInfo(&m_format, m_display, vinfo);
441 qglx_surfaceFormatFromGLXFBConfig(&m_format, m_display, m_config);
442 glXMakeCurrent(m_display, prevDrawable, prevContext);
443 XDestroyWindow(m_display, window);
452 m_shareContext =
static_cast<
const QGLXContext*>(share)->glxContext();
472bool QGLXContext::makeCurrent(QPlatformSurface *surface)
474 bool success =
false;
475 Q_ASSERT(surface->surface()->supportsOpenGL());
477 GLXDrawable glxDrawable = 0;
478 QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass();
479 if (surfaceClass == QSurface::Window) {
480 m_isPBufferCurrent =
false;
481 QXcbWindow *window =
static_cast<QXcbWindow *>(surface);
482 glxDrawable = window->xcb_window();
483 success = glXMakeCurrent(m_display, glxDrawable, m_context);
485 if (m_getGraphicsResetStatus && m_getGraphicsResetStatus() != GL_NO_ERROR) {
489 window->invalidateSurface();
491 }
else if (surfaceClass == QSurface::Offscreen) {
492 m_isPBufferCurrent =
true;
495 success = glXMakeContextCurrent(m_display, glxDrawable, glxDrawable, m_context);
497 if (m_getGraphicsResetStatus && m_getGraphicsResetStatus() != GL_NO_ERROR) {
503 if (success && surfaceClass == QSurface::Window) {
504 int interval = surface->format().swapInterval();
505 QXcbWindow *window =
static_cast<QXcbWindow *>(surface);
506 QXcbScreen *screen = screenForPlatformSurface(surface);
507 if (interval >= 0 && interval != window->swapInterval() && screen) {
508 typedef void (*qt_glXSwapIntervalEXT)(Display *, GLXDrawable,
int);
509 typedef void (*qt_glXSwapIntervalMESA)(
unsigned int);
510 static qt_glXSwapIntervalEXT glXSwapIntervalEXT =
nullptr;
511 static qt_glXSwapIntervalMESA glXSwapIntervalMESA =
nullptr;
512 static bool resolved =
false;
515 QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(m_display,
516 screen->screenNumber())).split(
' ');
517 if (glxExt.contains(
"GLX_EXT_swap_control"))
518 glXSwapIntervalEXT = (qt_glXSwapIntervalEXT) getProcAddress(
"glXSwapIntervalEXT");
519 if (glxExt.contains(
"GLX_MESA_swap_control"))
520 glXSwapIntervalMESA = (qt_glXSwapIntervalMESA) getProcAddress(
"glXSwapIntervalMESA");
522 if (glXSwapIntervalEXT)
523 glXSwapIntervalEXT(m_display, glxDrawable, interval);
524 else if (glXSwapIntervalMESA)
525 glXSwapIntervalMESA(interval);
526 window->setSwapInterval(interval);
599void QGLXContext::queryDummyContext()
601 if (m_queriedDummyContext)
603 m_queriedDummyContext =
true;
605 static bool skip = qEnvironmentVariableIsSet(
"QT_OPENGL_NO_SANITY_CHECK");
609 QOpenGLContext *oldContext = QOpenGLContext::currentContext();
610 QSurface *oldSurface =
nullptr;
612 oldSurface = oldContext->surface();
614 QScopedPointer<QSurface> surface;
615 Display *display = glXGetCurrentDisplay();
618 if (QScreen *screen = QGuiApplication::primaryScreen()) {
619 QXcbScreen *xcbScreen =
static_cast<QXcbScreen *>(screen->handle());
620 display =
static_cast<Display *>(xcbScreen->connection()->xlib_display());
623 const char *glxvendor = glXGetClientString(display, GLX_VENDOR);
624 if (glxvendor && !strcmp(glxvendor,
"ATI")) {
625 QWindow *window =
new QWindow;
626 window->resize(64, 64);
627 window->setSurfaceType(QSurface::OpenGLSurface);
629 surface.reset(window);
631 QOffscreenSurface *offSurface =
new QOffscreenSurface;
632 offSurface->create();
633 surface.reset(offSurface);
636 QOpenGLContext context;
637 if (!context.create() || !context.makeCurrent(surface.data())) {
638 qWarning(
"QGLXContext: Failed to create dummy context");
639 m_supportsThreading =
false;
643 m_supportsThreading =
true;
645 if (
const char *renderer = (
const char *) glGetString(GL_RENDERER)) {
648 qCDebug(lcQpaGl).nospace() <<
"Multithreaded OpenGL disabled: "
649 "blacklisted renderer \""
650 << qglx_threadedgl_blacklist_renderer[i]
652 m_supportsThreading =
false;
657 if (
const char *vendor = (
const char *) glGetString(GL_VENDOR)) {
660 qCDebug(lcQpaGl).nospace() <<
"Multithreaded OpenGL disabled: "
661 "blacklisted vendor \""
662 << qglx_threadedgl_blacklist_vendor[i]
664 m_supportsThreading =
false;
670 if (glxvendor && m_supportsThreading) {
673 const char *mesaVersionStr =
nullptr;
674 if (strstr(glxvendor,
"Mesa Project") !=
nullptr) {
675 mesaVersionStr = (
const char *) glGetString(GL_VERSION);
676 m_supportsThreading =
false;
679 if (mesaVersionStr) {
683#if QT_CONFIG(regularexpression)
684 QRegularExpression versionTest(QStringLiteral(
"Mesa (\\d+)"));
685 QRegularExpressionMatch result = versionTest.match(QString::fromLatin1(mesaVersionStr));
687 if (result.hasMatch())
688 versionNr = result.captured(1).toInt();
689 if (versionNr >= 17) {
691 m_supportsThreading =
true;
695 if (!m_supportsThreading) {
696 qCDebug(lcQpaGl).nospace() <<
"Multithreaded OpenGL disabled: "
697 "blacklisted vendor \"Mesa Project\"";
701 static bool nomultithread = qEnvironmentVariableIsSet(
"QT_XCB_NO_THREADED_OPENGL");
703 m_supportsThreading =
false;
705 context.doneCurrent();
706 if (oldContext && oldSurface)
707 oldContext->makeCurrent(oldSurface);
709 if (!m_supportsThreading) {
710 qCDebug(lcQpaGl) <<
"Force-enable multithreaded OpenGL by setting "
711 "environment variable QT_OPENGL_NO_SANITY_CHECK";
722 : QPlatformOffscreenSurface(offscreenSurface)
723 , m_screen(
static_cast<QXcbScreen *>(offscreenSurface->screen()->handle()))
724 , m_format(m_screen->surfaceFormatFor(offscreenSurface->requestedFormat()))
725 , m_display(
static_cast<Display *>(m_screen->connection()->xlib_display()))
728 GLXFBConfig config = qglx_findConfig(m_display, m_screen->screenNumber(), m_format);
731 const int attributes[] = {
732 GLX_PBUFFER_WIDTH, offscreenSurface->size().width(),
733 GLX_PBUFFER_HEIGHT, offscreenSurface->size().height(),
734 GLX_LARGEST_PBUFFER, False,
735 GLX_PRESERVED_CONTENTS, False,
739 m_pbuffer = glXCreatePbuffer(m_display, config, attributes);
742 qglx_surfaceFormatFromGLXFBConfig(&m_format, m_display, config);