1
/****************************************************************************
3
** Copyright (C) 2016 The Qt Company Ltd.
4
** Contact: https://www.qt.io/licensing/
6
** This file is part of the plugins of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:LGPL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and The Qt Company. For licensing terms
14
** and conditions see https://www.qt.io/terms-conditions. For further
15
** information use the contact form at https://www.qt.io/contact-us.
17
** GNU Lesser General Public License Usage
18
** Alternatively, this file may be used under the terms of the GNU Lesser
19
** General Public License version 3 as published by the Free Software
20
** Foundation and appearing in the file LICENSE.LGPL3 included in the
21
** packaging of this file. Please review the following information to
22
** ensure the GNU Lesser General Public License version 3 requirements
23
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25
** GNU General Public License Usage
26
** Alternatively, this file may be used under the terms of the GNU
27
** General Public License version 2.0 or (at your option) the GNU General
28
** Public license version 3 or any later version approved by the KDE Free
29
** Qt Foundation. The licenses are as published by the Free Software
30
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31
** included in the packaging of this file. Please review the following
32
** information to ensure the GNU General Public License requirements will
33
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34
** https://www.gnu.org/licenses/gpl-3.0.html.
38
****************************************************************************/
43
#include "qxcbwindow.h"
44
#include "qxcbscreen.h"
47
#include <X11/Xutil.h>
50
#include <QtGui/QOpenGLContext>
51
#include <QtGui/QOffscreenSurface>
53
#include "qglxintegration.h"
54
#include <QtPlatformSupport/private/qglxconvenience_p.h>
55
#include <QtPlatformHeaders/QGLXNativeContext>
57
#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
63
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
65
#ifndef GLX_CONTEXT_CORE_PROFILE_BIT_ARB
66
#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
69
#ifndef GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
70
#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
73
#ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT
74
#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
77
#ifndef GLX_CONTEXT_PROFILE_MASK_ARB
78
#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
81
#ifndef GL_CONTEXT_FLAG_DEBUG_BIT
82
#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
85
static Window createDummyWindow(Display *dpy, XVisualInfo *visualInfo, int screenNumber, Window rootWin)
87
Colormap cmap = XCreateColormap(dpy, rootWin, visualInfo->visual, AllocNone);
88
XSetWindowAttributes a;
89
a.background_pixel = WhitePixel(dpy, screenNumber);
90
a.border_pixel = BlackPixel(dpy, screenNumber);
92
a.override_redirect = true;
94
Window window = XCreateWindow(dpy, rootWin,
96
0, visualInfo->depth, InputOutput, visualInfo->visual,
97
CWBackPixel|CWBorderPixel|CWColormap|CWOverrideRedirect, &a);
99
XStoreName(dpy, window, "Qt GLX dummy window");
101
XFreeColormap(dpy, cmap);
105
static Window createDummyWindow(Display *dpy, GLXFBConfig config, int screenNumber, Window rootWin)
107
XVisualInfo *visualInfo = glXGetVisualFromFBConfig(dpy, config);
108
if (Q_UNLIKELY(!visualInfo))
109
qFatal("Could not initialize GLX");
110
Window window = createDummyWindow(dpy, visualInfo, screenNumber, rootWin);
115
static inline QByteArray getGlString(GLenum param)
117
if (const GLubyte *s = glGetString(param))
118
return QByteArray(reinterpret_cast<const char*>(s));
122
static void updateFormatFromContext(QSurfaceFormat &format)
124
// Update the version, profile, and context bit of the format
125
int major = 0, minor = 0;
126
QByteArray versionString(getGlString(GL_VERSION));
127
if (QPlatformOpenGLContext::parseOpenGLVersion(versionString, major, minor)) {
128
format.setMajorVersion(major);
129
format.setMinorVersion(minor);
132
format.setProfile(QSurfaceFormat::NoProfile);
133
format.setOptions(QSurfaceFormat::FormatOptions());
135
if (format.renderableType() == QSurfaceFormat::OpenGL) {
136
if (format.version() < qMakePair(3, 0)) {
137
format.setOption(QSurfaceFormat::DeprecatedFunctions);
141
// Version 3.0 onwards - check if it includes deprecated functionality or is
144
glGetIntegerv(GL_CONTEXT_FLAGS, &value);
145
if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT))
146
format.setOption(QSurfaceFormat::DeprecatedFunctions);
147
if (value & GL_CONTEXT_FLAG_DEBUG_BIT)
148
format.setOption(QSurfaceFormat::DebugContext);
149
if (format.version() < qMakePair(3, 2))
152
// Version 3.2 and newer have a profile
154
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value);
156
if (value & GL_CONTEXT_CORE_PROFILE_BIT)
157
format.setProfile(QSurfaceFormat::CoreProfile);
158
else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT)
159
format.setProfile(QSurfaceFormat::CompatibilityProfile);
163
QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share,
164
const QVariant &nativeHandle)
165
: QPlatformOpenGLContext()
166
, m_display(DISPLAY_FROM_XCB(screen))
171
, m_isPBufferCurrent(false)
173
, m_ownsContext(nativeHandle.isNull())
175
if (nativeHandle.isNull())
178
init(screen, share, nativeHandle);
181
void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
183
if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType)
184
#if defined(QT_OPENGL_ES_2)
185
m_format.setRenderableType(QSurfaceFormat::OpenGLES);
187
m_format.setRenderableType(QSurfaceFormat::OpenGL);
189
if (m_format.renderableType() != QSurfaceFormat::OpenGL && m_format.renderableType() != QSurfaceFormat::OpenGLES)
193
m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
195
GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),m_format);
197
XVisualInfo *visualInfo = 0;
198
Window window = 0; // Temporary window used to query OpenGL context
201
const QByteArrayList glxExt = QByteArray(glXQueryExtensionsString(m_display, screen->screenNumber())).split(' ');
203
// Resolve entry point for glXCreateContextAttribsARB
204
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
205
if (glxExt.contains("GLX_ARB_create_context"))
206
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB");
208
const bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile");
210
// Use glXCreateContextAttribsARB if available
211
// Also, GL ES context creation requires GLX_EXT_create_context_es2_profile
212
if (glXCreateContextAttribsARB != 0
213
&& (m_format.renderableType() != QSurfaceFormat::OpenGLES || (supportsProfiles && glxExt.contains("GLX_EXT_create_context_es2_profile")))) {
214
// Try to create an OpenGL context for each known OpenGL version in descending
215
// order from the requested version.
216
const int requestedVersion = m_format.majorVersion() * 10 + qMin(m_format.minorVersion(), 9);
218
QVector<int> glVersions;
219
if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
220
if (requestedVersion > 45)
221
glVersions << requestedVersion;
223
// Don't bother with versions below 2.0
224
glVersions << 45 << 44 << 43 << 42 << 41 << 40 << 33 << 32 << 31 << 30 << 21 << 20;
225
} else if (m_format.renderableType() == QSurfaceFormat::OpenGLES) {
226
if (requestedVersion > 31)
227
glVersions << requestedVersion;
229
// Don't bother with versions below ES 2.0
230
glVersions << 31 << 30 << 20;
231
// ES does not support any format option
232
m_format.setOptions(QSurfaceFormat::FormatOptions());
235
Q_ASSERT(glVersions.count() > 0);
237
for (int i = 0; !m_context && i < glVersions.count(); i++) {
238
const int version = glVersions[i];
239
if (version > requestedVersion)
242
const int majorVersion = version / 10;
243
const int minorVersion = version % 10;
245
QVector<int> contextAttributes;
246
contextAttributes << GLX_CONTEXT_MAJOR_VERSION_ARB << majorVersion
247
<< GLX_CONTEXT_MINOR_VERSION_ARB << minorVersion;
250
if (m_format.renderableType() == QSurfaceFormat::OpenGL) {
251
// If asking for OpenGL 3.2 or newer we should also specify a profile
252
if (version >= 32 && supportsProfiles) {
253
if (m_format.profile() == QSurfaceFormat::CoreProfile)
254
contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
256
contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
261
if (m_format.testOption(QSurfaceFormat::DebugContext))
262
flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
264
// A forward-compatible context may be requested for 3.0 and later
265
if (version >= 30 && !m_format.testOption(QSurfaceFormat::DeprecatedFunctions))
266
flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
269
contextAttributes << GLX_CONTEXT_FLAGS_ARB << flags;
270
} else if (m_format.renderableType() == QSurfaceFormat::OpenGLES) {
271
contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_ES2_PROFILE_BIT_EXT;
274
contextAttributes << None;
276
m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributes.data());
277
if (!m_context && m_shareContext) {
278
// re-try without a shared glx context
279
m_context = glXCreateContextAttribsARB(m_display, config, 0, true, contextAttributes.data());
286
// Could not create a context using glXCreateContextAttribsARB, falling back to glXCreateNewContext.
288
// requesting an OpenGL ES context requires glXCreateContextAttribsARB, so bail out
289
if (m_format.renderableType() == QSurfaceFormat::OpenGLES)
292
m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, m_shareContext, true);
293
if (!m_context && m_shareContext) {
294
// re-try without a shared glx context
295
m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, 0, true);
301
// Get the basic surface format details
303
qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(screen), config);
305
// Create a temporary window so that we can make the new context current
306
window = createDummyWindow(DISPLAY_FROM_XCB(screen), config, screen->screenNumber(), screen->root());
308
// requesting an OpenGL ES context requires glXCreateContextAttribsARB, so bail out
309
if (m_format.renderableType() == QSurfaceFormat::OpenGLES)
312
// Note that m_format gets updated with the used surface format
313
visualInfo = qglx_findVisualInfo(m_display, screen->screenNumber(), &m_format);
314
if (Q_UNLIKELY(!visualInfo))
315
qFatal("Could not initialize GLX");
316
m_context = glXCreateContext(m_display, visualInfo, m_shareContext, true);
317
if (!m_context && m_shareContext) {
318
// re-try without a shared glx context
320
m_context = glXCreateContext(m_display, visualInfo, Q_NULLPTR, true);
323
// Create a temporary window so that we can make the new context current
324
window = createDummyWindow(DISPLAY_FROM_XCB(screen), visualInfo, screen->screenNumber(), screen->root());
328
// Query the OpenGL version and profile
329
if (m_context && window) {
330
GLXContext prevContext = glXGetCurrentContext();
331
GLXDrawable prevDrawable = glXGetCurrentDrawable();
332
glXMakeCurrent(m_display, window, m_context);
333
updateFormatFromContext(m_format);
335
// Make our context non-current
336
glXMakeCurrent(m_display, prevDrawable, prevContext);
339
// Destroy our temporary window
340
XDestroyWindow(m_display, window);
343
void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle)
345
if (!nativeHandle.canConvert<QGLXNativeContext>()) {
346
qWarning("QGLXContext: Requires a QGLXNativeContext");
349
QGLXNativeContext handle = nativeHandle.value<QGLXNativeContext>();
350
GLXContext context = handle.context();
352
qWarning("QGLXContext: No GLXContext given");
356
// Use the provided Display, if available. If not, use our own. It may still work.
357
Display *dpy = handle.display();
359
dpy = DISPLAY_FROM_XCB(screen);
361
// Legacy contexts created using glXCreateContext are created using a visual
362
// and the FBConfig cannot be queried. The only way to adapt these contexts
363
// is to figure out the visual id.
364
XVisualInfo *vinfo = 0;
365
// If the VisualID is provided use it.
366
VisualID vid = handle.visualId();
368
// In the absence of the VisualID figure it out from the window.
369
Window wnd = handle.window();
371
XWindowAttributes attrs;
372
XGetWindowAttributes(dpy, wnd, &attrs);
373
vid = XVisualIDFromVisual(attrs.visual);
378
v.screen = screen->screenNumber();
381
vinfo = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, &v, &n);
388
// For contexts created with an FBConfig using the modern functions providing the
389
// visual or window is not mandatory. Just query the config from the context.
390
GLXFBConfig config = 0;
393
if (glXQueryContext(dpy, context, GLX_FBCONFIG_ID, &configId) != Success) {
394
qWarning("QGLXContext: Failed to query config from the provided context");
398
GLXFBConfig *configs;
400
static const int attribs[] = { GLX_FBCONFIG_ID, configId, None };
401
configs = glXChooseFBConfig(dpy, screen->screenNumber(), attribs, &numConfigs);
402
if (!configs || numConfigs < 1) {
403
qWarning("QGLXContext: Failed to find config");
406
if (configs && numConfigs > 1) // this is suspicious so warn but let it continue
407
qWarning("QGLXContext: Multiple configs for FBConfig ID %d", configId);
414
Q_ASSERT(vinfo || config);
416
int screenNumber = DefaultScreen(dpy);
419
window = createDummyWindow(dpy, vinfo, screenNumber, RootWindow(dpy, screenNumber));
421
window = createDummyWindow(dpy, config, screenNumber, RootWindow(dpy, screenNumber));
423
qWarning("QGLXContext: Failed to create dummy window");
427
// Update OpenGL version and buffer sizes in our format.
428
GLXContext prevContext = glXGetCurrentContext();
429
GLXDrawable prevDrawable = glXGetCurrentDrawable();
430
if (!glXMakeCurrent(dpy, 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, dpy, vinfo);
441
qglx_surfaceFormatFromGLXFBConfig(&m_format, dpy, config);
442
glXMakeCurrent(dpy, prevDrawable, prevContext);
443
XDestroyWindow(dpy, window);
448
// Success. Store the context. From this point on isValid() is true.
452
m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
455
QGLXContext::~QGLXContext()
458
glXDestroyContext(m_display, m_context);
461
static QXcbScreen *screenForPlatformSurface(QPlatformSurface *surface)
463
QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass();
464
if (surfaceClass == QSurface::Window) {
465
return static_cast<QXcbScreen *>(static_cast<QXcbWindow *>(surface)->screen());
466
} else if (surfaceClass == QSurface::Offscreen) {
467
return static_cast<QXcbScreen *>(static_cast<QGLXPbuffer *>(surface)->screen());
472
QVariant QGLXContext::nativeHandle() const
474
return QVariant::fromValue<QGLXNativeContext>(QGLXNativeContext(m_context));
477
bool QGLXContext::makeCurrent(QPlatformSurface *surface)
479
bool success = false;
480
Q_ASSERT(surface->surface()->supportsOpenGL());
482
GLXDrawable glxDrawable = 0;
483
QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass();
484
if (surfaceClass == QSurface::Window) {
485
m_isPBufferCurrent = false;
486
QXcbWindow *window = static_cast<QXcbWindow *>(surface);
487
glxDrawable = window->xcb_window();
488
success = glXMakeCurrent(m_display, glxDrawable, m_context);
489
} else if (surfaceClass == QSurface::Offscreen) {
490
m_isPBufferCurrent = true;
491
QGLXPbuffer *pbuffer = static_cast<QGLXPbuffer *>(surface);
492
glxDrawable = pbuffer->pbuffer();
493
success = glXMakeContextCurrent(m_display, glxDrawable, glxDrawable, m_context);
496
if (success && surfaceClass == QSurface::Window) {
497
int interval = surface->format().swapInterval();
498
QXcbScreen *screen = screenForPlatformSurface(surface);
499
if (interval >= 0 && m_swapInterval != interval && screen) {
500
m_swapInterval = interval;
501
typedef void (*qt_glXSwapIntervalEXT)(Display *, GLXDrawable, int);
502
typedef void (*qt_glXSwapIntervalMESA)(unsigned int);
503
static qt_glXSwapIntervalEXT glXSwapIntervalEXT = 0;
504
static qt_glXSwapIntervalMESA glXSwapIntervalMESA = 0;
505
static bool resolved = false;
508
QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(m_display,
509
screen->screenNumber())).split(' ');
510
if (glxExt.contains("GLX_EXT_swap_control"))
511
glXSwapIntervalEXT = (qt_glXSwapIntervalEXT) getProcAddress("glXSwapIntervalEXT");
512
if (glxExt.contains("GLX_MESA_swap_control"))
513
glXSwapIntervalMESA = (qt_glXSwapIntervalMESA) getProcAddress("glXSwapIntervalMESA");
515
if (glXSwapIntervalEXT)
516
glXSwapIntervalEXT(m_display, glxDrawable, interval);
517
else if (glXSwapIntervalMESA)
518
glXSwapIntervalMESA(interval);
525
void QGLXContext::doneCurrent()
527
if (m_isPBufferCurrent)
528
glXMakeContextCurrent(m_display, 0, 0, 0);
530
glXMakeCurrent(m_display, 0, 0);
531
m_isPBufferCurrent = false;
534
void QGLXContext::swapBuffers(QPlatformSurface *surface)
536
GLXDrawable glxDrawable = 0;
537
if (surface->surface()->surfaceClass() == QSurface::Offscreen)
538
glxDrawable = static_cast<QGLXPbuffer *>(surface)->pbuffer();
540
glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window();
541
glXSwapBuffers(m_display, glxDrawable);
543
if (surface->surface()->surfaceClass() == QSurface::Window) {
544
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(surface);
545
// OpenGL context might be bound to a non-gui thread use QueuedConnection to sync
546
// the window from the platformWindow's thread as QXcbWindow is no QObject, an
547
// event is sent to QXcbConnection. (this is faster than a metacall)
548
if (platformWindow->needsSync())
549
platformWindow->postSyncWindowRequest();
553
QFunctionPointer QGLXContext::getProcAddress(const char *procName)
556
return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName));
558
typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *);
559
static qt_glXGetProcAddressARB glXGetProcAddressARB = 0;
560
static bool resolved = false;
562
if (resolved && !glXGetProcAddressARB)
564
if (!glXGetProcAddressARB) {
565
QList<QByteArray> glxExt = QByteArray(glXGetClientString(m_display, GLX_EXTENSIONS)).split(' ');
566
if (glxExt.contains("GLX_ARB_get_proc_address")) {
567
#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
568
void *handle = dlopen(NULL, RTLD_LAZY);
570
glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB");
573
if (!glXGetProcAddressARB)
576
#ifndef QT_NO_LIBRARY
577
extern const QString qt_gl_library_name();
578
// QLibrary lib(qt_gl_library_name());
579
QLibrary lib(QLatin1String("GL"));
580
glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB");
586
if (!glXGetProcAddressARB)
588
return (void (*)())glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName));
592
QSurfaceFormat QGLXContext::format() const
597
bool QGLXContext::isSharing() const
599
return m_shareContext != 0;
602
bool QGLXContext::isValid() const
604
return m_context != 0;
607
bool QGLXContext::m_queriedDummyContext = false;
608
bool QGLXContext::m_supportsThreading = true;
611
// If this list grows to any significant size, change it a
612
// proper string table and make the implementation below use
614
static const char *qglx_threadedgl_blacklist_renderer[] = {
615
"Chromium", // QTBUG-32225 (initialization fails)
619
// This disables threaded rendering on anything using mesa, e.g.
623
// - some software opengl implementations
625
// The client glx vendor string is used to identify those setups as that seems to show the least
626
// variance between the bad configurations. It's always "Mesa Project and SGI". There are some
627
// configurations which don't use mesa and which can do threaded rendering (amd and nvidia chips
628
// with their own proprietary drivers).
630
// This, of course, is very broad and disables threaded rendering on a lot of devices which would
631
// be able to use it. However, the bugs listed below don't follow any easily recognizable pattern
632
// and we should rather be safe.
634
// http://cgit.freedesktop.org/xcb/libxcb/commit/?id=be0fe56c3bcad5124dcc6c47a2fad01acd16f71a will
635
// fix some of the issues. Basically, the proprietary drivers seem to have a way of working around
636
// a fundamental flaw with multithreaded access to xcb, but mesa doesn't. The blacklist should be
637
// reevaluated once that patch is released in some version of xcb.
638
static const char *qglx_threadedgl_blacklist_vendor[] = {
639
"Mesa Project and SGI", // QTCREATORBUG-10875 (crash in creator)
640
// QTBUG-34492 (flickering in fullscreen)
645
void QGLXContext::queryDummyContext()
647
if (m_queriedDummyContext)
649
m_queriedDummyContext = true;
651
static bool skip = qEnvironmentVariableIsSet("QT_OPENGL_NO_SANITY_CHECK");
655
QOpenGLContext *oldContext = QOpenGLContext::currentContext();
656
QSurface *oldSurface = 0;
658
oldSurface = oldContext->surface();
660
QScopedPointer<QSurface> surface;
661
Display *display = glXGetCurrentDisplay();
663
// FIXME: Since Qt 5.6 we don't need to check whether primary screen is NULL
664
if (QScreen *screen = QGuiApplication::primaryScreen())
665
display = DISPLAY_FROM_XCB(static_cast<QXcbScreen *>(screen->handle()));
667
const char *glxvendor = glXGetClientString(display, GLX_VENDOR);
668
if (glxvendor && !strcmp(glxvendor, "ATI")) {
669
QWindow *window = new QWindow;
670
window->resize(64, 64);
671
window->setSurfaceType(QSurface::OpenGLSurface);
673
surface.reset(window);
675
QOffscreenSurface *offSurface = new QOffscreenSurface;
676
offSurface->create();
677
surface.reset(offSurface);
680
QOpenGLContext context;
682
context.makeCurrent(surface.data());
684
m_supportsThreading = true;
686
if (const char *renderer = (const char *) glGetString(GL_RENDERER)) {
687
for (int i = 0; qglx_threadedgl_blacklist_renderer[i]; ++i) {
688
if (strstr(renderer, qglx_threadedgl_blacklist_renderer[i]) != 0) {
689
m_supportsThreading = false;
696
for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) {
697
if (strstr(glxvendor, qglx_threadedgl_blacklist_vendor[i]) != 0) {
698
m_supportsThreading = false;
704
context.doneCurrent();
705
if (oldContext && oldSurface)
706
oldContext->makeCurrent(oldSurface);
709
bool QGLXContext::supportsThreading()
711
if (!m_queriedDummyContext)
713
return m_supportsThreading;
716
QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface)
717
: QPlatformOffscreenSurface(offscreenSurface)
718
, m_screen(static_cast<QXcbScreen *>(offscreenSurface->screen()->handle()))
719
, m_format(m_screen->surfaceFormatFor(offscreenSurface->requestedFormat()))
722
GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), m_format);
725
const int attributes[] = {
726
GLX_PBUFFER_WIDTH, offscreenSurface->size().width(),
727
GLX_PBUFFER_HEIGHT, offscreenSurface->size().height(),
728
GLX_LARGEST_PBUFFER, False,
729
GLX_PRESERVED_CONTENTS, False,
733
m_pbuffer = glXCreatePbuffer(DISPLAY_FROM_XCB(m_screen), config, attributes);
736
qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(m_screen), config);
740
QGLXPbuffer::~QGLXPbuffer()
743
glXDestroyPbuffer(DISPLAY_FROM_XCB(m_screen), m_pbuffer);