15#if QT_CONFIG(regularexpression)
16# include <QtCore/QRegularExpression>
18#include <QtGui/qguiapplication.h>
19#include <QtGui/QOpenGLContext>
20#include <QtGui/QOffscreenSurface>
23#include <QtGui/private/qglxconvenience_p.h>
32#ifndef GLX_CONTEXT_CORE_PROFILE_BIT_ARB
33#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
36#ifndef GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
37#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
40#ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT
41#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
44#ifndef GLX_CONTEXT_PROFILE_MASK_ARB
45#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126
48#ifndef GL_CONTEXT_FLAG_DEBUG_BIT
49#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
52#ifndef GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB
53#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
56#ifndef GL_RESET_NOTIFICATION_STRATEGY_ARB
57#define GL_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
60#ifndef GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
61#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
64#ifndef GL_LOSE_CONTEXT_ON_RESET_ARB
65#define GL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
68#ifndef GLX_LOSE_CONTEXT_ON_RESET_ARB
69#define GLX_LOSE_CONTEXT_ON_RESET_ARB 0x8252
72#ifndef GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV
73#define GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV 0x20F7
78 Colormap cmap = XCreateColormap(dpy, rootWin, visualInfo->visual, AllocNone);
79 XSetWindowAttributes
a;
80 a.background_pixel = WhitePixel(dpy, screenNumber);
81 a.border_pixel = BlackPixel(dpy, screenNumber);
83 a.override_redirect =
true;
87 0, visualInfo->
depth, InputOutput, visualInfo->visual,
88 CWBackPixel|CWBorderPixel|CWColormap|CWOverrideRedirect, &
a);
90 XStoreName(dpy,
window,
"Qt GLX dummy window");
92 XFreeColormap(dpy, cmap);
98 XVisualInfo *visualInfo = glXGetVisualFromFBConfig(dpy,
config);
100 qFatal(
"Could not initialize GLX");
108 if (
const GLubyte *
s = glGetString(
param))
109 return QByteArray(
reinterpret_cast<const char*
>(
s));
115 if (
format.majorVersion() < 3) {
116 auto exts =
reinterpret_cast<const char *
>(glGetString(GL_EXTENSIONS));
117 return exts && strstr(exts,
ext);
120 glXGetProcAddress(
reinterpret_cast<const GLubyte*
>(
"glGetStringi")));
125 const char *
p =
reinterpret_cast<const char *
>(glGetStringi(GL_EXTENSIONS,
i));
126 if (
p && !strcmp(
p,
ext))
137 int major = 0, minor = 0;
140 format.setMajorVersion(major);
141 format.setMinorVersion(minor);
146 format.setOptions(QSurfaceFormat::FormatOptions());
190 , m_ownsContext(true)
203 XVisualInfo *visualInfo =
nullptr;
211 if (glxExt.contains(
"GLX_ARB_create_context"))
214 const bool supportsProfiles = glxExt.contains(
"GLX_ARB_create_context_profile");
215 const bool supportsRobustness = glxExt.contains(
"GLX_ARB_create_context_robustness");
216 const bool supportsVideoMemoryPurge = glxExt.contains(
"GLX_NV_robustness_video_memory_purge");
220 if (glXCreateContextAttribsARB !=
nullptr
228 if (requestedVersion > 46)
229 glVersions << requestedVersion;
232 glVersions << 46 << 45 << 44 << 43 << 42 << 41 << 40 << 33 << 32 << 31 << 30 << 21 << 20;
234 if (requestedVersion > 32)
235 glVersions << requestedVersion;
238 glVersions << 32 << 31 << 30 << 20;
240 m_format.
setOptions(QSurfaceFormat::FormatOptions());
247 for (
int i = 0; !m_context &&
i < glVersions.
size();
i++) {
248 const int version = glVersions[
i];
249 if (version > requestedVersion)
252 const int majorVersion = version / 10;
253 const int minorVersion = version % 10;
256 contextAttributes << GLX_CONTEXT_MAJOR_VERSION_ARB << majorVersion
257 << GLX_CONTEXT_MINOR_VERSION_ARB << minorVersion;
262 if (version >= 32 && supportsProfiles) {
271 if (supportsRobustness)
275 flags |= GLX_CONTEXT_DEBUG_BIT_ARB;
279 flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
282 contextAttributes << GLX_CONTEXT_FLAGS_ARB <<
flags;
288 QList<int> contextAttributesWithRobustness = contextAttributes;
290 if (supportsVideoMemoryPurge)
293 contextAttributesWithRobustness <<
None;
294 m_context = glXCreateContextAttribsARB(m_display,
config, m_shareContext,
true,
295 contextAttributesWithRobustness.
data());
303 contextAttributes <<
None;
304 m_context = glXCreateContextAttribsARB(m_display,
config, m_shareContext,
true, contextAttributes.
data());
305 if (!m_context && m_shareContext) {
307 m_context = glXCreateContextAttribsARB(m_display,
config,
nullptr,
true, contextAttributes.
data());
309 m_shareContext =
nullptr;
321 m_context = glXCreateNewContext(m_display,
config, GLX_RGBA_TYPE, m_shareContext,
true);
322 if (!m_context && m_shareContext) {
324 m_context = glXCreateNewContext(m_display,
config, GLX_RGBA_TYPE,
nullptr,
true);
326 m_shareContext =
nullptr;
344 qFatal(
"Could not initialize GLX");
345 m_context = glXCreateContext(m_display, visualInfo, m_shareContext,
true);
346 if (!m_context && m_shareContext) {
348 m_shareContext =
nullptr;
349 m_context = glXCreateContext(m_display, visualInfo,
nullptr,
true);
358 if (m_context &&
window) {
359 GLXContext prevContext = glXGetCurrentContext();
360 GLXDrawable prevDrawable = glXGetCurrentDrawable();
361 glXMakeCurrent(m_display,
window, m_context);
365 glXMakeCurrent(m_display, prevDrawable, prevContext);
369 XDestroyWindow(m_display,
window);
378 XVisualInfo *vinfo =
static_cast<XVisualInfo*
>(visualInfo);
383 if (glXQueryContext(m_display,
context, GLX_FBCONFIG_ID, &configId) !=
Success) {
384 qWarning(
"QGLXContext: Failed to query config from the provided context");
388 int screenNumber = 0;
389 if (glXQueryContext(m_display,
context, GLX_SCREEN, &screenNumber) !=
Success) {
390 qWarning(
"QGLXContext: Failed to query screen from the provided context");
391 screenNumber = DefaultScreen(m_display);
394 GLXFBConfig *configs;
396 static const int attribs[] = { GLX_FBCONFIG_ID, configId,
None };
397 configs = glXChooseFBConfig(m_display, screenNumber,
attribs, &numConfigs);
399 qWarning(
"QGLXContext: Failed to find config(invalid arguments for glXChooseFBConfig)");
401 }
else if (numConfigs < 1) {
402 qWarning(
"QGLXContext: Failed to find config");
406 if (configs && numConfigs > 1)
407 qWarning(
"QGLXContext: Multiple configs for FBConfig ID %d", configId);
409 m_config = configs[0];
415 int screenNumber = DefaultScreen(m_display);
422 qWarning(
"QGLXContext: Failed to create dummy window");
427 GLXContext prevContext = glXGetCurrentContext();
428 GLXDrawable prevDrawable = glXGetCurrentDrawable();
430 qWarning(
"QGLXContext: Failed to make provided context current");
441 glXMakeCurrent(m_display, prevDrawable, prevContext);
442 XDestroyWindow(m_display,
window);
457 glXDestroyContext(m_display, m_context);
473 bool success =
false;
476 GLXDrawable glxDrawable = 0;
479 m_isPBufferCurrent =
false;
481 glxDrawable =
window->xcb_window();
482 success = glXMakeCurrent(m_display, glxDrawable, m_context);
484 if (m_getGraphicsResetStatus && m_getGraphicsResetStatus() != GL_NO_ERROR) {
488 window->invalidateSurface();
491 m_isPBufferCurrent =
true;
493 glxDrawable = pbuffer->
pbuffer();
494 success = glXMakeContextCurrent(m_display, glxDrawable, glxDrawable, m_context);
496 if (m_getGraphicsResetStatus && m_getGraphicsResetStatus() != GL_NO_ERROR) {
506 if (interval >= 0 && interval !=
window->swapInterval() &&
screen) {
507 typedef void (*qt_glXSwapIntervalEXT)(
Display *, GLXDrawable, int);
508 typedef void (*qt_glXSwapIntervalMESA)(
unsigned int);
509 static qt_glXSwapIntervalEXT glXSwapIntervalEXT =
nullptr;
510 static qt_glXSwapIntervalMESA glXSwapIntervalMESA =
nullptr;
511 static bool resolved =
false;
516 if (glxExt.
contains(
"GLX_EXT_swap_control"))
517 glXSwapIntervalEXT = (qt_glXSwapIntervalEXT)
getProcAddress(
"glXSwapIntervalEXT");
518 if (glxExt.
contains(
"GLX_MESA_swap_control"))
519 glXSwapIntervalMESA = (qt_glXSwapIntervalMESA)
getProcAddress(
"glXSwapIntervalMESA");
521 if (glXSwapIntervalEXT)
522 glXSwapIntervalEXT(m_display, glxDrawable, interval);
523 else if (glXSwapIntervalMESA)
524 glXSwapIntervalMESA(interval);
525 window->setSwapInterval(interval);
534 if (m_isPBufferCurrent)
535 glXMakeContextCurrent(m_display, 0, 0,
nullptr);
537 glXMakeCurrent(m_display, 0,
nullptr);
538 m_isPBufferCurrent =
false;
543 GLXDrawable glxDrawable = 0;
545 glxDrawable =
static_cast<QGLXPbuffer *
>(surface)->pbuffer();
548 glXSwapBuffers(m_display, glxDrawable);
562 return glXGetProcAddress(
reinterpret_cast<const GLubyte *
>(procName));
572 return m_shareContext !=
nullptr;
577 return m_context !=
nullptr && !m_lost;
580bool QGLXContext::m_queriedDummyContext =
false;
581bool QGLXContext::m_supportsThreading =
true;
600 if (m_queriedDummyContext)
602 m_queriedDummyContext =
true;
611 oldSurface = oldContext->
surface();
622 const char *glxvendor = glXGetClientString(
display, GLX_VENDOR);
623 if (glxvendor && !strcmp(glxvendor,
"ATI")) {
632 surface.
reset(offSurface);
637 qWarning(
"QGLXContext: Failed to create dummy context");
638 m_supportsThreading =
false;
642 m_supportsThreading =
true;
644 if (
const char *
renderer = (
const char *) glGetString(GL_RENDERER)) {
647 qCDebug(lcQpaGl).nospace() <<
"Multithreaded OpenGL disabled: "
648 "blacklisted renderer \""
651 m_supportsThreading =
false;
656 if (
const char *vendor = (
const char *) glGetString(GL_VENDOR)) {
659 qCDebug(lcQpaGl).nospace() <<
"Multithreaded OpenGL disabled: "
660 "blacklisted vendor \""
663 m_supportsThreading =
false;
669 if (glxvendor && m_supportsThreading) {
672 const char *mesaVersionStr =
nullptr;
673 if (strstr(glxvendor,
"Mesa Project") !=
nullptr) {
674 mesaVersionStr = (
const char *) glGetString(GL_VERSION);
675 m_supportsThreading =
false;
678 if (mesaVersionStr) {
682#if QT_CONFIG(regularexpression)
688 if (versionNr >= 17) {
690 m_supportsThreading =
true;
694 if (!m_supportsThreading) {
695 qCDebug(lcQpaGl).nospace() <<
"Multithreaded OpenGL disabled: "
696 "blacklisted vendor \"Mesa Project\"";
702 m_supportsThreading =
false;
705 if (oldContext && oldSurface)
708 if (!m_supportsThreading) {
709 qCDebug(lcQpaGl) <<
"Force-enable multithreaded OpenGL by setting "
710 "environment variable QT_OPENGL_NO_SANITY_CHECK";
717 return m_supportsThreading;
723 , m_format(m_screen->surfaceFormatFor(offscreenSurface->requestedFormat()))
730 const int attributes[] = {
733 GLX_LARGEST_PBUFFER,
False,
734 GLX_PRESERVED_CONTENTS,
False,
738 m_pbuffer = glXCreatePbuffer(m_display,
config, attributes);
748 glXDestroyPbuffer(m_display, m_pbuffer);
QList< QByteArray > split(char sep) const
Splits the byte array into subarrays wherever sep occurs, and returns the list of those arrays.
bool makeCurrent(QPlatformSurface *surface) override
QSurfaceFormat format() const override
QGLXContext(Display *display, QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share)
static bool supportsThreading()
bool isValid() const override
void swapBuffers(QPlatformSurface *surface) override
Reimplement in subclass to native swap buffers calls.
static void queryDummyContext()
void doneCurrent() override
QFunctionPointer getProcAddress(const char *procName) override
Reimplement in subclass to allow dynamic querying of OpenGL symbols.
bool isSharing() const override
GLXContext glxContext() const
QGLXPbuffer(QOffscreenSurface *offscreenSurface)
GLXPbuffer pbuffer() const
QScreen * primaryScreen
the primary (or default) screen of the application.
qsizetype size() const noexcept
void create()
Allocates the platform resources associated with the offscreen surface.
QSize size() const override
Returns the size of the offscreen surface.
bool create()
Attempts to create the OpenGL context with the current configuration.
bool makeCurrent(QSurface *surface)
Makes the context current in the current thread, against the given surface.
static OpenGLModuleType openGLModuleType()
Returns the underlying OpenGL implementation type.
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
void doneCurrent()
Convenience function for calling makeCurrent with a 0 surface.
QSurface * surface() const
Returns the surface the context has been made current with.
The QPlatformOpenGLContext class provides an abstraction for native GL contexts.
virtual QSurfaceFormat format() const =0
QOpenGLContext * context() const
static bool parseOpenGLVersion(const QByteArray &versionString, int &major, int &minor)
\inmodule QtCore \reentrant
QString captured(int nth=0) const
Returns the substring captured by the nth capturing group.
\inmodule QtCore \reentrant
QRegularExpressionMatch match(const QString &subject, qsizetype offset=0, MatchType matchType=NormalMatch, MatchOptions matchOptions=NoMatchOption) const
Attempts to match the regular expression against the given subject string, starting at the position o...
T * data() const noexcept
Returns the value of the pointer referenced by this object.
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
The QScreen class is used to query screen properties. \inmodule QtGui.
QPlatformScreen * handle() const
Get the platform screen handle.
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
int toInt(bool *ok=nullptr, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
static QString fromLatin1(QByteArrayView ba)
This is an overloaded member function, provided for convenience. It differs from the above function o...
SurfaceClass surfaceClass() const
Returns the surface class of this surface.
bool supportsOpenGL() const
Returns true if the surface is OpenGL compatible and can be used in conjunction with QOpenGLContext; ...
SurfaceClass
The SurfaceClass enum describes the actual subclass of the surface.
QXcbConnection * connection() const
void postSyncWindowRequest()
[Window class with invokable method]
struct wl_display * display
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection * connection
#define GL_CONTEXT_PROFILE_MASK
#define GL_CONTEXT_COMPATIBILITY_PROFILE_BIT
#define GL_CONTEXT_CORE_PROFILE_BIT
#define GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, int flags)
void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo, int flags)
GLXFBConfig qglx_findConfig(Display *display, int screen, QSurfaceFormat format, bool highestPixelFormat, int drawableBit, int flags)
XVisualInfo * qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit, int flags)
#define GL_RESET_NOTIFICATION_STRATEGY_ARB
#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB
const GLubyte *(* glGetStringiProc)(GLenum, GLuint)
static Window createDummyWindow(Display *dpy, XVisualInfo *visualInfo, int screenNumber, Window rootWin)
#define GLX_GENERATE_RESET_ON_VIDEO_MEMORY_PURGE_NV
static void updateFormatFromContext(QSurfaceFormat &format)
QT_BEGIN_NAMESPACE typedef GLXContext(* glXCreateContextAttribsARBProc)(Display *, GLXFBConfig, GLXContext, Bool, const int *)
static QByteArray getGlString(GLenum param)
static const char * qglx_threadedgl_blacklist_vendor[]
static bool hasGlExtension(const QSurfaceFormat &format, const char *ext)
#define GLX_CONTEXT_ROBUST_ACCESS_BIT_ARB
static QXcbScreen * screenForPlatformSurface(QPlatformSurface *surface)
#define GL_LOSE_CONTEXT_ON_RESET_ARB
#define GLX_CONTEXT_PROFILE_MASK_ARB
static const char * qglx_threadedgl_blacklist_renderer[]
#define GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB
#define GL_CONTEXT_FLAG_DEBUG_BIT
#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB
#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT
#define GLX_LOSE_CONTEXT_ON_RESET_ARB
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
#define QOPENGLF_APIENTRYP
typedef GLint(GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC)(GLuint program
GLuint64 GLenum void * handle
GLboolean GLboolean GLboolean GLboolean a
[7]
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLenum const GLint * param
GLint GLsizei GLsizei GLenum format
const void * getProcAddress
#define GL_NUM_EXTENSIONS
constexpr decltype(auto) qMakePair(T1 &&value1, T2 &&value2) noexcept(noexcept(std::make_pair(std::forward< T1 >(value1), std::forward< T2 >(value2))))
#define QStringLiteral(str)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
static xcb_window_t xcb_window(QPlatformWindow *w)
QSvgRenderer * renderer
[0]
bool contains(const AT &t) const noexcept