diff --git a/CMakeLists.txt b/CMakeLists.txt
index b05e106030..d87291e39b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -195,6 +195,7 @@ find_package(XCB
IMAGE
SHM
XTEST
+ GLX
OPTIONAL_COMPONENTS
ICCCM
)
@@ -513,6 +514,7 @@ set(kwin_XCB_LIBS
XCB::KEYSYMS
XCB::SHM
XCB::XTEST
+ XCB::GLX
)
set(kwin_WAYLAND_LIBS
diff --git a/compositingprefs.cpp b/compositingprefs.cpp
index b675872faf..ee92851cff 100644
--- a/compositingprefs.cpp
+++ b/compositingprefs.cpp
@@ -116,20 +116,9 @@ QString CompositingPrefs::compositingNotPossibleReason()
return QString();
}
-static bool s_glxDetected = false;
-static bool s_hasGlx = false;
-
bool CompositingPrefs::hasGlx()
{
- if (s_glxDetected) {
- return s_hasGlx;
- }
-#ifndef KWIN_HAVE_OPENGLES
- int event_base, error_base;
- s_hasGlx = glXQueryExtension(display(), &event_base, &error_base);
-#endif
- s_glxDetected = true;
- return s_hasGlx;
+ return Xcb::Extensions::self()->hasGlx();
}
} // namespace
diff --git a/xcbutils.cpp b/xcbutils.cpp
index 1ac3b09e21..a536f67f7f 100644
--- a/xcbutils.cpp
+++ b/xcbutils.cpp
@@ -30,6 +30,7 @@ along with this program. If not, see .
#include
#include
#include
+#include
// system
#include
#include
@@ -266,6 +267,70 @@ QVector syncOpCodes()
QByteArrayLiteral("AwaitFence")});
}
+static QVector glxOpCodes()
+{
+ return QVector{
+ QByteArrayLiteral(""),
+ QByteArrayLiteral("Render"),
+ QByteArrayLiteral("RenderLarge"),
+ QByteArrayLiteral("CreateContext"),
+ QByteArrayLiteral("DestroyContext"),
+ QByteArrayLiteral("MakeCurrent"),
+ QByteArrayLiteral("IsDirect"),
+ QByteArrayLiteral("QueryVersion"),
+ QByteArrayLiteral("WaitGL"),
+ QByteArrayLiteral("WaitX"),
+ QByteArrayLiteral("CopyContext"),
+ QByteArrayLiteral("SwapBuffers"),
+ QByteArrayLiteral("UseXFont"),
+ QByteArrayLiteral("CreateGLXPixmap"),
+ QByteArrayLiteral("GetVisualConfigs"),
+ QByteArrayLiteral("DestroyGLXPixmap"),
+ QByteArrayLiteral("VendorPrivate"),
+ QByteArrayLiteral("VendorPrivateWithReply"),
+ QByteArrayLiteral("QueryExtensionsString"),
+ QByteArrayLiteral("QueryServerString"),
+ QByteArrayLiteral("ClientInfo"),
+ QByteArrayLiteral("GetFBConfigs"),
+ QByteArrayLiteral("CreatePixmap"),
+ QByteArrayLiteral("DestroyPixmap"),
+ QByteArrayLiteral("CreateNewContext"),
+ QByteArrayLiteral("QueryContext"),
+ QByteArrayLiteral("MakeContextCurrent"),
+ QByteArrayLiteral("CreatePbuffer"),
+ QByteArrayLiteral("DestroyPbuffer"),
+ QByteArrayLiteral("GetDrawableAttributes"),
+ QByteArrayLiteral("ChangeDrawableAttributes"),
+ QByteArrayLiteral("CreateWindow"),
+ QByteArrayLiteral("DeleteWindow"),
+ QByteArrayLiteral("SetClientInfoARB"),
+ QByteArrayLiteral("CreateContextAttribsARB"),
+ QByteArrayLiteral("SetClientInfo2ARB")
+ // Opcodes 36-100 are unused
+ // The GL single commands begin at opcode 101
+ };
+}
+
+static QVector glxErrorCodes()
+{
+ return QVector{
+ QByteArrayLiteral("BadContext"),
+ QByteArrayLiteral("BadContextState"),
+ QByteArrayLiteral("BadDrawable"),
+ QByteArrayLiteral("BadPixmap"),
+ QByteArrayLiteral("BadContextTag"),
+ QByteArrayLiteral("BadCurrentWindow"),
+ QByteArrayLiteral("BadRenderRequest"),
+ QByteArrayLiteral("BadLargeRequest"),
+ QByteArrayLiteral("UnsupportedPrivateRequest"),
+ QByteArrayLiteral("BadFBConfig"),
+ QByteArrayLiteral("BadPbuffer"),
+ QByteArrayLiteral("BadCurrentDrawable"),
+ QByteArrayLiteral("BadWindow"),
+ QByteArrayLiteral("GLXBadProfileARB")
+ };
+}
+
ExtensionData::ExtensionData()
: version(0)
, eventBase(0)
@@ -317,6 +382,7 @@ void Extensions::init()
xcb_prefetch_extension_data(c, &xcb_xfixes_id);
xcb_prefetch_extension_data(c, &xcb_render_id);
xcb_prefetch_extension_data(c, &xcb_sync_id);
+ xcb_prefetch_extension_data(c, &xcb_glx_id);
m_shape.name = QByteArray("SHAPE");
m_randr.name = QByteArray("RANDR");
@@ -325,6 +391,7 @@ void Extensions::init()
m_fixes.name = QByteArray("XFIXES");
m_render.name = QByteArray("RENDER");
m_sync.name = QByteArray("SYNC");
+ m_glx.name = QByteArray("GLX");
m_shape.opCodes = shapeOpCodes();
m_randr.opCodes = randrOpCodes();
@@ -333,10 +400,12 @@ void Extensions::init()
m_fixes.opCodes = fixesOpCodes();
m_render.opCodes = renderOpCodes();
m_sync.opCodes = syncOpCodes();
+ m_glx.opCodes = glxOpCodes();
m_randr.errorCodes = randrErrorCodes();
m_damage.errorCodes = damageErrorCodes();
m_fixes.errorCodes = fixesErrorCodes();
+ m_glx.errorCodes = glxErrorCodes();
extensionQueryReply(xcb_get_extension_data(c, &xcb_shape_id), &m_shape);
extensionQueryReply(xcb_get_extension_data(c, &xcb_randr_id), &m_randr);
@@ -345,6 +414,7 @@ void Extensions::init()
extensionQueryReply(xcb_get_extension_data(c, &xcb_xfixes_id), &m_fixes);
extensionQueryReply(xcb_get_extension_data(c, &xcb_render_id), &m_render);
extensionQueryReply(xcb_get_extension_data(c, &xcb_sync_id), &m_sync);
+ extensionQueryReply(xcb_get_extension_data(c, &xcb_glx_id), &m_glx);
// extension specific queries
xcb_shape_query_version_cookie_t shapeVersion;
@@ -480,7 +550,8 @@ QVector Extensions::extensions() const
<< m_composite
<< m_render
<< m_fixes
- << m_sync;
+ << m_sync
+ << m_glx;
return extensions;
}
diff --git a/xcbutils.h b/xcbutils.h
index 2640e52c94..39ca05b383 100644
--- a/xcbutils.h
+++ b/xcbutils.h
@@ -909,6 +909,15 @@ public:
}
int syncAlarmNotifyEvent() const;
QVector extensions() const;
+ bool hasGlx() const {
+ return m_glx.present;
+ }
+ int glxEventBase() const {
+ return m_glx.eventBase;
+ }
+ int glxMajorOpcode() const {
+ return m_glx.majorOpcode;
+ }
static Extensions *self();
static void destroy();
@@ -927,6 +936,7 @@ private:
ExtensionData m_render;
ExtensionData m_fixes;
ExtensionData m_sync;
+ ExtensionData m_glx;
static Extensions *s_self;
};