Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qxcbglxintegration.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#if QT_CONFIG(xcb_glx)
7#include <xcb/glx.h>
8#endif
9
10#include "qxcbnativeinterface.h"
11#include "qxcbglxwindow.h"
12#include "qxcbscreen.h"
13#include "qglxintegration.h"
14
15#include <QtCore/QVersionNumber>
16#include <QtGui/QOpenGLContext>
17#include <QtGui/private/qopenglcontext_p.h>
18
20
21#define register /* C++17 deprecated register */
22#include <X11/Xlibint.h>
23#undef register
24
26
27#if QT_CONFIG(xcb_glx)
28 #define QT_XCB_GLX_REQUIRED_MAJOR 1
29 #define QT_XCB_GLX_REQUIRED_MINOR 3
30
31 #if XCB_GLX_MAJOR_VERSION == 1 && XCB_GLX_MINOR_VERSION < 4
32 #define XCB_GLX_BUFFER_SWAP_COMPLETE 1
33 typedef struct xcb_glx_buffer_swap_complete_event_t {
34 uint8_t response_type;
35 uint8_t pad0;
36 uint16_t sequence;
37 uint16_t event_type;
38 uint8_t pad1[2];
39 xcb_glx_drawable_t drawable;
40 uint32_t ust_hi;
41 uint32_t ust_lo;
42 uint32_t msc_hi;
43 uint32_t msc_lo;
44 uint32_t sbc;
45 } xcb_glx_buffer_swap_complete_event_t;
46 #endif
47 typedef struct {
48 int type;
49 unsigned long serial; /* # of last request processed by server */
50 Bool send_event; /* true if this came from a SendEvent request */
51 Display *display; /* Display the event was read from */
52 Drawable drawable; /* drawable on which event was requested in event mask */
53 int event_type;
54 int64_t ust;
55 int64_t msc;
56 int64_t sbc;
57 } QGLXBufferSwapComplete;
58#endif
59
61 : m_connection(nullptr)
62 , m_glx_first_event(0)
63{
64 qCDebug(lcQpaGl) << "Xcb GLX gl-integration created";
65}
66
70
72{
73 m_connection = connection;
74#if QT_CONFIG(xcb_glx)
75
76 const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection->xcb_connection(), &xcb_glx_id);
77 if (!reply || !reply->present)
78 return false;
79
80 m_glx_first_event = reply->first_event;
81
82 auto xglx_query = Q_XCB_REPLY(xcb_glx_query_version, m_connection->xcb_connection(),
83 XCB_GLX_MAJOR_VERSION,
84 XCB_GLX_MINOR_VERSION);
85 if ((!xglx_query)
86 || (QVersionNumber(xglx_query->major_version, xglx_query->minor_version)
87 < QVersionNumber(QT_XCB_GLX_REQUIRED_MAJOR, QT_XCB_GLX_REQUIRED_MINOR))) {
88 qCWarning(lcQpaGl) << "QXcbConnection: Failed to initialize GLX";
89 return false;
90 }
91#endif
92
93 m_native_interface_handler.reset(new QXcbGlxNativeInterfaceHandler(connection->nativeInterface()));
94
95 qCDebug(lcQpaGl) << "Xcb GLX gl-integration successfully initialized";
96 return true;
97}
98
99bool QXcbGlxIntegration::handleXcbEvent(xcb_generic_event_t *event, uint responseType)
100{
101 bool handled = false;
102 // Check if a custom XEvent constructor was registered in xlib for this event type, and call it discarding the constructed XEvent if any.
103 // XESetWireToEvent might be used by libraries to intercept messages from the X server e.g. the OpenGL lib waiting for DRI2 events.
104 Display *xdisplay = static_cast<Display *>(m_connection->xlib_display());
105 XLockDisplay(xdisplay);
106 bool locked = true;
107 Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent(xdisplay, responseType, nullptr);
108 if (proc) {
109 XESetWireToEvent(xdisplay, responseType, proc);
110 XEvent dummy;
111 event->sequence = LastKnownRequestProcessed(xdisplay);
112 if (proc(xdisplay, &dummy, (xEvent*)event)) {
113#if QT_CONFIG(xcb_glx)
114 // DRI2 clients don't receive GLXBufferSwapComplete events on the wire.
115 // Instead the GLX event is synthesized from the DRI2BufferSwapComplete event
116 // by DRI2WireToEvent(). For an application to be able to see the event
117 // we have to convert it to an xcb_glx_buffer_swap_complete_event_t and
118 // pass it to the native event filter.
119 const uint swap_complete = m_glx_first_event + XCB_GLX_BUFFER_SWAP_COMPLETE;
121 if (dispatcher && uint(dummy.type) == swap_complete && responseType != swap_complete) {
122 QGLXBufferSwapComplete *xev = reinterpret_cast<QGLXBufferSwapComplete *>(&dummy);
123 xcb_glx_buffer_swap_complete_event_t ev;
124 memset(&ev, 0, sizeof(xcb_glx_buffer_swap_complete_event_t));
125 ev.response_type = xev->type;
126 ev.sequence = xev->serial;
127 ev.event_type = xev->event_type;
128 ev.drawable = xev->drawable;
129 ev.ust_hi = xev->ust >> 32;
130 ev.ust_lo = xev->ust & 0xffffffff;
131 ev.msc_hi = xev->msc >> 32;
132 ev.msc_lo = xev->msc & 0xffffffff;
133 ev.sbc = xev->sbc & 0xffffffff;
134 // Unlock the display before calling the native event filter
135 XUnlockDisplay(xdisplay);
136 locked = false;
137 auto eventType = m_connection->nativeInterface()->nativeEventType();
138 qintptr result = 0;
139 handled = dispatcher->filterNativeEvent(eventType, &ev, &result);
140 }
141#endif
142 }
143 }
144 if (locked)
145 XUnlockDisplay(xdisplay);
146 return handled;
147}
148
153
155{
156 QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle());
157 return new QGLXContext(static_cast<Display *>(m_connection->xlib_display()),
158 screen, screen->surfaceFormatFor(context->format()), context->shareHandle());
159}
160
161QOpenGLContext *QXcbGlxIntegration::createOpenGLContext(GLXContext glxContext, void *visualInfo, QOpenGLContext *shareContext) const
162{
163 if (!glxContext)
164 return nullptr;
165
166 QPlatformOpenGLContext *shareHandle = shareContext ? shareContext->handle() : nullptr;
167
168 auto *context = new QOpenGLContext;
169 auto *contextPrivate = QOpenGLContextPrivate::get(context);
170 auto *display = static_cast<Display *>(m_connection->xlib_display());
171 contextPrivate->adopt(new QGLXContext(display, glxContext, visualInfo, shareHandle));
172 return context;
173}
174
176{
177 static bool vendorChecked = false;
178 static bool glxPbufferUsable = true;
179 if (!vendorChecked) {
180 vendorChecked = true;
181 Display *display = glXGetCurrentDisplay();
182 if (!display)
183 display = static_cast<Display *>(m_connection->xlib_display());
184
185 const char *glxvendor = glXGetClientString(display, GLX_VENDOR);
186 if (glxvendor) {
187 if (!strcmp(glxvendor, "ATI") || !strcmp(glxvendor, "Chromium"))
188 glxPbufferUsable = false;
189 }
190 }
191 if (glxPbufferUsable)
192 return new QGLXPbuffer(surface);
193 else
194 return nullptr; // trigger fallback to hidden QWindow
195
196}
197
202
204{
205 static bool vendorChecked = false;
206 static bool isSwitchableWidgetCompositionAvailable = true;
207 if (!vendorChecked) {
208 vendorChecked = true;
209 Display *display = glXGetCurrentDisplay();
210 if (!display)
211 display = static_cast<Display *>(m_connection->xlib_display());
212
213 const char *glxvendor = glXGetClientString(display, GLX_VENDOR);
214 if (glxvendor) {
215 if (!strcmp(glxvendor, "Parallels Inc"))
216 isSwitchableWidgetCompositionAvailable = false;
217 }
218 }
219
220 return isSwitchableWidgetCompositionAvailable;
221}
222
223
static QAbstractEventDispatcher * instance(QThread *thread=nullptr)
Returns a pointer to the event dispatcher object for the specified thread.
bool filterNativeEvent(const QByteArray &eventType, void *message, qintptr *result)
Sends message through the event filters that were set by installNativeEventFilter().
static bool supportsThreading()
\inmodule QtGui
static QOpenGLContextPrivate * get(QOpenGLContext *context)
\inmodule QtGui
QPlatformOpenGLContext * handle() const
Returns the underlying platform context.
The QPlatformOpenGLContext class provides an abstraction for native GL contexts.
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.
\inmodule QtCore
\inmodule QtGui
Definition qwindow.h:63
xcb_connection_t * xcb_connection() const
QXcbNativeInterface * nativeInterface() const
QXcbWindow * createWindow(QWindow *window) const override
bool supportsThreadedOpenGL() const override
QPlatformOffscreenSurface * createPlatformOffscreenSurface(QOffscreenSurface *surface) const override
bool handleXcbEvent(xcb_generic_event_t *event, uint responseType) override
bool supportsSwitchableWidgetComposition() const override
QOpenGLContext * createOpenGLContext(GLXContext context, void *visualInfo, QOpenGLContext *shareContext) const override
QPlatformOpenGLContext * createPlatformOpenGLContext(QOpenGLContext *context) const override
bool initialize(QXcbConnection *connection) override
const QByteArray & nativeEventType() const
struct wl_display * display
Definition linuxdmabuf.h:41
Combined button and popup list for selecting options.
uint Bool
static void * context
DBusConnection * connection
#define qCWarning(category,...)
#define qCDebug(category,...)
GLenum type
struct _cl_event * event
GLuint64EXT * result
[6]
XID Drawable
QScreen * screen
[1]
Definition main.cpp:29
struct _XDisplay Display
unsigned int uint
Definition qtypes.h:34
ptrdiff_t qintptr
Definition qtypes.h:166
#define Q_XCB_REPLY(call,...)
QObject::connect nullptr
aWidget window() -> setWindowTitle("New Window Title")
[2]
QNetworkReply * reply