summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSamuel Rødal <samuel.rodal@nokia.com>2011-02-10 14:28:35 (GMT)
committerSamuel Rødal <samuel.rodal@nokia.com>2011-02-10 14:30:08 (GMT)
commit51b657a032cb0b9b3c4c7dbfab52c148cf9253af (patch)
treee2aad748bb7bed400758cd94ec2d7eb8bf9f679d
parente279d2ae598c7b05dff843e021fc8a08199c36de (diff)
downloadQt-51b657a032cb0b9b3c4c7dbfab52c148cf9253af.zip
Qt-51b657a032cb0b9b3c4c7dbfab52c148cf9253af.tar.gz
Qt-51b657a032cb0b9b3c4c7dbfab52c148cf9253af.tar.bz2
Added GL support to XCB backend.
We need to use a Xlib / XCB hybrid approach, as GLX depends on Xlib, and there's no replacement for XCB.
-rw-r--r--src/plugins/platforms/xcb/README2
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp360
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.h87
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp24
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h10
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp10
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp8
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h5
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp89
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h6
-rw-r--r--src/plugins/platforms/xcb/xcb.pro10
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)