summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qglxintegration.cpp
diff options
context:
space:
mode:
authorJørgen Lind <jorgen.lind@digia.com>2014-09-10 16:31:32 +0200
committerJørgen Lind <jorgen.lind@theqtcompany.com>2014-12-20 06:09:01 +0100
commit8758f532ae6209bcf9447e27edc4fd412c0f173d (patch)
tree082d8e259d6de5a783ad0b2ddcf7d405ad550ba8 /src/plugins/platforms/xcb/qglxintegration.cpp
parenteb2014382be588ea92e172d8b36385b8b86b64de (diff)
Make GLX and EGL dynamic dependencies for xcb
[ChangeLog][QPA][Xcb] GLX and EGL code paths are now dynamically resolved, making it possible for one build of a plugin to use both code paths. Default is to use the GLX code path if available. This can be overwritten by specifying QT_XCB_GL_INTEGRATION=xcb_egl as an evnironment variable. Enable qt.xcb.glintegration.debug to get debug log output of what integration is used Change-Id: Ia9fa95fcca3d901b91dadb8c98a695fea0ae3b1e Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
Diffstat (limited to 'src/plugins/platforms/xcb/qglxintegration.cpp')
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp723
1 files changed, 0 insertions, 723 deletions
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
deleted file mode 100644
index c0be836bce..0000000000
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ /dev/null
@@ -1,723 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
-** Contact: http://www.qt-project.org/legal
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL21$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia. For licensing terms and
-** conditions see http://qt.digia.com/licensing. For further information
-** use the contact form at http://qt.digia.com/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Digia gives you certain additional
-** rights. These rights are described in the Digia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QDebug>
-#include <QLibrary>
-
-#include "qxcbwindow.h"
-#include "qxcbscreen.h"
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <GL/glx.h>
-
-#include <QtGui/QOpenGLContext>
-#include <QtGui/QOffscreenSurface>
-
-#include "qglxintegration.h"
-#include <QtPlatformSupport/private/qglxconvenience_p.h>
-#include <QtPlatformHeaders/QGLXNativeContext>
-
-#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
-#include <dlfcn.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
-
-#ifndef GLX_CONTEXT_CORE_PROFILE_BIT_ARB
-#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
-#endif
-
-#ifndef GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
-#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
-#endif
-
-#ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT
-#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
-#endif
-
-#ifndef GLX_CONTEXT_PROFILE_MASK_ARB
-#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
-#endif
-
-#ifndef GL_CONTEXT_FLAG_DEBUG_BIT
-#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
-#endif
-
-static Window createDummyWindow(Display *dpy, XVisualInfo *visualInfo, int screenNumber, Window rootWin)
-{
- Colormap cmap = XCreateColormap(dpy, rootWin, visualInfo->visual, AllocNone);
- XSetWindowAttributes a;
- a.background_pixel = WhitePixel(dpy, screenNumber);
- a.border_pixel = BlackPixel(dpy, screenNumber);
- a.colormap = cmap;
- a.override_redirect = true;
-
- Window window = XCreateWindow(dpy, rootWin,
- 0, 0, 100, 100,
- 0, visualInfo->depth, InputOutput, visualInfo->visual,
- CWBackPixel|CWBorderPixel|CWColormap|CWOverrideRedirect, &a);
-#ifndef QT_NO_DEBUG
- XStoreName(dpy, window, "Qt GLX dummy window");
-#endif
- XFreeColormap(dpy, cmap);
- return window;
-}
-
-static Window createDummyWindow(Display *dpy, GLXFBConfig config, int screenNumber, Window rootWin)
-{
- XVisualInfo *visualInfo = glXGetVisualFromFBConfig(dpy, config);
- if (!visualInfo)
- qFatal("Could not initialize GLX");
- Window window = createDummyWindow(dpy, visualInfo, screenNumber, rootWin);
- XFree(visualInfo);
- return window;
-}
-
-static inline QByteArray getGlString(GLenum param)
-{
- if (const GLubyte *s = glGetString(param))
- return QByteArray(reinterpret_cast<const char*>(s));
- return QByteArray();
-}
-
-static void updateFormatFromContext(QSurfaceFormat &format)
-{
- // Update the version, profile, and context bit of the format
- int major = 0, minor = 0;
- QByteArray versionString(getGlString(GL_VERSION));
- if (QPlatformOpenGLContext::parseOpenGLVersion(versionString, major, minor)) {
- format.setMajorVersion(major);
- format.setMinorVersion(minor);
- }
-
- format.setProfile(QSurfaceFormat::NoProfile);
- format.setOptions(QSurfaceFormat::FormatOptions());
-
- if (format.renderableType() == QSurfaceFormat::OpenGL) {
- if (format.version() < qMakePair(3, 0)) {
- format.setOption(QSurfaceFormat::DeprecatedFunctions);
- return;
- }
-
- // Version 3.0 onwards - check if it includes deprecated functionality or is
- // a debug context
- GLint value = 0;
- glGetIntegerv(GL_CONTEXT_FLAGS, &value);
- if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
- format.setOption(QSurfaceFormat::DeprecatedFunctions);
- if (value & GL_CONTEXT_FLAG_DEBUG_BIT)
- format.setOption(QSurfaceFormat::DebugContext);
- if (format.version() < qMakePair(3, 2))
- return;
-
- // Version 3.2 and newer have a profile
- value = 0;
- glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
-
- if (value & GL_CONTEXT_CORE_PROFILE_BIT)
- format.setProfile(QSurfaceFormat::CoreProfile);
- else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
- format.setProfile(QSurfaceFormat::CompatibilityProfile);
- }
-}
-
-QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share,
- const QVariant &nativeHandle)
- : QPlatformOpenGLContext()
- , m_display(DISPLAY_FROM_XCB(screen))
- , m_config(0)
- , m_context(0)
- , m_shareContext(0)
- , m_format(format)
- , m_isPBufferCurrent(false)
- , m_swapInterval(-1)
- , m_ownsContext(nativeHandle.isNull())
-{
- if (nativeHandle.isNull())
- init(screen, share);
- else
- init(screen, share, nativeHandle);
-}
-
-void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
-{
- if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
- m_format.setRenderableType(QSurfaceFormat::OpenGL);
- if (m_format.renderableType() != QSurfaceFormat::OpenGL && m_format.renderableType() != QSurfaceFormat::OpenGLES)
- return;
-
- if (share)
- m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
-
- GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),m_format);
- m_config = config;
- XVisualInfo *visualInfo = 0;
- Window window = 0; // Temporary window used to query OpenGL context
-
- if (config) {
- // Resolve entry point for glXCreateContextAttribsARB
- glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
- glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
-
- QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(m_display, screen->screenNumber())).split(' ');
- bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile");
-
- // Use glXCreateContextAttribsARB if available
- // Also, GL ES context creation requires GLX_EXT_create_context_es2_profile
- if (glxExt.contains("GLX_ARB_create_context") && glXCreateContextAttribsARB != 0
- && (m_format.renderableType() != QSurfaceFormat::OpenGLES || (supportsProfiles && glxExt.contains("GLX_EXT_create_context_es2_profile")))) {
- // Try to create an OpenGL context for each known OpenGL version in descending
- // order from the requested version.
- const int requestedVersion = m_format.majorVersion() * 10 + qMin(m_format.minorVersion(), 9);
-
- QVector<int> glVersions;
- if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
- if (requestedVersion > 45)
- glVersions << requestedVersion;
-
- // Don't bother with versions below 2.0
- glVersions << 45 << 44 << 43 << 42 << 41 << 40 << 33 << 32 << 31 << 30 << 21 << 20;
- } else if (m_format.renderableType() == QSurfaceFormat::OpenGLES) {
- if (requestedVersion > 31)
- glVersions << requestedVersion;
-
- // Don't bother with versions below ES 2.0
- glVersions << 31 << 30 << 20;
- // ES does not support any format option
- m_format.setOptions(QSurfaceFormat::FormatOptions());
- }
-
- Q_ASSERT(glVersions.count() > 0);
-
- for (int i = 0; !m_context && i < glVersions.count(); i++) {
- const int version = glVersions[i];
- if (version > requestedVersion)
- continue;
-
- const int majorVersion = version / 10;
- const int minorVersion = version % 10;
-
- QVector<int> contextAttributes;
- contextAttributes << GLX_CONTEXT_MAJOR_VERSION_ARB << majorVersion
- << GLX_CONTEXT_MINOR_VERSION_ARB << minorVersion;
-
-
- if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
- // If asking for OpenGL 3.2 or newer we should also specify a profile
- if (version >= 32 && supportsProfiles) {
- if (m_format.profile() == QSurfaceFormat::CoreProfile)
- contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
- else
- contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
- }
-
- int flags = 0;
-
- if (m_format.testOption(QSurfaceFormat::DebugContext))
- flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
-
- // A forward-compatible context may be requested for 3.0 and later
- if (version >= 30 && !m_format.testOption(QSurfaceFormat::DeprecatedFunctions))
- flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
-
- if (flags != 0)
- contextAttributes << GLX_CONTEXT_FLAGS_ARB << flags;
- } else if (m_format.renderableType() == QSurfaceFormat::OpenGLES) {
- contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
- }
-
- contextAttributes << None;
-
- m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributes.data());
- if (!m_context && m_shareContext) {
- // re-try without a shared glx context
- m_context = glXCreateContextAttribsARB(m_display, config, 0, true, contextAttributes.data());
- if (m_context)
- m_shareContext = 0;
- }
- }
- }
-
- // Could not create a context using glXCreateContextAttribsARB, falling back to glXCreateNewContext.
- if (!m_context) {
- // requesting an OpenGL ES context requires glXCreateContextAttribsARB, so bail out
- if (m_format.renderableType() == QSurfaceFormat::OpenGLES)
- return;
-
- m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, m_shareContext, true);
- if (!m_context && m_shareContext) {
- // re-try without a shared glx context
- m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, 0, true);
- if (m_context)
- m_shareContext = 0;
- }
- }
-
- // Get the basic surface format details
- if (m_context)
- qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(screen), config);
-
- // Create a temporary window so that we can make the new context current
- window = createDummyWindow(DISPLAY_FROM_XCB(screen), config, screen->screenNumber(), screen->root());
- } else {
- // requesting an OpenGL ES context requires glXCreateContextAttribsARB, so bail out
- if (m_format.renderableType() == QSurfaceFormat::OpenGLES)
- return;
-
- // Note that m_format gets updated with the used surface format
- visualInfo = qglx_findVisualInfo(m_display, screen->screenNumber(), &m_format);
- if (!visualInfo)
- qFatal("Could not initialize GLX");
- m_context = glXCreateContext(m_display, visualInfo, m_shareContext, true);
- if (!m_context && m_shareContext) {
- // re-try without a shared glx context
- m_shareContext = 0;
- m_context = glXCreateContext(m_display, visualInfo, Q_NULLPTR, true);
- }
-
- // Create a temporary window so that we can make the new context current
- window = createDummyWindow(DISPLAY_FROM_XCB(screen), visualInfo, screen->screenNumber(), screen->root());
- XFree(visualInfo);
- }
-
- // Query the OpenGL version and profile
- if (m_context && window) {
- GLXContext prevContext = glXGetCurrentContext();
- GLXDrawable prevDrawable = glXGetCurrentDrawable();
- glXMakeCurrent(m_display, window, m_context);
- updateFormatFromContext(m_format);
-
- // Make our context non-current
- glXMakeCurrent(m_display, prevDrawable, prevContext);
- }
-
- // Destroy our temporary window
- XDestroyWindow(m_display, window);
-}
-
-void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle)
-{
- if (!nativeHandle.canConvert<QGLXNativeContext>()) {
- qWarning("QGLXContext: Requires a QGLXNativeContext");
- return;
- }
- QGLXNativeContext handle = nativeHandle.value<QGLXNativeContext>();
- GLXContext context = handle.context();
- if (!context) {
- qWarning("QGLXContext: No GLXContext given");
- return;
- }
-
- // Use the provided Display, if available. If not, use our own. It may still work.
- Display *dpy = handle.display();
- if (!dpy)
- dpy = DISPLAY_FROM_XCB(screen);
-
- // Legacy contexts created using glXCreateContext are created using a visual
- // and the FBConfig cannot be queried. The only way to adapt these contexts
- // is to figure out the visual id.
- XVisualInfo *vinfo = 0;
- // If the VisualID is provided use it.
- VisualID vid = handle.visualId();
- if (!vid) {
- // In the absence of the VisualID figure it out from the window.
- Window wnd = handle.window();
- if (wnd) {
- XWindowAttributes attrs;
- XGetWindowAttributes(dpy, wnd, &attrs);
- vid = XVisualIDFromVisual(attrs.visual);
- }
- }
- if (vid) {
- XVisualInfo v;
- v.screen = screen->screenNumber();
- v.visualid = vid;
- int n = 0;
- vinfo = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, &v, &n);
- if (n < 1) {
- XFree(vinfo);
- vinfo = 0;
- }
- }
-
- // For contexts created with an FBConfig using the modern functions providing the
- // visual or window is not mandatory. Just query the config from the context.
- GLXFBConfig config = 0;
- if (!vinfo) {
- int configId = 0;
- if (glXQueryContext(dpy, context, GLX_FBCONFIG_ID, &configId) != Success) {
- qWarning("QGLXContext: Failed to query config from the provided context");
- return;
- }
-
- GLXFBConfig *configs;
- int numConfigs = 0;
- static const int attribs[] = { GLX_FBCONFIG_ID, configId, None };
- configs = glXChooseFBConfig(dpy, screen->screenNumber(), attribs, &numConfigs);
- if (!configs || numConfigs < 1) {
- qWarning("QGLXContext: Failed to find config");
- return;
- }
- if (configs && numConfigs > 1) // this is suspicious so warn but let it continue
- qWarning("QGLXContext: Multiple configs for FBConfig ID %d", configId);
-
- config = configs[0];
- // Store the config.
- m_config = config;
- }
-
- Q_ASSERT(vinfo || config);
-
- int screenNumber = DefaultScreen(dpy);
- Window window;
- if (vinfo)
- window = createDummyWindow(dpy, vinfo, screenNumber, RootWindow(dpy, screenNumber));
- else
- window = createDummyWindow(dpy, config, screenNumber, RootWindow(dpy, screenNumber));
- if (!window) {
- qWarning("QGLXContext: Failed to create dummy window");
- return;
- }
-
- // Update OpenGL version and buffer sizes in our format.
- GLXContext prevContext = glXGetCurrentContext();
- GLXDrawable prevDrawable = glXGetCurrentDrawable();
- if (!glXMakeCurrent(dpy, window, context)) {
- qWarning("QGLXContext: Failed to make provided context current");
- return;
- }
- m_format = QSurfaceFormat();
- m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL
- ? QSurfaceFormat::OpenGL : QSurfaceFormat::OpenGLES);
- updateFormatFromContext(m_format);
- if (vinfo)
- qglx_surfaceFormatFromVisualInfo(&m_format, dpy, vinfo);
- else
- qglx_surfaceFormatFromGLXFBConfig(&m_format, dpy, config);
- glXMakeCurrent(dpy, prevDrawable, prevContext);
- XDestroyWindow(dpy, window);
-
- if (vinfo)
- XFree(vinfo);
-
- // Success. Store the context. From this point on isValid() is true.
- m_context = context;
-
- if (share)
- m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
-}
-
-QGLXContext::~QGLXContext()
-{
- if (m_ownsContext)
- glXDestroyContext(m_display, m_context);
-}
-
-static QXcbScreen *screenForPlatformSurface(QPlatformSurface *surface)
-{
- QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass();
- if (surfaceClass == QSurface::Window) {
- return static_cast<QXcbScreen *>(static_cast<QXcbWindow *>(surface)->screen());
- } else if (surfaceClass == QSurface::Offscreen) {
- return static_cast<QXcbScreen *>(static_cast<QGLXPbuffer *>(surface)->screen());
- }
- return Q_NULLPTR;
-}
-
-QVariant QGLXContext::nativeHandle() const
-{
- return QVariant::fromValue<QGLXNativeContext>(QGLXNativeContext(m_context));
-}
-
-bool QGLXContext::makeCurrent(QPlatformSurface *surface)
-{
- bool success = false;
- Q_ASSERT(surface->surface()->supportsOpenGL());
-
- GLXDrawable glxDrawable = 0;
- QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass();
- if (surfaceClass == QSurface::Window) {
- m_isPBufferCurrent = false;
- QXcbWindow *window = static_cast<QXcbWindow *>(surface);
- glxDrawable = window->xcb_window();
- success = glXMakeCurrent(m_display, glxDrawable, m_context);
- } else if (surfaceClass == QSurface::Offscreen) {
- m_isPBufferCurrent = true;
- QGLXPbuffer *pbuffer = static_cast<QGLXPbuffer *>(surface);
- glxDrawable = pbuffer->pbuffer();
- success = glXMakeContextCurrent(m_display, glxDrawable, glxDrawable, m_context);
- }
-
- if (success) {
- int interval = surface->format().swapInterval();
- QXcbScreen *screen = screenForPlatformSurface(surface);
- if (interval >= 0 && m_swapInterval != interval && screen) {
- m_swapInterval = interval;
- typedef void (*qt_glXSwapIntervalEXT)(Display *, GLXDrawable, int);
- typedef void (*qt_glXSwapIntervalMESA)(unsigned int);
- static qt_glXSwapIntervalEXT glXSwapIntervalEXT = 0;
- static qt_glXSwapIntervalMESA glXSwapIntervalMESA = 0;
- static bool resolved = false;
- if (!resolved) {
- resolved = true;
- QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(m_display,
- screen->screenNumber())).split(' ');
- if (glxExt.contains("GLX_EXT_swap_control"))
- glXSwapIntervalEXT = (qt_glXSwapIntervalEXT) getProcAddress("glXSwapIntervalEXT");
- if (glxExt.contains("GLX_MESA_swap_control"))
- glXSwapIntervalMESA = (qt_glXSwapIntervalMESA) getProcAddress("glXSwapIntervalMESA");
- }
- if (glXSwapIntervalEXT)
- glXSwapIntervalEXT(m_display, glxDrawable, interval);
- else if (glXSwapIntervalMESA)
- glXSwapIntervalMESA(interval);
- }
- }
-
- return success;
-}
-
-void QGLXContext::doneCurrent()
-{
- if (m_isPBufferCurrent)
- glXMakeContextCurrent(m_display, 0, 0, 0);
- else
- glXMakeCurrent(m_display, 0, 0);
- m_isPBufferCurrent = false;
-}
-
-void QGLXContext::swapBuffers(QPlatformSurface *surface)
-{
- GLXDrawable glxDrawable = 0;
- if (surface->surface()->surfaceClass() == QSurface::Offscreen)
- glxDrawable = static_cast<QGLXPbuffer *>(surface)->pbuffer();
- else
- glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window();
- glXSwapBuffers(m_display, glxDrawable);
-
- if (surface->surface()->surfaceClass() == QSurface::Window) {
- QXcbWindow *platformWindow = static_cast<QXcbWindow *>(surface);
- // OpenGL context might be bound to a non-gui thread use QueuedConnection to sync
- // the window from the platformWindow's thread as QXcbWindow is no QObject, an
- // event is sent to QXcbConnection. (this is faster than a metacall)
- if (platformWindow->needsSync())
- platformWindow->postSyncWindowRequest();
- }
-}
-
-void (*QGLXContext::getProcAddress(const QByteArray &procName)) ()
-{
- typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *);
- static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
- static bool resolved = false;
-
- if (resolved && !glXGetProcAddressARB)
- return 0;
- if (!glXGetProcAddressARB) {
- QList<QByteArray> glxExt = QByteArray(glXGetClientString(m_display, GLX_EXTENSIONS)).split(' ');
- if (glxExt.contains("GLX_ARB_get_proc_address")) {
-#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
- void *handle = dlopen(NULL, RTLD_LAZY);
- if (handle) {
- glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB");
- dlclose(handle);
- }
- if (!glXGetProcAddressARB)
-#endif
- {
- extern const QString qt_gl_library_name();
-// QLibrary lib(qt_gl_library_name());
- QLibrary lib(QLatin1String("GL"));
- glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB");
- }
- }
- resolved = true;
- }
- if (!glXGetProcAddressARB)
- return 0;
- return (void (*)())glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName.constData()));
-}
-
-QSurfaceFormat QGLXContext::format() const
-{
- return m_format;
-}
-
-bool QGLXContext::isSharing() const
-{
- return m_shareContext != 0;
-}
-
-bool QGLXContext::isValid() const
-{
- return m_context != 0;
-}
-
-bool QGLXContext::m_queriedDummyContext = false;
-bool QGLXContext::m_supportsThreading = true;
-
-
-// If this list grows to any significant size, change it a
-// proper string table and make the implementation below use
-// binary search.
-static const char *qglx_threadedgl_blacklist_renderer[] = {
- "Chromium", // QTBUG-32225 (initialization fails)
- 0
-};
-
-// This disables threaded rendering on anything using mesa, e.g.
-// - nvidia/nouveau
-// - amd/gallium
-// - intel
-// - some software opengl implementations
-//
-// The client glx vendor string is used to identify those setups as that seems to show the least
-// variance between the bad configurations. It's always "Mesa Project and SGI". There are some
-// configurations which don't use mesa and which can do threaded rendering (amd and nvidia chips
-// with their own proprietary drivers).
-//
-// This, of course, is very broad and disables threaded rendering on a lot of devices which would
-// be able to use it. However, the bugs listed below don't follow any easily recognizable pattern
-// and we should rather be safe.
-//
-// http://cgit.freedesktop.org/xcb/libxcb/commit/?id=be0fe56c3bcad5124dcc6c47a2fad01acd16f71a will
-// fix some of the issues. Basically, the proprietary drivers seem to have a way of working around
-// a fundamental flaw with multithreaded access to xcb, but mesa doesn't. The blacklist should be
-// reevaluated once that patch is released in some version of xcb.
-static const char *qglx_threadedgl_blacklist_vendor[] = {
- "Mesa Project and SGI", // QTCREATORBUG-10875 (crash in creator)
- // QTBUG-34492 (flickering in fullscreen)
- // QTBUG-38221
- 0
-};
-
-void QGLXContext::queryDummyContext()
-{
- if (m_queriedDummyContext)
- return;
- m_queriedDummyContext = true;
-
- static bool skip = qEnvironmentVariableIsSet("QT_OPENGL_NO_SANITY_CHECK");
- if (skip)
- return;
-
- QOpenGLContext *oldContext = QOpenGLContext::currentContext();
- QSurface *oldSurface = 0;
- if (oldContext)
- oldSurface = oldContext->surface();
-
- QScopedPointer<QSurface> surface;
- const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR);
- if (glxvendor && !strcmp(glxvendor, "ATI")) {
- QWindow *window = new QWindow;
- window->resize(64, 64);
- window->setSurfaceType(QSurface::OpenGLSurface);
- window->create();
- surface.reset(window);
- } else {
- QOffscreenSurface *offSurface = new QOffscreenSurface;
- offSurface->create();
- surface.reset(offSurface);
- }
-
- QOpenGLContext context;
- context.create();
- context.makeCurrent(surface.data());
-
- m_supportsThreading = true;
-
- if (const char *renderer = (const char *) glGetString(GL_RENDERER)) {
- for (int i = 0; qglx_threadedgl_blacklist_renderer[i]; ++i) {
- if (strstr(renderer, qglx_threadedgl_blacklist_renderer[i]) != 0) {
- m_supportsThreading = false;
- break;
- }
- }
- }
-
- if (glxvendor) {
- for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) {
- if (strstr(glxvendor, qglx_threadedgl_blacklist_vendor[i]) != 0) {
- m_supportsThreading = false;
- break;
- }
- }
- }
-
- context.doneCurrent();
- if (oldContext && oldSurface)
- oldContext->makeCurrent(oldSurface);
-}
-
-bool QGLXContext::supportsThreading()
-{
- if (!m_queriedDummyContext)
- queryDummyContext();
- return m_supportsThreading;
-}
-
-QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface)
- : QPlatformOffscreenSurface(offscreenSurface)
- , m_format(offscreenSurface->requestedFormat())
- , m_screen(static_cast<QXcbScreen *>(offscreenSurface->screen()->handle()))
- , m_pbuffer(0)
-{
- GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), m_format);
-
- if (config) {
- const int attributes[] = {
- GLX_PBUFFER_WIDTH, offscreenSurface->size().width(),
- GLX_PBUFFER_HEIGHT, offscreenSurface->size().height(),
- GLX_LARGEST_PBUFFER, False,
- GLX_PRESERVED_CONTENTS, False,
- None
- };
-
- m_pbuffer = glXCreatePbuffer(DISPLAY_FROM_XCB(m_screen), config, attributes);
-
- if (m_pbuffer)
- qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(m_screen), config);
- }
-}
-
-QGLXPbuffer::~QGLXPbuffer()
-{
- if (m_pbuffer)
- glXDestroyPbuffer(DISPLAY_FROM_XCB(m_screen), m_pbuffer);
-}
-
-
-QT_END_NAMESPACE