diff options
-rw-r--r-- | src/plugins/platforms/xcb/README | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qglxintegration.cpp | 360 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qglxintegration.h | 87 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.cpp | 24 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection.h | 10 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbintegration.cpp | 10 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbintegration.h | 1 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.cpp | 8 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbscreen.h | 5 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.cpp | 89 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbwindow.h | 6 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/xcb.pro | 10 |
12 files changed, 588 insertions, 24 deletions
diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README new file mode 100644 index 0000000..d250ad0 --- /dev/null +++ b/src/plugins/platforms/xcb/README @@ -0,0 +1,2 @@ +Required packages: +libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp new file mode 100644 index 0000000..0cb6b1d --- /dev/null +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -0,0 +1,360 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDebug> +#include <QLibrary> +#include <QGLFormat> + +#include "qxcbwindow.h" +#include "qxcbscreen.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <GL/glx.h> + +#include "qglxintegration.h" + +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) +#include <dlfcn.h> +#endif + +QMutex QGLXContext::m_defaultSharedContextMutex(QMutex::Recursive); + +QVector<int> QGLXContext::buildSpec(const QPlatformWindowFormat &format) +{ + QVector<int> spec(48); + int i = 0; + + spec[i++] = GLX_LEVEL; + spec[i++] = 0; + spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = GLX_WINDOW_BIT; + + if (format.rgba()) { + spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT; + spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize(); + spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize(); + spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize(); + if (format.alpha()) { + spec[i++] = GLX_ALPHA_SIZE; spec[i++] = (format.alphaBufferSize() == -1) ? 1 : format.alphaBufferSize(); + } + + spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + + if (format.alpha()) { + spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + } + + } else { + spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_COLOR_INDEX_BIT; //I'm really not sure if this works.... + spec[i++] = GLX_BUFFER_SIZE; spec[i++] = 8; + } + + spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.doubleBuffer() ? True : False; + spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False; + + if (format.depth()) { + spec[i++] = GLX_DEPTH_SIZE; spec[i++] = (format.depthBufferSize() == -1) ? 1 : format.depthBufferSize(); + } + + if (format.stencil()) { + spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize(); + } + if (format.sampleBuffers()) { + spec[i++] = GLX_SAMPLE_BUFFERS_ARB; + spec[i++] = 1; + spec[i++] = GLX_SAMPLES_ARB; + spec[i++] = format.samples() == -1 ? 4 : format.samples(); + } + + spec[i++] = None; + return spec; +} + +GLXFBConfig QGLXContext::findConfig(const QXcbScreen *screen, const QPlatformWindowFormat &format) +{ + bool reduced = true; + GLXFBConfig chosenConfig = 0; + QPlatformWindowFormat reducedFormat = format; + while (!chosenConfig && reduced) { + QVector<int> spec = buildSpec(reducedFormat); + int confcount = 0; + GLXFBConfig *configs; + configs = glXChooseFBConfig(DISPLAY_FROM_XCB(screen), screen->screenNumber(), spec.constData(), &confcount); + if (confcount) + { + for (int i = 0; i < confcount; i++) { + chosenConfig = configs[i]; + // Make sure we try to get an ARGB visual if the format asked for an alpha: + if (reducedFormat.alpha()) { + int alphaSize; + glXGetFBConfigAttrib(DISPLAY_FROM_XCB(screen), configs[i], GLX_ALPHA_SIZE, &alphaSize); + if (alphaSize > 0) + break; + } else { + break; // Just choose the first in the list if there's no alpha requested + } + } + + XFree(configs); + } + reducedFormat = reducePlatformWindowFormat(reducedFormat,&reduced); + } + + if (!chosenConfig) + qWarning("Warning no context created"); + + return chosenConfig; +} + +XVisualInfo *QGLXContext::findVisualInfo(const QXcbScreen *screen, const QPlatformWindowFormat &format) +{ + GLXFBConfig config = QGLXContext::findConfig(screen,format); + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config); + return visualInfo; +} + +QPlatformWindowFormat QGLXContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx) +{ + QPlatformWindowFormat format; + int redSize = 0; + int greenSize = 0; + int blueSize = 0; + int alphaSize = 0; + int depthSize = 0; + int stencilSize = 0; + int sampleBuffers = 0; + int sampleCount = 0; + int level = 0; + int rgba = 0; + int stereo = 0; + int accumSizeA = 0; + int accumSizeR = 0; + int accumSizeG = 0; + int accumSizeB = 0; + + XVisualInfo *vi = glXGetVisualFromFBConfig(display,config); + glXGetConfig(display,vi,GLX_RGBA,&rgba); + XFree(vi); + glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize); + glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize); + glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize); + glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize); + glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize); + glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize); + glXGetFBConfigAttrib(display, config, GLX_SAMPLES, &sampleBuffers); + glXGetFBConfigAttrib(display, config, GLX_LEVEL, &level); + glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_ALPHA_SIZE, &accumSizeA); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_RED_SIZE, &accumSizeR); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_GREEN_SIZE, &accumSizeG); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_BLUE_SIZE, &accumSizeB); + + format.setRedBufferSize(redSize); + format.setGreenBufferSize(greenSize); + format.setBlueBufferSize(blueSize); + format.setAlphaBufferSize(alphaSize); + format.setDepthBufferSize(depthSize); + format.setStencilBufferSize(stencilSize); + format.setSampleBuffers(sampleBuffers); + if (format.sampleBuffers()) { + glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount); + format.setSamples(sampleCount); + } + + format.setDirectRendering(glXIsDirect(display, ctx)); + format.setRgba(rgba); + format.setStereo(stereo); + format.setAccumBufferSize(accumSizeB); + + return format; +} + +QPlatformWindowFormat QGLXContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) +{ + QPlatformWindowFormat retFormat = format; + *reduced = true; + + if (retFormat.sampleBuffers()) { + retFormat.setSampleBuffers(false); + } else if (retFormat.stereo()) { + retFormat.setStereo(false); + } else if (retFormat.accum()) { + retFormat.setAccum(false); + }else if (retFormat.stencil()) { + retFormat.setStencil(false); + }else if (retFormat.alpha()) { + retFormat.setAlpha(false); + }else if (retFormat.depth()) { + retFormat.setDepth(false); + }else if (retFormat.doubleBuffer()) { + retFormat.setDoubleBuffer(false); + }else{ + *reduced = false; + } + return retFormat; +} + +QGLXContext::QGLXContext(Window window, QXcbScreen *screen, const QPlatformWindowFormat &format) + : QPlatformGLContext() + , m_screen(screen) + , m_drawable((Drawable)window) + , m_context(0) +{ + + const QPlatformGLContext *sharePlatformContext; + if (format.useDefaultSharedContext()) { + if (!QPlatformGLContext::defaultSharedContext()) { + if (m_defaultSharedContextMutex.tryLock()){ + createDefaultSharedContex(screen); + m_defaultSharedContextMutex.unlock(); + } else { + m_defaultSharedContextMutex.lock(); //wait to the the shared context is created + m_defaultSharedContextMutex.unlock(); + } + } + sharePlatformContext = QPlatformGLContext::defaultSharedContext(); + } else { + sharePlatformContext = format.sharedGLContext(); + } + GLXContext shareGlxContext = 0; + if (sharePlatformContext) + shareGlxContext = static_cast<const QGLXContext*>(sharePlatformContext)->glxContext(); + + GLXFBConfig config = findConfig(screen,format); + m_context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, shareGlxContext, TRUE); + m_windowFormat = QGLXContext::platformWindowFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context); +} + +QGLXContext::QGLXContext(QXcbScreen *screen, Drawable drawable, GLXContext context) + : QPlatformGLContext(), m_screen(screen), m_drawable(drawable), m_context(context) +{ + +} + +QGLXContext::~QGLXContext() +{ + if (m_context) + glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context); +} + +void QGLXContext::createDefaultSharedContex(QXcbScreen *screen) +{ + int x = 0; + int y = 0; + int w = 3; + int h = 3; + + QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat(); + GLXContext context; + GLXFBConfig config = findConfig(screen,format); + if (config) { + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config); + Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(screen), screen->root(), visualInfo->visual, AllocNone); + XSetWindowAttributes a; + a.colormap = cmap; + Window sharedWindow = XCreateWindow(DISPLAY_FROM_XCB(screen), screen->root(), x, y, w, h, + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + + context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, 0, TRUE); + QPlatformGLContext *sharedContext = new QGLXContext(screen, sharedWindow, context); + QPlatformGLContext::setDefaultSharedContext(sharedContext); + } else { + qWarning("Warning no shared context created"); + } +} + +void QGLXContext::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); + glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), m_drawable, m_context); +} + +void QGLXContext::doneCurrent() +{ + QPlatformGLContext::doneCurrent(); + glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0); +} + +void QGLXContext::swapBuffers() +{ + glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), m_drawable); +} + +void* QGLXContext::getProcAddress(const QString& procName) +{ + typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); + static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; + static bool resolved = false; + + if (resolved && !glXGetProcAddressARB) + return 0; + if (!glXGetProcAddressARB) { + QList<QByteArray> glxExt = QByteArray(glXGetClientString(DISPLAY_FROM_XCB(m_screen), GLX_EXTENSIONS)).split(' '); + if (glxExt.contains("GLX_ARB_get_proc_address")) { +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) + void *handle = dlopen(NULL, RTLD_LAZY); + if (handle) { + glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB"); + dlclose(handle); + } + if (!glXGetProcAddressARB) +#endif + { + extern const QString qt_gl_library_name(); +// QLibrary lib(qt_gl_library_name()); + QLibrary lib(QLatin1String("GL")); + glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB"); + } + } + resolved = true; + } + if (!glXGetProcAddressARB) + return 0; + return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName.toLatin1().data())); +} + +QPlatformWindowFormat QGLXContext::platformWindowFormat() const +{ + return m_windowFormat; +} diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h new file mode 100644 index 0000000..0006363 --- /dev/null +++ b/src/plugins/platforms/xcb/qglxintegration.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLXINTEGRATION_H +#define QGLXINTEGRATION_H + +#include "qxcbwindow.h" + +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformWindowFormat> + +#include <QtCore/QMutex> + +#include <GL/glx.h> + +class QGLXContext : public QPlatformGLContext +{ +public: + QGLXContext(Window window, QXcbScreen *xd, const QPlatformWindowFormat &format); + ~QGLXContext(); + + virtual void makeCurrent(); + virtual void doneCurrent(); + virtual void swapBuffers(); + virtual void* getProcAddress(const QString& procName); + + GLXContext glxContext() const { return m_context; } + + QPlatformWindowFormat platformWindowFormat() const; + + static XVisualInfo *findVisualInfo(const QXcbScreen *xd, const QPlatformWindowFormat &format); + +private: + static GLXFBConfig findConfig(const QXcbScreen *xd,const QPlatformWindowFormat &format); + static QVector<int> buildSpec(const QPlatformWindowFormat &format); + static QPlatformWindowFormat platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context); + static QPlatformWindowFormat reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced); + + QXcbScreen *m_screen; + Drawable m_drawable; + GLXContext m_context; + QPlatformWindowFormat m_windowFormat; + + QGLXContext (QXcbScreen *screen, Drawable drawable, GLXContext context); + static QMutex m_defaultSharedContextMutex; + static void createDefaultSharedContex(QXcbScreen *xd); +}; + +#endif diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 2977d76..eafd83a 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -49,19 +49,33 @@ #include <stdio.h> +#ifdef XCB_USE_XLIB_FOR_GLX +#include <X11/Xlib.h> +#include <X11/Xlib-xcb.h> +#endif + QXcbConnection::QXcbConnection(const char *displayName) : m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) { - int primaryScreen; - + int primaryScreen = 0; + +#ifdef XCB_USE_XLIB_FOR_GLX + Display *dpy = XOpenDisplay(m_displayName.constData()); + primaryScreen = DefaultScreen(dpy); + m_connection = XGetXCBConnection(dpy); + XSetEventQueueOwner(dpy, XCBOwnsEventQueue); + m_xlib_display = dpy; +#else m_connection = xcb_connect(m_displayName.constData(), &primaryScreen); +#endif m_setup = xcb_get_setup(xcb_connection()); xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); + int screenNumber = 0; while (it.rem) { - m_screens << new QXcbScreen(this, it.data); + m_screens << new QXcbScreen(this, it.data, screenNumber++); xcb_screen_next(&it); } @@ -77,7 +91,11 @@ QXcbConnection::~QXcbConnection() { qDeleteAll(m_screens); +#ifdef XCB_USE_XLIB_FOR_GLX + XCloseDisplay((Display *)m_xlib_display); +#else xcb_disconnect(xcb_connection()); +#endif delete m_keyboard; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 97f9ba5..8a225c2 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -232,6 +232,10 @@ public: QXcbKeyboard *keyboard() const { return m_keyboard; } +#ifdef XCB_USE_XLIB_FOR_GLX + void *xlib_display() const { return m_xlib_display; } +#endif + private slots: void eventDispatcher(); @@ -249,6 +253,12 @@ private: QByteArray m_displayName; QXcbKeyboard *m_keyboard; + +#ifdef XCB_USE_XLIB_FOR_GLX + void *m_xlib_display; +#endif }; +#define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) + #endif diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index 5da86010..89a6154 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -114,3 +114,13 @@ QPixmap QXcbIntegration::grabWindow(WId window, int x, int y, int width, int hei Q_UNUSED(height); return QPixmap(); } + + +bool QXcbIntegration::hasOpenGL() const +{ +#ifdef XCB_USE_XLIB_FOR_GLX + return true; +#else + return false; +#endif +} diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index 8b599b3..80f70fb 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -65,6 +65,7 @@ public: QPixmap grabWindow(WId window, int x, int y, int width, int height) const; QPlatformFontDatabase *fontDatabase() const; + bool hasOpenGL() const; private: QList<QPlatformScreen *> m_screens; diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 4faa617..519db63 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -43,9 +43,10 @@ #include <stdio.h> -QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen) +QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int number) : QXcbObject(connection) , m_screen(screen) + , m_number(number) { printf ("\n"); printf ("Informations of screen %d:\n", screen->root); @@ -91,3 +92,8 @@ QSize QXcbScreen::physicalSize() const { return QSize(m_screen->width_in_millimeters, m_screen->height_in_millimeters); } + +int QXcbScreen::screenNumber() const +{ + return m_number; +} diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index abebcd9..77ee46f 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -53,7 +53,7 @@ class QXcbConnection; class QXcbScreen : public QXcbObject, public QPlatformScreen { public: - QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen); + QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int number); ~QXcbScreen(); QRect geometry() const; @@ -61,11 +61,14 @@ public: QImage::Format format() const; QSize physicalSize() const; + int screenNumber() const; + xcb_screen_t *screen() const { return m_screen; } xcb_window_t root() const { return m_screen->root; } private: xcb_screen_t *m_screen; + int m_number; }; #endif diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 95110e6..e9ff5df 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -44,14 +44,24 @@ #include "qxcbconnection.h" #include "qxcbscreen.h" +#include <private/qapplication_p.h> #include <private/qwindowsurface_p.h> #include <QtGui/QWindowSystemInterface> #include <stdio.h> +#ifdef XCB_USE_XLIB_FOR_GLX +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "qglxintegration.h" +#endif + QXcbWindow::QXcbWindow(QWidget *tlw) : QPlatformWindow(tlw) +#ifdef XCB_USE_XLIB_FOR_GLX + , m_glx_context(0) +#endif { m_screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(tlw)); @@ -75,20 +85,44 @@ QXcbWindow::QXcbWindow(QWidget *tlw) | XCB_EVENT_MASK_FOCUS_CHANGE }; - m_window = xcb_generate_id(xcb_connection()); - xcb_create_window(xcb_connection(), - XCB_COPY_FROM_PARENT, // depth -- same as root - m_window, // window id - m_screen->root(), // parent window id - tlw->x(), - tlw->y(), - tlw->width(), - tlw->height(), - 0, // border width - XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class - m_screen->screen()->root_visual, // visual - mask, // value mask - values); // value list +#ifdef XCB_USE_XLIB_FOR_GLX + if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL + && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { + XVisualInfo *visualInfo = QGLXContext::findVisualInfo(m_screen, tlw->platformWindowFormat()); + if (visualInfo) { + Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), m_screen->root(), visualInfo->visual, AllocNone); + + XSetWindowAttributes a; + a.colormap = cmap; + m_window = XCreateWindow(DISPLAY_FROM_XCB(this), m_screen->root(), tlw->x(), tlw->y(), tlw->width(), tlw->height(), + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + + printf("created GL window: %d\n", m_window); + } else { + qFatal("no window!"); + } + } else +#endif + { + m_window = xcb_generate_id(xcb_connection()); + + xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, // depth -- same as root + m_window, // window id + m_screen->root(), // parent window id + tlw->x(), + tlw->y(), + tlw->width(), + tlw->height(), + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class + m_screen->screen()->root_visual, // visual + mask, // value mask + values); // value list + + printf("created regular window: %d\n", m_window); + } xcb_atom_t properties[4]; int propertyCount = 0; @@ -126,12 +160,12 @@ void QXcbWindow::setGeometry(const QRect &rect) void QXcbWindow::setVisible(bool visible) { - if (visible) + if (visible) { xcb_map_window(xcb_connection(), m_window); - else + } else { xcb_unmap_window(xcb_connection(), m_window); - - xcb_flush(xcb_connection()); + xcb_flush(xcb_connection()); + } } struct QtMWMHints { @@ -317,6 +351,25 @@ void QXcbWindow::requestActivateWindow() xcb_set_input_focus(xcb_connection(), m_window, XCB_INPUT_FOCUS_PARENT, XCB_TIME_CURRENT_TIME); } +QPlatformGLContext *QXcbWindow::glContext() const +{ +#ifdef XCB_USE_XLIB_FOR_GLX + if (!QApplicationPrivate::platformIntegration()->hasOpenGL()) { + printf("no opengl\n"); + return 0; + } + + if (!m_glx_context) { + QXcbWindow *that = const_cast<QXcbWindow *>(this); + that->m_glx_context = new QGLXContext(m_window, m_screen, widget()->platformWindowFormat()); + } + + return m_glx_context; +#else + return 0; +#endif +} + void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) { QWindowSurface *surface = widget()->windowSurface(); diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 17e1742..8db1a1e 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -48,6 +48,7 @@ #include "qxcbobject.h" +class QGLXContext; class QXcbScreen; class QXcbWindow : public QXcbObject, public QPlatformWindow @@ -69,7 +70,7 @@ public: void requestActivateWindow(); - QPlatformGLContext *glContext() const { return 0; } + QPlatformGLContext *glContext() const; xcb_window_t window() const { return m_window; } @@ -91,6 +92,9 @@ private: QXcbScreen *m_screen; xcb_window_t m_window; +#ifdef XCB_USE_XLIB_FOR_GLX + QGLXContext *m_glx_context; +#endif }; #endif diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro index 3aee0a2..58382c0 100644 --- a/src/plugins/platforms/xcb/xcb.pro +++ b/src/plugins/platforms/xcb/xcb.pro @@ -21,6 +21,16 @@ HEADERS = \ qxcbwindow.h \ qxcbwindowsurface.h +contains(QT_CONFIG, opengl):DEFINES += XCB_USE_XLIB_FOR_GLX + +contains(DEFINES, XCB_USE_XLIB_FOR_GLX) { + QT += opengl + + HEADERS += qglxintegration.h + SOURCES += qglxintegration.cpp + LIBS += -lX11 -lX11-xcb +} + LIBS += -lxcb -lxcb-image -lxcb-keysyms include (../fontdatabases/genericunix/genericunix.pri) |