diff options
author | Jørgen Lind <jorgen.lind@digia.com> | 2014-09-10 16:31:32 +0200 |
---|---|---|
committer | Jørgen Lind <jorgen.lind@theqtcompany.com> | 2014-12-20 06:09:01 +0100 |
commit | 8758f532ae6209bcf9447e27edc4fd412c0f173d (patch) | |
tree | 082d8e259d6de5a783ad0b2ddcf7d405ad550ba8 /src/plugins/platforms/xcb/qxcbconnection.cpp | |
parent | eb2014382be588ea92e172d8b36385b8b86b64de (diff) |
Make GLX and EGL dynamic dependencies for xcb
[ChangeLog][QPA][Xcb] GLX and EGL code paths are now dynamically
resolved, making it possible for one build of a plugin to use both code
paths. Default is to use the GLX code path if available. This can be
overwritten by specifying QT_XCB_GL_INTEGRATION=xcb_egl as an
evnironment variable. Enable qt.xcb.glintegration.debug to get debug log
output of what integration is used
Change-Id: Ia9fa95fcca3d901b91dadb8c98a695fea0ae3b1e
Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection.cpp')
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 179 |
1 files changed, 35 insertions, 144 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index ea13502a21..2e429939ba 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) { @@ -309,11 +270,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 +284,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 +303,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 +315,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 +331,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra initializeXRandr(); updateScreens(); - initializeGLX(); initializeXFixes(); initializeXRender(); m_xi2Enabled = false; @@ -405,6 +353,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")) @@ -435,11 +404,6 @@ QXcbConnection::~QXcbConnection() while (!m_screens.isEmpty()) delete m_screens.takeLast(); -#ifdef XCB_USE_EGL - if (m_has_egl) - eglTerminate(m_egl_display); -#endif //XCB_USE_EGL - #ifdef XCB_USE_XLIB XCloseDisplay((Display *)m_xlib_display); #else @@ -990,51 +954,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 +1153,11 @@ xcb_window_t QXcbConnection::rootWindow() return primaryScreen()->root(); } +void *QXcbConnection::xlib_display() const +{ + return m_xlib_display; +} + void QXcbConnection::processXcbEvents() { int connection_error = xcb_connection_has_error(xcb_connection()); @@ -1674,34 +1600,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 +1709,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) { |