diff options
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 191 |
1 files changed, 43 insertions, 148 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 5510c3b1b4..56b4a9abda 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -44,6 +44,8 @@ #include "qxcbnativeinterface.h" #include "qxcbintegration.h" #include "qxcbsystemtraytracker.h" +#include "qxcbglintegrationfactory.h" +#include "qxcbglintegration.h" #include <QSocketNotifier> #include <QAbstractEventDispatcher> @@ -74,14 +76,6 @@ #include <xcb/render.h> #endif -#if defined(XCB_HAS_XCB_GLX) -#include <xcb/glx.h> -#endif - -#ifdef XCB_USE_EGL //don't pull in eglext prototypes -#include <EGL/egl.h> -#endif - QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input") @@ -121,39 +115,6 @@ static int ioErrorHandler(Display *dpy) } #endif -#if defined(XCB_HAS_XCB_GLX) && XCB_GLX_MAJOR_VERSION == 1 && XCB_GLX_MINOR_VERSION < 4 - -#define XCB_GLX_BUFFER_SWAP_COMPLETE 1 - -typedef struct xcb_glx_buffer_swap_complete_event_t { - uint8_t response_type; - uint8_t pad0; - uint16_t sequence; - uint16_t event_type; - uint8_t pad1[2]; - xcb_glx_drawable_t drawable; - uint32_t ust_hi; - uint32_t ust_lo; - uint32_t msc_hi; - uint32_t msc_lo; - uint32_t sbc; -} xcb_glx_buffer_swap_complete_event_t; -#endif - -#if defined(XCB_USE_XLIB) && defined(XCB_USE_GLX) -typedef struct { - int type; - unsigned long serial; /* # of last request processed by server */ - Bool send_event; /* true if this came from a SendEvent request */ - Display *display; /* Display the event was read from */ - Drawable drawable; /* drawable on which event was requested in event mask */ - int event_type; - int64_t ust; - int64_t msc; - int64_t sbc; -} QGLXBufferSwapComplete; -#endif - QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& newScreens, int screenNumber, xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output) { @@ -166,7 +127,7 @@ QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& newScreens, int dotPos = displayName.lastIndexOf('.'); if (dotPos != -1) displayName.truncate(dotPos); - name = displayName + QLatin1Char('.') + QString::number(screenNumber); + name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(screenNumber); } foreach (QXcbScreen* scr, m_screens) if (scr->name() == name && scr->root() == xcbScreen->root) @@ -279,11 +240,12 @@ void QXcbConnection::updateScreens() ++xcbScreenNumber; } // for each xcb screen + QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration()); // Now activeScreens is the complete set of screens which are active at this time. // Delete any existing screens which are not in activeScreens for (int i = m_screens.count() - 1; i >= 0; --i) { if (!activeScreens.contains(m_screens[i])) { - delete m_screens[i]; + integration->destroyScreen(m_screens.at(i)); m_screens.removeAt(i); } } @@ -300,7 +262,7 @@ void QXcbConnection::updateScreens() // Now that they are in the right order, emit the added signals for new screens only foreach (QXcbScreen* screen, m_screens) if (newScreens.contains(screen)) - ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->screenAdded(screen); + integration->screenAdded(screen); } QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) @@ -309,11 +271,12 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , m_primaryScreenNumber(0) , m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) , m_nativeInterface(nativeInterface) +#ifdef XCB_USE_XLIB + , m_xlib_display(0) +#endif , xfixes_first_event(0) , xrandr_first_event(0) , xkb_first_event(0) - , glx_first_event(0) - , has_glx_extension(false) , has_shape_extension(false) , has_randr_extension(false) , has_input_shape(false) @@ -322,14 +285,10 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , m_buttons(0) , m_focusWindow(0) , m_systemTrayTracker(0) + , m_glIntegration(Q_NULLPTR) { -#ifdef XCB_USE_EGL - EGLNativeDisplayType dpy = EGL_DEFAULT_DISPLAY; -#elif defined(XCB_USE_XLIB) - Display *dpy; -#endif #ifdef XCB_USE_XLIB - dpy = XOpenDisplay(m_displayName.constData()); + Display *dpy = XOpenDisplay(m_displayName.constData()); if (dpy) { m_primaryScreenNumber = DefaultScreen(dpy); m_connection = XGetXCBConnection(dpy); @@ -345,12 +304,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra if (!m_connection || xcb_connection_has_error(m_connection)) qFatal("QXcbConnection: Could not connect to display %s", m_displayName.constData()); -#ifdef XCB_USE_EGL - EGLDisplay eglDisplay = eglGetDisplay(dpy); - m_egl_display = eglDisplay; - EGLint major, minor; - m_has_egl = eglInitialize(eglDisplay, &major, &minor); -#endif //XCB_USE_EGL m_reader = new QXcbEventReader(this); m_reader->start(); @@ -363,9 +316,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra #ifdef XCB_USE_RENDER &xcb_render_id, #endif -#ifdef XCB_HAS_XCB_GLX - &xcb_glx_id, -#endif 0 }; @@ -382,7 +332,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra initializeXRandr(); updateScreens(); - initializeGLX(); initializeXFixes(); initializeXRender(); m_xi2Enabled = false; @@ -405,6 +354,27 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra if (!m_startupId.isNull()) qunsetenv("DESKTOP_STARTUP_ID"); + + QStringList glIntegrationNames; + glIntegrationNames << QStringLiteral("xcb_glx") << QStringLiteral("xcb_egl"); + QString glIntegrationName = QString::fromLocal8Bit(qgetenv("QT_XCB_GL_INTEGRATION")); + if (glIntegrationName.size()) { + glIntegrationNames.removeAll(glIntegrationName); + glIntegrationNames.prepend(glIntegrationName); + } + + qCDebug(QT_XCB_GLINTEGRATION) << "Choosing xcb gl-integration based on following priority\n" << glIntegrationNames; + for (int i = 0; i < glIntegrationNames.size() && !m_glIntegration; i++) { + m_glIntegration = QXcbGlIntegrationFactory::create(glIntegrationNames.at(i)); + if (m_glIntegration && !m_glIntegration->initialize(this)) { + qCDebug(QT_XCB_GLINTEGRATION) << "Failed to initialize xcb gl-integration" << glIntegrationNames.at(i); + delete m_glIntegration; + m_glIntegration = Q_NULLPTR; + } + } + if (!m_glIntegration) + qCDebug(QT_XCB_GLINTEGRATION) << "Failed to create xcb gl-integration"; + sync(); if (qEnvironmentVariableIsEmpty("QT_IM_MODULE")) @@ -431,14 +401,10 @@ QXcbConnection::~QXcbConnection() delete m_reader; + QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration()); // Delete screens in reverse order to avoid crash in case of multiple screens while (!m_screens.isEmpty()) - delete m_screens.takeLast(); - -#ifdef XCB_USE_EGL - if (m_has_egl) - eglTerminate(m_egl_display); -#endif //XCB_USE_EGL + integration->destroyScreen(m_screens.takeLast()); #ifdef XCB_USE_XLIB XCloseDisplay((Display *)m_xlib_display); @@ -990,51 +956,8 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) } } -#ifdef XCB_USE_XLIB - if (!handled) { - // Check if a custom XEvent constructor was registered in xlib for this event type, and call it discarding the constructed XEvent if any. - // XESetWireToEvent might be used by libraries to intercept messages from the X server e.g. the OpenGL lib waiting for DRI2 events. - Display *xdisplay = (Display *)m_xlib_display; - XLockDisplay(xdisplay); - bool locked = true; - Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent(xdisplay, response_type, 0); - if (proc) { - XESetWireToEvent(xdisplay, response_type, proc); - XEvent dummy; - event->sequence = LastKnownRequestProcessed(m_xlib_display); - if (proc(xdisplay, &dummy, (xEvent*)event)) { -#if defined(XCB_USE_GLX) && defined(XCB_HAS_XCB_GLX) - // DRI2 clients don't receive GLXBufferSwapComplete events on the wire. - // Instead the GLX event is synthesized from the DRI2BufferSwapComplete event - // by DRI2WireToEvent(). For an application to be able to see the event - // we have to convert it to an xcb_glx_buffer_swap_complete_event_t and - // pass it to the native event filter. - const uint swap_complete = glx_first_event + XCB_GLX_BUFFER_SWAP_COMPLETE; - if (dispatcher && has_glx_extension && uint(dummy.type) == swap_complete && response_type != swap_complete) { - QGLXBufferSwapComplete *xev = reinterpret_cast<QGLXBufferSwapComplete *>(&dummy); - xcb_glx_buffer_swap_complete_event_t ev; - memset(&ev, 0, sizeof(xcb_glx_buffer_swap_complete_event_t)); - ev.response_type = xev->type; - ev.sequence = xev->serial; - ev.event_type = xev->event_type; - ev.drawable = xev->drawable; - ev.ust_hi = xev->ust >> 32; - ev.ust_lo = xev->ust & 0xffffffff; - ev.msc_hi = xev->msc >> 32; - ev.msc_lo = xev->msc & 0xffffffff; - ev.sbc = xev->sbc & 0xffffffff; - // Unlock the display before calling the native event filter - XUnlockDisplay(xdisplay); - locked = false; - handled = dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), &ev, &result); - } -#endif - } - } - if (locked) - XUnlockDisplay(xdisplay); - } -#endif + if (!handled) + handled = m_glIntegration->handleXcbEvent(event, response_type); if (handled) printXcbEvent("Handled XCB event", event); @@ -1232,6 +1155,13 @@ xcb_window_t QXcbConnection::rootWindow() return primaryScreen()->root(); } +#ifdef XCB_USE_XLIB +void *QXcbConnection::xlib_display() const +{ + return m_xlib_display; +} +#endif + void QXcbConnection::processXcbEvents() { int connection_error = xcb_connection_has_error(xcb_connection()); @@ -1674,34 +1604,6 @@ void QXcbConnection::initializeXRender() #endif } -void QXcbConnection::initializeGLX() -{ -#ifdef XCB_HAS_XCB_GLX - const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_glx_id); - if (!reply || !reply->present) - return; - - has_glx_extension = true; - glx_first_event = reply->first_event; - - xcb_generic_error_t *error = 0; - xcb_glx_query_version_cookie_t xglx_query_cookie = xcb_glx_query_version(m_connection, - XCB_GLX_MAJOR_VERSION, - XCB_GLX_MINOR_VERSION); - xcb_glx_query_version_reply_t *xglx_query = xcb_glx_query_version_reply(m_connection, - xglx_query_cookie, &error); - if (!xglx_query || error) { - qWarning("QXcbConnection: Failed to initialize GLX"); - free(error); - has_glx_extension = false; - } - free(xglx_query); -#else - // no way to check, assume GLX is present - has_glx_extension = true; -#endif -} - void QXcbConnection::initializeXRandr() { const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_randr_id); @@ -1811,13 +1713,6 @@ void QXcbConnection::initializeXKB() #endif } -#if defined(XCB_USE_EGL) -bool QXcbConnection::hasEgl() const -{ - return m_has_egl; -} -#endif // defined(XCB_USE_EGL) - #if defined(XCB_USE_XINPUT2) static int xi2ValuatorOffset(unsigned char *maskPtr, int maskLen, int number) { |