diff options
Diffstat (limited to 'src/plugins/platforms/xcb/gl_integrations')
32 files changed, 2911 insertions, 0 deletions
diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pri b/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pri new file mode 100644 index 0000000000..56bc126652 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pri @@ -0,0 +1,13 @@ +INCLUDEPATH += $$PWD + +HEADERS += \ + $$PWD/qxcbglintegration.h \ + $$PWD/qxcbglintegrationfactory.h \ + $$PWD/qxcbglintegrationplugin.h \ + $$PWD/qxcbnativeinterfacehandler.h + +SOURCES += \ + $$PWD/qxcbglintegrationfactory.cpp \ + $$PWD/qxcbglintegration.cpp \ + $$PWD/qxcbnativeinterfacehandler.cpp + diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro b/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro new file mode 100644 index 0000000000..29fddeabd4 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations.pro @@ -0,0 +1,9 @@ +TEMPLATE = subdirs + +contains(QT_CONFIG, egl):contains(QT_CONFIG, egl_x11) { + SUBDIRS += xcb_egl +} + +contains(QT_CONFIG, xcb-xlib):!contains(QT_CONFIG, opengles2) { + SUBDIRS += xcb_glx +} diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri new file mode 100644 index 0000000000..8c60268e0d --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri @@ -0,0 +1,38 @@ +QT += core-private gui-private platformsupport-private xcb_qpa_lib-private + +INCLUDEPATH += $$PWD +INCLUDEPATH += $$PWD/../ + +# needed by Xcursor ... +contains(QT_CONFIG, xcb-xlib) { + DEFINES += XCB_USE_XLIB + contains(QT_CONFIG, xinput2) { + DEFINES += XCB_USE_XINPUT2 + } +} + +# to support custom cursors with depth > 1 +contains(QT_CONFIG, xcb-render) { + DEFINES += XCB_USE_RENDER +} + +# build with session management support +contains(QT_CONFIG, xcb-sm) { + DEFINES += XCB_USE_SM +} + +DEFINES += $$QMAKE_DEFINES_XCB +LIBS += $$QMAKE_LIBS_XCB +QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB + +CONFIG += qpa/genericunixfontdatabase + +contains(QT_CONFIG, xcb-qt) { + DEFINES += XCB_USE_RENDER + XCB_DIR = ../../../3rdparty/xcb + INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude + LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static +} else { + LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms + !contains(DEFINES, QT_NO_XKB):LIBS += -lxcb-xkb +} diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.cpp new file mode 100644 index 0000000000..d864ee1198 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbglintegration.h" + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(QT_XCB_GLINTEGRATION, "qt.xcb.glintegration") + +QXcbGlIntegration::QXcbGlIntegration() +{ +} +QXcbGlIntegration::~QXcbGlIntegration() +{ +} + +bool QXcbGlIntegration::handleXcbEvent(xcb_generic_event_t *event, uint responseType) +{ + Q_UNUSED(event); + Q_UNUSED(responseType); + return false; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h new file mode 100644 index 0000000000..947ef15162 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegration.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBGLINTEGRATION_H + +#include "qxcbexport.h" +#include "qxcbwindow.h" + +#include <QtCore/QLoggingCategory> + +QT_BEGIN_NAMESPACE + +class QPlatformOffscreenSurface; +class QOffscreenSurface; +class QXcbNativeInterfaceHandler; + +Q_XCB_EXPORT Q_DECLARE_LOGGING_CATEGORY(QT_XCB_GLINTEGRATION) + +class Q_XCB_EXPORT QXcbGlIntegration +{ +public: + QXcbGlIntegration(); + virtual ~QXcbGlIntegration(); + virtual bool initialize(QXcbConnection *connection) = 0; + + virtual bool supportsThreadedOpenGL() const { return false; } + virtual bool handleXcbEvent(xcb_generic_event_t *event, uint responseType); + + virtual QXcbWindow *createWindow(QWindow *window) const = 0; + virtual QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const = 0; + virtual QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const = 0; + + virtual QXcbNativeInterfaceHandler *nativeInterfaceHandler() const { return Q_NULLPTR; } +}; + +QT_END_NAMESPACE + +#endif //QXCBGLINTEGRATION_H diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.cpp b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.cpp new file mode 100644 index 0000000000..c4546b990a --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbglintegrationfactory.h" +#include "qxcbglintegrationplugin.h" + +#include "qxcbglintegrationplugin.h" +#include "private/qfactoryloader_p.h" +#include "qguiapplication.h" +#include "qdir.h" + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_LIBRARY +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QXcbGlIntegrationFactoryInterface_iid, QLatin1String("/xcbglintegrations"), Qt::CaseInsensitive)) +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader, + (QXcbGlIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive)) + +static inline QXcbGlIntegration *loadIntegration(QFactoryLoader *loader, const QString &key) +{ + const int index = loader->indexOf(key); + if (index != -1) { + if (QXcbGlIntegrationPlugin *factory = qobject_cast<QXcbGlIntegrationPlugin *>(loader->instance(index))) + if (QXcbGlIntegration *result = factory->create()) + return result; + } + return Q_NULLPTR; +} +#endif // !QT_NO_LIBRARY + +QStringList QXcbGlIntegrationFactory::keys(const QString &pluginPath) +{ +#ifndef QT_NO_LIBRARY + QStringList list; + if (!pluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(pluginPath); + list = directLoader()->keyMap().values(); + if (!list.isEmpty()) { + const QString postFix = QStringLiteral(" (from ") + + QDir::toNativeSeparators(pluginPath) + + QLatin1Char(')'); + const QStringList::iterator end = list.end(); + for (QStringList::iterator it = list.begin(); it != end; ++it) + (*it).append(postFix); + } + } + list.append(loader()->keyMap().values()); + return list; +#else + return QStringList(); +#endif +} + +QXcbGlIntegration *QXcbGlIntegrationFactory::create(const QString &platform, const QString &pluginPath) +{ +#ifndef QT_NO_LIBRARY + // Try loading the plugin from platformPluginPath first: + if (!pluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(pluginPath); + if (QXcbGlIntegration *ret = loadIntegration(directLoader(), platform)) + return ret; + } + if (QXcbGlIntegration *ret = loadIntegration(loader(), platform)) + return ret; +#endif + return Q_NULLPTR; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.h new file mode 100644 index 0000000000..d1fb91dee8 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationfactory.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBGLINTEGRATIONFACTORY_H +#define QXCBGLINTEGRATIONFACTORY_H + +#include <QtCore/qstringlist.h> + +QT_BEGIN_NAMESPACE + +class QXcbGlIntegration; + +class QXcbGlIntegrationFactory +{ +public: + static QStringList keys(const QString &pluginPath = QString()); + static QXcbGlIntegration *create(const QString &name, const QString &platformPluginPath = QString()); +}; + +QT_END_NAMESPACE + +#endif //QXCBGLINTEGRATIONFACTORY_H + diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationplugin.h b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationplugin.h new file mode 100644 index 0000000000..ef630a4fbe --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbglintegrationplugin.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBGLINTEGRATIONPLUGIN_H +#define QXCBGLINTEGRATIONPLUGIN_H + +#include "qxcbexport.h" +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> + +QT_BEGIN_NAMESPACE + +#define QXcbGlIntegrationFactoryInterface_iid "org.qt-project.Qt.QPA.Xcb.QXcbGlIntegrationFactoryInterface.5.5" + +class QXcbGlIntegration; + +class Q_XCB_EXPORT QXcbGlIntegrationPlugin : public QObject +{ + Q_OBJECT +public: + explicit QXcbGlIntegrationPlugin(QObject *parent = 0) + : QObject(parent) + { } + + virtual QXcbGlIntegration *create() = 0; +}; +QT_END_NAMESPACE + +#endif //QXCBGLINTEGRATIONPLUGIN_H diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.cpp b/src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.cpp new file mode 100644 index 0000000000..78c6fe0ccb --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbnativeinterfacehandler.h" + +#include "qxcbnativeinterface.h" + +QT_BEGIN_NAMESPACE + +QXcbNativeInterfaceHandler::QXcbNativeInterfaceHandler(QXcbNativeInterface *nativeInterface) +{ + nativeInterface->addHandler(this); +} +QXcbNativeInterfaceHandler::~QXcbNativeInterfaceHandler() +{ + m_native_interface->removeHandler(this); +} + +QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterfaceHandler::nativeResourceFunctionForIntegration(const QByteArray &resource) const +{ + Q_UNUSED(resource); + return Q_NULLPTR; +} + +QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterfaceHandler::nativeResourceFunctionForContext(const QByteArray &resource) const +{ + Q_UNUSED(resource); + return Q_NULLPTR; +} + +QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterfaceHandler::nativeResourceFunctionForScreen(const QByteArray &resource) const +{ + Q_UNUSED(resource); + return Q_NULLPTR; +} + +QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterfaceHandler::nativeResourceFunctionForWindow(const QByteArray &resource) const +{ + Q_UNUSED(resource); + return Q_NULLPTR; +} + +QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterfaceHandler::nativeResourceFunctionForBackingStore(const QByteArray &resource) const +{ + Q_UNUSED(resource); + return Q_NULLPTR; +} + +QFunctionPointer QXcbNativeInterfaceHandler::platformFunction(const QByteArray &function) const +{ + Q_UNUSED(function); + return Q_NULLPTR; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.h b/src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.h new file mode 100644 index 0000000000..3c239c443d --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/qxcbnativeinterfacehandler.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBNATIVEINTERFACEHANDLER_H +#define QXCBNATIVEINTERFACEHANDLER_H + +#include <QtCore/QByteArray> +#include <QtGui/qpa/qplatformnativeinterface.h> + +#include "qxcbexport.h" + +QT_BEGIN_NAMESPACE + +class QXcbNativeInterface; +class Q_XCB_EXPORT QXcbNativeInterfaceHandler +{ +public: + QXcbNativeInterfaceHandler(QXcbNativeInterface *nativeInterface); + virtual ~QXcbNativeInterfaceHandler(); + + virtual QPlatformNativeInterface::NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) const; + virtual QPlatformNativeInterface::NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) const; + virtual QPlatformNativeInterface::NativeResourceForScreenFunction nativeResourceFunctionForScreen(const QByteArray &resource) const; + virtual QPlatformNativeInterface::NativeResourceForWindowFunction nativeResourceFunctionForWindow(const QByteArray &resource) const; + virtual QPlatformNativeInterface::NativeResourceForBackingStoreFunction nativeResourceFunctionForBackingStore(const QByteArray &resource) const; + + virtual QFunctionPointer platformFunction(const QByteArray &function) const; +protected: + QXcbNativeInterface *m_native_interface; +}; + +QT_END_NAMESPACE + +#endif //QXCBNATIVEINTERFACEHANDLER_H diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h new file mode 100644 index 0000000000..0dce728019 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBEGLCONTEXT_H +#define QXCBEGLCONTEXT_H + +#include "qxcbeglwindow.h" +#include <QtPlatformSupport/private/qeglplatformcontext_p.h> +#include <QtPlatformSupport/private/qeglpbuffer_p.h> +#include <QtPlatformHeaders/QEGLNativeContext> + +QT_BEGIN_NAMESPACE + +//####todo remove the noops (looks like their where there in the initial commit) +class QXcbEglContext : public QEGLPlatformContext +{ +public: + QXcbEglContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share, + EGLDisplay display, QXcbConnection *c, const QVariant &nativeHandle) + : QEGLPlatformContext(glFormat, share, display, 0, nativeHandle) + , m_connection(c) + { + Q_XCB_NOOP(m_connection); + } + + void swapBuffers(QPlatformSurface *surface) + { + Q_XCB_NOOP(m_connection); + QEGLPlatformContext::swapBuffers(surface); + Q_XCB_NOOP(m_connection); + } + + bool makeCurrent(QPlatformSurface *surface) + { + Q_XCB_NOOP(m_connection); + bool ret = QEGLPlatformContext::makeCurrent(surface); + Q_XCB_NOOP(m_connection); + return ret; + } + + void doneCurrent() + { + Q_XCB_NOOP(m_connection); + QEGLPlatformContext::doneCurrent(); + Q_XCB_NOOP(m_connection); + } + + EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) + { + if (surface->surface()->surfaceClass() == QSurface::Window) + return static_cast<QXcbEglWindow *>(surface)->eglSurface(); + else + return static_cast<QEGLPbuffer *>(surface)->pbuffer(); + } + + QVariant nativeHandle() const { + return QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(eglContext(), eglDisplay())); + } + +private: + QXcbConnection *m_connection; +}; + +QT_END_NAMESPACE +#endif //QXCBEGLCONTEXT_H + diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h new file mode 100644 index 0000000000..bcde872423 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglinclude.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBINCLUDE_H +#define QXCBINCLUDE_H + +#include <QtGui/QPalette> +#include <QtCore/QTextStream> +#include <QtGui/private/qmath_p.h> +#include <QtGui/private/qcssparser_p.h> +#include <QtGui/private/qtextengine_p.h> + +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +QT_END_NAMESPACE + +#endif //QXCBINCLUDE_H diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp new file mode 100644 index 0000000000..f5fc2e74c4 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbeglintegration.h" + +#include "qxcbeglcontext.h" + +#include <QtGui/QOffscreenSurface> + +#include "qxcbeglnativeinterfacehandler.h" + +QT_BEGIN_NAMESPACE + +QXcbEglIntegration::QXcbEglIntegration() + : m_connection(Q_NULLPTR) + , m_egl_display(EGL_NO_DISPLAY) +{ + qCDebug(QT_XCB_GLINTEGRATION) << "Xcb EGL gl-integration created"; +} + +QXcbEglIntegration::~QXcbEglIntegration() +{ + if (m_egl_display != EGL_NO_DISPLAY) + eglTerminate(m_egl_display); +} + +bool QXcbEglIntegration::initialize(QXcbConnection *connection) +{ + m_connection = connection; + + Display *dpy = (Display *)m_connection->xlib_display(); + m_egl_display = eglGetDisplay(dpy); + + EGLint major, minor; + bool success = eglInitialize(m_egl_display, &major, &minor); + if (!success) { + m_egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + qCDebug(QT_XCB_GLINTEGRATION) << "Xcb EGL gl-integration retrying with display" << m_egl_display; + success = eglInitialize(m_egl_display, &major, &minor); + } + + m_native_interface_handler.reset(new QXcbEglNativeInterfaceHandler(connection->nativeInterface())); + + qCDebug(QT_XCB_GLINTEGRATION) << "Xcb EGL gl-integration successfully initialized"; + return success; +} + +QXcbWindow *QXcbEglIntegration::createWindow(QWindow *window) const +{ + return new QXcbEglWindow(window, const_cast<QXcbEglIntegration *>(this)); +} + +QPlatformOpenGLContext *QXcbEglIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const +{ + QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle()); + QXcbEglContext *platformContext = new QXcbEglContext(context->format(), + context->shareHandle(), + eglDisplay(), + screen->connection(), + context->nativeHandle()); + context->setNativeHandle(platformContext->nativeHandle()); + return platformContext; +} + +QPlatformOffscreenSurface *QXcbEglIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + return new QEGLPbuffer(eglDisplay(), surface->requestedFormat(), surface); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h new file mode 100644 index 0000000000..9f42051804 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBEGLINTEGRATION_H +#define QXCBEGLINTEGRATION_H + +#include "qxcbglintegration.h" + +#include "qxcbeglwindow.h" + +#include <QtGui/QOpenGLContext> +#include <QtGui/qpa/qplatformscreen.h> +#include <QtGui/QScreen> + +#include "qxcbscreen.h" + +#include "qxcbeglinclude.h" + +QT_BEGIN_NAMESPACE + +class QXcbEglNativeInterfaceHandler; + +class QXcbEglIntegration : public QXcbGlIntegration +{ +public: + QXcbEglIntegration(); + ~QXcbEglIntegration(); + + bool initialize(QXcbConnection *connection) Q_DECL_OVERRIDE; + + QXcbWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; + + EGLDisplay eglDisplay() const { return m_egl_display; } + void *xlib_display() const { return m_connection->xlib_display(); } +private: + QXcbConnection *m_connection; + EGLDisplay m_egl_display; + + QScopedPointer<QXcbEglNativeInterfaceHandler> m_native_interface_handler; +}; + +QT_END_NAMESPACE +#endif //QXCBEGLINTEGRATION_H diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglmain.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglmain.cpp new file mode 100644 index 0000000000..9feb8f31ca --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglmain.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbglintegrationplugin.h" + +#include "qxcbeglintegration.h" + +QT_BEGIN_NAMESPACE + +class QXcbEglIntegrationPlugin : public QXcbGlIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QXcbGlIntegrationFactoryInterface_iid FILE "xcb_egl.json") +public: + QXcbGlIntegration *create() + { + return new QXcbEglIntegration(); + } + +}; + +QT_END_NAMESPACE + +#include "qxcbeglmain.moc" diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.cpp new file mode 100644 index 0000000000..3037d1e331 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.cpp @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbeglnativeinterfacehandler.h" + +#include "qxcbeglwindow.h" +#include "qxcbeglintegration.h" +#include "qxcbeglcontext.h" + +QT_BEGIN_NAMESPACE + +static int resourceType(const QByteArray &key) +{ + static const QByteArray names[] = { // match QXcbEglNativeInterfaceHandler::ResourceType + QByteArrayLiteral("egldisplay"), + QByteArrayLiteral("eglcontext"), + QByteArrayLiteral("eglconfig") + }; + for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); i++) { + if (key == names[i]) + return i; + } + + if (key == QByteArrayLiteral("get_egl_context")) + return QXcbEglNativeInterfaceHandler::EglContext; + + return sizeof(names) / sizeof(names[0]); +} + +QXcbEglNativeInterfaceHandler::QXcbEglNativeInterfaceHandler(QXcbNativeInterface *nativeInterface) + : QXcbNativeInterfaceHandler(nativeInterface) +{ +} + +QPlatformNativeInterface::NativeResourceForContextFunction QXcbEglNativeInterfaceHandler::nativeResourceFunctionForContext(const QByteArray &resource) const +{ + switch (resourceType(resource)) { + case EglContext: + return eglContextForContext; + case EglConfig: + return eglConfigForContext; + default: + break; + } + return Q_NULLPTR; +} + +QPlatformNativeInterface::NativeResourceForWindowFunction QXcbEglNativeInterfaceHandler::nativeResourceFunctionForWindow(const QByteArray &resource) const +{ + switch (resourceType(resource)) { + case EglDisplay: + return eglDisplayForWindow; + default: + break; + } + return Q_NULLPTR; +} + +void *QXcbEglNativeInterfaceHandler::eglDisplayForWindow(QWindow *window) +{ + Q_ASSERT(window); + Q_ASSERT(window->handle()); + if (window->supportsOpenGL()) + return static_cast<QXcbEglWindow *>(window->handle())->glIntegration()->eglDisplay(); + return Q_NULLPTR; +} + +void *QXcbEglNativeInterfaceHandler::eglContextForContext(QOpenGLContext *context) +{ + Q_ASSERT(context); + Q_ASSERT(context->handle()); + return static_cast<QXcbEglContext *>(context->handle())->eglContext(); +} + +void *QXcbEglNativeInterfaceHandler::eglConfigForContext(QOpenGLContext *context) +{ + Q_ASSERT(context); + Q_ASSERT(context->handle()); + return static_cast<QXcbEglContext *>(context->handle())->eglConfig(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.h new file mode 100644 index 0000000000..0485a87558 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBEGLNATIVEINTERFACEHANDLER_H +#define QXCBEGLNATIVEINTERFACEHANDLER_H + +#include "qxcbnativeinterfacehandler.h" + +QT_BEGIN_NAMESPACE + +class QXcbEglNativeInterfaceHandler : public QXcbNativeInterfaceHandler +{ +public: + enum ResourceType { + EglDisplay, + EglContext, + EglConfig + }; + + QXcbEglNativeInterfaceHandler(QXcbNativeInterface *nativeInterface); + + QPlatformNativeInterface::NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) const Q_DECL_OVERRIDE; + QPlatformNativeInterface::NativeResourceForWindowFunction nativeResourceFunctionForWindow(const QByteArray &resource) const Q_DECL_OVERRIDE; +private: + static void *eglDisplayForWindow(QWindow *window); + static void *eglContextForContext(QOpenGLContext *context); + static void *eglConfigForContext(QOpenGLContext *context); +}; + +QT_END_NAMESPACE + +#endif //QXCBEGLNATIVEINTERFACEHANDLER_H diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp new file mode 100644 index 0000000000..61dd8d5069 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.cpp @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbeglwindow.h" + +#include "qxcbeglintegration.h" + +#include <QtPlatformSupport/private/qeglconvenience_p.h> +#include <QtPlatformSupport/private/qxlibeglintegration_p.h> + +QT_BEGIN_NAMESPACE + +QXcbEglWindow::QXcbEglWindow(QWindow *window, QXcbEglIntegration *glIntegration) + : QXcbWindow(window) + , m_glIntegration(glIntegration) + , m_config(Q_NULLPTR) + , m_surface(EGL_NO_SURFACE) +{ +} + +QXcbEglWindow::~QXcbEglWindow() +{ + eglDestroySurface(m_glIntegration->eglDisplay(), m_surface); +} + +void QXcbEglWindow::resolveFormat() +{ + m_config = q_configFromGLFormat(m_glIntegration->eglDisplay(), window()->requestedFormat(), true); + m_format = q_glFormatFromConfig(m_glIntegration->eglDisplay(), m_config, m_format); +} + +void *QXcbEglWindow::createVisual() +{ + Display *xdpy = static_cast<Display *>(m_glIntegration->xlib_display()); + VisualID id = QXlibEglIntegration::getCompatibleVisualId(xdpy, m_glIntegration->eglDisplay(), m_config); + + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + visualInfoTemplate.visualid = id; + + XVisualInfo *visualInfo; + int matchingCount = 0; + visualInfo = XGetVisualInfo(xdpy, VisualIDMask, &visualInfoTemplate, &matchingCount); + return visualInfo; +} + +void QXcbEglWindow::create() +{ + QXcbWindow::create(); + + m_surface = eglCreateWindowSurface(m_glIntegration->eglDisplay(), m_config, m_window, 0); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h new file mode 100644 index 0000000000..7d1a4c8e37 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglwindow.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBEGLWINDOW_H +#define QXCBEGLWINDOW_H + +#include "qxcbwindow.h" + +#include "qxcbeglinclude.h" + +QT_BEGIN_NAMESPACE + +class QXcbEglIntegration; + +class QXcbEglWindow : public QXcbWindow +{ +public: + QXcbEglWindow(QWindow *window, QXcbEglIntegration *glIntegration); + ~QXcbEglWindow(); + + EGLSurface eglSurface() const { return m_surface; } + + QXcbEglIntegration *glIntegration() const { return m_glIntegration; } + +protected: + void create() Q_DECL_OVERRIDE; + void resolveFormat() Q_DECL_OVERRIDE; + void *createVisual() Q_DECL_OVERRIDE; + +private: + QXcbEglIntegration *m_glIntegration; + EGLConfig m_config; + EGLSurface m_surface; +}; + +QT_END_NAMESPACE +#endif //QXCBEGLWINDOW_H diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/xcb_egl.json b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/xcb_egl.json new file mode 100644 index 0000000000..6d6785691d --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/xcb_egl.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "xcb_egl" ] +} diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/xcb_egl.pro b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/xcb_egl.pro new file mode 100644 index 0000000000..082c22821a --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/xcb_egl.pro @@ -0,0 +1,27 @@ +TARGET = qxcb-egl-integration + +PLUGIN_CLASS_NAME = QXcbEglIntegrationPlugin +PLUGIN_TYPE = xcbglintegrations + +load(qt_plugin) + +include(../gl_integrations_plugin_base.pri) + +CONFIG += egl + +DEFINES += SUPPORT_X11 +#should be removed from sources +DEFINES += XCB_USE_EGL XCB_USE_XLIB + + +HEADERS += \ + qxcbeglcontext.h \ + qxcbeglintegration.h \ + qxcbeglwindow.h \ + qxcbeglnativeinterfacehandler.h + +SOURCES += \ + qxcbeglintegration.cpp \ + qxcbeglwindow.cpp \ + qxcbeglmain.cpp \ + qxcbeglnativeinterfacehandler.cpp diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp new file mode 100644 index 0000000000..c0be836bce --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -0,0 +1,723 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDebug> +#include <QLibrary> + +#include "qxcbwindow.h" +#include "qxcbscreen.h" + +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <GL/glx.h> + +#include <QtGui/QOpenGLContext> +#include <QtGui/QOffscreenSurface> + +#include "qglxintegration.h" +#include <QtPlatformSupport/private/qglxconvenience_p.h> +#include <QtPlatformHeaders/QGLXNativeContext> + +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) +#include <dlfcn.h> +#endif + +QT_BEGIN_NAMESPACE + +typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*); + +#ifndef GLX_CONTEXT_CORE_PROFILE_BIT_ARB +#define GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001 +#endif + +#ifndef GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB +#define GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002 +#endif + +#ifndef GLX_CONTEXT_ES2_PROFILE_BIT_EXT +#define GLX_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004 +#endif + +#ifndef GLX_CONTEXT_PROFILE_MASK_ARB +#define GLX_CONTEXT_PROFILE_MASK_ARB 0x9126 +#endif + +#ifndef GL_CONTEXT_FLAG_DEBUG_BIT +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#endif + +static Window createDummyWindow(Display *dpy, XVisualInfo *visualInfo, int screenNumber, Window rootWin) +{ + Colormap cmap = XCreateColormap(dpy, rootWin, visualInfo->visual, AllocNone); + XSetWindowAttributes a; + a.background_pixel = WhitePixel(dpy, screenNumber); + a.border_pixel = BlackPixel(dpy, screenNumber); + a.colormap = cmap; + a.override_redirect = true; + + Window window = XCreateWindow(dpy, rootWin, + 0, 0, 100, 100, + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWBackPixel|CWBorderPixel|CWColormap|CWOverrideRedirect, &a); +#ifndef QT_NO_DEBUG + XStoreName(dpy, window, "Qt GLX dummy window"); +#endif + XFreeColormap(dpy, cmap); + return window; +} + +static Window createDummyWindow(Display *dpy, GLXFBConfig config, int screenNumber, Window rootWin) +{ + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(dpy, config); + if (!visualInfo) + qFatal("Could not initialize GLX"); + Window window = createDummyWindow(dpy, visualInfo, screenNumber, rootWin); + XFree(visualInfo); + return window; +} + +static inline QByteArray getGlString(GLenum param) +{ + if (const GLubyte *s = glGetString(param)) + return QByteArray(reinterpret_cast<const char*>(s)); + return QByteArray(); +} + +static void updateFormatFromContext(QSurfaceFormat &format) +{ + // Update the version, profile, and context bit of the format + int major = 0, minor = 0; + QByteArray versionString(getGlString(GL_VERSION)); + if (QPlatformOpenGLContext::parseOpenGLVersion(versionString, major, minor)) { + format.setMajorVersion(major); + format.setMinorVersion(minor); + } + + format.setProfile(QSurfaceFormat::NoProfile); + format.setOptions(QSurfaceFormat::FormatOptions()); + + if (format.renderableType() == QSurfaceFormat::OpenGL) { + if (format.version() < qMakePair(3, 0)) { + format.setOption(QSurfaceFormat::DeprecatedFunctions); + return; + } + + // Version 3.0 onwards - check if it includes deprecated functionality or is + // a debug context + GLint value = 0; + glGetIntegerv(GL_CONTEXT_FLAGS, &value); + if (!(value & GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT)) + format.setOption(QSurfaceFormat::DeprecatedFunctions); + if (value & GL_CONTEXT_FLAG_DEBUG_BIT) + format.setOption(QSurfaceFormat::DebugContext); + if (format.version() < qMakePair(3, 2)) + return; + + // Version 3.2 and newer have a profile + value = 0; + glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &value); + + if (value & GL_CONTEXT_CORE_PROFILE_BIT) + format.setProfile(QSurfaceFormat::CoreProfile); + else if (value & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) + format.setProfile(QSurfaceFormat::CompatibilityProfile); + } +} + +QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share, + const QVariant &nativeHandle) + : QPlatformOpenGLContext() + , m_display(DISPLAY_FROM_XCB(screen)) + , m_config(0) + , m_context(0) + , m_shareContext(0) + , m_format(format) + , m_isPBufferCurrent(false) + , m_swapInterval(-1) + , m_ownsContext(nativeHandle.isNull()) +{ + if (nativeHandle.isNull()) + init(screen, share); + else + init(screen, share, nativeHandle); +} + +void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) +{ + if (m_format.renderableType() == QSurfaceFormat::DefaultRenderableType) + m_format.setRenderableType(QSurfaceFormat::OpenGL); + if (m_format.renderableType() != QSurfaceFormat::OpenGL && m_format.renderableType() != QSurfaceFormat::OpenGLES) + return; + + if (share) + m_shareContext = static_cast<const QGLXContext*>(share)->glxContext(); + + GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),m_format); + m_config = config; + XVisualInfo *visualInfo = 0; + Window window = 0; // Temporary window used to query OpenGL context + + if (config) { + // Resolve entry point for glXCreateContextAttribsARB + glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; + glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); + + QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(m_display, screen->screenNumber())).split(' '); + bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile"); + + // Use glXCreateContextAttribsARB if available + // Also, GL ES context creation requires GLX_EXT_create_context_es2_profile + if (glxExt.contains("GLX_ARB_create_context") && glXCreateContextAttribsARB != 0 + && (m_format.renderableType() != QSurfaceFormat::OpenGLES || (supportsProfiles && glxExt.contains("GLX_EXT_create_context_es2_profile")))) { + // Try to create an OpenGL context for each known OpenGL version in descending + // order from the requested version. + const int requestedVersion = m_format.majorVersion() * 10 + qMin(m_format.minorVersion(), 9); + + QVector<int> glVersions; + if (m_format.renderableType() == QSurfaceFormat::OpenGL) { + if (requestedVersion > 45) + glVersions << requestedVersion; + + // Don't bother with versions below 2.0 + glVersions << 45 << 44 << 43 << 42 << 41 << 40 << 33 << 32 << 31 << 30 << 21 << 20; + } else if (m_format.renderableType() == QSurfaceFormat::OpenGLES) { + if (requestedVersion > 31) + glVersions << requestedVersion; + + // Don't bother with versions below ES 2.0 + glVersions << 31 << 30 << 20; + // ES does not support any format option + m_format.setOptions(QSurfaceFormat::FormatOptions()); + } + + Q_ASSERT(glVersions.count() > 0); + + for (int i = 0; !m_context && i < glVersions.count(); i++) { + const int version = glVersions[i]; + if (version > requestedVersion) + continue; + + const int majorVersion = version / 10; + const int minorVersion = version % 10; + + QVector<int> contextAttributes; + contextAttributes << GLX_CONTEXT_MAJOR_VERSION_ARB << majorVersion + << GLX_CONTEXT_MINOR_VERSION_ARB << minorVersion; + + + if (m_format.renderableType() == QSurfaceFormat::OpenGL) { + // If asking for OpenGL 3.2 or newer we should also specify a profile + if (version >= 32 && supportsProfiles) { + if (m_format.profile() == QSurfaceFormat::CoreProfile) + contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_CORE_PROFILE_BIT_ARB; + else + contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; + } + + int flags = 0; + + if (m_format.testOption(QSurfaceFormat::DebugContext)) + flags |= GLX_CONTEXT_DEBUG_BIT_ARB; + + // A forward-compatible context may be requested for 3.0 and later + if (version >= 30 && !m_format.testOption(QSurfaceFormat::DeprecatedFunctions)) + flags |= GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB; + + if (flags != 0) + contextAttributes << GLX_CONTEXT_FLAGS_ARB << flags; + } else if (m_format.renderableType() == QSurfaceFormat::OpenGLES) { + contextAttributes << GLX_CONTEXT_PROFILE_MASK_ARB << GLX_CONTEXT_ES2_PROFILE_BIT_EXT; + } + + contextAttributes << None; + + m_context = glXCreateContextAttribsARB(m_display, config, m_shareContext, true, contextAttributes.data()); + if (!m_context && m_shareContext) { + // re-try without a shared glx context + m_context = glXCreateContextAttribsARB(m_display, config, 0, true, contextAttributes.data()); + if (m_context) + m_shareContext = 0; + } + } + } + + // Could not create a context using glXCreateContextAttribsARB, falling back to glXCreateNewContext. + if (!m_context) { + // requesting an OpenGL ES context requires glXCreateContextAttribsARB, so bail out + if (m_format.renderableType() == QSurfaceFormat::OpenGLES) + return; + + m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, m_shareContext, true); + if (!m_context && m_shareContext) { + // re-try without a shared glx context + m_context = glXCreateNewContext(m_display, config, GLX_RGBA_TYPE, 0, true); + if (m_context) + m_shareContext = 0; + } + } + + // Get the basic surface format details + if (m_context) + qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(screen), config); + + // Create a temporary window so that we can make the new context current + window = createDummyWindow(DISPLAY_FROM_XCB(screen), config, screen->screenNumber(), screen->root()); + } else { + // requesting an OpenGL ES context requires glXCreateContextAttribsARB, so bail out + if (m_format.renderableType() == QSurfaceFormat::OpenGLES) + return; + + // Note that m_format gets updated with the used surface format + visualInfo = qglx_findVisualInfo(m_display, screen->screenNumber(), &m_format); + if (!visualInfo) + qFatal("Could not initialize GLX"); + m_context = glXCreateContext(m_display, visualInfo, m_shareContext, true); + if (!m_context && m_shareContext) { + // re-try without a shared glx context + m_shareContext = 0; + m_context = glXCreateContext(m_display, visualInfo, Q_NULLPTR, true); + } + + // Create a temporary window so that we can make the new context current + window = createDummyWindow(DISPLAY_FROM_XCB(screen), visualInfo, screen->screenNumber(), screen->root()); + XFree(visualInfo); + } + + // Query the OpenGL version and profile + if (m_context && window) { + GLXContext prevContext = glXGetCurrentContext(); + GLXDrawable prevDrawable = glXGetCurrentDrawable(); + glXMakeCurrent(m_display, window, m_context); + updateFormatFromContext(m_format); + + // Make our context non-current + glXMakeCurrent(m_display, prevDrawable, prevContext); + } + + // Destroy our temporary window + XDestroyWindow(m_display, window); +} + +void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle) +{ + if (!nativeHandle.canConvert<QGLXNativeContext>()) { + qWarning("QGLXContext: Requires a QGLXNativeContext"); + return; + } + QGLXNativeContext handle = nativeHandle.value<QGLXNativeContext>(); + GLXContext context = handle.context(); + if (!context) { + qWarning("QGLXContext: No GLXContext given"); + return; + } + + // Use the provided Display, if available. If not, use our own. It may still work. + Display *dpy = handle.display(); + if (!dpy) + dpy = DISPLAY_FROM_XCB(screen); + + // Legacy contexts created using glXCreateContext are created using a visual + // and the FBConfig cannot be queried. The only way to adapt these contexts + // is to figure out the visual id. + XVisualInfo *vinfo = 0; + // If the VisualID is provided use it. + VisualID vid = handle.visualId(); + if (!vid) { + // In the absence of the VisualID figure it out from the window. + Window wnd = handle.window(); + if (wnd) { + XWindowAttributes attrs; + XGetWindowAttributes(dpy, wnd, &attrs); + vid = XVisualIDFromVisual(attrs.visual); + } + } + if (vid) { + XVisualInfo v; + v.screen = screen->screenNumber(); + v.visualid = vid; + int n = 0; + vinfo = XGetVisualInfo(dpy, VisualScreenMask | VisualIDMask, &v, &n); + if (n < 1) { + XFree(vinfo); + vinfo = 0; + } + } + + // For contexts created with an FBConfig using the modern functions providing the + // visual or window is not mandatory. Just query the config from the context. + GLXFBConfig config = 0; + if (!vinfo) { + int configId = 0; + if (glXQueryContext(dpy, context, GLX_FBCONFIG_ID, &configId) != Success) { + qWarning("QGLXContext: Failed to query config from the provided context"); + return; + } + + GLXFBConfig *configs; + int numConfigs = 0; + static const int attribs[] = { GLX_FBCONFIG_ID, configId, None }; + configs = glXChooseFBConfig(dpy, screen->screenNumber(), attribs, &numConfigs); + if (!configs || numConfigs < 1) { + qWarning("QGLXContext: Failed to find config"); + return; + } + if (configs && numConfigs > 1) // this is suspicious so warn but let it continue + qWarning("QGLXContext: Multiple configs for FBConfig ID %d", configId); + + config = configs[0]; + // Store the config. + m_config = config; + } + + Q_ASSERT(vinfo || config); + + int screenNumber = DefaultScreen(dpy); + Window window; + if (vinfo) + window = createDummyWindow(dpy, vinfo, screenNumber, RootWindow(dpy, screenNumber)); + else + window = createDummyWindow(dpy, config, screenNumber, RootWindow(dpy, screenNumber)); + if (!window) { + qWarning("QGLXContext: Failed to create dummy window"); + return; + } + + // Update OpenGL version and buffer sizes in our format. + GLXContext prevContext = glXGetCurrentContext(); + GLXDrawable prevDrawable = glXGetCurrentDrawable(); + if (!glXMakeCurrent(dpy, window, context)) { + qWarning("QGLXContext: Failed to make provided context current"); + return; + } + m_format = QSurfaceFormat(); + m_format.setRenderableType(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL + ? QSurfaceFormat::OpenGL : QSurfaceFormat::OpenGLES); + updateFormatFromContext(m_format); + if (vinfo) + qglx_surfaceFormatFromVisualInfo(&m_format, dpy, vinfo); + else + qglx_surfaceFormatFromGLXFBConfig(&m_format, dpy, config); + glXMakeCurrent(dpy, prevDrawable, prevContext); + XDestroyWindow(dpy, window); + + if (vinfo) + XFree(vinfo); + + // Success. Store the context. From this point on isValid() is true. + m_context = context; + + if (share) + m_shareContext = static_cast<const QGLXContext*>(share)->glxContext(); +} + +QGLXContext::~QGLXContext() +{ + if (m_ownsContext) + glXDestroyContext(m_display, m_context); +} + +static QXcbScreen *screenForPlatformSurface(QPlatformSurface *surface) +{ + QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass(); + if (surfaceClass == QSurface::Window) { + return static_cast<QXcbScreen *>(static_cast<QXcbWindow *>(surface)->screen()); + } else if (surfaceClass == QSurface::Offscreen) { + return static_cast<QXcbScreen *>(static_cast<QGLXPbuffer *>(surface)->screen()); + } + return Q_NULLPTR; +} + +QVariant QGLXContext::nativeHandle() const +{ + return QVariant::fromValue<QGLXNativeContext>(QGLXNativeContext(m_context)); +} + +bool QGLXContext::makeCurrent(QPlatformSurface *surface) +{ + bool success = false; + Q_ASSERT(surface->surface()->supportsOpenGL()); + + GLXDrawable glxDrawable = 0; + QSurface::SurfaceClass surfaceClass = surface->surface()->surfaceClass(); + if (surfaceClass == QSurface::Window) { + m_isPBufferCurrent = false; + QXcbWindow *window = static_cast<QXcbWindow *>(surface); + glxDrawable = window->xcb_window(); + success = glXMakeCurrent(m_display, glxDrawable, m_context); + } else if (surfaceClass == QSurface::Offscreen) { + m_isPBufferCurrent = true; + QGLXPbuffer *pbuffer = static_cast<QGLXPbuffer *>(surface); + glxDrawable = pbuffer->pbuffer(); + success = glXMakeContextCurrent(m_display, glxDrawable, glxDrawable, m_context); + } + + if (success) { + int interval = surface->format().swapInterval(); + QXcbScreen *screen = screenForPlatformSurface(surface); + if (interval >= 0 && m_swapInterval != interval && screen) { + m_swapInterval = interval; + typedef void (*qt_glXSwapIntervalEXT)(Display *, GLXDrawable, int); + typedef void (*qt_glXSwapIntervalMESA)(unsigned int); + static qt_glXSwapIntervalEXT glXSwapIntervalEXT = 0; + static qt_glXSwapIntervalMESA glXSwapIntervalMESA = 0; + static bool resolved = false; + if (!resolved) { + resolved = true; + QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(m_display, + screen->screenNumber())).split(' '); + if (glxExt.contains("GLX_EXT_swap_control")) + glXSwapIntervalEXT = (qt_glXSwapIntervalEXT) getProcAddress("glXSwapIntervalEXT"); + if (glxExt.contains("GLX_MESA_swap_control")) + glXSwapIntervalMESA = (qt_glXSwapIntervalMESA) getProcAddress("glXSwapIntervalMESA"); + } + if (glXSwapIntervalEXT) + glXSwapIntervalEXT(m_display, glxDrawable, interval); + else if (glXSwapIntervalMESA) + glXSwapIntervalMESA(interval); + } + } + + return success; +} + +void QGLXContext::doneCurrent() +{ + if (m_isPBufferCurrent) + glXMakeContextCurrent(m_display, 0, 0, 0); + else + glXMakeCurrent(m_display, 0, 0); + m_isPBufferCurrent = false; +} + +void QGLXContext::swapBuffers(QPlatformSurface *surface) +{ + GLXDrawable glxDrawable = 0; + if (surface->surface()->surfaceClass() == QSurface::Offscreen) + glxDrawable = static_cast<QGLXPbuffer *>(surface)->pbuffer(); + else + glxDrawable = static_cast<QXcbWindow *>(surface)->xcb_window(); + glXSwapBuffers(m_display, glxDrawable); + + if (surface->surface()->surfaceClass() == QSurface::Window) { + QXcbWindow *platformWindow = static_cast<QXcbWindow *>(surface); + // OpenGL context might be bound to a non-gui thread use QueuedConnection to sync + // the window from the platformWindow's thread as QXcbWindow is no QObject, an + // event is sent to QXcbConnection. (this is faster than a metacall) + if (platformWindow->needsSync()) + platformWindow->postSyncWindowRequest(); + } +} + +void (*QGLXContext::getProcAddress(const QByteArray &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(m_display, 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 (void (*)())glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName.constData())); +} + +QSurfaceFormat QGLXContext::format() const +{ + return m_format; +} + +bool QGLXContext::isSharing() const +{ + return m_shareContext != 0; +} + +bool QGLXContext::isValid() const +{ + return m_context != 0; +} + +bool QGLXContext::m_queriedDummyContext = false; +bool QGLXContext::m_supportsThreading = true; + + +// If this list grows to any significant size, change it a +// proper string table and make the implementation below use +// binary search. +static const char *qglx_threadedgl_blacklist_renderer[] = { + "Chromium", // QTBUG-32225 (initialization fails) + 0 +}; + +// This disables threaded rendering on anything using mesa, e.g. +// - nvidia/nouveau +// - amd/gallium +// - intel +// - some software opengl implementations +// +// The client glx vendor string is used to identify those setups as that seems to show the least +// variance between the bad configurations. It's always "Mesa Project and SGI". There are some +// configurations which don't use mesa and which can do threaded rendering (amd and nvidia chips +// with their own proprietary drivers). +// +// This, of course, is very broad and disables threaded rendering on a lot of devices which would +// be able to use it. However, the bugs listed below don't follow any easily recognizable pattern +// and we should rather be safe. +// +// http://cgit.freedesktop.org/xcb/libxcb/commit/?id=be0fe56c3bcad5124dcc6c47a2fad01acd16f71a will +// fix some of the issues. Basically, the proprietary drivers seem to have a way of working around +// a fundamental flaw with multithreaded access to xcb, but mesa doesn't. The blacklist should be +// reevaluated once that patch is released in some version of xcb. +static const char *qglx_threadedgl_blacklist_vendor[] = { + "Mesa Project and SGI", // QTCREATORBUG-10875 (crash in creator) + // QTBUG-34492 (flickering in fullscreen) + // QTBUG-38221 + 0 +}; + +void QGLXContext::queryDummyContext() +{ + if (m_queriedDummyContext) + return; + m_queriedDummyContext = true; + + static bool skip = qEnvironmentVariableIsSet("QT_OPENGL_NO_SANITY_CHECK"); + if (skip) + return; + + QOpenGLContext *oldContext = QOpenGLContext::currentContext(); + QSurface *oldSurface = 0; + if (oldContext) + oldSurface = oldContext->surface(); + + QScopedPointer<QSurface> surface; + const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR); + if (glxvendor && !strcmp(glxvendor, "ATI")) { + QWindow *window = new QWindow; + window->resize(64, 64); + window->setSurfaceType(QSurface::OpenGLSurface); + window->create(); + surface.reset(window); + } else { + QOffscreenSurface *offSurface = new QOffscreenSurface; + offSurface->create(); + surface.reset(offSurface); + } + + QOpenGLContext context; + context.create(); + context.makeCurrent(surface.data()); + + m_supportsThreading = true; + + if (const char *renderer = (const char *) glGetString(GL_RENDERER)) { + for (int i = 0; qglx_threadedgl_blacklist_renderer[i]; ++i) { + if (strstr(renderer, qglx_threadedgl_blacklist_renderer[i]) != 0) { + m_supportsThreading = false; + break; + } + } + } + + if (glxvendor) { + for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) { + if (strstr(glxvendor, qglx_threadedgl_blacklist_vendor[i]) != 0) { + m_supportsThreading = false; + break; + } + } + } + + context.doneCurrent(); + if (oldContext && oldSurface) + oldContext->makeCurrent(oldSurface); +} + +bool QGLXContext::supportsThreading() +{ + if (!m_queriedDummyContext) + queryDummyContext(); + return m_supportsThreading; +} + +QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface) + : QPlatformOffscreenSurface(offscreenSurface) + , m_format(offscreenSurface->requestedFormat()) + , m_screen(static_cast<QXcbScreen *>(offscreenSurface->screen()->handle())) + , m_pbuffer(0) +{ + GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), m_format); + + if (config) { + const int attributes[] = { + GLX_PBUFFER_WIDTH, offscreenSurface->size().width(), + GLX_PBUFFER_HEIGHT, offscreenSurface->size().height(), + GLX_LARGEST_PBUFFER, False, + GLX_PRESERVED_CONTENTS, False, + None + }; + + m_pbuffer = glXCreatePbuffer(DISPLAY_FROM_XCB(m_screen), config, attributes); + + if (m_pbuffer) + qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(m_screen), config); + } +} + +QGLXPbuffer::~QGLXPbuffer() +{ + if (m_pbuffer) + glXDestroyPbuffer(DISPLAY_FROM_XCB(m_screen), m_pbuffer); +} + + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h new file mode 100644 index 0000000000..73a17d69b4 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLXINTEGRATION_H +#define QGLXINTEGRATION_H + +#include "qxcbwindow.h" +#include "qxcbscreen.h" + +#include <qpa/qplatformopenglcontext.h> +#include <qpa/qplatformoffscreensurface.h> +#include <QtGui/QSurfaceFormat> + +#include <QtCore/QMutex> + +#include <GL/glx.h> + +QT_BEGIN_NAMESPACE + +class QGLXContext : public QPlatformOpenGLContext +{ +public: + QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share, + const QVariant &nativeHandle); + ~QGLXContext(); + + bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE; + void doneCurrent() Q_DECL_OVERRIDE; + void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE; + void (*getProcAddress(const QByteArray &procName)) () Q_DECL_OVERRIDE; + + QSurfaceFormat format() const Q_DECL_OVERRIDE; + bool isSharing() const Q_DECL_OVERRIDE; + bool isValid() const Q_DECL_OVERRIDE; + + GLXContext glxContext() const { return m_context; } + GLXFBConfig glxConfig() const { return m_config; } + + QVariant nativeHandle() const; + + static bool supportsThreading(); + static void queryDummyContext(); + +private: + void init(QXcbScreen *screen, QPlatformOpenGLContext *share); + void init(QXcbScreen *screen, QPlatformOpenGLContext *share, const QVariant &nativeHandle); + + Display *m_display; + GLXFBConfig m_config; + GLXContext m_context; + GLXContext m_shareContext; + QSurfaceFormat m_format; + bool m_isPBufferCurrent; + int m_swapInterval; + bool m_ownsContext; + static bool m_queriedDummyContext; + static bool m_supportsThreading; +}; + + +class QGLXPbuffer : public QPlatformOffscreenSurface +{ +public: + explicit QGLXPbuffer(QOffscreenSurface *offscreenSurface); + ~QGLXPbuffer(); + + QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; } + bool isValid() const Q_DECL_OVERRIDE { return m_pbuffer != 0; } + + GLXPbuffer pbuffer() const { return m_pbuffer; } + +private: + QSurfaceFormat m_format; + QXcbScreen *m_screen; + GLXPbuffer m_pbuffer; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp new file mode 100644 index 0000000000..a4e603f599 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -0,0 +1,217 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbglxintegration.h" + +#if defined(XCB_HAS_XCB_GLX) +#include <xcb/glx.h> +#endif + +#include "qxcbnativeinterface.h" +#include "qxcbglxwindow.h" +#include "qxcbscreen.h" +#include "qglxintegration.h" + +#include <QtGui/QOpenGLContext> + +#include "qxcbglxnativeinterfacehandler.h" + +#include <X11/Xlibint.h> + +QT_BEGIN_NAMESPACE + +#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 + +QXcbGlxIntegration::QXcbGlxIntegration() + : m_connection(Q_NULLPTR) + , m_glx_first_event(0) +{ + qCDebug(QT_XCB_GLINTEGRATION) << "Xcb GLX gl-integration created"; +} + +QXcbGlxIntegration::~QXcbGlxIntegration() +{ +} + +bool QXcbGlxIntegration::initialize(QXcbConnection *connection) +{ + m_connection = connection; +#ifdef XCB_HAS_XCB_GLX + + const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection->xcb_connection(), &xcb_glx_id); + if (!reply || !reply->present) + return false; + + m_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_connection(), + XCB_GLX_MAJOR_VERSION, + XCB_GLX_MINOR_VERSION); + xcb_glx_query_version_reply_t *xglx_query = xcb_glx_query_version_reply(m_connection->xcb_connection(), + xglx_query_cookie, &error); + if (!xglx_query || error) { + qCWarning(QT_XCB_GLINTEGRATION) << "QXcbConnection: Failed to initialize GLX"; + free(error); + return false; + } + free(xglx_query); +#endif + + m_native_interface_handler.reset(new QXcbGlxNativeInterfaceHandler(connection->nativeInterface())); + + qCDebug(QT_XCB_GLINTEGRATION) << "Xcb GLX gl-integration successfully initialized"; + return true; +} + +bool QXcbGlxIntegration::handleXcbEvent(xcb_generic_event_t *event, uint responseType) +{ + bool handled = false; + // 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 = static_cast<Display *>(m_connection->xlib_display()); + XLockDisplay(xdisplay); + bool locked = true; + Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent(xdisplay, responseType, 0); + if (proc) { + XESetWireToEvent(xdisplay, responseType, proc); + XEvent dummy; + event->sequence = LastKnownRequestProcessed(xdisplay); + if (proc(xdisplay, &dummy, (xEvent*)event)) { +#ifdef 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 = m_glx_first_event + XCB_GLX_BUFFER_SWAP_COMPLETE; + QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance(); + if (dispatcher && uint(dummy.type) == swap_complete && responseType != 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; + QByteArray genericEventFilterType = m_connection->nativeInterface()->genericEventFilterType(); + long result = 0; + handled = dispatcher->filterNativeEvent(genericEventFilterType, &ev, &result); + } +#endif + } + } + if (locked) + XUnlockDisplay(xdisplay); + return handled; +} + +QXcbWindow *QXcbGlxIntegration::createWindow(QWindow *window) const +{ + return new QXcbGlxWindow(window); +} + +QPlatformOpenGLContext *QXcbGlxIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const +{ + QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle()); + QGLXContext *platformContext = new QGLXContext(screen, context->format(), + context->shareHandle(), context->nativeHandle()); + context->setNativeHandle(platformContext->nativeHandle()); + return platformContext; +} + +QPlatformOffscreenSurface *QXcbGlxIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const +{ + static bool vendorChecked = false; + static bool glxPbufferUsable = true; + if (!vendorChecked) { + vendorChecked = true; + const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR); + if (glxvendor && !strcmp(glxvendor, "ATI")) + glxPbufferUsable = false; + } + if (glxPbufferUsable) + return new QGLXPbuffer(surface); + else + return 0; // trigger fallback to hidden QWindow + +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h new file mode 100644 index 0000000000..2ef40f9ab6 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBGLXINTEGRATION_H +#define QXCBGLXINTEGRATION_H + +#include "qxcbglintegration.h" + +QT_BEGIN_NAMESPACE + +class QXcbNativeInterfaceHandler; + +class QXcbGlxIntegration : public QXcbGlIntegration +{ +public: + QXcbGlxIntegration(); + ~QXcbGlxIntegration(); + + bool initialize(QXcbConnection *connection) Q_DECL_OVERRIDE; + bool handleXcbEvent(xcb_generic_event_t *event, uint responseType) Q_DECL_OVERRIDE; + + QXcbWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; +private: + QXcbConnection *m_connection; + uint32_t m_glx_first_event; + + QScopedPointer<QXcbNativeInterfaceHandler> m_native_interface_handler; +}; + +QT_END_NAMESPACE + +#endif //QXCBGLXINTEGRATION_H diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxmain.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxmain.cpp new file mode 100644 index 0000000000..93bb76f92f --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxmain.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbglintegrationplugin.h" + +#include "qxcbglxintegration.h" + +QT_BEGIN_NAMESPACE + +class QXcbGlxIntegrationPlugin : public QXcbGlIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QXcbGlIntegrationFactoryInterface_iid FILE "xcb_glx.json") +public: + QXcbGlIntegration *create() + { + return new QXcbGlxIntegration(); + } + +}; + +QT_END_NAMESPACE + +#include "qxcbglxmain.moc" diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.cpp new file mode 100644 index 0000000000..6cdd4101e0 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbglxnativeinterfacehandler.h" + +#include "qglxintegration.h" +#include <QtGui/QOpenGLContext> +QT_BEGIN_NAMESPACE + +static int resourceType(const QByteArray &key) +{ + static const QByteArray names[] = { // match QXcbGlxNativeInterfaceHandler::ResourceType + QByteArrayLiteral("glxconfig"), + QByteArrayLiteral("glxcontext"), + }; + for (size_t i = 0; i < sizeof(names) / sizeof(names[0]); i++) { + if (key == names[i]) + return i; + } + + return sizeof(names) / sizeof(names[0]); +} + +QXcbGlxNativeInterfaceHandler::QXcbGlxNativeInterfaceHandler(QXcbNativeInterface *nativeInterface) + : QXcbNativeInterfaceHandler(nativeInterface) +{ +} + +QPlatformNativeInterface::NativeResourceForContextFunction QXcbGlxNativeInterfaceHandler::nativeResourceFunctionForContext(const QByteArray &resource) const +{ + switch (resourceType(resource)) { + case GLXConfig: + return glxConfigForContext; + case GLXContext: + return glxContextForContext; + default: + break; + } + return Q_NULLPTR; +} + +void *QXcbGlxNativeInterfaceHandler::glxContextForContext(QOpenGLContext *context) +{ + Q_ASSERT(context); + QGLXContext *glxPlatformContext = static_cast<QGLXContext *>(context->handle()); + return glxPlatformContext->glxContext(); +} + +void *QXcbGlxNativeInterfaceHandler::glxConfigForContext(QOpenGLContext *context) +{ + Q_ASSERT(context); + QGLXContext *glxPlatformContext = static_cast<QGLXContext *>(context->handle()); + return glxPlatformContext->glxConfig(); + +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.h new file mode 100644 index 0000000000..e9df28ea39 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxnativeinterfacehandler.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBGLXNATIVEINTERFACEHANDLER_H +#define QXCBGLXNATIVEINTERFACEHANDLER_H + +#include "qxcbnativeinterfacehandler.h" + +QT_BEGIN_NAMESPACE + +class QXcbGlxNativeInterfaceHandler : public QXcbNativeInterfaceHandler +{ +public: + enum ResourceType { + GLXConfig, + GLXContext, + }; + + QXcbGlxNativeInterfaceHandler(QXcbNativeInterface *nativeInterface); + QPlatformNativeInterface::NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) const Q_DECL_OVERRIDE; + +private: + static void *glxContextForContext(QOpenGLContext *context); + static void *glxConfigForContext(QOpenGLContext *context); +}; + +QT_END_NAMESPACE + +#endif //QXCBGLXNATIVEINTERFACEHANDLER_H diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp new file mode 100644 index 0000000000..8aabde8129 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbglxwindow.h" + +#include "qxcbscreen.h" +#include <QtPlatformSupport/private/qglxconvenience_p.h> + +QT_BEGIN_NAMESPACE + +QXcbGlxWindow::QXcbGlxWindow(QWindow *window) + : QXcbWindow(window) +{ +} + +QXcbGlxWindow::~QXcbGlxWindow() +{ +} + +void QXcbGlxWindow::resolveFormat() +{ + m_format = window()->requestedFormat(); //qglx_findVisualInfo sets the resovled format +} + +void *QXcbGlxWindow::createVisual() +{ + return qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), &m_format); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.h new file mode 100644 index 0000000000..bb7cd7bef2 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** 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, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBGLXWINDOW_H +#define QXCBGLXWINDOW_H + +#include "qxcbglxintegration.h" +#include "qxcbwindow.h" + +QT_BEGIN_NAMESPACE + +class QXcbGlxWindow : public QXcbWindow +{ +public: + QXcbGlxWindow(QWindow *window); + ~QXcbGlxWindow(); + +protected: + void resolveFormat() Q_DECL_OVERRIDE; + void *createVisual() Q_DECL_OVERRIDE; +}; + +QT_END_NAMESPACE + +#endif //QXCBGLXWINDOW_H diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.json b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.json new file mode 100644 index 0000000000..1e2641ae7c --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "xcb_glx" ] +} diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro new file mode 100644 index 0000000000..57cd81ec3b --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/xcb_glx.pro @@ -0,0 +1,31 @@ +TARGET = qxcb-glx-integration + +PLUGIN_CLASS_NAME = QXcbGlxIntegrationPlugin +PLUGIN_TYPE = xcbglintegrations + +load(qt_plugin) + +include(../gl_integrations_plugin_base.pri) + +#should be removed from the sources +DEFINES += XCB_USE_GLX XCB_USE_XLIB + +LIBS += -lxcb + +contains(QT_CONFIG, xcb-glx) { + DEFINES += XCB_HAS_XCB_GLX + LIBS += -lxcb-glx +} + +HEADERS += \ + qxcbglxintegration.h \ + qxcbglxwindow.h \ + qglxintegration.h \ + qxcbglxnativeinterfacehandler.h + +SOURCES += \ + qxcbglxmain.cpp \ + qxcbglxintegration.cpp \ + qxcbglxwindow.cpp \ + qglxintegration.cpp \ + qxcbglxnativeinterfacehandler.cpp |