diff options
Diffstat (limited to 'src/plugins/platforms')
168 files changed, 5975 insertions, 1939 deletions
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp index 3a80f9437a..59125ac0d2 100644 --- a/src/plugins/platforms/android/androidjniinput.cpp +++ b/src/plugins/platforms/android/androidjniinput.cpp @@ -155,7 +155,7 @@ namespace QtAndroidInput static void longPress(JNIEnv */*env*/, jobject /*thiz*/, jint /*winId*/, jint x, jint y) { //### TODO: add proper API for Qt 5.2 - static bool rightMouseFromLongPress = qgetenv("QT_NECESSITAS_COMPATIBILITY_LONG_PRESS").toInt(); + static bool rightMouseFromLongPress = qEnvironmentVariableIntValue("QT_NECESSITAS_COMPATIBILITY_LONG_PRESS"); if (!rightMouseFromLongPress) return; m_ignoreMouseEvents = true; diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index 1c157c79c3..ab653860f3 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -410,7 +410,7 @@ namespace QtAndroid bool blockEventLoopsWhenSuspended() { - static bool block = qgetenv("QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED").toInt(); + static bool block = qEnvironmentVariableIntValue("QT_BLOCK_EVENT_LOOPS_WHEN_SUSPENDED"); return block; } diff --git a/src/plugins/platforms/android/androidjnimenu.cpp b/src/plugins/platforms/android/androidjnimenu.cpp index 23182c6e57..36c349f6b4 100644 --- a/src/plugins/platforms/android/androidjnimenu.cpp +++ b/src/plugins/platforms/android/androidjnimenu.cpp @@ -199,7 +199,7 @@ namespace QtAndroidMenu env->DeleteLocalRef(env->CallObjectMethod(menuItem, setEnabledMenuItemMethodID, enabled)); if (!icon.isNull()) { // isNull() only checks the d pointer, not the actual image data. - int sz = qMax(36, qgetenv("QT_ANDROID_APP_ICON_SIZE").toInt()); + int sz = qMax(36, qEnvironmentVariableIntValue("QT_ANDROID_APP_ICON_SIZE")); QImage img = icon.pixmap(QSize(sz,sz), enabled ? QIcon::Normal diff --git a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp index 06303cdd10..2010c19bd4 100644 --- a/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp +++ b/src/plugins/platforms/android/qandroidassetsfileenginehandler.cpp @@ -254,7 +254,7 @@ private: AndroidAssetsFileEngineHandler::AndroidAssetsFileEngineHandler() - : m_assetsCache(std::max(5, qgetenv("QT_ANDROID_MAX_ASSETS_CACHE_SIZE").toInt())) + : m_assetsCache(std::max(5, qEnvironmentVariableIntValue("QT_ANDROID_MAX_ASSETS_CACHE_SIZE"))) , m_hasPrepopulatedCache(false) , m_hasTriedPrepopulatingCache(false) { diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp index 092ade2e4a..a4e82a29ef 100644 --- a/src/plugins/platforms/android/qandroidplatformscreen.cpp +++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp @@ -85,7 +85,7 @@ QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen() m_size = QSize(QAndroidPlatformIntegration::m_defaultScreenWidth, QAndroidPlatformIntegration::m_defaultScreenHeight); // Raster only apps should set QT_ANDROID_RASTER_IMAGE_DEPTH to 16 // is way much faster than 32 - if (qgetenv("QT_ANDROID_RASTER_IMAGE_DEPTH").toInt() == 16) { + if (qEnvironmentVariableIntValue("QT_ANDROID_RASTER_IMAGE_DEPTH") == 16) { m_format = QImage::Format_RGB16; m_depth = 16; } else { diff --git a/src/plugins/platforms/android/qandroidplatformtheme.cpp b/src/plugins/platforms/android/qandroidplatformtheme.cpp index 35eb282994..f1ddcefef6 100644 --- a/src/plugins/platforms/android/qandroidplatformtheme.cpp +++ b/src/plugins/platforms/android/qandroidplatformtheme.cpp @@ -450,7 +450,7 @@ QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const { switch (hint) { case StyleNames: - if (qgetenv("QT_USE_ANDROID_NATIVE_STYLE").toInt() + if (qEnvironmentVariableIntValue("QT_USE_ANDROID_NATIVE_STYLE") && m_androidStyleData) { return QStringList("android"); } @@ -458,7 +458,7 @@ QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const case MouseDoubleClickDistance: { - int minimumDistance = qgetenv("QT_ANDROID_MINIMUM_MOUSE_DOUBLE_CLICK_DISTANCE").toInt(); + int minimumDistance = qEnvironmentVariableIntValue("QT_ANDROID_MINIMUM_MOUSE_DOUBLE_CLICK_DISTANCE"); int ret = minimumDistance; QAndroidPlatformIntegration *platformIntegration @@ -502,7 +502,7 @@ QString QAndroidPlatformTheme::standardButtonText(int button) const bool QAndroidPlatformTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const { if (type == MessageDialog) - return qgetenv("QT_USE_ANDROID_NATIVE_DIALOGS").toInt() == 1; + return qEnvironmentVariableIntValue("QT_USE_ANDROID_NATIVE_DIALOGS") == 1; return false; } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 72bd09625a..180cb23669 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -337,7 +337,7 @@ QCocoaIntegration::~QCocoaIntegration() // Delete screens in reverse order to avoid crash in case of multiple screens while (!mScreens.isEmpty()) { - delete mScreens.takeLast(); + destroyScreen(mScreens.takeLast()); } clearToolbars(); @@ -397,7 +397,7 @@ void QCocoaIntegration::updateScreens() // Now the leftovers in remainingScreens are no longer current, so we can delete them. foreach (QCocoaScreen* screen, remainingScreens) { mScreens.removeOne(screen); - delete screen; + destroyScreen(screen); } // All screens in mScreens are siblings, because we ignored the mirrors. foreach (QCocoaScreen* screen, mScreens) diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h index c527c478ff..c426cacc35 100755 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h @@ -57,7 +57,7 @@ public: virtual void updateToolTip(const QString &toolTip); virtual void updateMenu(QPlatformMenu *menu); virtual QRect geometry() const; - virtual void showMessage(const QString &msg, const QString &title, + virtual void showMessage(const QString &title, const QString &msg, const QIcon& icon, MessageIcon iconType, int secs); virtual bool isSystemTrayAvailable() const; diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index fa71ab4086..c36634db74 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -74,6 +74,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); NSString *m_inputSource; QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) *m_mouseMoveHelper; bool m_resendKeyEvent; + bool m_scrolling; } - (id)init; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 771b464805..9c24851115 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** 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. @@ -160,6 +160,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; m_inputSource = 0; m_mouseMoveHelper = [[QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) alloc] initWithView:self]; m_resendKeyEvent = false; + m_scrolling = false; if (!touchDevice) { touchDevice = new QTouchDevice; @@ -415,8 +416,8 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; && [notificationName isEqualToString:_q_NSWindowDidChangeOcclusionStateNotification]) { #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 // ### HACK Remove the enum declaration, the warning disabling and the cast further down once 10.8 is unsupported -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wobjc-method-access" +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wobjc-method-access") enum { NSWindowOcclusionStateVisible = 1UL << 1 }; #endif if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible) { @@ -431,7 +432,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; m_platformWindow->obscureWindow(); } #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9 -#pragma clang diagnostic pop +QT_WARNING_POP #endif } else if (notificationName == NSWindowDidChangeScreenNotification) { if (m_window) { @@ -1265,12 +1266,10 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) { if (m_window->flags() & Qt::WindowTransparentForInput) return [super scrollWheel:theEvent]; - const EventRef carbonEvent = (EventRef)[theEvent eventRef]; - const UInt32 carbonEventKind = carbonEvent ? ::GetEventKind(carbonEvent) : 0; - const bool scrollEvent = carbonEventKind == kEventMouseScroll; QPoint angleDelta; - if (scrollEvent) { + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized; + if ([theEvent hasPreciseScrollingDeltas]) { // The mouse device contains pixel scroll wheel support (Mighty Mouse, Trackpad). // Since deviceDelta is delivered as pixels rather than degrees, we need to // convert from pixels to degrees in a sensible manner. @@ -1279,8 +1278,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) const int pixelsToDegrees = 2; // 8 * 1/4 angleDelta.setX([theEvent scrollingDeltaX] * pixelsToDegrees); angleDelta.setY([theEvent scrollingDeltaY] * pixelsToDegrees); + source = Qt::MouseEventSynthesizedBySystem; } else { - // carbonEventKind == kEventMouseWheelMoved // Remove acceleration, and use either -120 or 120 as delta: angleDelta.setX(qBound(-120, int([theEvent deltaX] * 10000), 120)); angleDelta.setY(qBound(-120, int([theEvent deltaY] * 10000), 120)); @@ -1321,19 +1320,23 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_8 if (QSysInfo::QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { // On 10.8 and above, MayBegin is likely to happen. We treat it the same as an actual begin. - if (phase == NSEventPhaseMayBegin) + if (phase == NSEventPhaseMayBegin) { + m_scrolling = true; ph = Qt::ScrollBegin; - } else + } + } #endif - if (phase == NSEventPhaseBegan) { - // On 10.7, MayBegin will not happen, so Began is the actual beginning. + if (phase == NSEventPhaseBegan) { + // If MayBegin did not happen, Began is the actual beginning. + if (!m_scrolling) ph = Qt::ScrollBegin; - } - if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled) { + m_scrolling = true; + } else if (phase == NSEventPhaseEnded || phase == NSEventPhaseCancelled) { ph = Qt::ScrollEnd; + m_scrolling = false; } - QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph); + QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph, source); } #endif //QT_NO_WHEELEVENT @@ -1419,7 +1422,7 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) if (m_sendKeyEvent && m_composingText.isEmpty()) QWindowSystemInterface::handleExtendedKeyEvent(focusWindow, timestamp, QEvent::Type(eventType), keyCode, modifiers, - nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat]); + nativeScanCode, nativeVirtualKey, nativeModifiers, text, [nsevent isARepeat], false); m_sendKeyEvent = false; m_resendKeyEvent = false; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index a86bb0ee04..8c70f70edd 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -923,7 +923,11 @@ public: static const char keyC[] = "HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes"; const QString familyName = QString::fromWCharArray(lf.lfFaceName); const QString nameSubstitute = QSettings(QLatin1String(keyC), QSettings::NativeFormat).value(familyName, familyName).toString(); - memcpy(lf.lfFaceName, nameSubstitute.utf16(), sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE)); + if (nameSubstitute != familyName) { + const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1); + memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t)); + lf.lfFaceName[nameSubstituteLength] = 0; + } ComPtr<IDWriteFont> dwriteFont; HRESULT hr = QWindowsDirect2DContext::instance()->dwriteGdiInterop()->CreateFontFromLOGFONT(&lf, &dwriteFont); diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro new file mode 100644 index 0000000000..d8ce385636 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +contains(QT_CONFIG, egl_x11): SUBDIRS += eglfs_x11 +contains(QT_CONFIG, kms): SUBDIRS += eglfs_kms diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.json new file mode 100644 index 0000000000..70fec1cacf --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs_kms" ] +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro new file mode 100644 index 0000000000..f79653127e --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro @@ -0,0 +1,32 @@ +TARGET = qeglfs-kms-integration + +PLUGIN_CLASS_NAME=QEglFSKmsIntegrationPlugin +PLUGIN_TYPE=egldeviceintegrations + +load(qt_plugin) + +QT += core-private gui-private platformsupport-private eglfs_device_lib-private + +INCLUDEPATH += $$PWD/../.. + +# Avoid X11 header collision +DEFINES += MESA_EGL_NO_X11_HEADERS + +CONFIG += link_pkgconfig +PKGCONFIG += libdrm gbm + +CONFIG += egl +QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF + +SOURCES += $$PWD/qeglfskmsmain.cpp \ + $$PWD/qeglfskmsintegration.cpp \ + $$PWD/qeglfskmsdevice.cpp \ + $$PWD/qeglfskmsscreen.cpp \ + $$PWD/qeglfskmscursor.cpp + +HEADERS += $$PWD/qeglfskmsintegration.h \ + $$PWD/qeglfskmsdevice.h \ + $$PWD/qeglfskmsscreen.h \ + $$PWD/qeglfskmscursor.h + +OTHER_FILES += $$PWD/eglfs_kms.json diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp new file mode 100644 index 0000000000..e337e832e2 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** 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 "qeglfskmscursor.h" +#include "qeglfskmsscreen.h" +#include "qeglfskmsdevice.h" + +#include <QtCore/QJsonDocument> +#include <QtCore/QJsonObject> +#include <QtCore/QJsonArray> +#include <QtCore/QLoggingCategory> +#include <QtGui/QPainter> + +#include <xf86drm.h> +#include <xf86drmMode.h> + +#ifndef DRM_CAP_CURSOR_WIDTH +#define DRM_CAP_CURSOR_WIDTH 0x8 +#endif + +#ifndef DRM_CAP_CURSOR_HEIGHT +#define DRM_CAP_CURSOR_HEIGHT 0x9 +#endif + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen) + : m_screen(screen) + , m_cursorSize(64, 64) // 64x64 is the old standard size, we now try to query the real size below + , m_bo(Q_NULLPTR) + , m_cursorImage(0, 0, 0, 0, 0, 0) + , m_visible(true) +{ + uint64_t width, height; + if ((drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_WIDTH, &width) == 0) + && (drmGetCap(m_screen->device()->fd(), DRM_CAP_CURSOR_HEIGHT, &height) == 0)) { + m_cursorSize.setWidth(width); + m_cursorSize.setHeight(height); + } + + m_bo = gbm_bo_create(m_screen->device()->device(), m_cursorSize.width(), m_cursorSize.height(), + GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); + if (!m_bo) { + qWarning("Could not create buffer for cursor!"); + } else { + initCursorAtlas(); + } + +#ifndef QT_NO_CURSOR + QCursor cursor(Qt::ArrowCursor); + changeCursor(&cursor, 0); +#endif + setPos(QPoint(0, 0)); +} + +QEglFSKmsCursor::~QEglFSKmsCursor() +{ + drmModeSetCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0, 0); + drmModeMoveCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0); + + gbm_bo_destroy(m_bo); + m_bo = Q_NULLPTR; +} + +void QEglFSKmsCursor::pointerEvent(const QMouseEvent &event) +{ + setPos(event.screenPos().toPoint()); +} + +#ifndef QT_NO_CURSOR +void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window) +{ + Q_UNUSED(window); + + if (!m_visible) + return; + + const Qt::CursorShape newShape = windowCursor ? windowCursor->shape() : Qt::ArrowCursor; + if (newShape == Qt::BitmapCursor) { + m_cursorImage.set(windowCursor->pixmap().toImage(), + windowCursor->hotSpot().x(), + windowCursor->hotSpot().y()); + } else { + // Standard cursor, look up in atlas + const int width = m_cursorAtlas.cursorWidth; + const int height = m_cursorAtlas.cursorHeight; + const qreal ws = (qreal)m_cursorAtlas.cursorWidth / m_cursorAtlas.width; + const qreal hs = (qreal)m_cursorAtlas.cursorHeight / m_cursorAtlas.height; + + QRect textureRect(ws * (newShape % m_cursorAtlas.cursorsPerRow) * m_cursorAtlas.width, + hs * (newShape / m_cursorAtlas.cursorsPerRow) * m_cursorAtlas.height, + width, + height); + QPoint hotSpot = m_cursorAtlas.hotSpots[newShape]; + m_cursorImage.set(m_cursorAtlas.image.copy(textureRect), + hotSpot.x(), + hotSpot.y()); + } + + if (m_cursorImage.image()->width() > m_cursorSize.width() || m_cursorImage.image()->height() > m_cursorSize.height()) + qWarning("Cursor larger than %dx%d, cursor will be clipped.", m_cursorSize.width(), m_cursorSize.height()); + + QImage cursorImage(m_cursorSize, QImage::Format_ARGB32); + cursorImage.fill(Qt::transparent); + + QPainter painter; + painter.begin(&cursorImage); + painter.drawImage(0, 0, *m_cursorImage.image()); + painter.end(); + + gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.byteCount()); + + uint32_t handle = gbm_bo_get_handle(m_bo).u32; + int status = drmModeSetCursor(m_screen->device()->fd(), m_screen->output().crtc_id, handle, + m_cursorSize.width(), m_cursorSize.height()); + if (status != 0) + qWarning("Could not set cursor: %d", status); +} +#endif // QT_NO_CURSOR + +QPoint QEglFSKmsCursor::pos() const +{ + return m_pos; +} + +void QEglFSKmsCursor::setPos(const QPoint &pos) +{ + QPoint adjustedPos = pos - m_cursorImage.hotspot(); + int ret = drmModeMoveCursor(m_screen->device()->fd(), m_screen->output().crtc_id, adjustedPos.x(), adjustedPos.y()); + if (ret == 0) { + m_pos = pos; + } else { + qWarning("Failed to move cursor: %d", ret); + } +} + +void QEglFSKmsCursor::initCursorAtlas() +{ + static QByteArray json = qgetenv("QT_QPA_EGLFS_CURSOR"); + if (json.isEmpty()) + json = ":/cursor.json"; + + qCDebug(qLcEglfsKmsDebug) << "Initializing cursor atlas from" << json; + + QFile file(QString::fromUtf8(json)); + if (!file.open(QFile::ReadOnly)) { + drmModeSetCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0, 0); + drmModeMoveCursor(m_screen->device()->fd(), m_screen->output().crtc_id, 0, 0); + m_visible = false; + return; + } + + QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + QJsonObject object = doc.object(); + + QString atlas = object.value(QLatin1String("image")).toString(); + Q_ASSERT(!atlas.isEmpty()); + + const int cursorsPerRow = object.value(QLatin1String("cursorsPerRow")).toDouble(); + Q_ASSERT(cursorsPerRow); + m_cursorAtlas.cursorsPerRow = cursorsPerRow; + + const QJsonArray hotSpots = object.value(QLatin1String("hotSpots")).toArray(); + Q_ASSERT(hotSpots.count() == Qt::LastCursor + 1); + for (int i = 0; i < hotSpots.count(); i++) { + QPoint hotSpot(hotSpots[i].toArray()[0].toDouble(), hotSpots[i].toArray()[1].toDouble()); + m_cursorAtlas.hotSpots << hotSpot; + } + + QImage image = QImage(atlas).convertToFormat(QImage::Format_ARGB32); + m_cursorAtlas.cursorWidth = image.width() / m_cursorAtlas.cursorsPerRow; + m_cursorAtlas.cursorHeight = image.height() / ((Qt::LastCursor + cursorsPerRow) / cursorsPerRow); + m_cursorAtlas.width = image.width(); + m_cursorAtlas.height = image.height(); + m_cursorAtlas.image = image; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h new file mode 100644 index 0000000000..4b07000c35 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmscursor.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** 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 QEGLFSKMSCURSOR_H +#define QEGLFSKMSCURSOR_H + +#include <qpa/qplatformcursor.h> +#include <QtCore/QList> +#include <QtGui/QImage> + +#include <gbm.h> + +QT_BEGIN_NAMESPACE + +class QEglFSKmsScreen; + +class QEglFSKmsCursor : public QPlatformCursor +{ + Q_OBJECT + +public: + QEglFSKmsCursor(QEglFSKmsScreen *screen); + ~QEglFSKmsCursor(); + + // input methods + void pointerEvent(const QMouseEvent & event) Q_DECL_OVERRIDE; +#ifndef QT_NO_CURSOR + void changeCursor(QCursor * windowCursor, QWindow * window) Q_DECL_OVERRIDE; +#endif + QPoint pos() const Q_DECL_OVERRIDE; + void setPos(const QPoint &pos) Q_DECL_OVERRIDE; + +private: + void initCursorAtlas(); + + QEglFSKmsScreen *m_screen; + QSize m_cursorSize; + gbm_bo *m_bo; + QPoint m_pos; + QPlatformCursorImage m_cursorImage; + bool m_visible; + + // cursor atlas information + struct CursorAtlas { + CursorAtlas() : cursorsPerRow(0), cursorWidth(0), cursorHeight(0) { } + int cursorsPerRow; + int width, height; // width and height of the atlas + int cursorWidth, cursorHeight; // width and height of cursors inside the atlas + QList<QPoint> hotSpots; + QImage image; + } m_cursorAtlas; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp new file mode 100644 index 0000000000..d8f0f01aff --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.cpp @@ -0,0 +1,408 @@ +/**************************************************************************** +** +** 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 "qeglfskmsdevice.h" +#include "qeglfskmsscreen.h" + +#include "qeglfsintegration.h" + +#include <QtCore/QLoggingCategory> +#include <QtCore/private/qcore_unix_p.h> +#include <QtGui/private/qguiapplication_p.h> + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +enum OutputConfiguration { + OutputConfigOff, + OutputConfigPreferred, + OutputConfigCurrent, + OutputConfigMode, + OutputConfigModeline +}; + +int QEglFSKmsDevice::crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector) +{ + for (int i = 0; i < connector->count_encoders; i++) { + drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->encoders[i]); + if (!encoder) { + qWarning("Failed to get encoder"); + continue; + } + + quint32 possibleCrtcs = encoder->possible_crtcs; + drmModeFreeEncoder(encoder); + + for (int j = 0; j < resources->count_crtcs; j++) { + bool isPossible = possibleCrtcs & (1 << j); + bool isAvailable = !(m_crtc_allocator & 1 << resources->crtcs[j]); + + if (isPossible && isAvailable) + return j; + } + } + + return -1; +} + +static const char * const connector_type_names[] = { + "None", + "VGA", + "DVI", + "DVI", + "DVI", + "Composite", + "TV", + "LVDS", + "CTV", + "DIN", + "DP", + "HDMI", + "HDMI", + "TV", + "eDP", +}; + +static QString nameForConnector(const drmModeConnectorPtr connector) +{ + QString connectorName = "UNKNOWN"; + + if (connector->connector_type < ARRAY_LENGTH(connector_type_names)) + connectorName = connector_type_names[connector->connector_type]; + + connectorName += QString::number(connector->connector_type_id); + + return connectorName; +} + +static bool parseModeline(const QString &s, drmModeModeInfoPtr mode) +{ + char hsync[16]; + char vsync[16]; + float fclock; + + mode->type = DRM_MODE_TYPE_USERDEF; + mode->hskew = 0; + mode->vscan = 0; + mode->vrefresh = 0; + mode->flags = 0; + + if (sscanf(qPrintable(s), "%f %hd %hd %hd %hd %hd %hd %hd %hd %15s %15s", + &fclock, + &mode->hdisplay, + &mode->hsync_start, + &mode->hsync_end, + &mode->htotal, + &mode->vdisplay, + &mode->vsync_start, + &mode->vsync_end, + &mode->vtotal, hsync, vsync) != 11) + return false; + + mode->clock = fclock * 1000; + + if (strcmp(hsync, "+hsync") == 0) + mode->flags |= DRM_MODE_FLAG_PHSYNC; + else if (strcmp(hsync, "-hsync") == 0) + mode->flags |= DRM_MODE_FLAG_NHSYNC; + else + return false; + + if (strcmp(vsync, "+vsync") == 0) + mode->flags |= DRM_MODE_FLAG_PVSYNC; + else if (strcmp(vsync, "-vsync") == 0) + mode->flags |= DRM_MODE_FLAG_NVSYNC; + else + return false; + + return true; +} + +QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos) +{ + const QString connectorName = nameForConnector(connector); + + const int crtc = crtcForConnector(resources, connector); + if (crtc < 0) { + qWarning() << "No usable crtc/encoder pair for connector" << connectorName; + return Q_NULLPTR; + } + + OutputConfiguration configuration; + QSize configurationSize; + drmModeModeInfo configurationModeline; + + const QString mode = m_integration->outputSettings().value(connectorName).value("mode", "preferred").toString().toLower(); + if (mode == "off") { + configuration = OutputConfigOff; + } else if (mode == "preferred") { + configuration = OutputConfigPreferred; + } else if (mode == "current") { + configuration = OutputConfigCurrent; + } else if (sscanf(qPrintable(mode), "%dx%d", &configurationSize.rwidth(), &configurationSize.rheight()) == 2) { + configuration = OutputConfigMode; + } else if (parseModeline(mode, &configurationModeline)) { + configuration = OutputConfigModeline; + } else { + qWarning("Invalid mode \"%s\" for output %s", qPrintable(mode), qPrintable(connectorName)); + configuration = OutputConfigPreferred; + } + + const uint32_t crtc_id = resources->crtcs[crtc]; + + if (configuration == OutputConfigOff) { + qCDebug(qLcEglfsKmsDebug) << "Turning off output" << connectorName; + drmModeSetCrtc(m_dri_fd, crtc_id, 0, 0, 0, 0, 0, Q_NULLPTR); + return Q_NULLPTR; + } + + // Get the current mode on the current crtc + drmModeModeInfo crtc_mode; + memset(&crtc_mode, 0, sizeof crtc_mode); + if (drmModeEncoderPtr encoder = drmModeGetEncoder(m_dri_fd, connector->connector_id)) { + drmModeCrtcPtr crtc = drmModeGetCrtc(m_dri_fd, encoder->crtc_id); + drmModeFreeEncoder(encoder); + + if (!crtc) + return Q_NULLPTR; + + if (crtc->mode_valid) + crtc_mode = crtc->mode; + + drmModeFreeCrtc(crtc); + } + + QList<drmModeModeInfo> modes; + qCDebug(qLcEglfsKmsDebug) << connectorName << "mode count:" << connector->count_modes; + for (int i = 0; i < connector->count_modes; i++) { + const drmModeModeInfo &mode = connector->modes[i]; + qCDebug(qLcEglfsKmsDebug) << "mode" << i << mode.hdisplay << "x" << mode.vdisplay + << "@" << mode.vrefresh << "hz"; + modes << connector->modes[i]; + } + + int preferred = -1; + int current = -1; + int configured = -1; + int best = -1; + + for (int i = modes.size() - 1; i >= 0; i--) { + const drmModeModeInfo &m = modes.at(i); + + if (configuration == OutputConfigMode && + m.hdisplay == configurationSize.width() && + m.vdisplay == configurationSize.height()) { + configured = i; + } + + if (!memcmp(&crtc_mode, &m, sizeof m)) + current = i; + + if (m.type & DRM_MODE_TYPE_PREFERRED) + preferred = i; + + best = i; + } + + if (configuration == OutputConfigModeline) { + modes << configurationModeline; + configured = modes.size() - 1; + } + + if (current < 0 && crtc_mode.clock != 0) { + modes << crtc_mode; + current = mode.size() - 1; + } + + if (configuration == OutputConfigCurrent) + configured = current; + + int selected_mode = -1; + + if (configured >= 0) + selected_mode = configured; + else if (preferred >= 0) + selected_mode = preferred; + else if (current >= 0) + selected_mode = current; + else if (best >= 0) + selected_mode = best; + + if (selected_mode < 0) { + qWarning() << "No modes available for output" << connectorName; + return Q_NULLPTR; + } else { + int width = modes[selected_mode].hdisplay; + int height = modes[selected_mode].vdisplay; + int refresh = modes[selected_mode].vrefresh; + qCDebug(qLcEglfsKmsDebug) << "Selected mode" << selected_mode << ":" << width << "x" << height + << "@" << refresh << "hz for output" << connectorName; + } + + QEglFSKmsOutput output = { + connectorName, + connector->connector_id, + crtc_id, + QSizeF(connector->mmWidth, connector->mmHeight), + selected_mode, + false, + drmModeGetCrtc(m_dri_fd, crtc_id), + modes + }; + + m_crtc_allocator |= (1 << output.crtc_id); + m_connector_allocator |= (1 << output.connector_id); + + return new QEglFSKmsScreen(m_integration, this, output, pos); +} + +void QEglFSKmsDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data) +{ + Q_UNUSED(fd); + Q_UNUSED(sequence); + Q_UNUSED(tv_sec); + Q_UNUSED(tv_usec); + + QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(user_data); + screen->flipFinished(); +} + +QEglFSKmsDevice::QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path) + : m_integration(integration) + , m_path(path) + , m_dri_fd(-1) + , m_gbm_device(Q_NULLPTR) + , m_crtc_allocator(0) + , m_connector_allocator(0) +{ +} + +bool QEglFSKmsDevice::open() +{ + Q_ASSERT(m_dri_fd == -1); + Q_ASSERT(m_gbm_device == Q_NULLPTR); + + qCDebug(qLcEglfsKmsDebug) << "Opening device" << m_path; + m_dri_fd = qt_safe_open(m_path.toLocal8Bit().constData(), O_RDWR | O_CLOEXEC); + if (m_dri_fd == -1) { + qErrnoWarning("Could not open DRM device %s", qPrintable(m_path)); + return false; + } + + qCDebug(qLcEglfsKmsDebug) << "Creating GBM device for file descriptor" << m_dri_fd + << "obtained from" << m_path; + m_gbm_device = gbm_create_device(m_dri_fd); + if (!m_gbm_device) { + qErrnoWarning("Could not create GBM device"); + qt_safe_close(m_dri_fd); + m_dri_fd = -1; + return false; + } + + return true; +} + +void QEglFSKmsDevice::close() +{ + if (m_gbm_device) { + gbm_device_destroy(m_gbm_device); + m_gbm_device = Q_NULLPTR; + } + + if (m_dri_fd != -1) { + qt_safe_close(m_dri_fd); + m_dri_fd = -1; + } +} + +void QEglFSKmsDevice::createScreens() +{ + drmModeResPtr resources = drmModeGetResources(m_dri_fd); + if (!resources) { + qWarning("drmModeGetResources failed"); + return; + } + + QPoint pos(0, 0); + QEglFSIntegration *integration = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration()); + + for (int i = 0; i < resources->count_connectors; i++) { + drmModeConnectorPtr connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]); + if (!connector) + continue; + + QEglFSKmsScreen *screen = screenForConnector(resources, connector, pos); + if (screen) { + integration->addScreen(screen); + pos.rx() += screen->geometry().width(); + } + + drmModeFreeConnector(connector); + } + + drmModeFreeResources(resources); +} + +gbm_device *QEglFSKmsDevice::device() const +{ + return m_gbm_device; +} + +int QEglFSKmsDevice::fd() const +{ + return m_dri_fd; +} + +void QEglFSKmsDevice::handleDrmEvent() +{ + drmEventContext drmEvent = { + DRM_EVENT_CONTEXT_VERSION, + Q_NULLPTR, // vblank handler + pageFlipHandler // page flip handler + }; + + drmHandleEvent(m_dri_fd, &drmEvent); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h new file mode 100644 index 0000000000..ebe6f62f5b --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsdevice.h @@ -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$ +** +****************************************************************************/ + +#ifndef QEGLFSKMSDEVICE_H +#define QEGLFSKMSDEVICE_H + +#include "qeglfskmsintegration.h" + +#include <xf86drm.h> +#include <xf86drmMode.h> +#include <gbm.h> + +QT_BEGIN_NAMESPACE + +class QEglFSKmsScreen; + +class QEglFSKmsDevice +{ +public: + QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path); + + bool open(); + void close(); + + void createScreens(); + + gbm_device *device() const; + int fd() const; + + void handleDrmEvent(); + +private: + Q_DISABLE_COPY(QEglFSKmsDevice) + + QEglFSKmsIntegration *m_integration; + QString m_path; + int m_dri_fd; + gbm_device *m_gbm_device; + + quint32 m_crtc_allocator; + quint32 m_connector_allocator; + + int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector); + QEglFSKmsScreen *screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos); + + static void pageFlipHandler(int fd, + unsigned int sequence, + unsigned int tv_sec, + unsigned int tv_usec, + void *user_data); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp new file mode 100644 index 0000000000..f5aba0742a --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp @@ -0,0 +1,268 @@ +/**************************************************************************** +** +** 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 "qeglfskmsintegration.h" +#include "qeglfskmsdevice.h" +#include "qeglfskmsscreen.h" +#include "qeglfskmscursor.h" + +#include <QtPlatformSupport/private/qeglplatformcursor_p.h> +#include <QtPlatformSupport/private/qdevicediscovery_p.h> +#include <QtCore/QLoggingCategory> +#include <QtCore/QJsonDocument> +#include <QtCore/QJsonObject> +#include <QtCore/QJsonArray> +#include <QtGui/qpa/qplatformwindow.h> +#include <QtGui/qpa/qplatformcursor.h> +#include <QtGui/QScreen> + +#include <xf86drm.h> +#include <xf86drmMode.h> +#include <gbm.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms") + +QMutex QEglFSKmsScreen::m_waitForFlipMutex; + +QEglFSKmsIntegration::QEglFSKmsIntegration() + : m_device(Q_NULLPTR) + , m_hwCursor(true) + , m_pbuffers(false) +{} + +void QEglFSKmsIntegration::platformInit() +{ + loadConfig(); + + if (!m_devicePath.isEmpty()) { + qCDebug(qLcEglfsKmsDebug) << "Using DRM device" << m_devicePath << "specified in config file"; + } else { + + QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask); + QStringList devices = d->scanConnectedDevices(); + qCDebug(qLcEglfsKmsDebug) << "Found the following video devices:" << devices; + d->deleteLater(); + + if (devices.isEmpty()) + qFatal("Could not find DRM device!"); + + m_devicePath = devices.first(); + qCDebug(qLcEglfsKmsDebug) << "Using" << m_devicePath; + } + + m_device = new QEglFSKmsDevice(this, m_devicePath); + if (!m_device->open()) + qFatal("Could not open device %s - aborting!", qPrintable(m_devicePath)); +} + +void QEglFSKmsIntegration::platformDestroy() +{ + m_device->close(); + delete m_device; + m_device = Q_NULLPTR; +} + +EGLNativeDisplayType QEglFSKmsIntegration::platformDisplay() const +{ + Q_ASSERT(m_device); + return reinterpret_cast<EGLNativeDisplayType>(m_device->device()); +} + +bool QEglFSKmsIntegration::usesDefaultScreen() +{ + return false; +} + +void QEglFSKmsIntegration::screenInit() +{ + m_device->createScreens(); +} + +QSurfaceFormat QEglFSKmsIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +{ + QSurfaceFormat format(inputFormat); + format.setRenderableType(QSurfaceFormat::OpenGLES); + format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); + format.setRedBufferSize(8); + format.setGreenBufferSize(8); + format.setBlueBufferSize(8); + return format; +} + +EGLNativeWindowType QEglFSKmsIntegration::createNativeWindow(QPlatformWindow *platformWindow, + const QSize &size, + const QSurfaceFormat &format) +{ + Q_UNUSED(size); + Q_UNUSED(format); + + QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(platformWindow->screen()); + if (screen->surface()) { + qWarning("Only single window per screen supported!"); + return 0; + } + + return reinterpret_cast<EGLNativeWindowType>(screen->createSurface()); +} + +EGLNativeWindowType QEglFSKmsIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format) +{ + Q_UNUSED(format); + Q_ASSERT(m_device); + + qCDebug(qLcEglfsKmsDebug) << "Creating native off screen window"; + gbm_surface *surface = gbm_surface_create(m_device->device(), + 1, 1, + GBM_FORMAT_XRGB8888, + GBM_BO_USE_RENDERING); + + return reinterpret_cast<EGLNativeWindowType>(surface); +} + +void QEglFSKmsIntegration::destroyNativeWindow(EGLNativeWindowType window) +{ + gbm_surface *surface = reinterpret_cast<gbm_surface *>(window); + gbm_surface_destroy(surface); +} + +bool QEglFSKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case QPlatformIntegration::ThreadedPixmaps: + case QPlatformIntegration::OpenGL: + case QPlatformIntegration::ThreadedOpenGL: + return true; + default: + return false; + } +} + +QPlatformCursor *QEglFSKmsIntegration::createCursor(QPlatformScreen *screen) const +{ + if (m_hwCursor) + return Q_NULLPTR; + else + return new QEGLPlatformCursor(screen); +} + +void QEglFSKmsIntegration::waitForVSync(QPlatformSurface *surface) const +{ + QWindow *window = static_cast<QWindow *>(surface->surface()); + QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(window->screen()->handle()); + + screen->waitForFlip(); +} + +void QEglFSKmsIntegration::presentBuffer(QPlatformSurface *surface) +{ + QWindow *window = static_cast<QWindow *>(surface->surface()); + QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(window->screen()->handle()); + + screen->flip(); +} + +bool QEglFSKmsIntegration::supportsPBuffers() const +{ + return m_pbuffers; +} + +bool QEglFSKmsIntegration::hwCursor() const +{ + return m_hwCursor; +} + +QMap<QString, QVariantMap> QEglFSKmsIntegration::outputSettings() const +{ + return m_outputSettings; +} + +void QEglFSKmsIntegration::loadConfig() +{ + static QByteArray json = qgetenv("QT_QPA_EGLFS_KMS_CONFIG"); + if (json.isEmpty()) + return; + + qCDebug(qLcEglfsKmsDebug) << "Loading KMS setup from" << json; + + QFile file(QString::fromUtf8(json)); + if (!file.open(QFile::ReadOnly)) { + qCDebug(qLcEglfsKmsDebug) << "Could not open config file" + << json << "for reading"; + return; + } + + QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + if (!doc.isObject()) { + qCDebug(qLcEglfsKmsDebug) << "Invalid config file" << json + << "- no top-level JSON object"; + return; + } + + QJsonObject object = doc.object(); + + m_hwCursor = object.value("hwcursor").toBool(m_hwCursor); + m_pbuffers = object.value("pbuffers").toBool(m_pbuffers); + m_devicePath = object.value("device").toString(); + + QJsonArray outputs = object.value("outputs").toArray(); + for (int i = 0; i < outputs.size(); i++) { + QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap(); + + if (outputSettings.contains("name")) { + QString name = outputSettings.value("name").toString(); + + if (m_outputSettings.contains(name)) { + qCDebug(qLcEglfsKmsDebug) << "Output" << name << "configured multiple times!"; + } + + m_outputSettings.insert(name, outputSettings); + } + } + + qCDebug(qLcEglfsKmsDebug) << "Configuration:\n" + << "\thwcursor:" << m_hwCursor << "\n" + << "\tpbuffers:" << m_pbuffers << "\n" + << "\toutputs:" << m_outputSettings; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h new file mode 100644 index 0000000000..434f337176 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** 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 QEGLFSKMSINTEGRATION_H +#define QEGLFSKMSINTEGRATION_H + +#include "qeglfsdeviceintegration.h" +#include <QtCore/QMap> +#include <QtCore/QVariant> + +QT_BEGIN_NAMESPACE + +class QEglFSKmsDevice; + +class QEglFSKmsIntegration : public QEGLDeviceIntegration +{ +public: + QEglFSKmsIntegration(); + + void platformInit() Q_DECL_OVERRIDE; + void platformDestroy() Q_DECL_OVERRIDE; + EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; + bool usesDefaultScreen() Q_DECL_OVERRIDE; + void screenInit() Q_DECL_OVERRIDE; + QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE; + EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, + const QSize &size, + const QSurfaceFormat &format) Q_DECL_OVERRIDE; + EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format) Q_DECL_OVERRIDE; + void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; + QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE; + void waitForVSync(QPlatformSurface *surface) const Q_DECL_OVERRIDE; + void presentBuffer(QPlatformSurface *surface) Q_DECL_OVERRIDE; + bool supportsPBuffers() const Q_DECL_OVERRIDE; + + bool hwCursor() const; + QMap<QString, QVariantMap> outputSettings() const; + +private: + void loadConfig(); + + QEglFSKmsDevice *m_device; + bool m_hwCursor; + bool m_pbuffers; + QString m_devicePath; + QMap<QString, QVariantMap> m_outputSettings; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsmain.cpp new file mode 100644 index 0000000000..8d75ff797e --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsmain.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the qmake spec 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 "qeglfsdeviceintegration.h" +#include "qeglfskmsintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSKmsIntegrationPlugin : public QEGLDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_kms.json") + +public: + QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsIntegration; } +}; + +QT_END_NAMESPACE + +#include "qeglfskmsmain.moc" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp new file mode 100644 index 0000000000..0a4d5fe2bc --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp @@ -0,0 +1,286 @@ +/**************************************************************************** +** +** 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 "qeglfskmsscreen.h" +#include "qeglfskmsdevice.h" +#include "qeglfskmscursor.h" + +#include <QtCore/QLoggingCategory> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) + +void QEglFSKmsScreen::bufferDestroyedHandler(gbm_bo *bo, void *data) +{ + FrameBuffer *fb = static_cast<FrameBuffer *>(data); + + if (fb->fb) { + gbm_device *device = gbm_bo_get_device(bo); + drmModeRmFB(gbm_device_get_fd(device), fb->fb); + } + + delete fb; +} + +QEglFSKmsScreen::FrameBuffer *QEglFSKmsScreen::framebufferForBufferObject(gbm_bo *bo) +{ + { + FrameBuffer *fb = static_cast<FrameBuffer *>(gbm_bo_get_user_data(bo)); + if (fb) + return fb; + } + + uint32_t width = gbm_bo_get_width(bo); + uint32_t height = gbm_bo_get_height(bo); + uint32_t stride = gbm_bo_get_stride(bo); + uint32_t handle = gbm_bo_get_handle(bo).u32; + + QScopedPointer<FrameBuffer> fb(new FrameBuffer); + + int ret = drmModeAddFB(m_device->fd(), width, height, 24, 32, + stride, handle, &fb->fb); + + if (ret) { + qWarning("Failed to create KMS FB!"); + return Q_NULLPTR; + } + + gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler); + return fb.take(); +} + +QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position) + : QEglFSScreen(eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(device->device()))) + , m_integration(integration) + , m_device(device) + , m_gbm_surface(Q_NULLPTR) + , m_gbm_bo_current(Q_NULLPTR) + , m_gbm_bo_next(Q_NULLPTR) + , m_output(output) + , m_pos(position) + , m_cursor(Q_NULLPTR) +{ +} + +QEglFSKmsScreen::~QEglFSKmsScreen() +{ + restoreMode(); +} + +QRect QEglFSKmsScreen::geometry() const +{ + const int mode = m_output.mode; + return QRect(m_pos.x(), m_pos.y(), + m_output.modes[mode].hdisplay, + m_output.modes[mode].vdisplay); +} + +int QEglFSKmsScreen::depth() const +{ + return 32; +} + +QImage::Format QEglFSKmsScreen::format() const +{ + return QImage::Format_RGB32; +} + +QSizeF QEglFSKmsScreen::physicalSize() const +{ + return m_output.physical_size; +} + +QDpi QEglFSKmsScreen::logicalDpi() const +{ + QSizeF ps = physicalSize(); + QSize s = geometry().size(); + + if (ps.isValid() && s.isValid()) + return QDpi(25.4 * s.width() / ps.width(), + 25.4 * s.height() / ps.height()); + else + return QDpi(100, 100); +} + +Qt::ScreenOrientation QEglFSKmsScreen::nativeOrientation() const +{ + return Qt::PrimaryOrientation; +} + +Qt::ScreenOrientation QEglFSKmsScreen::orientation() const +{ + return Qt::PrimaryOrientation; +} + +QString QEglFSKmsScreen::name() const +{ + return m_output.name; +} + +QPlatformCursor *QEglFSKmsScreen::cursor() const +{ + if (m_integration->hwCursor()) { + if (m_cursor.isNull()) { + QEglFSKmsScreen *that = const_cast<QEglFSKmsScreen *>(this); + that->m_cursor.reset(new QEglFSKmsCursor(that)); + } + + return m_cursor.data(); + } else { + return QEglFSScreen::cursor(); + } +} + +gbm_surface *QEglFSKmsScreen::createSurface() +{ + if (!m_gbm_surface) { + qCDebug(qLcEglfsKmsDebug) << "Creating window for screen" << name(); + m_gbm_surface = gbm_surface_create(m_device->device(), + geometry().width(), + geometry().height(), + GBM_FORMAT_XRGB8888, + GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); + } + return m_gbm_surface; +} + +void QEglFSKmsScreen::destroySurface() +{ + if (m_gbm_bo_current) { + gbm_bo_destroy(m_gbm_bo_current); + m_gbm_bo_current = Q_NULLPTR; + } + + if (m_gbm_bo_next) { + gbm_bo_destroy(m_gbm_bo_next); + m_gbm_bo_next = Q_NULLPTR; + } + + if (m_gbm_surface) { + gbm_surface_destroy(m_gbm_surface); + m_gbm_surface = Q_NULLPTR; + } +} + +void QEglFSKmsScreen::waitForFlip() +{ + // Don't lock the mutex unless we actually need to + if (!m_gbm_bo_next) + return; + + QMutexLocker lock(&m_waitForFlipMutex); + while (m_gbm_bo_next) + m_device->handleDrmEvent(); +} + +void QEglFSKmsScreen::flip() +{ + if (!m_gbm_surface) { + qWarning("Cannot sync before platform init!"); + return; + } + + m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface); + if (!m_gbm_bo_next) { + qWarning("Could not lock GBM surface front buffer!"); + return; + } + + FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next); + + if (!m_output.mode_set) { + int ret = drmModeSetCrtc(m_device->fd(), + m_output.crtc_id, + fb->fb, + 0, 0, + &m_output.connector_id, 1, + &m_output.modes[m_output.mode]); + + if (ret) + qErrnoWarning("Could not set DRM mode!"); + else + m_output.mode_set = true; + } + + int ret = drmModePageFlip(m_device->fd(), + m_output.crtc_id, + fb->fb, + DRM_MODE_PAGE_FLIP_EVENT, + this); + if (ret) { + qErrnoWarning("Could not queue DRM page flip!"); + gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next); + m_gbm_bo_next = Q_NULLPTR; + } +} + +void QEglFSKmsScreen::flipFinished() +{ + if (m_gbm_bo_current) + gbm_surface_release_buffer(m_gbm_surface, + m_gbm_bo_current); + + m_gbm_bo_current = m_gbm_bo_next; + m_gbm_bo_next = Q_NULLPTR; +} + +void QEglFSKmsScreen::restoreMode() +{ + if (m_output.mode_set && m_output.saved_crtc) { + drmModeSetCrtc(m_device->fd(), + m_output.saved_crtc->crtc_id, + m_output.saved_crtc->buffer_id, + 0, 0, + &m_output.connector_id, 1, + &m_output.saved_crtc->mode); + + drmModeFreeCrtc(m_output.saved_crtc); + m_output.saved_crtc = Q_NULLPTR; + + m_output.mode_set = false; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h new file mode 100644 index 0000000000..e4d5ee9e0a --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** 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 QEGLFSKMSSCREEN_H +#define QEGLFSKMSSCREEN_H + +#include "qeglfskmsintegration.h" +#include "qeglfsscreen.h" +#include <QtCore/QList> +#include <QtCore/QMutex> + +#include <xf86drm.h> +#include <xf86drmMode.h> +#include <gbm.h> + +QT_BEGIN_NAMESPACE + +class QEglFSKmsDevice; +class QEglFSKmsCursor; + +struct QEglFSKmsOutput +{ + QString name; + uint32_t connector_id; + uint32_t crtc_id; + QSizeF physical_size; + int mode; // index of selected mode in list below + bool mode_set; + drmModeCrtcPtr saved_crtc; + QList<drmModeModeInfo> modes; +}; + +class QEglFSKmsScreen : public QEglFSScreen +{ +public: + QEglFSKmsScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position); + ~QEglFSKmsScreen(); + + QRect geometry() const Q_DECL_OVERRIDE; + int depth() const Q_DECL_OVERRIDE; + QImage::Format format() const Q_DECL_OVERRIDE; + + QSizeF physicalSize() const Q_DECL_OVERRIDE; + QDpi logicalDpi() const Q_DECL_OVERRIDE; + Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE; + Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE; + + QString name() const Q_DECL_OVERRIDE; + + QPlatformCursor *cursor() const Q_DECL_OVERRIDE; + + QEglFSKmsDevice *device() const { return m_device; } + + gbm_surface *surface() const { return m_gbm_surface; } + gbm_surface *createSurface(); + void destroySurface(); + + void waitForFlip(); + void flip(); + void flipFinished(); + + QEglFSKmsOutput &output() { return m_output; } + void restoreMode(); + +private: + QEglFSKmsIntegration *m_integration; + QEglFSKmsDevice *m_device; + gbm_surface *m_gbm_surface; + + gbm_bo *m_gbm_bo_current; + gbm_bo *m_gbm_bo_next; + + QEglFSKmsOutput m_output; + QPoint m_pos; + QScopedPointer<QEglFSKmsCursor> m_cursor; + + struct FrameBuffer { + FrameBuffer() : fb(0) {} + uint32_t fb; + }; + static void bufferDestroyedHandler(gbm_bo *bo, void *data); + FrameBuffer *framebufferForBufferObject(gbm_bo *bo); + + static QMutex m_waitForFlipMutex; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.json new file mode 100644 index 0000000000..846252789a --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs_x11" ] +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro new file mode 100644 index 0000000000..a1d08248ff --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro @@ -0,0 +1,24 @@ +TARGET = qeglfs-x11-integration + +PLUGIN_CLASS_NAME=QEglFSX11IntegrationPlugin +PLUGIN_TYPE=egldeviceintegrations + +load(qt_plugin) + +QT += core-private gui-private platformsupport-private eglfs_device_lib-private + +# Avoid X11 header collision +DEFINES += MESA_EGL_NO_X11_HEADERS + +INCLUDEPATH += $$PWD/../.. + +CONFIG += egl +LIBS += -lX11 -lX11-xcb -lxcb +QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF + +SOURCES += $$PWD/qeglfsx11main.cpp \ + $$PWD/qeglfsx11integration.cpp + +HEADERS += $$PWD/qeglfsx11integration.h + +OTHER_FILES += $$PWD/eglfs_x11.json diff --git a/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp index b16857297c..e41c007df9 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** -** This file is part of the qmake spec of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage @@ -31,75 +31,28 @@ ** ****************************************************************************/ -#include "qeglfshooks.h" - -#include <qpa/qwindowsysteminterface.h> -#include <qpa/qplatformwindow.h> +#include "qeglfsx11integration.h" #include <QThread> #include <X11/Xlib.h> #include <X11/Xlib-xcb.h> -#include <xcb/xcb.h> -QT_BEGIN_NAMESPACE +/* Make no mistake: This is not a replacement for the xcb platform plugin. + This here is barely an extremely useful tool for developing eglfs itself because + it allows to do so without any requirements for devices or drivers. */ -class QEglFSX11Hooks; +QT_BEGIN_NAMESPACE class EventReader : public QThread { public: - EventReader(QEglFSX11Hooks *hooks) - : m_hooks(hooks) { } + EventReader(QEglFSX11Integration *integration) + : m_integration(integration) { } void run(); private: - QEglFSX11Hooks *m_hooks; -}; - -namespace Atoms { - enum { - _NET_WM_NAME = 0, - UTF8_STRING, - WM_PROTOCOLS, - WM_DELETE_WINDOW, - _NET_WM_STATE, - _NET_WM_STATE_FULLSCREEN, - - N_ATOMS - }; -} - -class QEglFSX11Hooks : public QEglFSHooks -{ -public: - QEglFSX11Hooks() : m_connection(0), m_window(0), m_eventReader(0) {} - - virtual void platformInit(); - virtual void platformDestroy(); - virtual EGLNativeDisplayType platformDisplay() const; - virtual QSize screenSize() const; - virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *window, - const QSize &size, - const QSurfaceFormat &format); - virtual void destroyNativeWindow(EGLNativeWindowType window); - virtual bool hasCapability(QPlatformIntegration::Capability cap) const; - - xcb_connection_t *connection() { return m_connection; } - const xcb_atom_t *atoms() const { return m_atoms; } - QPlatformWindow *platformWindow() { return m_platformWindow; } - -private: - void sendConnectionEvent(xcb_atom_t a); - - Display *m_display; - xcb_connection_t *m_connection; - xcb_atom_t m_atoms[Atoms::N_ATOMS]; - xcb_window_t m_window; - EventReader *m_eventReader; - xcb_window_t m_connectionEventListener; - QPlatformWindow *m_platformWindow; - mutable QSize m_screenSize; + QEglFSX11Integration *m_integration; }; QAtomicInt running; @@ -156,7 +109,7 @@ void EventReader::run() Qt::MouseButtons buttons; xcb_generic_event_t *event; - while (running.load() && (event = xcb_wait_for_event(m_hooks->connection()))) { + while (running.load() && (event = xcb_wait_for_event(m_integration->connection()))) { uint response_type = event->response_type & ~0x80; switch (response_type) { case XCB_BUTTON_PRESS: { @@ -183,11 +136,11 @@ void EventReader::run() } case XCB_CLIENT_MESSAGE: { xcb_client_message_event_t *client = (xcb_client_message_event_t *) event; - const xcb_atom_t *atoms = m_hooks->atoms(); + const xcb_atom_t *atoms = m_integration->atoms(); if (client->format == 32 && client->type == atoms[Atoms::WM_PROTOCOLS] && client->data.data32[0] == atoms[Atoms::WM_DELETE_WINDOW]) { - QWindow *window = m_hooks->platformWindow() ? m_hooks->platformWindow()->window() : 0; + QWindow *window = m_integration->platformWindow() ? m_integration->platformWindow()->window() : 0; if (window) QWindowSystemInterface::handleCloseEvent(window); } @@ -199,7 +152,7 @@ void EventReader::run() } } -void QEglFSX11Hooks::sendConnectionEvent(xcb_atom_t a) +void QEglFSX11Integration::sendConnectionEvent(xcb_atom_t a) { xcb_client_message_event_t event; memset(&event, 0, sizeof(event)); @@ -214,14 +167,16 @@ void QEglFSX11Hooks::sendConnectionEvent(xcb_atom_t a) xcb_flush(m_connection); } -void QEglFSX11Hooks::platformInit() +#define DISPLAY ((Display *) m_display) + +void QEglFSX11Integration::platformInit() { m_display = XOpenDisplay(0); if (!m_display) qFatal("Could not open display"); - XSetEventQueueOwner(m_display, XCBOwnsEventQueue); - m_connection = XGetXCBConnection(m_display); + XSetEventQueueOwner(DISPLAY, XCBOwnsEventQueue); + m_connection = XGetXCBConnection(DISPLAY); running.ref(); @@ -237,7 +192,7 @@ void QEglFSX11Hooks::platformInit() m_eventReader->start(); } -void QEglFSX11Hooks::platformDestroy() +void QEglFSX11Integration::platformDestroy() { running.deref(); @@ -247,31 +202,32 @@ void QEglFSX11Hooks::platformDestroy() delete m_eventReader; m_eventReader = 0; - XCloseDisplay(m_display); + XCloseDisplay(DISPLAY); m_display = 0; m_connection = 0; } -EGLNativeDisplayType QEglFSX11Hooks::platformDisplay() const +EGLNativeDisplayType QEglFSX11Integration::platformDisplay() const { - return m_display; + return DISPLAY; } -QSize QEglFSX11Hooks::screenSize() const +QSize QEglFSX11Integration::screenSize() const { if (m_screenSize.isEmpty()) { QList<QByteArray> env = qgetenv("EGLFS_X11_SIZE").split('x'); if (env.length() == 2) { m_screenSize = QSize(env.at(0).toInt(), env.at(1).toInt()); } else { - m_screenSize = QSize(640, 480); - qDebug("EGLFS_X11_SIZE not set, falling back to 640x480"); + XWindowAttributes a; + if (XGetWindowAttributes(DISPLAY, DefaultRootWindow(DISPLAY), &a)) + m_screenSize = QSize(a.width, a.height); } } return m_screenSize; } -EGLNativeWindowType QEglFSX11Hooks::createNativeWindow(QPlatformWindow *platformWindow, +EGLNativeWindowType QEglFSX11Integration::createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format) { @@ -286,8 +242,6 @@ EGLNativeWindowType QEglFSX11Hooks::createNativeWindow(QPlatformWindow *platform XCB_WINDOW_CLASS_INPUT_OUTPUT, it.data->root_visual, 0, 0); - xcb_map_window(m_connection, m_window); - xcb_intern_atom_cookie_t cookies[Atoms::N_ATOMS]; static const char *atomNames[Atoms::N_ATOMS] = { "_NET_WM_NAME", @@ -313,30 +267,26 @@ EGLNativeWindowType QEglFSX11Hooks::createNativeWindow(QPlatformWindow *platform xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window, m_atoms[Atoms::WM_PROTOCOLS], XCB_ATOM_ATOM, 32, 1, &m_atoms[Atoms::WM_DELETE_WINDOW]); - if (qgetenv("EGLFS_X11_FULLSCREEN").toInt()) { - // Go fullscreen. The QScreen and QWindow size is controlled by EGLFS_X11_SIZE regardless, - // this is just the native window. - xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window, - m_atoms[Atoms::_NET_WM_STATE], XCB_ATOM_ATOM, 32, 1, &m_atoms[Atoms::_NET_WM_STATE_FULLSCREEN]); - } + // Go fullscreen. + xcb_change_property(m_connection, XCB_PROP_MODE_REPLACE, m_window, + m_atoms[Atoms::_NET_WM_STATE], XCB_ATOM_ATOM, 32, 1, &m_atoms[Atoms::_NET_WM_STATE_FULLSCREEN]); + + xcb_map_window(m_connection, m_window); xcb_flush(m_connection); return m_window; } -void QEglFSX11Hooks::destroyNativeWindow(EGLNativeWindowType window) +void QEglFSX11Integration::destroyNativeWindow(EGLNativeWindowType window) { xcb_destroy_window(m_connection, window); } -bool QEglFSX11Hooks::hasCapability(QPlatformIntegration::Capability cap) const +bool QEglFSX11Integration::hasCapability(QPlatformIntegration::Capability cap) const { Q_UNUSED(cap); return false; } -static QEglFSX11Hooks eglFSX11Hooks; -QEglFSHooks *platformHooks = &eglFSX11Hooks; - QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h new file mode 100644 index 0000000000..78db504f3b --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11integration.h @@ -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: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 QEGLFSX11INTEGRATION_H +#define QEGLFSX11INTEGRATION_H + +#include "qeglfsdeviceintegration.h" + +#include <qpa/qwindowsysteminterface.h> +#include <qpa/qplatformwindow.h> + +#include <xcb/xcb.h> + +QT_BEGIN_NAMESPACE + +namespace Atoms { + enum { + _NET_WM_NAME = 0, + UTF8_STRING, + WM_PROTOCOLS, + WM_DELETE_WINDOW, + _NET_WM_STATE, + _NET_WM_STATE_FULLSCREEN, + + N_ATOMS + }; +} + +class EventReader; + +class QEglFSX11Integration : public QEGLDeviceIntegration +{ +public: + QEglFSX11Integration() : m_connection(0), m_window(0), m_eventReader(0) {} + + void platformInit() Q_DECL_OVERRIDE; + void platformDestroy() Q_DECL_OVERRIDE; + EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; + QSize screenSize() const Q_DECL_OVERRIDE; + EGLNativeWindowType createNativeWindow(QPlatformWindow *window, + const QSize &size, + const QSurfaceFormat &format) Q_DECL_OVERRIDE; + void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; + + xcb_connection_t *connection() { return m_connection; } + const xcb_atom_t *atoms() const { return m_atoms; } + QPlatformWindow *platformWindow() { return m_platformWindow; } + +private: + void sendConnectionEvent(xcb_atom_t a); + + void *m_display; + xcb_connection_t *m_connection; + xcb_atom_t m_atoms[Atoms::N_ATOMS]; + xcb_window_t m_window; + EventReader *m_eventReader; + xcb_window_t m_connectionEventListener; + QPlatformWindow *m_platformWindow; + mutable QSize m_screenSize; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11main.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11main.cpp new file mode 100644 index 0000000000..2eee03f595 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/qeglfsx11main.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the qmake spec 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 "qeglfsdeviceintegration.h" +#include "qeglfsx11integration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSX11IntegrationPlugin : public QEGLDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_x11.json") + +public: + QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSX11Integration; } +}; + +QT_END_NAMESPACE + +#include "qeglfsx11main.moc" diff --git a/src/plugins/platforms/eglfs/eglfs-plugin.pro b/src/plugins/platforms/eglfs/eglfs-plugin.pro new file mode 100644 index 0000000000..0f493fdc01 --- /dev/null +++ b/src/plugins/platforms/eglfs/eglfs-plugin.pro @@ -0,0 +1,12 @@ +TARGET = qeglfs + +PLUGIN_TYPE = platforms +PLUGIN_CLASS_NAME = QEglFSIntegrationPlugin +!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - +load(qt_plugin) + +QT += platformsupport-private eglfs_device_lib-private + +SOURCES += $$PWD/qeglfsmain.cpp + +OTHER_FILES += $$PWD/eglfs.json diff --git a/src/plugins/platforms/eglfs/eglfs.pri b/src/plugins/platforms/eglfs/eglfs.pri deleted file mode 100644 index 6f463ba7d9..0000000000 --- a/src/plugins/platforms/eglfs/eglfs.pri +++ /dev/null @@ -1,44 +0,0 @@ -QT += core-private gui-private platformsupport-private - -# Avoid X11 header collision -DEFINES += MESA_EGL_NO_X11_HEADERS - -# Uncomment these to enable the X hooks, allowing to test the platform -# plugin in a regular X11 environment (as long as EGL is available). -# EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_x11.cpp -# LIBS += -lX11 -lX11-xcb -lxcb - -# Uncomment these to enable the KMS hooks. -# EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_kms.cpp -# CONFIG += link_pkgconfig -# PKGCONFIG += libdrm gbm - -SOURCES += $$PWD/qeglfsintegration.cpp \ - $$PWD/qeglfswindow.cpp \ - $$PWD/qeglfsscreen.cpp \ - $$PWD/qeglfshooks_stub.cpp \ - $$PWD/qeglfscontext.cpp - -HEADERS += $$PWD/qeglfsintegration.h \ - $$PWD/qeglfswindow.h \ - $$PWD/qeglfsscreen.h \ - $$PWD/qeglfshooks.h \ - $$PWD/qeglfscontext.h - -QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF - -INCLUDEPATH += $$PWD - -!isEmpty(EGLFS_PLATFORM_HOOKS_SOURCES) { - HEADERS += $$EGLFS_PLATFORM_HOOKS_HEADERS - SOURCES += $$EGLFS_PLATFORM_HOOKS_SOURCES - LIBS += $$EGLFS_PLATFORM_HOOKS_LIBS - DEFINES += EGLFS_PLATFORM_HOOKS -} - -CONFIG += egl qpa/genericunixfontdatabase - -RESOURCES += $$PWD/cursor.qrc - -OTHER_FILES += \ - $$PWD/eglfs.json diff --git a/src/plugins/platforms/eglfs/eglfs.pro b/src/plugins/platforms/eglfs/eglfs.pro index 3ebe05b35e..03c96ca1d9 100644 --- a/src/plugins/platforms/eglfs/eglfs.pro +++ b/src/plugins/platforms/eglfs/eglfs.pro @@ -1,10 +1,6 @@ -TARGET = qeglfs +TEMPLATE = subdirs +CONFIG += ordered -PLUGIN_TYPE = platforms -PLUGIN_CLASS_NAME = QEglFSIntegrationPlugin -!equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - -load(qt_plugin) - -SOURCES += $$PWD/main.cpp - -include(eglfs.pri) +SUBDIRS += eglfs_device_lib.pro +SUBDIRS += eglfs-plugin.pro +SUBDIRS += deviceintegration diff --git a/src/plugins/platforms/eglfs/eglfs_device_lib.pro b/src/plugins/platforms/eglfs/eglfs_device_lib.pro new file mode 100644 index 0000000000..d8ce421a69 --- /dev/null +++ b/src/plugins/platforms/eglfs/eglfs_device_lib.pro @@ -0,0 +1,59 @@ +# The device integration plugin base class has to live in a shared library, +# placing it into a static lib like platformsupport is not sufficient since we +# have to keep the QObject magic like qobject_cast working. +# Hence this header-less, private-only module. + +TARGET = QtEglDeviceIntegration +CONFIG += no_module_headers internal_module + +MODULE_INCLUDES = \ + \$\$QT_MODULE_INCLUDE_BASE \ + \$\$QT_MODULE_INCLUDE_BASE/QtQGui +MODULE_PRIVATE_INCLUDES = \ + \$\$QT_MODULE_INCLUDE_BASE/QtGui/$$QT.gui.VERSION \ + \$\$QT_MODULE_INCLUDE_BASE/QtGui/$$QT.gui.VERSION/QtGui + +load(qt_module) + +QT += core-private gui-private platformsupport-private +LIBS += $$QMAKE_LIBS_DYNLOAD + +# Avoid X11 header collision +DEFINES += MESA_EGL_NO_X11_HEADERS + +DEFINES += QT_BUILD_EGL_DEVICE_LIB + +SOURCES += $$PWD/qeglfsintegration.cpp \ + $$PWD/qeglfswindow.cpp \ + $$PWD/qeglfsscreen.cpp \ + $$PWD/qeglfshooks.cpp \ + $$PWD/qeglfscontext.cpp \ + $$PWD/qeglfsoffscreenwindow.cpp \ + $$PWD/qeglfsdeviceintegration.cpp + +HEADERS += $$PWD/qeglfsintegration.h \ + $$PWD/qeglfswindow.h \ + $$PWD/qeglfsscreen.h \ + $$PWD/qeglfshooks.h \ + $$PWD/qeglfscontext.h \ + $$PWD/qeglfsoffscreenwindow.h \ + $$PWD/qeglfsdeviceintegration.h + +QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF + +INCLUDEPATH += $$PWD + +!isEmpty(EGLFS_PLATFORM_HOOKS_SOURCES) { + HEADERS += $$EGLFS_PLATFORM_HOOKS_HEADERS + SOURCES += $$EGLFS_PLATFORM_HOOKS_SOURCES + LIBS += $$EGLFS_PLATFORM_HOOKS_LIBS + DEFINES += EGLFS_PLATFORM_HOOKS +} + +!isEmpty(EGLFS_DEVICE_INTEGRATION) { + DEFINES += EGLFS_PREFERRED_PLUGIN=$$EGLFS_DEVICE_INTEGRATION +} + +CONFIG += egl qpa/genericunixfontdatabase + +RESOURCES += $$PWD/cursor.qrc diff --git a/src/plugins/platforms/eglfs/qeglfscontext.cpp b/src/plugins/platforms/eglfs/qeglfscontext.cpp index 6216fa8575..7054c90521 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -45,7 +45,8 @@ QT_BEGIN_NAMESPACE QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLConfig *config, const QVariant &nativeHandle) - : QEGLPlatformContext(format, share, display, config, nativeHandle) + : QEGLPlatformContext(format, share, display, config, nativeHandle), + m_tempWindow(0) { } @@ -57,17 +58,45 @@ EGLSurface QEglFSContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface return static_cast<QEGLPbuffer *>(surface)->pbuffer(); } +EGLSurface QEglFSContext::createTemporaryOffscreenSurface() +{ + if (qt_egl_device_integration()->supportsPBuffers()) + return QEGLPlatformContext::createTemporaryOffscreenSurface(); + + if (!m_tempWindow) { + m_tempWindow = qt_egl_device_integration()->createNativeOffscreenWindow(format()); + if (!m_tempWindow) { + qWarning("QEglFSContext: Failed to create temporary native window"); + return EGL_NO_SURFACE; + } + } + EGLConfig config = q_configFromGLFormat(eglDisplay(), format()); + return eglCreateWindowSurface(eglDisplay(), config, m_tempWindow, 0); +} + +void QEglFSContext::destroyTemporaryOffscreenSurface(EGLSurface surface) +{ + if (qt_egl_device_integration()->supportsPBuffers()) { + QEGLPlatformContext::destroyTemporaryOffscreenSurface(surface); + } else { + eglDestroySurface(eglDisplay(), surface); + qt_egl_device_integration()->destroyNativeWindow(m_tempWindow); + m_tempWindow = 0; + } +} + void QEglFSContext::swapBuffers(QPlatformSurface *surface) { // draw the cursor if (surface->surface()->surfaceClass() == QSurface::Window) { QPlatformWindow *window = static_cast<QPlatformWindow *>(surface); - if (QEGLPlatformCursor *cursor = static_cast<QEGLPlatformCursor *>(window->screen()->cursor())) + if (QEGLPlatformCursor *cursor = qobject_cast<QEGLPlatformCursor *>(window->screen()->cursor())) cursor->paintOnScreen(); } - QEglFSHooks::hooks()->waitForVSync(); + qt_egl_device_integration()->waitForVSync(surface); QEGLPlatformContext::swapBuffers(surface); + qt_egl_device_integration()->presentBuffer(surface); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfscontext.h b/src/plugins/platforms/eglfs/qeglfscontext.h index fcdad5ed22..245f690822 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.h +++ b/src/plugins/platforms/eglfs/qeglfscontext.h @@ -36,16 +36,22 @@ #include <QtPlatformSupport/private/qeglplatformcontext_p.h> #include <QtCore/QVariant> +#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE -class QEglFSContext : public QEGLPlatformContext +class Q_EGLFS_EXPORT QEglFSContext : public QEGLPlatformContext { public: QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLConfig *config, const QVariant &nativeHandle); EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) Q_DECL_OVERRIDE; + EGLSurface createTemporaryOffscreenSurface() Q_DECL_OVERRIDE; + void destroyTemporaryOffscreenSurface(EGLSurface surface) Q_DECL_OVERRIDE; void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE; + +private: + EGLNativeWindowType m_tempWindow; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp new file mode 100644 index 0000000000..69a5f67ea9 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp @@ -0,0 +1,311 @@ +/**************************************************************************** +** +** 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 "qeglfsdeviceintegration.h" +#include "qeglfsintegration.h" +#include <QtPlatformSupport/private/qeglconvenience_p.h> +#include <QtPlatformSupport/private/qeglplatformcursor_p.h> +#include <QGuiApplication> +#include <private/qguiapplication_p.h> +#include <QScreen> +#include <QDir> +#include <QRegularExpression> +#include <QLoggingCategory> + +#if defined(Q_OS_LINUX) +#include <fcntl.h> +#include <unistd.h> +#include <linux/fb.h> +#include <sys/ioctl.h> +#endif + +#include <private/qfactoryloader_p.h> +#include <private/qcore_unix_p.h> + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(qLcEglDevDebug, "qt.qpa.egldeviceintegration") + +#ifndef QT_NO_LIBRARY + +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QEGLDeviceIntegrationFactoryInterface_iid, QLatin1String("/egldeviceintegrations"), Qt::CaseInsensitive)) + +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, directLoader, + (QEGLDeviceIntegrationFactoryInterface_iid, QLatin1String(""), Qt::CaseInsensitive)) + +static inline QEGLDeviceIntegration *loadIntegration(QFactoryLoader *loader, const QString &key) +{ + const int index = loader->indexOf(key); + if (index != -1) { + QObject *plugin = loader->instance(index); + if (QEGLDeviceIntegrationPlugin *factory = qobject_cast<QEGLDeviceIntegrationPlugin *>(plugin)) { + if (QEGLDeviceIntegration *result = factory->create()) + return result; + } + } + return Q_NULLPTR; +} + +#endif // QT_NO_LIBRARY + +QStringList QEGLDeviceIntegrationFactory::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()); + qCDebug(qLcEglDevDebug) << "EGL device integration plugin keys:" << list; + return list; +#else + return QStringList(); +#endif +} + +QEGLDeviceIntegration *QEGLDeviceIntegrationFactory::create(const QString &key, const QString &pluginPath) +{ + QEGLDeviceIntegration *integration = Q_NULLPTR; +#ifndef QT_NO_LIBRARY + if (!pluginPath.isEmpty()) { + QCoreApplication::addLibraryPath(pluginPath); + integration = loadIntegration(directLoader(), key); + } + if (!integration) + integration = loadIntegration(loader(), key); + if (integration) + qCDebug(qLcEglDevDebug) << "Using EGL device integration" << key; + else + qCWarning(qLcEglDevDebug) << "Failed to load EGL device integration" << key; +#endif + return integration; +} + +static int framebuffer = -1; + +QByteArray QEGLDeviceIntegration::fbDeviceName() const +{ + QByteArray fbDev = qgetenv("QT_QPA_EGLFS_FB"); + if (fbDev.isEmpty()) + fbDev = QByteArrayLiteral("/dev/fb0"); + + return fbDev; +} + +int QEGLDeviceIntegration::framebufferIndex() const +{ + int fbIndex = 0; +#ifndef QT_NO_REGULAREXPRESSION + QRegularExpression fbIndexRx(QLatin1String("fb(\\d+)")); + QRegularExpressionMatch match = fbIndexRx.match(QString::fromLocal8Bit(fbDeviceName())); + if (match.hasMatch()) + fbIndex = match.captured(1).toInt(); +#endif + return fbIndex; +} + +void QEGLDeviceIntegration::platformInit() +{ + QByteArray fbDev = fbDeviceName(); + + framebuffer = qt_safe_open(fbDev, O_RDONLY); + + if (framebuffer == -1) { + qWarning("EGLFS: Failed to open %s", fbDev.constData()); + qFatal("EGLFS: Can't continue without a display"); + } +} + +void QEGLDeviceIntegration::platformDestroy() +{ + if (framebuffer != -1) + close(framebuffer); +} + +EGLNativeDisplayType QEGLDeviceIntegration::platformDisplay() const +{ + return EGL_DEFAULT_DISPLAY; +} + +bool QEGLDeviceIntegration::usesDefaultScreen() +{ + return true; +} + +void QEGLDeviceIntegration::screenInit() +{ + // Nothing to do here. Called only when usesDefaultScreen is false. +} + +void QEGLDeviceIntegration::screenDestroy() +{ + QGuiApplication *app = qGuiApp; + QEglFSIntegration *platformIntegration = static_cast<QEglFSIntegration *>( + QGuiApplicationPrivate::platformIntegration()); + while (!app->screens().isEmpty()) + platformIntegration->removeScreen(app->screens().last()->handle()); +} + +QSizeF QEGLDeviceIntegration::physicalScreenSize() const +{ + return q_physicalScreenSizeFromFb(framebuffer, screenSize()); +} + +QSize QEGLDeviceIntegration::screenSize() const +{ + return q_screenSizeFromFb(framebuffer); +} + +QDpi QEGLDeviceIntegration::logicalDpi() const +{ + QSizeF ps = physicalScreenSize(); + QSize s = screenSize(); + + return QDpi(25.4 * s.width() / ps.width(), + 25.4 * s.height() / ps.height()); +} + +Qt::ScreenOrientation QEGLDeviceIntegration::nativeOrientation() const +{ + return Qt::PrimaryOrientation; +} + +Qt::ScreenOrientation QEGLDeviceIntegration::orientation() const +{ + return Qt::PrimaryOrientation; +} + +int QEGLDeviceIntegration::screenDepth() const +{ + return q_screenDepthFromFb(framebuffer); +} + +QImage::Format QEGLDeviceIntegration::screenFormat() const +{ + return screenDepth() == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32; +} + +QSurfaceFormat QEGLDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +{ + QSurfaceFormat format = inputFormat; + + static const bool force888 = qEnvironmentVariableIntValue("QT_QPA_EGLFS_FORCE888"); + if (force888) { + format.setRedBufferSize(8); + format.setGreenBufferSize(8); + format.setBlueBufferSize(8); + } + + return format; +} + +bool QEGLDeviceIntegration::filterConfig(EGLDisplay, EGLConfig) const +{ + return true; +} + +EGLNativeWindowType QEGLDeviceIntegration::createNativeWindow(QPlatformWindow *platformWindow, + const QSize &size, + const QSurfaceFormat &format) +{ + Q_UNUSED(platformWindow); + Q_UNUSED(size); + Q_UNUSED(format); + return 0; +} + +EGLNativeWindowType QEGLDeviceIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format) +{ + Q_UNUSED(format); + return 0; +} + +void QEGLDeviceIntegration::destroyNativeWindow(EGLNativeWindowType window) +{ + Q_UNUSED(window); +} + +bool QEGLDeviceIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + Q_UNUSED(cap); + return false; +} + +QPlatformCursor *QEGLDeviceIntegration::createCursor(QPlatformScreen *screen) const +{ + return new QEGLPlatformCursor(screen); +} + +void QEGLDeviceIntegration::waitForVSync(QPlatformSurface *surface) const +{ + Q_UNUSED(surface); + +#if defined(FBIO_WAITFORVSYNC) + static const bool forceSync = qEnvironmentVariableIntValue("QT_QPA_EGLFS_FORCEVSYNC"); + if (forceSync && framebuffer != -1) { + int arg = 0; + if (ioctl(framebuffer, FBIO_WAITFORVSYNC, &arg) == -1) + qWarning("Could not wait for vsync."); + } +#endif +} + +void QEGLDeviceIntegration::presentBuffer(QPlatformSurface *surface) +{ + Q_UNUSED(surface); +} + +bool QEGLDeviceIntegration::supportsPBuffers() const +{ + return true; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h new file mode 100644 index 0000000000..42abc23c31 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** 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 QEGLFSDEVICEINTEGRATION_H +#define QEGLFSDEVICEINTEGRATION_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qpa/qplatformintegration.h> +#include <qpa/qplatformscreen.h> +#include <QtCore/QString> +#include <QtGui/QSurfaceFormat> +#include <QtGui/QImage> +#include <EGL/egl.h> +#include "qeglfsglobal.h" + +QT_BEGIN_NAMESPACE + +class QPlatformSurface; + +#define QEGLDeviceIntegrationFactoryInterface_iid "org.qt-project.qt.qpa.egl.QEGLDeviceIntegrationFactoryInterface.5.5" + +class Q_EGLFS_EXPORT QEGLDeviceIntegration +{ +public: + virtual ~QEGLDeviceIntegration() { } + + virtual void platformInit(); + virtual void platformDestroy(); + virtual EGLNativeDisplayType platformDisplay() const; + virtual bool usesDefaultScreen(); + virtual void screenInit(); + virtual void screenDestroy(); + virtual QSizeF physicalScreenSize() const; + virtual QSize screenSize() const; + virtual QDpi logicalDpi() const; + virtual Qt::ScreenOrientation nativeOrientation() const; + virtual Qt::ScreenOrientation orientation() const; + virtual int screenDepth() const; + virtual QImage::Format screenFormat() const; + virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const; + virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, + const QSize &size, + const QSurfaceFormat &format); + virtual EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format); + virtual void destroyNativeWindow(EGLNativeWindowType window); + virtual bool hasCapability(QPlatformIntegration::Capability cap) const; + virtual QPlatformCursor *createCursor(QPlatformScreen *screen) const; + virtual bool filterConfig(EGLDisplay display, EGLConfig config) const; + virtual void waitForVSync(QPlatformSurface *surface) const; + virtual void presentBuffer(QPlatformSurface *surface); + virtual QByteArray fbDeviceName() const; + virtual int framebufferIndex() const; + virtual bool supportsPBuffers() const; +}; + +class Q_EGLFS_EXPORT QEGLDeviceIntegrationPlugin : public QObject +{ + Q_OBJECT + +public: + virtual QEGLDeviceIntegration *create() = 0; +}; + +class Q_EGLFS_EXPORT QEGLDeviceIntegrationFactory +{ +public: + static QStringList keys(const QString &pluginPath = QString()); + static QEGLDeviceIntegration *create(const QString &name, const QString &platformPluginPath = QString()); +}; + +QT_END_NAMESPACE + +#endif // QEGLDEVICEINTEGRATION_H diff --git a/src/plugins/platforms/eglfs/qeglfsglobal.h b/src/plugins/platforms/eglfs/qeglfsglobal.h new file mode 100644 index 0000000000..db9a76f899 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsglobal.h @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** 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 QEGLFSGLOBAL_H +#define QEGLFSGLOBAL_H + +#include <qglobal.h> + +#ifdef QT_BUILD_EGL_DEVICE_LIB +#define Q_EGLFS_EXPORT Q_DECL_EXPORT +#else +#define Q_EGLFS_EXPORT Q_DECL_IMPORT +#endif + +#endif diff --git a/src/plugins/platforms/eglfs/qeglfshooks.cpp b/src/plugins/platforms/eglfs/qeglfshooks.cpp new file mode 100644 index 0000000000..2f12c61f99 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfshooks.cpp @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the qmake spec 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 "qeglfshooks.h" +#include <QLoggingCategory> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(qLcEglDevDebug) + +#ifdef EGLFS_PLATFORM_HOOKS + +QEGLDeviceIntegration *qt_egl_device_integration() +{ + extern QEglFSHooks *platformHooks; + return platformHooks; +} + +#else + +class DeviceIntegration +{ +public: + DeviceIntegration(); + ~DeviceIntegration() { delete m_integration; } + QEGLDeviceIntegration *integration() { return m_integration; } +private: + QEGLDeviceIntegration *m_integration; +}; + +Q_GLOBAL_STATIC(DeviceIntegration, deviceIntegration) + +DeviceIntegration::DeviceIntegration() +{ + QStringList pluginKeys = QEGLDeviceIntegrationFactory::keys(); + if (!pluginKeys.isEmpty()) { + // Some built-in logic: Prioritize either X11 or KMS/DRM. + if (qEnvironmentVariableIsSet("DISPLAY")) { + const QString x11key = QStringLiteral("eglfs_x11"); + if (pluginKeys.contains(x11key)) { + pluginKeys.removeOne(x11key); + pluginKeys.prepend(x11key); + } + } else { + const QString kmskey = QStringLiteral("eglfs_kms"); + if (pluginKeys.contains(kmskey)) { + pluginKeys.removeOne(kmskey); + pluginKeys.prepend(kmskey); + } + } + + QByteArray requested; + + // The environment variable can override everything. + if (qEnvironmentVariableIsSet("QT_QPA_EGLFS_INTEGRATION")) { + requested = qgetenv("QT_QPA_EGLFS_INTEGRATION"); + } else { + // Device-specific makespecs may define a preferred plugin. +#ifdef EGLFS_PREFERRED_PLUGIN +#define DEFAULT_PLUGIN EGLFS_PREFERRED_PLUGIN +#define STR(s) #s +#define STRQ(s) STR(s) + requested = STRQ(DEFAULT_PLUGIN); +#endif + } + + // Treat "none" as special. There has to be a way to indicate + // that plugins must be ignored when the device is known to be + // functional with the default, non-specialized integration. + if (requested != QByteArrayLiteral("none")) { + if (!requested.isEmpty()) { + QString reqStr = QString::fromLocal8Bit(requested); + pluginKeys.removeOne(reqStr); + pluginKeys.prepend(reqStr); + } + qCDebug(qLcEglDevDebug) << "EGL device integration plugin keys (sorted):" << pluginKeys; + while (!m_integration && !pluginKeys.isEmpty()) { + QString key = pluginKeys.takeFirst(); + qCDebug(qLcEglDevDebug) << "Trying to load device EGL integration" << key; + m_integration = QEGLDeviceIntegrationFactory::create(key); + } + } + } + + if (!m_integration) { + // Use a default, non-specialized device integration when no plugin is available. + // For some systems this is sufficient. + qCDebug(qLcEglDevDebug) << "Using base device integration"; + m_integration = new QEGLDeviceIntegration; + } +} + +QEGLDeviceIntegration *qt_egl_device_integration() +{ + return deviceIntegration()->integration(); +} + +#endif // EGLFS_PLATFORM_HOOKS + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfshooks.h b/src/plugins/platforms/eglfs/qeglfshooks.h index c51af17a56..1fcfc5bd08 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks.h +++ b/src/plugins/platforms/eglfs/qeglfshooks.h @@ -34,56 +34,17 @@ #ifndef QEGLFSHOOKS_H #define QEGLFSHOOKS_H -#include <qpa/qplatformintegration.h> -#include <qpa/qplatformscreen.h> -#include <QtGui/QSurfaceFormat> -#include <QtGui/QImage> -#include <EGL/egl.h> +#include "qeglfsdeviceintegration.h" +#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE -class QEGLPlatformCursor; -class QEglFSScreen; - -class QEglFSHooks +class QEglFSHooks : public QEGLDeviceIntegration { -public: - virtual ~QEglFSHooks() {} - virtual void platformInit(); - virtual void platformDestroy(); - virtual EGLNativeDisplayType platformDisplay() const; - virtual QSizeF physicalScreenSize() const; - virtual QSize screenSize() const; - virtual QDpi logicalDpi() const; - virtual Qt::ScreenOrientation nativeOrientation() const; - virtual Qt::ScreenOrientation orientation() const; - virtual int screenDepth() const; - virtual QImage::Format screenFormat() const; - virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const; - virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, - const QSize &size, - const QSurfaceFormat &format); - virtual void destroyNativeWindow(EGLNativeWindowType window); - virtual bool hasCapability(QPlatformIntegration::Capability cap) const; - virtual QEGLPlatformCursor *createCursor(QPlatformScreen *screen) const; - virtual bool filterConfig(EGLDisplay display, EGLConfig config) const; - virtual void waitForVSync() const; - - virtual QByteArray fbDeviceName() const; - virtual int framebufferIndex() const; - - static QEglFSHooks *hooks() - { -#ifdef EGLFS_PLATFORM_HOOKS - extern QEglFSHooks *platformHooks; - return platformHooks; -#else - extern QEglFSHooks stubHooks; - return &stubHooks; -#endif - } }; +Q_EGLFS_EXPORT QEGLDeviceIntegration *qt_egl_device_integration(); + QT_END_NAMESPACE #endif // QEGLFSHOOKS_H diff --git a/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp b/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp deleted file mode 100644 index 9e5d624d87..0000000000 --- a/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp +++ /dev/null @@ -1,422 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the qmake spec 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 "qeglfshooks.h" -#include <QtPlatformSupport/private/qdevicediscovery_p.h> -#include <QtCore/private/qcore_unix_p.h> -#include <QtCore/QScopedPointer> -#include <QtGui/qpa/qplatformwindow.h> - -#include <xf86drm.h> -#include <xf86drmMode.h> -#include <gbm.h> - -QT_USE_NAMESPACE - -class QEglKmsHooks : public QEglFSHooks -{ -public: - QEglKmsHooks(); - - void platformInit() Q_DECL_OVERRIDE; - void platformDestroy() Q_DECL_OVERRIDE; - EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; - QSizeF physicalScreenSize() const Q_DECL_OVERRIDE; - QSize screenSize() const Q_DECL_OVERRIDE; - int screenDepth() const Q_DECL_OVERRIDE; - QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE; - EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow, - const QSize &size, - const QSurfaceFormat &format) Q_DECL_OVERRIDE; - void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; - bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - void waitForVSync() const Q_DECL_OVERRIDE; - - void waitForVSyncImpl(); - bool setup_kms(); - - struct FrameBuffer { - FrameBuffer() : fb(0) {} - uint32_t fb; - }; - FrameBuffer *framebufferForBufferObject(gbm_bo *bo); - -private: - // device bits - QByteArray m_device; - int m_dri_fd; - gbm_device *m_gbm_device; - - // KMS bits - drmModeConnector *m_drm_connector; - drmModeEncoder *m_drm_encoder; - drmModeModeInfo m_drm_mode; - quint32 m_drm_crtc; - - // Drawing bits - gbm_surface *m_gbm_surface; -}; - -static QEglKmsHooks kms_hooks; -QEglFSHooks *platformHooks = &kms_hooks; - -QEglKmsHooks::QEglKmsHooks() - : m_dri_fd(-1) - , m_gbm_device(Q_NULLPTR) - , m_drm_connector(Q_NULLPTR) - , m_drm_encoder(Q_NULLPTR) - , m_drm_crtc(0) - , m_gbm_surface(Q_NULLPTR) -{ - -} - -void QEglKmsHooks::platformInit() -{ - QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask); - QStringList devices = d->scanConnectedDevices(); - d->deleteLater(); - - if (devices.isEmpty()) - qFatal("Could not find DRM device!"); - - m_device = devices.first().toLocal8Bit(); - m_dri_fd = qt_safe_open(m_device.constData(), O_RDWR | O_CLOEXEC); - if (m_dri_fd == -1) { - qErrnoWarning("Could not open DRM device %s", m_device.constData()); - qFatal("DRM device required, aborting."); - } - - if (!setup_kms()) - qFatal("Could not set up KMS on device %s!", m_device.constData()); - - m_gbm_device = gbm_create_device(m_dri_fd); - if (!m_gbm_device) - qFatal("Could not initialize gbm on device %s!", m_device.constData()); -} - -void QEglKmsHooks::platformDestroy() -{ - gbm_device_destroy(m_gbm_device); - m_gbm_device = Q_NULLPTR; - - if (qt_safe_close(m_dri_fd) == -1) - qErrnoWarning("Could not close DRM device %s", m_device.constData()); - - m_dri_fd = -1; -} - -EGLNativeDisplayType QEglKmsHooks::platformDisplay() const -{ - return static_cast<EGLNativeDisplayType>(m_gbm_device); -} - -QSizeF QEglKmsHooks::physicalScreenSize() const -{ - return QSizeF(m_drm_connector->mmWidth, - m_drm_connector->mmHeight); -} - -QSize QEglKmsHooks::screenSize() const -{ - return QSize(m_drm_mode.hdisplay, - m_drm_mode.vdisplay); -} - -int QEglKmsHooks::screenDepth() const -{ - return 32; -} - -QSurfaceFormat QEglKmsHooks::surfaceFormatFor(const QSurfaceFormat &inputFormat) const -{ - QSurfaceFormat format(inputFormat); - format.setRenderableType(QSurfaceFormat::OpenGLES); - format.setSwapBehavior(QSurfaceFormat::DoubleBuffer); - format.setRedBufferSize(8); - format.setGreenBufferSize(8); - format.setBlueBufferSize(8); - return format; -} - -EGLNativeWindowType QEglKmsHooks::createNativeWindow(QPlatformWindow *platformWindow, - const QSize &size, - const QSurfaceFormat &format) -{ - Q_UNUSED(platformWindow); - Q_UNUSED(size); - Q_UNUSED(format); - - if (m_gbm_surface) { - qWarning("Only single window apps supported!"); - return 0; - } - - m_gbm_surface = gbm_surface_create(m_gbm_device, - screenSize().width(), - screenSize().height(), - GBM_FORMAT_XRGB8888, - GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); - if (!m_gbm_surface) - qFatal("Could not initialize GBM surface"); - - return reinterpret_cast<EGLNativeWindowType>(m_gbm_surface); -} - -void QEglKmsHooks::destroyNativeWindow(EGLNativeWindowType window) -{ - gbm_surface *surface = reinterpret_cast<gbm_surface *>(window); - if (surface == m_gbm_surface) - m_gbm_surface = Q_NULLPTR; - gbm_surface_destroy(surface); -} - -bool QEglKmsHooks::hasCapability(QPlatformIntegration::Capability cap) const -{ - switch (cap) { - case QPlatformIntegration::ThreadedPixmaps: - case QPlatformIntegration::OpenGL: - case QPlatformIntegration::ThreadedOpenGL: - case QPlatformIntegration::BufferQueueingOpenGL: - return true; - default: - return false; - } -} - -static void gbm_bo_destroyed_callback(gbm_bo *bo, void *data) -{ - QEglKmsHooks::FrameBuffer *fb = static_cast<QEglKmsHooks::FrameBuffer *>(data); - - if (fb->fb) { - gbm_device *device = gbm_bo_get_device(bo); - drmModeRmFB(gbm_device_get_fd(device), fb->fb); - } - - delete fb; -} - -QEglKmsHooks::FrameBuffer *QEglKmsHooks::framebufferForBufferObject(gbm_bo *bo) -{ - { - FrameBuffer *fb = static_cast<FrameBuffer *>(gbm_bo_get_user_data(bo)); - if (fb) - return fb; - } - - uint32_t width = gbm_bo_get_width(bo); - uint32_t height = gbm_bo_get_height(bo); - uint32_t stride = gbm_bo_get_stride(bo); - uint32_t handle = gbm_bo_get_handle(bo).u32; - - QScopedPointer<FrameBuffer> fb(new FrameBuffer); - - int ret = drmModeAddFB(m_dri_fd, width, height, 24, 32, - stride, handle, &fb->fb); - - if (ret) { - qWarning("Failed to create KMS FB!"); - return Q_NULLPTR; - } - - gbm_bo_set_user_data(bo, fb.data(), gbm_bo_destroyed_callback); - return fb.take(); -} - -static void page_flip_handler(int fd, - unsigned int sequence, - unsigned int tv_sec, - unsigned int tv_usec, - void *user_data) -{ - Q_UNUSED(fd); - Q_UNUSED(sequence); - Q_UNUSED(tv_sec); - Q_UNUSED(tv_usec); - - // We are no longer flipping - *static_cast<bool *>(user_data) = false; -} - -void QEglKmsHooks::waitForVSync() const -{ - const_cast<QEglKmsHooks*>(this)->waitForVSyncImpl(); -} - -void QEglKmsHooks::waitForVSyncImpl() -{ - if (!m_gbm_surface) { - qWarning("Cannot sync before platform init!"); - return; - } - - if (!gbm_surface_has_free_buffers(m_gbm_surface)) { - qWarning("Out of free GBM buffers!"); - return; - } - - gbm_bo *front_buffer = gbm_surface_lock_front_buffer(m_gbm_surface); - if (!front_buffer) { - qWarning("Could not lock GBM surface front buffer!"); - return; - } - - QEglKmsHooks::FrameBuffer *fb = framebufferForBufferObject(front_buffer); - - int ret = drmModeSetCrtc(m_dri_fd, - m_drm_crtc, - fb->fb, - 0, 0, - &m_drm_connector->connector_id, 1, - &m_drm_mode); - if (ret) { - qErrnoWarning("Could not set DRM mode!"); - return; - } - - bool flipping = true; - ret = drmModePageFlip(m_dri_fd, - m_drm_encoder->crtc_id, - fb->fb, - DRM_MODE_PAGE_FLIP_EVENT, - &flipping); - if (ret) { - qErrnoWarning("Could not queue DRM page flip!"); - return; - } - - drmEventContext drmEvent = { - DRM_EVENT_CONTEXT_VERSION, - Q_NULLPTR, // vblank handler - page_flip_handler // page flip handler - }; - - fd_set fds; - FD_ZERO(&fds); - FD_SET(m_dri_fd, &fds); - - time_t start, cur; - time(&start); - - while (flipping && (time(&cur) < start + 1)) { - timespec v; - memset(&v, 0, sizeof(v)); - v.tv_sec = start + 1 - cur; - - ret = qt_safe_select(m_dri_fd + 1, &fds, Q_NULLPTR, Q_NULLPTR, &v); - - if (ret == 0) { - // timeout - break; - } else if (ret == -1) { - qErrnoWarning("Error while selecting on DRM fd"); - break; - } else if (drmHandleEvent(m_dri_fd, &drmEvent)) { - qWarning("Could not handle DRM event!"); - } - } - - gbm_surface_release_buffer(m_gbm_surface, front_buffer); -} - -bool QEglKmsHooks::setup_kms() -{ - drmModeRes *resources; - drmModeConnector *connector; - drmModeEncoder *encoder; - quint32 crtc = 0; - int i; - - resources = drmModeGetResources(m_dri_fd); - if (!resources) { - qWarning("drmModeGetResources failed"); - return false; - } - - for (i = 0; i < resources->count_connectors; i++) { - connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]); - if (connector == NULL) - continue; - - if (connector->connection == DRM_MODE_CONNECTED && - connector->count_modes > 0) { - break; - } - - drmModeFreeConnector(connector); - } - - if (i == resources->count_connectors) { - qWarning("No currently active connector found."); - return false; - } - - for (i = 0; i < resources->count_encoders; i++) { - encoder = drmModeGetEncoder(m_dri_fd, resources->encoders[i]); - - if (encoder == NULL) - continue; - - if (encoder->encoder_id == connector->encoder_id) - break; - - drmModeFreeEncoder(encoder); - } - - for (int j = 0; j < resources->count_crtcs; j++) { - if ((encoder->possible_crtcs & (1 << j))) { - crtc = resources->crtcs[j]; - break; - } - } - - if (crtc == 0) - qFatal("No suitable CRTC available"); - - m_drm_connector = connector; - m_drm_encoder = encoder; - m_drm_mode = connector->modes[0]; - m_drm_crtc = crtc; - - drmModeFreeResources(resources); - - return true; -} diff --git a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp deleted file mode 100644 index 26d77a2abb..0000000000 --- a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp +++ /dev/null @@ -1,199 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of the qmake spec 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 "qeglfshooks.h" -#include <QtPlatformSupport/private/qeglplatformcursor_p.h> -#include <QtPlatformSupport/private/qeglconvenience_p.h> -#include <QtCore/QRegularExpression> - -#if defined(Q_OS_LINUX) -#include <fcntl.h> -#include <unistd.h> -#include <linux/fb.h> -#include <sys/ioctl.h> -#endif - -#include <private/qcore_unix_p.h> - -QT_BEGIN_NAMESPACE - -// file descriptor for the frame buffer -// this is a global static to keep the QEglFSHooks interface as clean as possible -static int framebuffer = -1; - -QByteArray QEglFSHooks::fbDeviceName() const -{ - QByteArray fbDev = qgetenv("QT_QPA_EGLFS_FB"); - if (fbDev.isEmpty()) - fbDev = QByteArrayLiteral("/dev/fb0"); - - return fbDev; -} - -int QEglFSHooks::framebufferIndex() const -{ - int fbIndex = 0; -#ifndef QT_NO_REGULAREXPRESSION - QRegularExpression fbIndexRx(QLatin1String("fb(\\d+)")); - QRegularExpressionMatch match = fbIndexRx.match(fbDeviceName()); - if (match.hasMatch()) - fbIndex = match.captured(1).toInt(); - -#endif - return fbIndex; -} - -void QEglFSHooks::platformInit() -{ - QByteArray fbDev = fbDeviceName(); - - framebuffer = qt_safe_open(fbDev, O_RDONLY); - - if (framebuffer == -1) { - qWarning("EGLFS: Failed to open %s", qPrintable(fbDev)); - qFatal("EGLFS: Can't continue without a display"); - } -} - -void QEglFSHooks::platformDestroy() -{ - if (framebuffer != -1) - close(framebuffer); -} - -EGLNativeDisplayType QEglFSHooks::platformDisplay() const -{ - return EGL_DEFAULT_DISPLAY; -} - -QSizeF QEglFSHooks::physicalScreenSize() const -{ - return q_physicalScreenSizeFromFb(framebuffer, screenSize()); -} - -QSize QEglFSHooks::screenSize() const -{ - return q_screenSizeFromFb(framebuffer); -} - -QDpi QEglFSHooks::logicalDpi() const -{ - QSizeF ps = physicalScreenSize(); - QSize s = screenSize(); - - return QDpi(25.4 * s.width() / ps.width(), - 25.4 * s.height() / ps.height()); -} - -Qt::ScreenOrientation QEglFSHooks::nativeOrientation() const -{ - return Qt::PrimaryOrientation; -} - -Qt::ScreenOrientation QEglFSHooks::orientation() const -{ - return Qt::PrimaryOrientation; -} - -int QEglFSHooks::screenDepth() const -{ - return q_screenDepthFromFb(framebuffer); -} - -QImage::Format QEglFSHooks::screenFormat() const -{ - return screenDepth() == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32; -} - -QSurfaceFormat QEglFSHooks::surfaceFormatFor(const QSurfaceFormat &inputFormat) const -{ - QSurfaceFormat format = inputFormat; - - static const bool force888 = qgetenv("QT_QPA_EGLFS_FORCE888").toInt(); - if (force888) { - format.setRedBufferSize(8); - format.setGreenBufferSize(8); - format.setBlueBufferSize(8); - } - - return format; -} - -bool QEglFSHooks::filterConfig(EGLDisplay, EGLConfig) const -{ - return true; -} - -EGLNativeWindowType QEglFSHooks::createNativeWindow(QPlatformWindow *platformWindow, - const QSize &size, - const QSurfaceFormat &format) -{ - Q_UNUSED(platformWindow); - Q_UNUSED(size); - Q_UNUSED(format); - return 0; -} - -void QEglFSHooks::destroyNativeWindow(EGLNativeWindowType window) -{ - Q_UNUSED(window); -} - -bool QEglFSHooks::hasCapability(QPlatformIntegration::Capability cap) const -{ - Q_UNUSED(cap); - return false; -} - -QEGLPlatformCursor *QEglFSHooks::createCursor(QPlatformScreen *screen) const -{ - return new QEGLPlatformCursor(screen); -} - -void QEglFSHooks::waitForVSync() const -{ -#if defined(FBIO_WAITFORVSYNC) - static const bool forceSync = qgetenv("QT_QPA_EGLFS_FORCEVSYNC").toInt(); - if (forceSync && framebuffer != -1) { - int arg = 0; - if (ioctl(framebuffer, FBIO_WAITFORVSYNC, &arg) == -1) - qWarning("Could not wait for vsync."); - } -#endif -} - -#ifndef EGLFS_PLATFORM_HOOKS -QEglFSHooks stubHooks; -#endif - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index 2a4eae3fe2..80a029c27f 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -36,6 +36,7 @@ #include "qeglfswindow.h" #include "qeglfshooks.h" #include "qeglfscontext.h" +#include "qeglfsoffscreenwindow.h" #include <QtGui/private/qguiapplication_p.h> @@ -62,43 +63,55 @@ QT_BEGIN_NAMESPACE QEglFSIntegration::QEglFSIntegration() { - mDisableInputHandlers = qgetenv("QT_QPA_EGLFS_DISABLE_INPUT").toInt(); + mDisableInputHandlers = qEnvironmentVariableIntValue("QT_QPA_EGLFS_DISABLE_INPUT"); initResources(); } -QEglFSIntegration::~QEglFSIntegration() -{ - QEglFSHooks::hooks()->platformDestroy(); -} - bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) const { // We assume that devices will have more and not less capabilities - if (QEglFSHooks::hooks() && QEglFSHooks::hooks()->hasCapability(cap)) + if (qt_egl_device_integration()->hasCapability(cap)) return true; return QEGLPlatformIntegration::hasCapability(cap); } +void QEglFSIntegration::addScreen(QPlatformScreen *screen) +{ + screenAdded(screen); +} + +void QEglFSIntegration::removeScreen(QPlatformScreen *screen) +{ + destroyScreen(screen); +} + void QEglFSIntegration::initialize() { - QEglFSHooks::hooks()->platformInit(); + qt_egl_device_integration()->platformInit(); QEGLPlatformIntegration::initialize(); if (!mDisableInputHandlers) createInputHandlers(); + + if (qt_egl_device_integration()->usesDefaultScreen()) + addScreen(new QEglFSScreen(display())); + else + qt_egl_device_integration()->screenInit(); } -EGLNativeDisplayType QEglFSIntegration::nativeDisplay() const +void QEglFSIntegration::destroy() { - return QEglFSHooks::hooks()->platformDisplay(); + qt_egl_device_integration()->screenDestroy(); + QEGLPlatformIntegration::destroy(); + qt_egl_device_integration()->platformDestroy(); } -QEGLPlatformScreen *QEglFSIntegration::createScreen() const +EGLNativeDisplayType QEglFSIntegration::nativeDisplay() const { - return new QEglFSScreen(display()); + return qt_egl_device_integration()->platformDisplay(); } QEGLPlatformWindow *QEglFSIntegration::createWindow(QWindow *window) const @@ -112,12 +125,12 @@ QEGLPlatformContext *QEglFSIntegration::createContext(const QSurfaceFormat &form QVariant *nativeHandle) const { QEglFSContext *ctx; - QSurfaceFormat adjustedFormat = QEglFSHooks::hooks()->surfaceFormatFor(format); + QSurfaceFormat adjustedFormat = qt_egl_device_integration()->surfaceFormatFor(format); if (!nativeHandle || nativeHandle->isNull()) { EGLConfig config = QEglFSIntegration::chooseConfig(display, adjustedFormat); - ctx = new QEglFSContext(adjustedFormat, shareContext, display, &config, QVariant()); + ctx = new QEglFSContext(adjustedFormat, shareContext, display, &config, QVariant()); } else { - ctx = new QEglFSContext(adjustedFormat, shareContext, display, 0, *nativeHandle); + ctx = new QEglFSContext(adjustedFormat, shareContext, display, 0, *nativeHandle); } *nativeHandle = QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(ctx->eglContext(), display)); return ctx; @@ -127,41 +140,28 @@ QPlatformOffscreenSurface *QEglFSIntegration::createOffscreenSurface(EGLDisplay const QSurfaceFormat &format, QOffscreenSurface *surface) const { - return new QEGLPbuffer(display, QEglFSHooks::hooks()->surfaceFormatFor(format), surface); -} + QSurfaceFormat fmt = qt_egl_device_integration()->surfaceFormatFor(format); + if (qt_egl_device_integration()->supportsPBuffers()) + return new QEGLPbuffer(display, fmt, surface); + else + return new QEglFSOffscreenWindow(display, fmt, surface); -QVariant QEglFSIntegration::styleHint(QPlatformIntegration::StyleHint hint) const -{ - switch (hint) - { - case QPlatformIntegration::ShowIsFullScreen: - return screen()->compositingWindow() == 0; - default: - return QPlatformIntegration::styleHint(hint); - } + // Never return null. Multiple QWindows are not supported by this plugin. } EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format) { class Chooser : public QEglConfigChooser { public: - Chooser(EGLDisplay display, QEglFSHooks *hooks) - : QEglConfigChooser(display) - , m_hooks(hooks) - { - } - - protected: - bool filterConfig(EGLConfig config) const - { - return m_hooks->filterConfig(display(), config) && QEglConfigChooser::filterConfig(config); + Chooser(EGLDisplay display) + : QEglConfigChooser(display) { } + bool filterConfig(EGLConfig config) const Q_DECL_OVERRIDE { + return qt_egl_device_integration()->filterConfig(display(), config) + && QEglConfigChooser::filterConfig(config); } - - private: - QEglFSHooks *m_hooks; }; - Chooser chooser(display, QEglFSHooks::hooks()); + Chooser chooser(display); chooser.setSurfaceFormat(format); return chooser.chooseConfig(); } diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h index d612a270f2..2074d80e56 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -37,24 +37,26 @@ #include <QtPlatformSupport/private/qeglplatformintegration_p.h> #include <qpa/qplatformscreen.h> #include <EGL/egl.h> +#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE -class QEglFSIntegration : public QEGLPlatformIntegration +class Q_EGLFS_EXPORT QEglFSIntegration : public QEGLPlatformIntegration { public: QEglFSIntegration(); - ~QEglFSIntegration(); + + void addScreen(QPlatformScreen *screen); + void removeScreen(QPlatformScreen *screen); void initialize() Q_DECL_OVERRIDE; + void destroy() Q_DECL_OVERRIDE; bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - QVariant styleHint(QPlatformIntegration::StyleHint hint) const Q_DECL_OVERRIDE; static EGLConfig chooseConfig(EGLDisplay display, const QSurfaceFormat &format); protected: - QEGLPlatformScreen *createScreen() const Q_DECL_OVERRIDE; QEGLPlatformWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; QEGLPlatformContext *createContext(const QSurfaceFormat &format, QPlatformOpenGLContext *shareContext, diff --git a/src/plugins/platforms/eglfs/main.cpp b/src/plugins/platforms/eglfs/qeglfsmain.cpp index be91fbf3c3..2c5e79534d 100644 --- a/src/plugins/platforms/eglfs/main.cpp +++ b/src/plugins/platforms/eglfs/qeglfsmain.cpp @@ -41,7 +41,7 @@ class QEglFSIntegrationPlugin : public QPlatformIntegrationPlugin Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "eglfs.json") public: - QPlatformIntegration *create(const QString&, const QStringList&); + QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; QPlatformIntegration* QEglFSIntegrationPlugin::create(const QString& system, const QStringList& paramList) @@ -55,4 +55,4 @@ QPlatformIntegration* QEglFSIntegrationPlugin::create(const QString& system, con QT_END_NAMESPACE -#include "main.moc" +#include "qeglfsmain.moc" diff --git a/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.cpp b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.cpp new file mode 100644 index 0000000000..7bf53ef351 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.cpp @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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 "qeglfsoffscreenwindow.h" +#include "qeglfshooks.h" +#include <QtGui/QOffscreenSurface> +#include <QtPlatformSupport/private/qeglconvenience_p.h> + +QT_BEGIN_NAMESPACE + +/* + In some cases pbuffers are not available. Triggering QtGui's built-in + fallback for a hidden QWindow is not suitable for eglfs since this would be + treated as an attempt to create multiple top-level, native windows. + + Therefore this class is provided as an alternative to QEGLPbuffer. + + This class requires the hooks to implement createNativeOffscreenWindow(). +*/ + +QEglFSOffscreenWindow::QEglFSOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface) + : QPlatformOffscreenSurface(offscreenSurface) + , m_format(format) + , m_display(display) + , m_surface(EGL_NO_SURFACE) + , m_window(0) +{ + m_window = qt_egl_device_integration()->createNativeOffscreenWindow(format); + if (!m_window) { + qWarning("QEglFSOffscreenWindow: Failed to create native window"); + return; + } + EGLConfig config = q_configFromGLFormat(m_display, m_format); + m_surface = eglCreateWindowSurface(m_display, config, m_window, 0); + if (m_surface != EGL_NO_SURFACE) + m_format = q_glFormatFromConfig(m_display, config); +} + +QEglFSOffscreenWindow::~QEglFSOffscreenWindow() +{ + if (m_surface != EGL_NO_SURFACE) + eglDestroySurface(m_display, m_surface); + if (m_window) + qt_egl_device_integration()->destroyNativeWindow(m_window); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h new file mode 100644 index 0000000000..128ff56968 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** 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 QEGLFSOFFSCREENWINDOW_H +#define QEGLFSOFFSCREENWINDOW_H + +#include <EGL/egl.h> +#include <qpa/qplatformoffscreensurface.h> +#include "qeglfsglobal.h" + +QT_BEGIN_NAMESPACE + +class Q_EGLFS_EXPORT QEglFSOffscreenWindow : public QPlatformOffscreenSurface +{ +public: + QEglFSOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface); + ~QEglFSOffscreenWindow(); + + QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; } + bool isValid() const Q_DECL_OVERRIDE { return m_surface != EGL_NO_SURFACE; } + +private: + QSurfaceFormat m_format; + EGLDisplay m_display; + EGLSurface m_surface; + EGLNativeWindowType m_window; +}; + +QT_END_NAMESPACE + +#endif // QEGLFSOFFSCREENWINDOW_H diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp index cd68540581..84ea1c6483 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -34,18 +34,16 @@ #include "qeglfsscreen.h" #include "qeglfswindow.h" #include "qeglfshooks.h" -#include <QtPlatformSupport/private/qeglplatformcursor_p.h> +#include <QtGui/qpa/qplatformcursor.h> QT_BEGIN_NAMESPACE QEglFSScreen::QEglFSScreen(EGLDisplay dpy) : QEGLPlatformScreen(dpy), m_surface(EGL_NO_SURFACE), - m_cursor(0), - m_rootWindow(0), - m_rootContext(0) + m_cursor(0) { - m_cursor = QEglFSHooks::hooks()->createCursor(this); + m_cursor = qt_egl_device_integration()->createCursor(this); } QEglFSScreen::~QEglFSScreen() @@ -55,37 +53,37 @@ QEglFSScreen::~QEglFSScreen() QRect QEglFSScreen::geometry() const { - return QRect(QPoint(0, 0), QEglFSHooks::hooks()->screenSize()); + return QRect(QPoint(0, 0), qt_egl_device_integration()->screenSize()); } int QEglFSScreen::depth() const { - return QEglFSHooks::hooks()->screenDepth(); + return qt_egl_device_integration()->screenDepth(); } QImage::Format QEglFSScreen::format() const { - return QEglFSHooks::hooks()->screenFormat(); + return qt_egl_device_integration()->screenFormat(); } QSizeF QEglFSScreen::physicalSize() const { - return QEglFSHooks::hooks()->physicalScreenSize(); + return qt_egl_device_integration()->physicalScreenSize(); } QDpi QEglFSScreen::logicalDpi() const { - return QEglFSHooks::hooks()->logicalDpi(); + return qt_egl_device_integration()->logicalDpi(); } Qt::ScreenOrientation QEglFSScreen::nativeOrientation() const { - return QEglFSHooks::hooks()->nativeOrientation(); + return qt_egl_device_integration()->nativeOrientation(); } Qt::ScreenOrientation QEglFSScreen::orientation() const { - return QEglFSHooks::hooks()->orientation(); + return qt_egl_device_integration()->orientation(); } QPlatformCursor *QEglFSScreen::cursor() const diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h index 132646d7a6..59f55d33fb 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.h +++ b/src/plugins/platforms/eglfs/qeglfsscreen.h @@ -34,19 +34,16 @@ #ifndef QEGLFSSCREEN_H #define QEGLFSSCREEN_H +#include "qeglfsglobal.h" #include <QtPlatformSupport/private/qeglplatformscreen_p.h> - -#include <QtCore/QTextStream> - #include <EGL/egl.h> QT_BEGIN_NAMESPACE -class QEGLPlatformCursor; class QEglFSWindow; class QOpenGLContext; -class QEglFSScreen : public QEGLPlatformScreen +class Q_EGLFS_EXPORT QEglFSScreen : public QEGLPlatformScreen { public: QEglFSScreen(EGLDisplay display); @@ -65,12 +62,6 @@ public: EGLSurface primarySurface() const { return m_surface; } - QEGLPlatformWindow *compositingWindow() Q_DECL_OVERRIDE { return m_rootWindow; } - QOpenGLContext *compositingContext() Q_DECL_OVERRIDE { return m_rootContext; } - - void setRootWindow(QEGLPlatformWindow *window) { m_rootWindow = window; } - void setRootContext(QOpenGLContext *context) { m_rootContext = context; } - protected: void setPrimarySurface(EGLSurface surface); @@ -78,9 +69,7 @@ private: friend class QEglFSWindow; EGLSurface m_surface; - QEGLPlatformCursor *m_cursor; - QEGLPlatformWindow *m_rootWindow; - QOpenGLContext *m_rootContext; + QPlatformCursor *m_cursor; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index f5839e086d..d568d50e59 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -39,7 +39,6 @@ #include <QtGui/QOpenGLContext> #include <QtPlatformSupport/private/qeglplatformcursor_p.h> #include <QtPlatformSupport/private/qeglconvenience_p.h> - #include <QtDebug> QT_BEGIN_NAMESPACE @@ -73,9 +72,10 @@ void QEglFSWindow::create() // raster windows will not have their own native window, surface and context. Instead, // they will be composited onto the root window's surface. QEglFSScreen *screen = this->screen(); + QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); if (screen->primarySurface() != EGL_NO_SURFACE) { - if (isRaster() && screen->compositingWindow()) { - m_format = screen->compositingWindow()->format(); + if (isRaster() && compositor->targetWindow()) { + m_format = compositor->targetWindow()->format(); return; } @@ -93,7 +93,7 @@ void QEglFSWindow::create() QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size())); EGLDisplay display = static_cast<QEglFSScreen *>(screen)->display(); - QSurfaceFormat platformFormat = QEglFSHooks::hooks()->surfaceFormatFor(window()->requestedFormat()); + QSurfaceFormat platformFormat = qt_egl_device_integration()->surfaceFormatFor(window()->requestedFormat()); m_config = QEglFSIntegration::chooseConfig(display, platformFormat); m_format = q_glFormatFromConfig(display, m_config, platformFormat); @@ -107,8 +107,7 @@ void QEglFSWindow::create() context->setScreen(window()->screen()); if (!context->create()) qFatal("EGLFS: Failed to create compositing context"); - screen->setRootContext(context); - screen->setRootWindow(this); + compositor->setTarget(context, window()); } } @@ -116,7 +115,7 @@ void QEglFSWindow::destroy() { QEglFSScreen *screen = this->screen(); if (m_flags.testFlag(HasNativeWindow)) { - QEGLPlatformCursor *cursor = static_cast<QEGLPlatformCursor *>(screen->cursor()); + QEGLPlatformCursor *cursor = qobject_cast<QEGLPlatformCursor *>(screen->cursor()); if (cursor) cursor->resetResources(); @@ -127,7 +126,7 @@ void QEglFSWindow::destroy() } m_flags = 0; - screen->removeWindow(this); + QOpenGLCompositor::instance()->removeWindow(this); } // The virtual functions resetSurface and invalidateSurface may get overridden @@ -141,14 +140,15 @@ void QEglFSWindow::invalidateSurface() eglDestroySurface(display, m_surface); m_surface = EGL_NO_SURFACE; } - QEglFSHooks::hooks()->destroyNativeWindow(m_window); + qt_egl_device_integration()->destroyNativeWindow(m_window); m_window = 0; } void QEglFSWindow::resetSurface() { - EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display(); - m_window = QEglFSHooks::hooks()->createNativeWindow(this, QEglFSHooks::hooks()->screenSize(), m_format); + QEglFSScreen *nativeScreen = static_cast<QEglFSScreen *>(screen()); + EGLDisplay display = nativeScreen->display(); + m_window = qt_egl_device_integration()->createNativeWindow(this, nativeScreen->geometry().size(), m_format); m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL); if (m_surface == EGL_NO_SURFACE) { EGLint error = eglGetError(); @@ -159,17 +159,18 @@ void QEglFSWindow::resetSurface() void QEglFSWindow::setVisible(bool visible) { - QList<QEGLPlatformWindow *> windows = screen()->windows(); + QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); + QList<QOpenGLCompositorWindow *> windows = compositor->windows(); QWindow *wnd = window(); if (wnd->type() != Qt::Desktop) { if (visible) { - screen()->addWindow(this); + compositor->addWindow(this); } else { - screen()->removeWindow(this); - windows = screen()->windows(); + compositor->removeWindow(this); + windows = compositor->windows(); if (windows.size()) - windows.last()->requestActivateWindow(); + windows.last()->sourceWindow()->requestActivate(); } } @@ -209,7 +210,7 @@ QRect QEglFSWindow::geometry() const void QEglFSWindow::requestActivateWindow() { if (window()->type() != Qt::Desktop) - screen()->moveToTop(this); + QOpenGLCompositor::instance()->moveToTop(this); QWindow *wnd = window(); QWindowSystemInterface::handleWindowActivated(wnd); @@ -220,20 +221,21 @@ void QEglFSWindow::raise() { QWindow *wnd = window(); if (wnd->type() != Qt::Desktop) { - screen()->moveToTop(this); + QOpenGLCompositor::instance()->moveToTop(this); QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size())); } } void QEglFSWindow::lower() { - QList<QEGLPlatformWindow *> windows = screen()->windows(); + QOpenGLCompositor *compositor = QOpenGLCompositor::instance(); + QList<QOpenGLCompositorWindow *> windows = compositor->windows(); if (window()->type() != Qt::Desktop && windows.count() > 1) { int idx = windows.indexOf(this); if (idx > 0) { - screen()->changeWindowIndex(this, idx - 1); - QWindowSystemInterface::handleExposeEvent(windows.last()->window(), - QRect(QPoint(0, 0), windows.last()->geometry().size())); + compositor->changeWindowIndex(this, idx - 1); + QWindowSystemInterface::handleExposeEvent(windows.last()->sourceWindow(), + QRect(QPoint(0, 0), windows.last()->sourceWindow()->geometry().size())); } } } diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index 5dfa35197f..a3e3722b5a 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.h +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -36,12 +36,12 @@ #include "qeglfsintegration.h" #include "qeglfsscreen.h" - +#include "qeglfsglobal.h" #include <QtPlatformSupport/private/qeglplatformwindow_p.h> QT_BEGIN_NAMESPACE -class QEglFSWindow : public QEGLPlatformWindow +class Q_EGLFS_EXPORT QEglFSWindow : public QEGLPlatformWindow { public: QEglFSWindow(QWindow *w); @@ -70,7 +70,7 @@ public: bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); } - virtual void invalidateSurface(); + virtual void invalidateSurface() Q_DECL_OVERRIDE; virtual void resetSurface(); protected: diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index 461f160892..ff4b753cc1 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -120,7 +120,7 @@ QIOSIntegration::~QIOSIntegration() m_inputContext = 0; foreach (QScreen *screen, QGuiApplication::screens()) - delete screen->handle(); + destroyScreen(screen->handle()); delete m_platformServices; m_platformServices = 0; diff --git a/src/plugins/platforms/ios/quiaccessibilityelement.mm b/src/plugins/platforms/ios/quiaccessibilityelement.mm index 63b6827ad3..3dff271d00 100644 --- a/src/plugins/platforms/ios/quiaccessibilityelement.mm +++ b/src/plugins/platforms/ios/quiaccessibilityelement.mm @@ -193,4 +193,33 @@ action->doAction(QAccessibleActionInterface::decreaseAction()); } +- (BOOL) accessibilityScroll : (UIAccessibilityScrollDirection) direction +{ + QAccessibleInterface *iface = QAccessible::accessibleInterface(self.axid); + QAccessibleActionInterface *action = iface->actionInterface(); + if (!action) + return NO; + switch (direction) { + case UIAccessibilityScrollDirectionRight: + action->doAction(QAccessibleActionInterface::scrollRightAction()); + return YES; + case UIAccessibilityScrollDirectionLeft: + action->doAction(QAccessibleActionInterface::scrollLeftAction()); + return YES; + case UIAccessibilityScrollDirectionUp: + action->doAction(QAccessibleActionInterface::scrollUpAction()); + return YES; + case UIAccessibilityScrollDirectionDown: + action->doAction(QAccessibleActionInterface::scrollDownAction()); + return YES; + case UIAccessibilityScrollDirectionNext: + action->doAction(QAccessibleActionInterface::nextPageAction()); + return YES; + case UIAccessibilityScrollDirectionPrevious: + action->doAction(QAccessibleActionInterface::previousPageAction()); + return YES; + } + return NO; +} + @end diff --git a/src/plugins/platforms/kms/main.cpp b/src/plugins/platforms/kms/main.cpp index 39ca77bd56..9e9e2c7344 100644 --- a/src/plugins/platforms/kms/main.cpp +++ b/src/plugins/platforms/kms/main.cpp @@ -41,7 +41,7 @@ class QKmsIntegrationPlugin : public QPlatformIntegrationPlugin Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "kms.json") public: - QPlatformIntegration *create(const QString&, const QStringList&); + QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; QPlatformIntegration *QKmsIntegrationPlugin::create(const QString& system, const QStringList& paramList) diff --git a/src/plugins/platforms/kms/qkmsbackingstore.h b/src/plugins/platforms/kms/qkmsbackingstore.h index 56d57313e8..a8f2dddd03 100644 --- a/src/plugins/platforms/kms/qkmsbackingstore.h +++ b/src/plugins/platforms/kms/qkmsbackingstore.h @@ -49,12 +49,12 @@ public: QKmsBackingStore(QWindow *window); ~QKmsBackingStore(); - QPaintDevice *paintDevice(); + QPaintDevice *paintDevice() Q_DECL_OVERRIDE; - void beginPaint(const QRegion &); + void beginPaint(const QRegion &) Q_DECL_OVERRIDE; - void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); - void resize(const QSize &size, const QRegion &staticContents); + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; + void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; QImage toImage() const Q_DECL_OVERRIDE { return m_image; } diff --git a/src/plugins/platforms/kms/qkmscontext.h b/src/plugins/platforms/kms/qkmscontext.h index b388dba7d5..fabe3c2524 100644 --- a/src/plugins/platforms/kms/qkmscontext.h +++ b/src/plugins/platforms/kms/qkmscontext.h @@ -48,14 +48,14 @@ class QKmsContext : public QPlatformOpenGLContext public: QKmsContext(QOpenGLContext *context, QKmsDevice *device); - bool makeCurrent(QPlatformSurface *surface); - void doneCurrent(); - void swapBuffers(QPlatformSurface *surface); - void (*getProcAddress(const QByteArray &procName)) (); + 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; - bool isValid() const; + bool isValid() const Q_DECL_OVERRIDE; - QSurfaceFormat format() const; + QSurfaceFormat format() const Q_DECL_OVERRIDE; EGLContext eglContext() const; diff --git a/src/plugins/platforms/kms/qkmscursor.h b/src/plugins/platforms/kms/qkmscursor.h index 3eef4e599c..35d9814224 100644 --- a/src/plugins/platforms/kms/qkmscursor.h +++ b/src/plugins/platforms/kms/qkmscursor.h @@ -49,8 +49,8 @@ public: QKmsCursor(QKmsScreen *screen); ~QKmsCursor(); - void pointerEvent(const QMouseEvent &event); - void changeCursor(QCursor *windowCursor, QWindow *window); + void pointerEvent(const QMouseEvent &event) Q_DECL_OVERRIDE; + void changeCursor(QCursor *windowCursor, QWindow *window) Q_DECL_OVERRIDE; private: QKmsScreen *m_screen; diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp index d94d7d9aaa..5ad58ba54f 100644 --- a/src/plugins/platforms/kms/qkmsintegration.cpp +++ b/src/plugins/platforms/kms/qkmsintegration.cpp @@ -74,7 +74,7 @@ QKmsIntegration::~QKmsIntegration() delete device; } foreach (QPlatformScreen *screen, m_screens) { - delete screen; + destroyScreen(screen); } delete m_fontDatabase; delete m_vtHandler; diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.cpp b/src/plugins/platforms/kms/qkmsnativeinterface.cpp index 3ed1643fdb..c133b48086 100644 --- a/src/plugins/platforms/kms/qkmsnativeinterface.cpp +++ b/src/plugins/platforms/kms/qkmsnativeinterface.cpp @@ -52,6 +52,21 @@ public: Q_GLOBAL_STATIC(QKmsResourceMap, qKmsResourceMap) +void *QKmsNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString) +{ + QByteArray lowerCaseResource = resourceString.toLower(); + ResourceType resource = qKmsResourceMap()->value(lowerCaseResource); + void *result = 0; + switch (resource) { + case EglDisplay: + result = eglDisplay(); + break; + default: + result = 0; + } + return result; + +} void *QKmsNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) { QByteArray lowerCaseResource = resourceString.toLower(); @@ -79,7 +94,14 @@ QPlatformNativeInterface::NativeResourceForContextFunction QKmsNativeInterface:: return 0; } - +void *QKmsNativeInterface::eglDisplay() +{ + //QKmsIntegration *integration = static_cast<QKmsIntegration *>(QGuiApplicationPrivate::platformIntegration()); + QKmsScreen *screen = static_cast<QKmsScreen *>(QGuiApplication::primaryScreen()->handle()); + if (!screen || !screen->device()) + return 0; + return screen->device()->eglDisplay(); +} void *QKmsNativeInterface::eglDisplayForWindow(QWindow *window) { diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.h b/src/plugins/platforms/kms/qkmsnativeinterface.h index b9ef914045..402c8b7f6f 100644 --- a/src/plugins/platforms/kms/qkmsnativeinterface.h +++ b/src/plugins/platforms/kms/qkmsnativeinterface.h @@ -46,10 +46,12 @@ public: EglContext }; - void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window); + void *nativeResourceForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE; + void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE; - NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource); + NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE; + void *eglDisplay(); void *eglDisplayForWindow(QWindow *window); void *eglContextForWindow(QWindow *window); static void *eglContextForContext(QOpenGLContext *context); diff --git a/src/plugins/platforms/kms/qkmsscreen.cpp b/src/plugins/platforms/kms/qkmsscreen.cpp index ddcdd10928..84c1eba448 100644 --- a/src/plugins/platforms/kms/qkmsscreen.cpp +++ b/src/plugins/platforms/kms/qkmsscreen.cpp @@ -216,7 +216,7 @@ void QKmsScreen::performPageFlip() // Initialize cursor - static int hideCursor = qgetenv("QT_QPA_KMS_HIDECURSOR").toInt(); + static int hideCursor = qEnvironmentVariableIntValue("QT_QPA_KMS_HIDECURSOR"); if (!hideCursor) { QCursor cursor(Qt::ArrowCursor); m_cursor->changeCursor(&cursor, 0); diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h index 552541503c..8557e12a03 100644 --- a/src/plugins/platforms/kms/qkmsscreen.h +++ b/src/plugins/platforms/kms/qkmsscreen.h @@ -67,11 +67,11 @@ public: QKmsScreen(QKmsDevice *device, const drmModeRes *resources, const drmModeConnector *connector); ~QKmsScreen(); - QRect geometry() const; - int depth() const; - QImage::Format format() const; - QSizeF physicalSize() const; - QPlatformCursor *cursor() const; + QRect geometry() const Q_DECL_OVERRIDE; + int depth() const Q_DECL_OVERRIDE; + QImage::Format format() const Q_DECL_OVERRIDE; + QSizeF physicalSize() const Q_DECL_OVERRIDE; + QPlatformCursor *cursor() const Q_DECL_OVERRIDE; quint32 crtcId() const { return m_crtcId; } QKmsDevice *device() const; diff --git a/src/plugins/platforms/linuxfb/main.cpp b/src/plugins/platforms/linuxfb/main.cpp index 14cd3611d9..1fcf3fa0a8 100644 --- a/src/plugins/platforms/linuxfb/main.cpp +++ b/src/plugins/platforms/linuxfb/main.cpp @@ -41,7 +41,7 @@ class QLinuxFbIntegrationPlugin : public QPlatformIntegrationPlugin Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "linuxfb.json") public: - QPlatformIntegration *create(const QString&, const QStringList&); + QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; QPlatformIntegration* QLinuxFbIntegrationPlugin::create(const QString& system, const QStringList& paramList) diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp index cb870847f2..1600ee3f2b 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -46,6 +46,16 @@ #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatforminputcontextfactory_p.h> +#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) +#include <QtPlatformSupport/private/qevdevmousemanager_p.h> +#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h> +#include <QtPlatformSupport/private/qevdevtouch_p.h> +#endif + +#if !defined(QT_NO_TSLIB) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) +#include <QtPlatformSupport/private/qtslib_p.h> +#endif + QT_BEGIN_NAMESPACE QLinuxFbIntegration::QLinuxFbIntegration(const QStringList ¶mList) @@ -57,7 +67,7 @@ QLinuxFbIntegration::QLinuxFbIntegration(const QStringList ¶mList) QLinuxFbIntegration::~QLinuxFbIntegration() { - delete m_primaryScreen; + destroyScreen(m_primaryScreen); } void QLinuxFbIntegration::initialize() @@ -70,6 +80,9 @@ void QLinuxFbIntegration::initialize() m_inputContext = QPlatformInputContextFactory::create(); m_vtHandler.reset(new QFbVtHandler); + + if (!qEnvironmentVariableIntValue("QT_QPA_FB_DISABLE_INPUT")) + createInputHandlers(); } bool QLinuxFbIntegration::hasCapability(QPlatformIntegration::Capability cap) const @@ -113,4 +126,24 @@ QPlatformServices *QLinuxFbIntegration::services() const return m_services.data(); } +void QLinuxFbIntegration::createInputHandlers() +{ +#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)) + new QEvdevKeyboardManager(QLatin1String("EvdevKeyboard"), QString(), this); + QEvdevMouseManager *mouseMgr = new QEvdevMouseManager(QLatin1String("EvdevMouse"), QString(), this); + Q_FOREACH (QScreen *screen, QGuiApplication::screens()) { + QFbCursor *cursor = qobject_cast<QFbCursor *>(screen->handle()->cursor()); + if (cursor) + cursor->setMouseDeviceDiscovery(mouseMgr->deviceDiscovery()); + } +#ifndef QT_NO_TSLIB + const bool useTslib = qEnvironmentVariableIntValue("QT_QPA_FB_TSLIB"); + if (useTslib) + new QTsLibMouseHandler(QLatin1String("TsLib"), QString()); + else +#endif // QT_NO_TSLIB + new QEvdevTouchScreenHandlerThread(QString(), this); +#endif +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h index cabd943921..3e7e1c57f4 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h @@ -35,6 +35,7 @@ #define QLINUXFBINTEGRATION_H #include <qpa/qplatformintegration.h> +#include <qpa/qplatformnativeinterface.h> QT_BEGIN_NAMESPACE @@ -42,7 +43,7 @@ class QAbstractEventDispatcher; class QLinuxFbScreen; class QFbVtHandler; -class QLinuxFbIntegration : public QPlatformIntegration +class QLinuxFbIntegration : public QPlatformIntegration, public QPlatformNativeInterface { public: QLinuxFbIntegration(const QStringList ¶mList); @@ -63,6 +64,8 @@ public: QList<QPlatformScreen *> screens() const; private: + void createInputHandlers(); + QLinuxFbScreen *m_primaryScreen; QPlatformInputContext *m_inputContext; QScopedPointer<QPlatformFontDatabase> m_fontDb; diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h index 1997d46ad1..32b8c3f4ab 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h +++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h @@ -51,7 +51,7 @@ public: bool initialize(); public slots: - QRegion doRedraw(); + QRegion doRedraw() Q_DECL_OVERRIDE; private: QStringList mArgs; diff --git a/src/plugins/platforms/minimal/main.cpp b/src/plugins/platforms/minimal/main.cpp index 191de630b2..d4db29016d 100644 --- a/src/plugins/platforms/minimal/main.cpp +++ b/src/plugins/platforms/minimal/main.cpp @@ -42,7 +42,7 @@ class QMinimalIntegrationPlugin : public QPlatformIntegrationPlugin Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "minimal.json") public: - QPlatformIntegration *create(const QString&, const QStringList&); + QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; QPlatformIntegration *QMinimalIntegrationPlugin::create(const QString& system, const QStringList& paramList) diff --git a/src/plugins/platforms/minimal/qminimalbackingstore.h b/src/plugins/platforms/minimal/qminimalbackingstore.h index d356153b62..e373d99783 100644 --- a/src/plugins/platforms/minimal/qminimalbackingstore.h +++ b/src/plugins/platforms/minimal/qminimalbackingstore.h @@ -46,9 +46,9 @@ public: QMinimalBackingStore(QWindow *window); ~QMinimalBackingStore(); - QPaintDevice *paintDevice(); - void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); - void resize(const QSize &size, const QRegion &staticContents); + QPaintDevice *paintDevice() Q_DECL_OVERRIDE; + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; + void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; private: QImage mImage; diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp index 252f842df4..8a2bf79116 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.cpp +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -66,7 +66,7 @@ QMinimalIntegration::QMinimalIntegration(const QStringList ¶meters) , m_options(parseOptions(parameters)) { if (qEnvironmentVariableIsSet(debugBackingStoreEnvironmentVariable) - && qgetenv(debugBackingStoreEnvironmentVariable).toInt() > 0) { + && qEnvironmentVariableIntValue(debugBackingStoreEnvironmentVariable) > 0) { m_options |= DebugBackingStore | EnableFonts; } @@ -99,7 +99,7 @@ bool QMinimalIntegration::hasCapability(QPlatformIntegration::Capability cap) co class DummyFontDatabase : public QPlatformFontDatabase { public: - virtual void populateFontDatabase() {} + virtual void populateFontDatabase() Q_DECL_OVERRIDE {} }; QPlatformFontDatabase *QMinimalIntegration::fontDatabase() const diff --git a/src/plugins/platforms/minimal/qminimalintegration.h b/src/plugins/platforms/minimal/qminimalintegration.h index d9392df510..d1ab02c0dc 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.h +++ b/src/plugins/platforms/minimal/qminimalintegration.h @@ -45,9 +45,9 @@ public: QMinimalScreen() : mDepth(32), mFormat(QImage::Format_ARGB32_Premultiplied) {} - QRect geometry() const { return mGeometry; } - int depth() const { return mDepth; } - QImage::Format format() const { return mFormat; } + QRect geometry() const Q_DECL_OVERRIDE { return mGeometry; } + int depth() const Q_DECL_OVERRIDE { return mDepth; } + QImage::Format format() const Q_DECL_OVERRIDE { return mFormat; } public: QRect mGeometry; @@ -67,12 +67,12 @@ public: explicit QMinimalIntegration(const QStringList ¶meters); ~QMinimalIntegration(); - bool hasCapability(QPlatformIntegration::Capability cap) const; - QPlatformFontDatabase *fontDatabase() const; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; + QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; - QPlatformWindow *createPlatformWindow(QWindow *window) const; - QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; - QAbstractEventDispatcher *createEventDispatcher() const; + QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; + QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; unsigned options() const { return m_options; } diff --git a/src/plugins/platforms/minimalegl/main.cpp b/src/plugins/platforms/minimalegl/main.cpp index de130ae2ff..f66c8008d0 100644 --- a/src/plugins/platforms/minimalegl/main.cpp +++ b/src/plugins/platforms/minimalegl/main.cpp @@ -41,7 +41,7 @@ class QMinimalEglIntegrationPlugin : public QPlatformIntegrationPlugin Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "minimalegl.json") public: - QPlatformIntegration *create(const QString&, const QStringList&); + QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; QPlatformIntegration* QMinimalEglIntegrationPlugin::create(const QString& system, const QStringList& paramList) diff --git a/src/plugins/platforms/minimalegl/qminimaleglbackingstore.h b/src/plugins/platforms/minimalegl/qminimaleglbackingstore.h index 617ab9a1b9..483c5fc789 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglbackingstore.h +++ b/src/plugins/platforms/minimalegl/qminimaleglbackingstore.h @@ -47,13 +47,13 @@ public: QMinimalEglBackingStore(QWindow *window); ~QMinimalEglBackingStore(); - QPaintDevice *paintDevice(); + QPaintDevice *paintDevice() Q_DECL_OVERRIDE; - void beginPaint(const QRegion &); - void endPaint(); + void beginPaint(const QRegion &) Q_DECL_OVERRIDE; + void endPaint() Q_DECL_OVERRIDE; - void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); - void resize(const QSize &size, const QRegion &staticContents); + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; + void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; private: QOpenGLContext *m_context; diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp index 0b12e62cc1..3fbed1ec26 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp +++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp @@ -60,7 +60,7 @@ QMinimalEglIntegration::QMinimalEglIntegration() QMinimalEglIntegration::~QMinimalEglIntegration() { - delete mScreen; + destroyScreen(mScreen); } bool QMinimalEglIntegration::hasCapability(QPlatformIntegration::Capability cap) const diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.h b/src/plugins/platforms/minimalegl/qminimaleglintegration.h index 5c42184926..452185bcdb 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglintegration.h +++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.h @@ -47,17 +47,17 @@ public: QMinimalEglIntegration(); ~QMinimalEglIntegration(); - bool hasCapability(QPlatformIntegration::Capability cap) const; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - QPlatformWindow *createPlatformWindow(QWindow *window) const; - QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; - QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; + QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; - QPlatformFontDatabase *fontDatabase() const; + QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; - QAbstractEventDispatcher *createEventDispatcher() const; + QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; - QVariant styleHint(QPlatformIntegration::StyleHint hint) const; + QVariant styleHint(QPlatformIntegration::StyleHint hint) const Q_DECL_OVERRIDE; private: QPlatformFontDatabase *mFontDb; diff --git a/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp b/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp index a0ebffa806..af99a8c664 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp +++ b/src/plugins/platforms/minimalegl/qminimaleglscreen.cpp @@ -54,7 +54,7 @@ public: { } - EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) + EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface) Q_DECL_OVERRIDE { QMinimalEglWindow *window = static_cast<QMinimalEglWindow *>(surface); QMinimalEglScreen *screen = static_cast<QMinimalEglScreen *>(window->screen()); diff --git a/src/plugins/platforms/minimalegl/qminimaleglscreen.h b/src/plugins/platforms/minimalegl/qminimaleglscreen.h index 9e5dc90971..e70d52f1aa 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglscreen.h +++ b/src/plugins/platforms/minimalegl/qminimaleglscreen.h @@ -50,9 +50,9 @@ public: QMinimalEglScreen(EGLNativeDisplayType display); ~QMinimalEglScreen(); - QRect geometry() const; - int depth() const; - QImage::Format format() const; + QRect geometry() const Q_DECL_OVERRIDE; + int depth() const Q_DECL_OVERRIDE; + QImage::Format format() const Q_DECL_OVERRIDE; QPlatformOpenGLContext *platformContext() const; diff --git a/src/plugins/platforms/minimalegl/qminimaleglwindow.h b/src/plugins/platforms/minimalegl/qminimaleglwindow.h index 5c3006663f..536cae6f46 100644 --- a/src/plugins/platforms/minimalegl/qminimaleglwindow.h +++ b/src/plugins/platforms/minimalegl/qminimaleglwindow.h @@ -46,8 +46,8 @@ class QMinimalEglWindow : public QPlatformWindow public: QMinimalEglWindow(QWindow *w); - void setGeometry(const QRect &); - WId winId() const; + void setGeometry(const QRect &) Q_DECL_OVERRIDE; + WId winId() const Q_DECL_OVERRIDE; private: WId m_winid; diff --git a/src/plugins/platforms/offscreen/main.cpp b/src/plugins/platforms/offscreen/main.cpp index 98b8e2ba95..102b349b7a 100644 --- a/src/plugins/platforms/offscreen/main.cpp +++ b/src/plugins/platforms/offscreen/main.cpp @@ -42,7 +42,7 @@ class QOffscreenIntegrationPlugin : public QPlatformIntegrationPlugin Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "offscreen.json") public: - QPlatformIntegration *create(const QString&, const QStringList&); + QPlatformIntegration *create(const QString&, const QStringList&) Q_DECL_OVERRIDE; }; QPlatformIntegration *QOffscreenIntegrationPlugin::create(const QString& system, const QStringList& paramList) diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.cpp b/src/plugins/platforms/offscreen/qoffscreencommon.cpp index 50c9a85fcf..5acb245be0 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.cpp +++ b/src/plugins/platforms/offscreen/qoffscreencommon.cpp @@ -49,8 +49,8 @@ class QOffscreenCursor : public QPlatformCursor public: QOffscreenCursor() : m_pos(10, 10) {} - QPoint pos() const { return m_pos; } - void setPos(const QPoint &pos) + QPoint pos() const Q_DECL_OVERRIDE { return m_pos; } + void setPos(const QPoint &pos) Q_DECL_OVERRIDE { m_pos = pos; QWindowList wl = QGuiApplication::topLevelWindows(); @@ -76,7 +76,7 @@ public: QOffscreenScreen::windowContainingCursor = containing ? containing->handle() : 0; } - void changeCursor(QCursor *windowCursor, QWindow *window) + void changeCursor(QCursor *windowCursor, QWindow *window) Q_DECL_OVERRIDE { Q_UNUSED(windowCursor); Q_UNUSED(window); diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.h b/src/plugins/platforms/offscreen/qoffscreencommon.h index 88615d2da4..394d20bce5 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.h +++ b/src/plugins/platforms/offscreen/qoffscreencommon.h @@ -51,12 +51,12 @@ class QOffscreenScreen : public QPlatformScreen public: QOffscreenScreen(); - QRect geometry() const { return m_geometry; } - int depth() const { return 32; } - QImage::Format format() const { return QImage::Format_RGB32; } - QPlatformCursor *cursor() const { return m_cursor.data(); } + QRect geometry() const Q_DECL_OVERRIDE { return m_geometry; } + int depth() const Q_DECL_OVERRIDE { return 32; } + QImage::Format format() const Q_DECL_OVERRIDE { return QImage::Format_RGB32; } + QPlatformCursor *cursor() const Q_DECL_OVERRIDE { return m_cursor.data(); } - QPixmap grabWindow(WId window, int x, int y, int width, int height) const; + QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE; static QPlatformWindow *windowContainingCursor; @@ -69,8 +69,8 @@ public: class QOffscreenDrag : public QPlatformDrag { public: - QMimeData *platformDropData() { return 0; } - Qt::DropAction drag(QDrag *) { return Qt::IgnoreAction; } + QMimeData *platformDropData() Q_DECL_OVERRIDE { return 0; } + Qt::DropAction drag(QDrag *) Q_DECL_OVERRIDE { return Qt::IgnoreAction; } }; #endif @@ -80,10 +80,10 @@ public: QOffscreenBackingStore(QWindow *window); ~QOffscreenBackingStore(); - QPaintDevice *paintDevice(); - void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); - void resize(const QSize &size, const QRegion &staticContents); - bool scroll(const QRegion &area, int dx, int dy); + QPaintDevice *paintDevice() Q_DECL_OVERRIDE; + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; + void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; + bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE; QPixmap grabWindow(WId window, const QRect &rect) const; diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.h b/src/plugins/platforms/offscreen/qoffscreenintegration.h index 714c5eb081..4572269d27 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration.h +++ b/src/plugins/platforms/offscreen/qoffscreenintegration.h @@ -48,17 +48,17 @@ public: QOffscreenIntegration(); ~QOffscreenIntegration(); - bool hasCapability(QPlatformIntegration::Capability cap) const; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - QPlatformWindow *createPlatformWindow(QWindow *window) const; - QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; + QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; #ifndef QT_NO_DRAGANDDROP - QPlatformDrag *drag() const; + QPlatformDrag *drag() const Q_DECL_OVERRIDE; #endif - QPlatformServices *services() const; + QPlatformServices *services() const Q_DECL_OVERRIDE; - QPlatformFontDatabase *fontDatabase() const; - QAbstractEventDispatcher *createEventDispatcher() const; + QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; + QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; static QOffscreenIntegration *createOffscreenIntegration(); diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h index c50e812777..59e62c3c20 100644 --- a/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h +++ b/src/plugins/platforms/offscreen/qoffscreenintegration_x11.h @@ -49,9 +49,9 @@ class QOffscreenX11Info; class QOffscreenX11Integration : public QOffscreenIntegration { public: - bool hasCapability(QPlatformIntegration::Capability cap) const; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; private: mutable QScopedPointer<QOffscreenX11Connection> m_connection; @@ -82,14 +82,14 @@ public: QOffscreenX11GLXContext(QOffscreenX11Info *x11, QOpenGLContext *context); ~QOffscreenX11GLXContext(); - bool makeCurrent(QPlatformSurface *surface); - void doneCurrent(); - void swapBuffers(QPlatformSurface *surface); - void (*getProcAddress(const QByteArray &procName)) (); + 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; - bool isSharing() const; - bool isValid() const; + QSurfaceFormat format() const Q_DECL_OVERRIDE; + bool isSharing() const Q_DECL_OVERRIDE; + bool isValid() const Q_DECL_OVERRIDE; private: QScopedPointer<QOffscreenX11GLXContextData> d; diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.h b/src/plugins/platforms/offscreen/qoffscreenwindow.h index d168d28ee8..e50a5a08ff 100644 --- a/src/plugins/platforms/offscreen/qoffscreenwindow.h +++ b/src/plugins/platforms/offscreen/qoffscreenwindow.h @@ -47,15 +47,15 @@ public: QOffscreenWindow(QWindow *window); ~QOffscreenWindow(); - void setGeometry(const QRect &rect); - void setWindowState(Qt::WindowState state); + void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; + void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE; - QMargins frameMargins() const; + QMargins frameMargins() const Q_DECL_OVERRIDE; - void setVisible(bool visible); - void requestActivateWindow(); + void setVisible(bool visible) Q_DECL_OVERRIDE; + void requestActivateWindow() Q_DECL_OVERRIDE; - WId winId() const; + WId winId() const Q_DECL_OVERRIDE; static QOffscreenWindow *windowForWinId(WId id); diff --git a/src/plugins/platforms/openwfd/qopenwfdintegration.cpp b/src/plugins/platforms/openwfd/qopenwfdintegration.cpp index 1e29fcc9b1..26bdd14327 100644 --- a/src/plugins/platforms/openwfd/qopenwfdintegration.cpp +++ b/src/plugins/platforms/openwfd/qopenwfdintegration.cpp @@ -133,3 +133,8 @@ void QOpenWFDIntegration::addScreen(QOpenWFDScreen *screen) { screenAdded(screen); } + +void QOpenWFDIntegration::destroyScreen(QOpenWFDScreen *screen) +{ + QPlatformIntegration::destroyScreen(screen); +} diff --git a/src/plugins/platforms/openwfd/qopenwfdintegration.h b/src/plugins/platforms/openwfd/qopenwfdintegration.h index 6c086b73be..9243205caa 100644 --- a/src/plugins/platforms/openwfd/qopenwfdintegration.h +++ b/src/plugins/platforms/openwfd/qopenwfdintegration.h @@ -63,6 +63,7 @@ public: QPlatformPrinterSupport *printerSupport() const; void addScreen(QOpenWFDScreen *screen); + void destroyScreen(QOpenWFDScreen *screen); private: QList<QPlatformScreen *> mScreens; QList<QOpenWFDDevice *>mDevices; diff --git a/src/plugins/platforms/openwfd/qopenwfdport.cpp b/src/plugins/platforms/openwfd/qopenwfdport.cpp index 0bdc6b2d4b..b643644800 100644 --- a/src/plugins/platforms/openwfd/qopenwfdport.cpp +++ b/src/plugins/platforms/openwfd/qopenwfdport.cpp @@ -140,7 +140,7 @@ void QOpenWFDPort::detach() mAttached = false; mOn = false; - delete mScreen; + mDevice->integration()->destroyScreen(mScreen); wfdDestroyPipeline(mDevice->handle(),mPipeline); mPipelineId = WFD_INVALID_PIPELINE_ID; diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 69f6f308b5..4e1b7e3026 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -35,8 +35,4 @@ contains(QT_CONFIG, directfb) { SUBDIRS += directfb } -contains(QT_CONFIG, kms):contains(QT_CONFIG, opengl) { - SUBDIRS += kms -} - contains(QT_CONFIG, linuxfb): SUBDIRS += linuxfb diff --git a/src/plugins/platforms/qnx/qqnxglcontext.cpp b/src/plugins/platforms/qnx/qqnxglcontext.cpp index 09736304e1..7133d01e87 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.cpp +++ b/src/plugins/platforms/qnx/qqnxglcontext.cpp @@ -164,7 +164,7 @@ EGLenum QQnxGLContext::checkEGLError(const char *msg) return error; } -void QQnxGLContext::initialize() +void QQnxGLContext::initializeContext() { qGLContextDebug() << Q_FUNC_INFO; @@ -182,7 +182,7 @@ void QQnxGLContext::initialize() } } -void QQnxGLContext::shutdown() +void QQnxGLContext::shutdownContext() { qGLContextDebug() << Q_FUNC_INFO; diff --git a/src/plugins/platforms/qnx/qqnxglcontext.h b/src/plugins/platforms/qnx/qqnxglcontext.h index 090c7ed49d..a91a89901f 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.h +++ b/src/plugins/platforms/qnx/qqnxglcontext.h @@ -53,8 +53,8 @@ public: static EGLenum checkEGLError(const char *msg); - static void initialize(); - static void shutdown(); + static void initializeContext(); + static void shutdownContext(); void requestSurfaceChange(); diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index 34b79b61da..dba4ba67a8 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -182,7 +182,7 @@ QQnxIntegration::QQnxIntegration(const QStringList ¶mList) #if !defined(QT_NO_OPENGL) // Initialize global OpenGL resources - QQnxGLContext::initialize(); + QQnxGLContext::initializeContext(); #endif // Create/start event thread @@ -306,7 +306,7 @@ QQnxIntegration::~QQnxIntegration() #if !defined(QT_NO_OPENGL) // Cleanup global OpenGL resources - QQnxGLContext::shutdown(); + QQnxGLContext::shutdownContext(); #endif #if defined(QQNX_PPS) @@ -554,7 +554,7 @@ void QQnxIntegration::removeDisplay(QQnxScreen *screen) Q_CHECK_PTR(screen); Q_ASSERT(m_screens.contains(screen)); m_screens.removeAll(screen); - screen->deleteLater(); + destroyScreen(screen); } void QQnxIntegration::destroyDisplays() diff --git a/src/plugins/platforms/qnx/qqnxscreen.cpp b/src/plugins/platforms/qnx/qqnxscreen.cpp index d42babb8ab..d4407842f5 100644 --- a/src/plugins/platforms/qnx/qqnxscreen.cpp +++ b/src/plugins/platforms/qnx/qqnxscreen.cpp @@ -305,7 +305,7 @@ static int defaultDepth() if (defaultDepth == 0) { // check if display depth was specified in environment variable; // use default value if no valid value found - defaultDepth = qgetenv("QQNX_DISPLAY_DEPTH").toInt(); + defaultDepth = qEnvironmentVariableIntValue("QQNX_DISPLAY_DEPTH"); if (defaultDepth != 16 && defaultDepth != 32) defaultDepth = 32; } @@ -680,7 +680,7 @@ void QQnxScreen::adjustOrientation() return; bool ok = false; - const int rotation = qgetenv("ORIENTATION").toInt(&ok); + const int rotation = qEnvironmentVariableIntValue("ORIENTATION", &ok); if (ok) setRotation(rotation); @@ -859,7 +859,7 @@ void QQnxScreen::setRootWindow(QQnxWindow *window) { // Optionally disable the screen power save bool ok = false; - const int disablePowerSave = qgetenv("QQNX_DISABLE_POWER_SAVE").toInt(&ok); + const int disablePowerSave = qEnvironmentVariableIntValue("QQNX_DISABLE_POWER_SAVE", &ok); if (ok && disablePowerSave) { const int mode = SCREEN_IDLE_MODE_KEEP_AWAKE; int result = screen_set_window_property_iv(window->nativeHandle(), SCREEN_PROPERTY_IDLE_MODE, &mode); diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 7f60be0d50..3d6a6ced6e 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -121,7 +121,7 @@ AccessibleRelation::AccessibleRelation(const QList<QAccessibleInterface *> &targ HRESULT STDMETHODCALLTYPE AccessibleRelation::QueryInterface(REFIID id, LPVOID *iface) { *iface = 0; - if (id == IID_IUnknown) + if (id == IID_IUnknown || id == IID_IAccessibleRelation) *iface = (IUnknown*)this; if (*iface) { diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index 351bf2555c..f7f5e022c3 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -39,24 +39,7 @@ #include "qwindowsmsaaaccessible.h" #include "comutils.h" -#include "Accessible2.h" -#include "AccessibleAction.h" -#include "AccessibleApplication.h" -#include "AccessibleComponent.h" -#include "AccessibleEditableText.h" -#include "AccessibleHyperlink.h" -#include "AccessibleHypertext.h" -#include "AccessibleImage.h" -#include "AccessibleRelation.h" -#include "AccessibleTable.h" -#include "AccessibleTable2.h" -#include "AccessibleTableCell.h" -#include "AccessibleText.h" -#include "AccessibleValue.h" - -#include "AccessibleEventID.h" -#include "AccessibleRole.h" -#include "AccessibleStates.h" +#include "ia2_api_all.h" #include <servprov.h> diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h index a78d821b1d..c522cf281e 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h @@ -42,7 +42,7 @@ #include <QtGui/qaccessible.h> #ifndef Q_CC_MINGW # include <oleacc.h> -# include "Accessible2.h" // IAccessible2 inherits from IAccessible +# include "ia2_api_all.h" // IAccessible2 inherits from IAccessible #else // MinGW # include <basetyps.h> diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index f1f472b3e2..3a0c3b9fe9 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -1580,14 +1580,14 @@ QWindowsNativeDialogBase *QWindowsFileDialogHelper::createNativeDialog() QWindowsNativeFileDialogBase *result = QWindowsNativeFileDialogBase::create(options()->acceptMode(), m_data); if (!result) return 0; - QObject::connect(result, SIGNAL(accepted()), this, SIGNAL(accept())); - QObject::connect(result, SIGNAL(rejected()), this, SIGNAL(reject())); - QObject::connect(result, SIGNAL(directoryEntered(QUrl)), - this, SIGNAL(directoryEntered(QUrl))); - QObject::connect(result, SIGNAL(currentChanged(QUrl)), - this, SIGNAL(currentChanged(QUrl))); - QObject::connect(result, SIGNAL(filterSelected(QString)), - this, SIGNAL(filterSelected(QString))); + QObject::connect(result, &QWindowsNativeDialogBase::accepted, this, &QPlatformDialogHelper::accept); + QObject::connect(result, &QWindowsNativeDialogBase::rejected, this, &QPlatformDialogHelper::reject); + QObject::connect(result, &QWindowsNativeFileDialogBase::directoryEntered, + this, &QPlatformFileDialogHelper::directoryEntered); + QObject::connect(result, &QWindowsNativeFileDialogBase::currentChanged, + this, &QPlatformFileDialogHelper::currentChanged); + QObject::connect(result, &QWindowsNativeFileDialogBase::filterSelected, + this, &QPlatformFileDialogHelper::filterSelected); // Apply settings. const QSharedPointer<QFileDialogOptions> &opts = options(); @@ -1961,8 +1961,8 @@ QWindowsNativeDialogBase *QWindowsXpFileDialogHelper::createNativeDialog() { m_data.fromOptions(options()); if (QWindowsXpNativeFileDialog *result = QWindowsXpNativeFileDialog::create(options(), m_data)) { - QObject::connect(result, SIGNAL(accepted()), this, SIGNAL(accept())); - QObject::connect(result, SIGNAL(rejected()), this, SIGNAL(reject())); + QObject::connect(result, &QWindowsNativeDialogBase::accepted, this, &QPlatformDialogHelper::accept); + QObject::connect(result, &QWindowsNativeDialogBase::rejected, this, &QPlatformDialogHelper::reject); return result; } return 0; @@ -2117,8 +2117,8 @@ QWindowsNativeDialogBase *QWindowsColorDialogHelper::createNativeDialog() { QWindowsNativeColorDialog *nativeDialog = new QWindowsNativeColorDialog(m_currentColor); nativeDialog->setWindowTitle(options()->windowTitle()); - connect(nativeDialog, SIGNAL(accepted()), this, SIGNAL(accept())); - connect(nativeDialog, SIGNAL(rejected()), this, SIGNAL(reject())); + connect(nativeDialog, &QWindowsNativeDialogBase::accepted, this, &QPlatformDialogHelper::accept); + connect(nativeDialog, &QWindowsNativeDialogBase::rejected, this, &QPlatformDialogHelper::reject); return nativeDialog; } #endif // USE_NATIVE_COLOR_DIALOG diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index f15783490e..46b05de4ae 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -618,20 +618,6 @@ QDebug operator<<(QDebug d, const QFontDef &def) return d; } -// convert 0 ~ 1000 integer to QFont::Weight -static inline QFont::Weight weightFromInteger(long weight) -{ - if (weight < 400) - return QFont::Light; - if (weight < 600) - return QFont::Normal; - if (weight < 700) - return QFont::DemiBold; - if (weight < 800) - return QFont::Bold; - return QFont::Black; -} - static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSet) { switch (charSet) { @@ -808,7 +794,7 @@ QString getEnglishName(const QString &familyName) HDC hdc = GetDC( 0 ); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); - memcpy(lf.lfFaceName, familyName.utf16(), qMin(LF_FACESIZE, familyName.length()) * sizeof(wchar_t)); + memcpy(lf.lfFaceName, familyName.utf16(), qMin(familyName.length(), LF_FACESIZE - 1) * sizeof(wchar_t)); lf.lfCharSet = DEFAULT_CHARSET; HFONT hfont = CreateFontIndirect(&lf); @@ -865,7 +851,7 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, const int size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; const QFont::Style style = tm->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; const bool antialias = false; - const QFont::Weight weight = weightFromInteger(tm->tmWeight); + const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(tm->tmWeight); const QFont::Stretch stretch = QFont::Unstretched; #ifndef QT_NO_DEBUG_OUTPUT @@ -972,14 +958,9 @@ static int QT_WIN_CALLBACK storeFontSub(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textm HDC dummy = GetDC(0); LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); lf.lfCharSet = DEFAULT_CHARSET; - if (wcslen(f->elfLogFont.lfFaceName) >= LF_FACESIZE) { - qWarning("%s: Unable to enumerate family '%s'.", - __FUNCTION__, qPrintable(QString::fromWCharArray(f->elfLogFont.lfFaceName))); - return 1; - } - wmemcpy(lf.lfFaceName, f->elfLogFont.lfFaceName, - wcslen(f->elfLogFont.lfFaceName) + 1); + memcpy(lf.lfFaceName, f->elfLogFont.lfFaceName, LF_FACESIZE * sizeof(wchar_t)); lf.lfPitchAndFamily = 0; EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, (LPARAM)namesSetIn, 0); @@ -1015,20 +996,21 @@ void QWindowsFontDatabase::populate(const QString &family) HDC dummy = GetDC(0); LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); lf.lfCharSet = DEFAULT_CHARSET; if (family.size() >= LF_FACESIZE) { qWarning("%s: Unable to enumerate family '%s'.", __FUNCTION__, qPrintable(family)); return; } - wmemcpy(lf.lfFaceName, reinterpret_cast<const wchar_t*>(family.utf16()), - family.size() + 1); + lf.lfPitchAndFamily = 0; if (family.isEmpty()) { EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFontSub, (LPARAM)&m_families, 0); } else { + memcpy(lf.lfFaceName, family.utf16(), family.size() * sizeof(wchar_t)); EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, (LPARAM)&m_families, 0); } @@ -1093,7 +1075,7 @@ QFontEngineMulti *QWindowsFontDatabase::fontEngineMulti(QFontEngine *fontEngine, if (script == QChar::Script_Common) return new QWindowsMultiFontEngine(fontEngine, script); // ### as long as fallbacksForFamily() does not take script parameter into account, - // prefer QFontEngineMultiBasicImpl's loadEngine() implementation for complex scripts + // prefer QFontEngineMulti's loadEngine() implementation for complex scripts return QPlatformFontDatabase::fontEngineMulti(fontEngine, script); } @@ -1253,7 +1235,7 @@ QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal else fontEngine->fontDef.style = QFont::StyleNormal; - fontEngine->fontDef.weight = weightFromInteger(qFromBigEndian<quint16>(os2Table->weightClass)); + fontEngine->fontDef.weight = QPlatformFontDatabase::weightFromInteger(qFromBigEndian<quint16>(os2Table->weightClass)); } } @@ -1364,7 +1346,7 @@ QStringList QWindowsFontDatabase::addApplicationFont(const QByteArray &fontData, HDC hdc = GetDC(0); LOGFONT lf; memset(&lf, 0, sizeof(LOGFONT)); - memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE, familyName.size())); + memcpy(lf.lfFaceName, familyName.utf16(), sizeof(wchar_t) * qMin(LF_FACESIZE - 1, familyName.size())); lf.lfCharSet = DEFAULT_CHARSET; HFONT hfont = CreateFontIndirect(&lf); HGDIOBJ oldobj = SelectObject(hdc, hfont); @@ -1589,6 +1571,10 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request) lf.lfPitchAndFamily = DEFAULT_PITCH | hint; QString fam = request.family; + if (fam.size() >= LF_FACESIZE) { + qCritical("%s: Family name '%s' is too long.", __FUNCTION__, qPrintable(fam)); + fam.truncate(LF_FACESIZE - 1); + } if (fam.isEmpty()) fam = QStringLiteral("MS Sans Serif"); @@ -1600,7 +1586,7 @@ LOGFONT QWindowsFontDatabase::fontDefToLOGFONT(const QFontDef &request) if (fam == QLatin1String("Courier") && !(request.styleStrategy & QFont::PreferBitmap)) fam = QStringLiteral("Courier New"); - memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded + memcpy(lf.lfFaceName, fam.utf16(), fam.size() * sizeof(wchar_t)); return lf; } @@ -1781,9 +1767,13 @@ QFontEngine *QWindowsFontDatabase::createEngine(const QFontDef &request, // turns out okay) useDirectWrite = false; if (initDirectWrite(data.data())) { - const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName)); - memcpy(lf.lfFaceName, nameSubstitute.utf16(), - sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE)); + const QString fam = QString::fromWCharArray(lf.lfFaceName); + const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam); + if (nameSubstitute != fam) { + const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1); + memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t)); + lf.lfFaceName[nameSubstituteLength] = 0; + } HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT( &lf, @@ -1854,7 +1844,7 @@ QFont QWindowsFontDatabase::LOGFONT_to_QFont(const LOGFONT& logFont, int vertica QFont qFont(QString::fromWCharArray(logFont.lfFaceName)); qFont.setItalic(logFont.lfItalic); if (logFont.lfWeight != FW_DONTCARE) - qFont.setWeight(weightFromInteger(logFont.lfWeight)); + qFont.setWeight(QPlatformFontDatabase::weightFromInteger(logFont.lfWeight)); const qreal logFontHeight = qAbs(logFont.lfHeight); qFont.setPointSizeF(logFontHeight * 72.0 / qreal(verticalDPI_In)); qFont.setUnderline(logFont.lfUnderline); diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index 42e5a8c6ad..a2d9c3e75b 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -52,20 +52,6 @@ QT_BEGIN_NAMESPACE -// convert 0 ~ 1000 integer to QFont::Weight -static inline QFont::Weight weightFromInteger(long weight) -{ - if (weight < 400) - return QFont::Light; - if (weight < 600) - return QFont::Normal; - if (weight < 700) - return QFont::DemiBold; - if (weight < 800) - return QFont::Bold; - return QFont::Black; -} - static inline QFontDatabase::WritingSystem writingSystemFromCharSet(uchar charSet) { switch (charSet) { @@ -139,7 +125,7 @@ static bool addFontToDatabase(const QString &familyName, uchar charSet, const int size = scalable ? SMOOTH_SCALABLE : tm->tmHeight; const QFont::Style style = tm->tmItalic ? QFont::StyleItalic : QFont::StyleNormal; const bool antialias = false; - const QFont::Weight weight = weightFromInteger(tm->tmWeight); + const QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(tm->tmWeight); const QFont::Stretch stretch = QFont::Unstretched; #ifndef QT_NO_DEBUG_OUTPUT @@ -383,14 +369,9 @@ static int QT_WIN_CALLBACK storeFontSub(ENUMLOGFONTEX* f, NEWTEXTMETRICEX *textm HDC dummy = GetDC(0); LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); lf.lfCharSet = DEFAULT_CHARSET; - if (wcslen(f->elfLogFont.lfFaceName) >= LF_FACESIZE) { - qWarning("%s: Unable to enumerate family '%s'.", - __FUNCTION__, qPrintable(QString::fromWCharArray(f->elfLogFont.lfFaceName))); - return 1; - } - wmemcpy(lf.lfFaceName, f->elfLogFont.lfFaceName, - wcslen(f->elfLogFont.lfFaceName) + 1); + memcpy(lf.lfFaceName, f->elfLogFont.lfFaceName, LF_FACESIZE * sizeof(wchar_t)); lf.lfPitchAndFamily = 0; EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, (LPARAM)namesSetIn, 0); @@ -425,20 +406,21 @@ void QWindowsFontDatabaseFT::populate(const QString &family) HDC dummy = GetDC(0); LOGFONT lf; + memset(&lf, 0, sizeof(LOGFONT)); lf.lfCharSet = DEFAULT_CHARSET; if (family.size() >= LF_FACESIZE) { qWarning("%s: Unable to enumerate family '%s'.", __FUNCTION__, qPrintable(family)); return; } - wmemcpy(lf.lfFaceName, reinterpret_cast<const wchar_t*>(family.utf16()), - family.size() + 1); + lf.lfPitchAndFamily = 0; if (family.isEmpty()) { EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFontSub, (LPARAM)&m_families, 0); } else { + memcpy(lf.lfFaceName, family.utf16(), family.size() * sizeof(wchar_t)); EnumFontFamiliesEx(dummy, &lf, (FONTENUMPROC)storeFont, (LPARAM)&m_families, 0); } diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index e45ff5d744..5790360d34 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -1182,19 +1182,13 @@ QImage QWindowsFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &xfo return QImage(); } - QImage indexed(mask->width(), mask->height(), QImage::Format_Indexed8); + QImage alphaMap(mask->width(), mask->height(), QImage::Format_Alpha8); - // ### This part is kinda pointless, but we'll crash later if we don't because some - // code paths expects there to be colortables for index8-bit... - QVector<QRgb> colors(256); - for (int i=0; i<256; ++i) - colors[i] = qRgba(0, 0, 0, i); - indexed.setColorTable(colors); // Copy data... Cannot use QPainter here as GDI has messed up the // Alpha channel of the ni.image pixels... for (int y=0; y<mask->height(); ++y) { - uchar *dest = indexed.scanLine(y); + uchar *dest = alphaMap.scanLine(y); if (mask->image().format() == QImage::Format_RGB16) { const qint16 *src = (qint16 *) ((const QImage &) mask->image()).scanLine(y); for (int x=0; x<mask->width(); ++x) @@ -1216,7 +1210,7 @@ QImage QWindowsFontEngine::alphaMapForGlyph(glyph_t glyph, const QTransform &xfo DeleteObject(font); } - return indexed; + return alphaMap; } #define SPI_GETFONTSMOOTHINGCONTRAST 0x200C @@ -1309,17 +1303,13 @@ void QWindowsFontEngine::initFontInfo(const QFontDef &request, Will probably be superseded by a common Free Type font engine in Qt 5.X. */ QWindowsMultiFontEngine::QWindowsMultiFontEngine(QFontEngine *fe, int script) - : QFontEngineMultiBasicImpl(fe, script) + : QFontEngineMulti(fe, script) { } -void QWindowsMultiFontEngine::loadEngine(int at) +QFontEngine *QWindowsMultiFontEngine::loadEngine(int at) { - ensureFallbackFamiliesQueried(); - Q_ASSERT(at < engines.size()); - Q_ASSERT(engines.at(at) == 0); - - QFontEngine *fontEngine = engines.at(0); + QFontEngine *fontEngine = engine(0); QSharedPointer<QWindowsFontEngineData> data; LOGFONT lf; @@ -1339,36 +1329,36 @@ void QWindowsMultiFontEngine::loadEngine(int at) } const QString fam = fallbackFamilyAt(at - 1); - memcpy(lf.lfFaceName, fam.utf16(), sizeof(wchar_t) * qMin(fam.length() + 1, 32)); // 32 = Windows hard-coded + const int faceNameLength = qMin(fam.length(), LF_FACESIZE - 1); + memcpy(lf.lfFaceName, fam.utf16(), faceNameLength * sizeof(wchar_t)); + lf.lfFaceName[faceNameLength] = 0; #ifndef QT_NO_DIRECTWRITE if (fontEngine->type() == QFontEngine::DirectWrite) { - const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(QString::fromWCharArray(lf.lfFaceName)); - memcpy(lf.lfFaceName, nameSubstitute.utf16(), - sizeof(wchar_t) * qMin(nameSubstitute.length() + 1, LF_FACESIZE)); + const QString nameSubstitute = QWindowsFontEngineDirectWrite::fontNameSubstitute(fam); + if (nameSubstitute != fam) { + const int nameSubstituteLength = qMin(nameSubstitute.length(), LF_FACESIZE - 1); + memcpy(lf.lfFaceName, nameSubstitute.utf16(), nameSubstituteLength * sizeof(wchar_t)); + lf.lfFaceName[nameSubstituteLength] = 0; + } IDWriteFont *directWriteFont = 0; HRESULT hr = data->directWriteGdiInterop->CreateFontFromLOGFONT(&lf, &directWriteFont); if (FAILED(hr)) { qErrnoWarning("%s: CreateFontFromLOGFONT failed", __FUNCTION__); } else { + Q_ASSERT(directWriteFont); IDWriteFontFace *directWriteFontFace = NULL; HRESULT hr = directWriteFont->CreateFontFace(&directWriteFontFace); if (SUCCEEDED(hr)) { + Q_ASSERT(directWriteFontFace); QWindowsFontEngineDirectWrite *fedw = new QWindowsFontEngineDirectWrite(directWriteFontFace, fontEngine->fontDef.pixelSize, data); - fedw->fontDef = fontDef; - fedw->fontDef.family = fam; - fedw->ref.ref(); - engines[at] = fedw; - - qCDebug(lcQpaFonts) << __FUNCTION__ << at << fam; - return; + return fedw; } else { qErrnoWarning("%s: CreateFontFace failed", __FUNCTION__); } - } } #endif @@ -1382,13 +1372,8 @@ void QWindowsMultiFontEngine::loadEngine(int at) hfont = (HFONT)GetStockObject(ANSI_VAR_FONT); stockFont = true; } - engines[at] = new QWindowsFontEngine(fam, hfont, stockFont, lf, data); - engines[at]->ref.ref(); - engines[at]->fontDef = fontDef; - engines[at]->fontDef.family = fam; - qCDebug(lcQpaFonts) << __FUNCTION__ << at << fam; - // TODO: increase cost in QFontCache for the font engine loaded here + return new QWindowsFontEngine(fam, hfont, stockFont, lf, data); } bool QWindowsFontEngine::supportsTransformation(const QTransform &transform) const diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h index 02bc4008d1..fdcb74d67d 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.h +++ b/src/plugins/platforms/windows/qwindowsfontengine.h @@ -163,13 +163,12 @@ private: mutable int designAdvancesSize; }; - -class QWindowsMultiFontEngine : public QFontEngineMultiBasicImpl +class QWindowsMultiFontEngine : public QFontEngineMulti { public: explicit QWindowsMultiFontEngine(QFontEngine *fe, int script); - void loadEngine(int at); + QFontEngine *loadEngine(int at) Q_DECL_OVERRIDE; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index ed512f78ca..5c241b1fc8 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -485,15 +485,11 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub { QImage im = imageForGlyph(glyph, subPixelPosition, 0, QTransform()); - QImage indexed(im.width(), im.height(), QImage::Format_Indexed8); - QVector<QRgb> colors(256); - for (int i=0; i<256; ++i) - colors[i] = qRgba(0, 0, 0, i); - indexed.setColorTable(colors); + QImage alphaMap(im.width(), im.height(), QImage::Format_Alpha8); for (int y=0; y<im.height(); ++y) { uint *src = (uint*) im.scanLine(y); - uchar *dst = indexed.scanLine(y); + uchar *dst = alphaMap.scanLine(y); for (int x=0; x<im.width(); ++x) { *dst = 255 - (m_fontEngineData->pow_gamma[qGray(0xffffffff - *src)] * 255. / 2047.); ++dst; @@ -501,7 +497,7 @@ QImage QWindowsFontEngineDirectWrite::alphaMapForGlyph(glyph_t glyph, QFixed sub } } - return indexed; + return alphaMap; } bool QWindowsFontEngineDirectWrite::supportsSubPixelPositions() const diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index 94a27d146f..d8e4900780 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -156,8 +156,8 @@ QWindowsInputContext::QWindowsInputContext() : m_WM_MSIME_MOUSE(RegisterWindowMessage(L"MSIMEMouseOperation")), m_endCompositionRecursionGuard(false) { - connect(QGuiApplication::inputMethod(), SIGNAL(cursorRectangleChanged()), - this, SLOT(cursorRectChanged())); + connect(QGuiApplication::inputMethod(), &QInputMethod::cursorRectangleChanged, + this, &QWindowsInputContext::cursorRectChanged); } QWindowsInputContext::~QWindowsInputContext() diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index d1617eaa3c..7fb37bc1f1 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -94,6 +94,7 @@ public: static QWindowsIntegration *instance(); inline void emitScreenAdded(QPlatformScreen *s) { screenAdded(s); } + inline void emitDestroyScreen(QPlatformScreen *s) { destroyScreen(s); } unsigned options() const; diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp index d781cdbe9c..25d6937d8f 100644 --- a/src/plugins/platforms/windows/qwindowskeymapper.cpp +++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp @@ -1192,6 +1192,8 @@ Qt::KeyboardModifiers QWindowsKeyMapper::queryKeyboardModifiers() modifiers |= Qt::ControlModifier; if (GetKeyState(VK_MENU) < 0) modifiers |= Qt::AltModifier; + if (GetKeyState(VK_LWIN) < 0 || GetKeyState(VK_RWIN) < 0) + modifiers |= Qt::MetaModifier; return modifiers; } diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index bc8e9347dc..42f4e66d6c 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -343,10 +343,11 @@ static bool setData(const QByteArray &data, STGMEDIUM *pmedium) return true; } -static QByteArray getData(int cf, IDataObject *pDataObj) +static QByteArray getData(int cf, IDataObject *pDataObj, int lindex = -1) { QByteArray data; FORMATETC formatetc = setCf(cf); + formatetc.lindex = lindex; STGMEDIUM s; if (pDataObj->GetData(&formatetc, &s) == S_OK) { DWORD * val = (DWORD*)GlobalLock(s.hGlobal); @@ -791,7 +792,6 @@ QVariant QWindowsMimeURI::convertToMime(const QString &mimeType, LPDATAOBJECT pD { if (mimeType == QLatin1String("text/uri-list")) { if (canGetData(CF_HDROP, pDataObj)) { - QByteArray texturi; QList<QVariant> urls; QByteArray data = getData(CF_HDROP, pDataObj); @@ -1340,21 +1340,34 @@ static bool isCustomMimeType(const QString &mimeType) return mimeType.startsWith(QLatin1String(x_qt_windows_mime), Qt::CaseInsensitive); } -static QString customMimeType(const QString &mimeType) +static QString customMimeType(const QString &mimeType, int *lindex = 0) { int len = sizeof(x_qt_windows_mime) - 1; - int n = mimeType.lastIndexOf(QLatin1Char('\"'))-len; - return mimeType.mid(len, n); + int n = mimeType.lastIndexOf(QLatin1Char('\"')) - len; + QString ret = mimeType.mid(len, n); + + const int beginPos = mimeType.indexOf(QLatin1String(";index=")); + if (beginPos > -1) { + const int endPos = mimeType.indexOf(QLatin1Char(';'), beginPos + 1); + const int indexStartPos = beginPos + 7; + if (lindex) + *lindex = mimeType.midRef(indexStartPos, endPos == -1 ? endPos : endPos - indexStartPos).toInt(); + } else { + if (lindex) + *lindex = -1; + } + return ret; } bool QLastResortMimes::canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const { if (isCustomMimeType(mimeType)) { + // MSDN documentation for QueryGetData says only -1 is supported, so ignore lindex here. QString clipFormat = customMimeType(mimeType); int cf = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (clipFormat.utf16())); return canGetData(cf, pDataObj); } else if (formats.keys(mimeType).isEmpty()) { - // if it is not in there then register it an see if we can get it + // if it is not in there then register it and see if we can get it int cf = QWindowsMime::registerMimeType(mimeType); return canGetData(cf, pDataObj); } else { @@ -1370,9 +1383,10 @@ QVariant QLastResortMimes::convertToMime(const QString &mimeType, IDataObject *p if (canConvertToMime(mimeType, pDataObj)) { QByteArray data; if (isCustomMimeType(mimeType)) { - QString clipFormat = customMimeType(mimeType); + int lindex; + QString clipFormat = customMimeType(mimeType, &lindex); int cf = RegisterClipboardFormat(reinterpret_cast<const wchar_t *> (clipFormat.utf16())); - data = getData(cf, pDataObj); + data = getData(cf, pDataObj, lindex); } else if (formats.keys(mimeType).isEmpty()) { int cf = QWindowsMime::registerMimeType(mimeType); data = getData(cf, pDataObj); @@ -1452,6 +1466,7 @@ QWindowsMime * QWindowsMimeConverter::converterToMime(const QString &mimeType, I QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) const { + qCDebug(lcQpaMime) << "QWindowsMime::allMimesForFormats()"; ensureInitialized(); QStringList formats; LPENUMFORMATETC FAR fmtenum; @@ -1461,10 +1476,9 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con FORMATETC fmtetc; while (S_OK == fmtenum->Next(1, &fmtetc, 0)) { #if defined(QMIME_DEBUG) - qDebug("QWindowsMime::allMimesForFormats()"); wchar_t buf[256] = {0}; GetClipboardFormatName(fmtetc.cfFormat, buf, 255); - qDebug("CF = %d : %s", fmtetc.cfFormat, QString::fromWCharArray(buf)); + qDebug("CF = %d : %s", fmtetc.cfFormat, qPrintable(QString::fromWCharArray(buf))); #endif for (int i= m_mimes.size() - 1; i >= 0; --i) { QString format = m_mimes.at(i)->mimeForFormat(fmtetc); @@ -1478,7 +1492,7 @@ QStringList QWindowsMimeConverter::allMimesForFormats(IDataObject *pDataObj) con } fmtenum->Release(); } - qCDebug(lcQpaMime) << __FUNCTION__ << pDataObj << formats; + qCDebug(lcQpaMime) << pDataObj << formats; return formats; } diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index 002f4ae92c..bd5022505f 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -216,4 +216,11 @@ int QWindowsNativeInterface::registerMimeType(const QString &mimeType) return QWindowsMime::registerMimeType(mimeType); } +QFunctionPointer QWindowsNativeInterface::platformFunction(const QByteArray &function) const +{ + if (function == QWindowsWindowFunctions::setTouchWindowTouchTypeIdentifier()) + return QFunctionPointer(QWindowsWindow::setTouchWindowTouchTypeStatic); + return Q_NULLPTR; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index 3d47dbe721..9b2ac00986 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -85,6 +85,8 @@ public: QVariant windowProperty(QPlatformWindow *window, const QString &name) const Q_DECL_OVERRIDE; QVariant windowProperty(QPlatformWindow *window, const QString &name, const QVariant &defaultValue) const Q_DECL_OVERRIDE; void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value) Q_DECL_OVERRIDE; + + QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index fd57d9ee61..79219e361a 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -462,7 +462,7 @@ void QWindowsScreenManager::removeScreen(int index) if (movedWindowCount) QWindowSystemInterface::flushWindowSystemEvents(); } - delete m_screens.takeAt(index); + QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeAt(index)); } /*! @@ -497,4 +497,11 @@ bool QWindowsScreenManager::handleScreenChanges() return true; } +void QWindowsScreenManager::clearScreens() +{ + // Delete screens in reverse order to avoid crash in case of multiple screens + while (!m_screens.isEmpty()) + QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeLast()); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index aa1408358b..924912dbc2 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -127,11 +127,7 @@ public: QWindowsScreenManager(); - inline void clearScreens() { - // Delete screens in reverse order to avoid crash in case of multiple screens - while (!m_screens.isEmpty()) - delete m_screens.takeLast(); - } + void clearScreens(); bool handleScreenChanges(); bool handleDisplayChange(WPARAM wParam, LPARAM lParam); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index e7061dbfde..5d94ec3c38 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -889,16 +889,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) #endif // QT_NO_OPENGL updateDropSite(); -#ifndef Q_OS_WINCE - if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch) - && aWindow->type() != Qt::ForeignWindow) { - if (QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, 0)) { - setFlag(TouchRegistered); - } else { - qErrnoWarning("RegisterTouchWindow() failed for window '%s'.", qPrintable(aWindow->objectName())); - } - } -#endif // !Q_OS_WINCE + registerTouchWindow(); setWindowState(aWindow->windowState()); const qreal opacity = qt_window_private(aWindow)->opacity; if (!qFuzzyCompare(opacity, qreal(1.0))) @@ -2303,4 +2294,24 @@ void *QWindowsWindow::surface(void *nativeConfig) #endif } +void QWindowsWindow::setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes) +{ + if (!window->handle()) + return; + static_cast<QWindowsWindow *>(window->handle())->registerTouchWindow(touchTypes); +} + +void QWindowsWindow::registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes) +{ +#ifndef Q_OS_WINCE + if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch) + && window()->type() != Qt::ForeignWindow) { + if (QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, (ULONG)touchTypes)) + setFlag(TouchRegistered); + else + qErrnoWarning("RegisterTouchWindow() failed for window '%s'.", qPrintable(window()->objectName())); + } +#endif // !Q_OS_WINCE +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 9822ebce45..66102511e0 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -43,6 +43,7 @@ #include "qwindowsopenglcontext.h" #include <qpa/qplatformwindow.h> +#include <QtPlatformHeaders/qwindowswindowfunctions.h> QT_BEGIN_NAMESPACE @@ -261,6 +262,9 @@ public: void stopAlertWindow(); #endif + static void setTouchWindowTouchTypeStatic(QWindow *window, QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes); + void registerTouchWindow(QWindowsWindowFunctions::TouchWindowTouchTypes touchTypes = QWindowsWindowFunctions::NormalTouch); + private: inline void show_sys() const; inline void hide_sys() const; diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp index a41e5f8f38..41bd2e108d 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.cpp @@ -80,6 +80,11 @@ QFont QWinRTFontDatabase::defaultFont() const return QFont(QStringLiteral("Segoe UI")); } +bool QWinRTFontDatabase::fontsAlwaysScalable() const +{ + return true; +} + void QWinRTFontDatabase::populateFontDatabase() { ComPtr<IDWriteFactory1> factory; @@ -204,31 +209,7 @@ void QWinRTFontDatabase::populateFamily(const QString &familyName) } } - QFont::Weight weight; - switch (font->GetWeight()) { - case DWRITE_FONT_WEIGHT_THIN: - case DWRITE_FONT_WEIGHT_EXTRA_LIGHT: - case DWRITE_FONT_WEIGHT_LIGHT: - case DWRITE_FONT_WEIGHT_SEMI_LIGHT: - weight = QFont::Light; - break; - default: - case DWRITE_FONT_WEIGHT_NORMAL: - case DWRITE_FONT_WEIGHT_MEDIUM: - weight = QFont::Normal; - break; - case DWRITE_FONT_WEIGHT_DEMI_BOLD: - weight = QFont::DemiBold; - break; - case DWRITE_FONT_WEIGHT_BOLD: - case DWRITE_FONT_WEIGHT_EXTRA_BOLD: - weight = QFont::Bold; - break; - case DWRITE_FONT_WEIGHT_BLACK: - case DWRITE_FONT_WEIGHT_EXTRA_BLACK: - weight = QFont::Black; - break; - } + QFont::Weight weight = QPlatformFontDatabase::weightFromInteger(font->GetWeight()); QFont::Style style; switch (font->GetStyle()) { diff --git a/src/plugins/platforms/winrt/qwinrtfontdatabase.h b/src/plugins/platforms/winrt/qwinrtfontdatabase.h index f0c4714911..cf8ed3b06a 100644 --- a/src/plugins/platforms/winrt/qwinrtfontdatabase.h +++ b/src/plugins/platforms/winrt/qwinrtfontdatabase.h @@ -53,9 +53,10 @@ class QWinRTFontDatabase : public QBasicFontDatabase { public: QString fontDir() const; - QFont defaultFont() const Q_DECL_OVERRIDE; #ifdef QT_WINRT_USE_DWRITE ~QWinRTFontDatabase(); + QFont defaultFont() const Q_DECL_OVERRIDE; + bool fontsAlwaysScalable() const Q_DECL_OVERRIDE; void populateFontDatabase() Q_DECL_OVERRIDE; void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/winrt/qwinrttheme.cpp b/src/plugins/platforms/winrt/qwinrttheme.cpp index f64b47960a..339a658c3e 100644 --- a/src/plugins/platforms/winrt/qwinrttheme.cpp +++ b/src/plugins/platforms/winrt/qwinrttheme.cpp @@ -170,7 +170,7 @@ QWinRTTheme::QWinRTTheme() bool QWinRTTheme::usePlatformNativeDialog(DialogType type) const { static bool useNativeDialogs = qEnvironmentVariableIsSet("QT_USE_WINRT_NATIVE_DIALOGS") - ? qgetenv("QT_USE_WINRT_NATIVE_DIALOGS").toInt() : true; + ? qEnvironmentVariableIntValue("QT_USE_WINRT_NATIVE_DIALOGS") : true; if (type == FileDialog || type == MessageDialog) return useNativeDialogs; 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..75b35f4fb8 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** 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; + +#ifdef USE_XCB_XLIB + Display *dpy = (Display *)m_connection->xlib_display(); +#else + EGLNativeDisplayType dpy = EGL_DEFAULT_DISPLAY; +#endif + 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..2a49cd0ca9 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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; + + bool supportsThreadedOpenGL() const Q_DECL_OVERRIDE { return true; } + + 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..9d06502158 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** 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 <QtGui/private/qguiapplication_p.h> +#include "qxcbeglwindow.h" +#include "qxcbintegration.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::NativeResourceForIntegrationFunction QXcbEglNativeInterfaceHandler::nativeResourceFunctionForIntegration(const QByteArray &resource) const{ + switch (resourceType(resource)) { + case EglDisplay: + return eglDisplay; + default: + break; + } + return Q_NULLPTR; +} + +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::eglDisplay() +{ + QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration()); + QXcbEglIntegration *eglIntegration = static_cast<QXcbEglIntegration *>(integration->defaultConnection()->glIntegration()); + return eglIntegration->eglDisplay(); +} + +void *QXcbEglNativeInterfaceHandler::eglDisplayForWindow(QWindow *window) +{ + Q_ASSERT(window); + if (window->supportsOpenGL() && window->handle() == Q_NULLPTR) + return eglDisplay(); + else 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..7734bcd048 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglnativeinterfacehandler.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 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::NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) const Q_DECL_OVERRIDE; + QPlatformNativeInterface::NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) const Q_DECL_OVERRIDE; + QPlatformNativeInterface::NativeResourceForWindowFunction nativeResourceFunctionForWindow(const QByteArray &resource) const Q_DECL_OVERRIDE; +private: + static void *eglDisplay(); + 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/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index c0be836bce..c0be836bce 100644 --- a/src/plugins/platforms/xcb/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h index 5777980093..73a17d69b4 100644 --- a/src/plugins/platforms/xcb/qglxintegration.h +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h @@ -54,14 +54,14 @@ public: const QVariant &nativeHandle); ~QGLXContext(); - bool makeCurrent(QPlatformSurface *surface); - void doneCurrent(); - void swapBuffers(QPlatformSurface *surface); - void (*getProcAddress(const QByteArray &procName)) (); + 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; - bool isSharing() const; - bool isValid() const; + 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; } @@ -94,8 +94,8 @@ public: explicit QGLXPbuffer(QOffscreenSurface *offscreenSurface); ~QGLXPbuffer(); - QSurfaceFormat format() const { return m_format; } - bool isValid() const { return m_pbuffer != 0; } + 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; } 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..c8ea2053e3 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -0,0 +1,223 @@ +/**************************************************************************** +** +** 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 + +} + +bool QXcbGlxIntegration::supportsThreadedOpenGL() const +{ + return QGLXContext::supportsThreading(); +} + + +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..2869fc20a4 --- /dev/null +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.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 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; + + virtual bool supportsThreadedOpenGL() 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 diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index f4382c7b50..bbde948090 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -49,6 +49,7 @@ #include <qdebug.h> #include <qpainter.h> #include <qscreen.h> +#include <qpa/qplatformgraphicsbuffer.h> #include <algorithm> QT_BEGIN_NAMESPACE @@ -60,6 +61,8 @@ public: ~QXcbShmImage() { destroy(); } QImage *image() { return &m_qimage; } + QPlatformGraphicsBuffer *graphicsBuffer() { return m_graphics_buffer; } + QSize size() const { return m_qimage.size(); } void put(xcb_window_t window, const QPoint &dst, const QRect &source); @@ -73,6 +76,7 @@ private: xcb_image_t *m_xcb_image; QImage m_qimage; + QPlatformGraphicsBuffer *m_graphics_buffer; xcb_gcontext_t m_gc; xcb_window_t m_gc_window; @@ -80,8 +84,39 @@ private: QRegion m_dirty; }; +class QXcbShmGraphicsBuffer : public QPlatformGraphicsBuffer +{ +public: + QXcbShmGraphicsBuffer(QImage *image) + : QPlatformGraphicsBuffer(image->size(), QImage::toPixelFormat(image->format())) + , m_access_lock(QPlatformGraphicsBuffer::None) + , m_image(image) + { } + + bool doLock(AccessTypes access, const QRect &rect) Q_DECL_OVERRIDE + { + Q_UNUSED(rect); + if (access & ~(QPlatformGraphicsBuffer::SWReadAccess | QPlatformGraphicsBuffer::SWWriteAccess)) + return false; + + m_access_lock |= access; + return true; + } + void doUnlock() Q_DECL_OVERRIDE { m_access_lock = None; } + + const uchar *data() const Q_DECL_OVERRIDE { return m_image->bits(); } + uchar *data() Q_DECL_OVERRIDE { return m_image->bits(); } + int bytesPerLine() const Q_DECL_OVERRIDE { return m_image->bytesPerLine(); } + + Origin origin() const Q_DECL_OVERRIDE { return QPlatformGraphicsBuffer::OriginTopLeft; } +private: + AccessTypes m_access_lock; + QImage *m_image; +}; + QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QImage::Format format) : QXcbObject(screen->connection()) + , m_graphics_buffer(Q_NULLPTR) , m_gc(0) , m_gc_window(0) { @@ -137,6 +172,7 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI } m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format); + m_graphics_buffer = new QXcbShmGraphicsBuffer(&m_qimage); } void QXcbShmImage::destroy() @@ -158,6 +194,8 @@ void QXcbShmImage::destroy() if (m_gc) Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc)); + delete m_graphics_buffer; + m_graphics_buffer = Q_NULLPTR; } void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &source) @@ -287,10 +325,17 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) } } +#ifndef QT_NO_OPENGL QImage QXcbBackingStore::toImage() const { return m_image && m_image->image() ? *m_image->image() : QImage(); } +#endif + +QPlatformGraphicsBuffer *QXcbBackingStore::graphicsBuffer() const +{ + return m_image ? m_image->graphicsBuffer() : Q_NULLPTR; +} void QXcbBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) { diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h index 38fb5a7ae4..aa2c953983 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.h +++ b/src/plugins/platforms/xcb/qxcbbackingstore.h @@ -50,18 +50,21 @@ public: QXcbBackingStore(QWindow *widget); ~QXcbBackingStore(); - QPaintDevice *paintDevice(); - void flush(QWindow *window, const QRegion ®ion, const QPoint &offset); + QPaintDevice *paintDevice() Q_DECL_OVERRIDE; + void flush(QWindow *window, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; #ifndef QT_NO_OPENGL void composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset, QPlatformTextureList *textures, QOpenGLContext *context, - bool translucentBackground); + bool translucentBackground) Q_DECL_OVERRIDE; + QImage toImage() const Q_DECL_OVERRIDE; #endif - QImage toImage() const; - void resize(const QSize &size, const QRegion &staticContents); - bool scroll(const QRegion &area, int dx, int dy); - void beginPaint(const QRegion &); + QPlatformGraphicsBuffer *graphicsBuffer() const Q_DECL_OVERRIDE; + + void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE; + bool scroll(const QRegion &area, int dx, int dy) Q_DECL_OVERRIDE; + + void beginPaint(const QRegion &) Q_DECL_OVERRIDE; private: QXcbShmImage *m_image; diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index f56a29d985..61e9860802 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -84,7 +84,7 @@ public: } protected: - QStringList formats_sys() const + QStringList formats_sys() const Q_DECL_OVERRIDE { if (isEmpty()) return QStringList(); @@ -114,13 +114,13 @@ protected: return formatList; } - bool hasFormat_sys(const QString &format) const + bool hasFormat_sys(const QString &format) const Q_DECL_OVERRIDE { QStringList list = formats(); return list.contains(format); } - QVariant retrieveData_sys(const QString &fmt, QVariant::Type requestedType) const + QVariant retrieveData_sys(const QString &fmt, QVariant::Type requestedType) const Q_DECL_OVERRIDE { if (fmt.isEmpty() || isEmpty()) return QByteArray(); @@ -232,7 +232,7 @@ public: } protected: - void timerEvent(QTimerEvent *ev) + void timerEvent(QTimerEvent *ev) Q_DECL_OVERRIDE { if (ev->timerId() == abort_timer) { // this can happen when the X client we are sending data diff --git a/src/plugins/platforms/xcb/qxcbclipboard.h b/src/plugins/platforms/xcb/qxcbclipboard.h index e76d502691..5993eea326 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.h +++ b/src/plugins/platforms/xcb/qxcbclipboard.h @@ -53,11 +53,11 @@ public: QXcbClipboard(QXcbConnection *connection); ~QXcbClipboard(); - QMimeData *mimeData(QClipboard::Mode mode); - void setMimeData(QMimeData *data, QClipboard::Mode mode); + QMimeData *mimeData(QClipboard::Mode mode) Q_DECL_OVERRIDE; + void setMimeData(QMimeData *data, QClipboard::Mode mode) Q_DECL_OVERRIDE; - bool supportsMode(QClipboard::Mode mode) const; - bool ownsMode(QClipboard::Mode mode) const; + bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE; + bool ownsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE; QXcbScreen *screen() const { return m_screen; } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 5510c3b1b4..56b4a9abda 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -44,6 +44,8 @@ #include "qxcbnativeinterface.h" #include "qxcbintegration.h" #include "qxcbsystemtraytracker.h" +#include "qxcbglintegrationfactory.h" +#include "qxcbglintegration.h" #include <QSocketNotifier> #include <QAbstractEventDispatcher> @@ -74,14 +76,6 @@ #include <xcb/render.h> #endif -#if defined(XCB_HAS_XCB_GLX) -#include <xcb/glx.h> -#endif - -#ifdef XCB_USE_EGL //don't pull in eglext prototypes -#include <EGL/egl.h> -#endif - QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input") @@ -121,39 +115,6 @@ static int ioErrorHandler(Display *dpy) } #endif -#if defined(XCB_HAS_XCB_GLX) && XCB_GLX_MAJOR_VERSION == 1 && XCB_GLX_MINOR_VERSION < 4 - -#define XCB_GLX_BUFFER_SWAP_COMPLETE 1 - -typedef struct xcb_glx_buffer_swap_complete_event_t { - uint8_t response_type; - uint8_t pad0; - uint16_t sequence; - uint16_t event_type; - uint8_t pad1[2]; - xcb_glx_drawable_t drawable; - uint32_t ust_hi; - uint32_t ust_lo; - uint32_t msc_hi; - uint32_t msc_lo; - uint32_t sbc; -} xcb_glx_buffer_swap_complete_event_t; -#endif - -#if defined(XCB_USE_XLIB) && defined(XCB_USE_GLX) -typedef struct { - int type; - unsigned long serial; /* # of last request processed by server */ - Bool send_event; /* true if this came from a SendEvent request */ - Display *display; /* Display the event was read from */ - Drawable drawable; /* drawable on which event was requested in event mask */ - int event_type; - int64_t ust; - int64_t msc; - int64_t sbc; -} QGLXBufferSwapComplete; -#endif - QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& newScreens, int screenNumber, xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output) { @@ -166,7 +127,7 @@ QXcbScreen* QXcbConnection::findOrCreateScreen(QList<QXcbScreen *>& newScreens, int dotPos = displayName.lastIndexOf('.'); if (dotPos != -1) displayName.truncate(dotPos); - name = displayName + QLatin1Char('.') + QString::number(screenNumber); + name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(screenNumber); } foreach (QXcbScreen* scr, m_screens) if (scr->name() == name && scr->root() == xcbScreen->root) @@ -279,11 +240,12 @@ void QXcbConnection::updateScreens() ++xcbScreenNumber; } // for each xcb screen + QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration()); // Now activeScreens is the complete set of screens which are active at this time. // Delete any existing screens which are not in activeScreens for (int i = m_screens.count() - 1; i >= 0; --i) { if (!activeScreens.contains(m_screens[i])) { - delete m_screens[i]; + integration->destroyScreen(m_screens.at(i)); m_screens.removeAt(i); } } @@ -300,7 +262,7 @@ void QXcbConnection::updateScreens() // Now that they are in the right order, emit the added signals for new screens only foreach (QXcbScreen* screen, m_screens) if (newScreens.contains(screen)) - ((QXcbIntegration*)QGuiApplicationPrivate::platformIntegration())->screenAdded(screen); + integration->screenAdded(screen); } QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) @@ -309,11 +271,12 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , m_primaryScreenNumber(0) , m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) , m_nativeInterface(nativeInterface) +#ifdef XCB_USE_XLIB + , m_xlib_display(0) +#endif , xfixes_first_event(0) , xrandr_first_event(0) , xkb_first_event(0) - , glx_first_event(0) - , has_glx_extension(false) , has_shape_extension(false) , has_randr_extension(false) , has_input_shape(false) @@ -322,14 +285,10 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra , m_buttons(0) , m_focusWindow(0) , m_systemTrayTracker(0) + , m_glIntegration(Q_NULLPTR) { -#ifdef XCB_USE_EGL - EGLNativeDisplayType dpy = EGL_DEFAULT_DISPLAY; -#elif defined(XCB_USE_XLIB) - Display *dpy; -#endif #ifdef XCB_USE_XLIB - dpy = XOpenDisplay(m_displayName.constData()); + Display *dpy = XOpenDisplay(m_displayName.constData()); if (dpy) { m_primaryScreenNumber = DefaultScreen(dpy); m_connection = XGetXCBConnection(dpy); @@ -345,12 +304,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra if (!m_connection || xcb_connection_has_error(m_connection)) qFatal("QXcbConnection: Could not connect to display %s", m_displayName.constData()); -#ifdef XCB_USE_EGL - EGLDisplay eglDisplay = eglGetDisplay(dpy); - m_egl_display = eglDisplay; - EGLint major, minor; - m_has_egl = eglInitialize(eglDisplay, &major, &minor); -#endif //XCB_USE_EGL m_reader = new QXcbEventReader(this); m_reader->start(); @@ -363,9 +316,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra #ifdef XCB_USE_RENDER &xcb_render_id, #endif -#ifdef XCB_HAS_XCB_GLX - &xcb_glx_id, -#endif 0 }; @@ -382,7 +332,6 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra initializeXRandr(); updateScreens(); - initializeGLX(); initializeXFixes(); initializeXRender(); m_xi2Enabled = false; @@ -405,6 +354,27 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra if (!m_startupId.isNull()) qunsetenv("DESKTOP_STARTUP_ID"); + + QStringList glIntegrationNames; + glIntegrationNames << QStringLiteral("xcb_glx") << QStringLiteral("xcb_egl"); + QString glIntegrationName = QString::fromLocal8Bit(qgetenv("QT_XCB_GL_INTEGRATION")); + if (glIntegrationName.size()) { + glIntegrationNames.removeAll(glIntegrationName); + glIntegrationNames.prepend(glIntegrationName); + } + + qCDebug(QT_XCB_GLINTEGRATION) << "Choosing xcb gl-integration based on following priority\n" << glIntegrationNames; + for (int i = 0; i < glIntegrationNames.size() && !m_glIntegration; i++) { + m_glIntegration = QXcbGlIntegrationFactory::create(glIntegrationNames.at(i)); + if (m_glIntegration && !m_glIntegration->initialize(this)) { + qCDebug(QT_XCB_GLINTEGRATION) << "Failed to initialize xcb gl-integration" << glIntegrationNames.at(i); + delete m_glIntegration; + m_glIntegration = Q_NULLPTR; + } + } + if (!m_glIntegration) + qCDebug(QT_XCB_GLINTEGRATION) << "Failed to create xcb gl-integration"; + sync(); if (qEnvironmentVariableIsEmpty("QT_IM_MODULE")) @@ -431,14 +401,10 @@ QXcbConnection::~QXcbConnection() delete m_reader; + QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration()); // Delete screens in reverse order to avoid crash in case of multiple screens while (!m_screens.isEmpty()) - delete m_screens.takeLast(); - -#ifdef XCB_USE_EGL - if (m_has_egl) - eglTerminate(m_egl_display); -#endif //XCB_USE_EGL + integration->destroyScreen(m_screens.takeLast()); #ifdef XCB_USE_XLIB XCloseDisplay((Display *)m_xlib_display); @@ -990,51 +956,8 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) } } -#ifdef XCB_USE_XLIB - if (!handled) { - // Check if a custom XEvent constructor was registered in xlib for this event type, and call it discarding the constructed XEvent if any. - // XESetWireToEvent might be used by libraries to intercept messages from the X server e.g. the OpenGL lib waiting for DRI2 events. - Display *xdisplay = (Display *)m_xlib_display; - XLockDisplay(xdisplay); - bool locked = true; - Bool (*proc)(Display*, XEvent*, xEvent*) = XESetWireToEvent(xdisplay, response_type, 0); - if (proc) { - XESetWireToEvent(xdisplay, response_type, proc); - XEvent dummy; - event->sequence = LastKnownRequestProcessed(m_xlib_display); - if (proc(xdisplay, &dummy, (xEvent*)event)) { -#if defined(XCB_USE_GLX) && defined(XCB_HAS_XCB_GLX) - // DRI2 clients don't receive GLXBufferSwapComplete events on the wire. - // Instead the GLX event is synthesized from the DRI2BufferSwapComplete event - // by DRI2WireToEvent(). For an application to be able to see the event - // we have to convert it to an xcb_glx_buffer_swap_complete_event_t and - // pass it to the native event filter. - const uint swap_complete = glx_first_event + XCB_GLX_BUFFER_SWAP_COMPLETE; - if (dispatcher && has_glx_extension && uint(dummy.type) == swap_complete && response_type != swap_complete) { - QGLXBufferSwapComplete *xev = reinterpret_cast<QGLXBufferSwapComplete *>(&dummy); - xcb_glx_buffer_swap_complete_event_t ev; - memset(&ev, 0, sizeof(xcb_glx_buffer_swap_complete_event_t)); - ev.response_type = xev->type; - ev.sequence = xev->serial; - ev.event_type = xev->event_type; - ev.drawable = xev->drawable; - ev.ust_hi = xev->ust >> 32; - ev.ust_lo = xev->ust & 0xffffffff; - ev.msc_hi = xev->msc >> 32; - ev.msc_lo = xev->msc & 0xffffffff; - ev.sbc = xev->sbc & 0xffffffff; - // Unlock the display before calling the native event filter - XUnlockDisplay(xdisplay); - locked = false; - handled = dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), &ev, &result); - } -#endif - } - } - if (locked) - XUnlockDisplay(xdisplay); - } -#endif + if (!handled) + handled = m_glIntegration->handleXcbEvent(event, response_type); if (handled) printXcbEvent("Handled XCB event", event); @@ -1232,6 +1155,13 @@ xcb_window_t QXcbConnection::rootWindow() return primaryScreen()->root(); } +#ifdef XCB_USE_XLIB +void *QXcbConnection::xlib_display() const +{ + return m_xlib_display; +} +#endif + void QXcbConnection::processXcbEvents() { int connection_error = xcb_connection_has_error(xcb_connection()); @@ -1674,34 +1604,6 @@ void QXcbConnection::initializeXRender() #endif } -void QXcbConnection::initializeGLX() -{ -#ifdef XCB_HAS_XCB_GLX - const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_glx_id); - if (!reply || !reply->present) - return; - - has_glx_extension = true; - glx_first_event = reply->first_event; - - xcb_generic_error_t *error = 0; - xcb_glx_query_version_cookie_t xglx_query_cookie = xcb_glx_query_version(m_connection, - XCB_GLX_MAJOR_VERSION, - XCB_GLX_MINOR_VERSION); - xcb_glx_query_version_reply_t *xglx_query = xcb_glx_query_version_reply(m_connection, - xglx_query_cookie, &error); - if (!xglx_query || error) { - qWarning("QXcbConnection: Failed to initialize GLX"); - free(error); - has_glx_extension = false; - } - free(xglx_query); -#else - // no way to check, assume GLX is present - has_glx_extension = true; -#endif -} - void QXcbConnection::initializeXRandr() { const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_randr_id); @@ -1811,13 +1713,6 @@ void QXcbConnection::initializeXKB() #endif } -#if defined(XCB_USE_EGL) -bool QXcbConnection::hasEgl() const -{ - return m_has_egl; -} -#endif // defined(XCB_USE_EGL) - #if defined(XCB_USE_XINPUT2) static int xi2ValuatorOffset(unsigned char *maskPtr, int maskLen, int number) { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index 7286b6b89b..18fc8113e1 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -36,6 +36,7 @@ #include <xcb/xcb.h> +#include "qxcbexport.h" #include <QHash> #include <QList> #include <QMutex> @@ -85,6 +86,7 @@ class QXcbClipboard; class QXcbWMSupport; class QXcbNativeInterface; class QXcbSystemTrayTracker; +class QXcbGlIntegration; namespace QXcbAtom { enum Atom { @@ -295,7 +297,7 @@ class QXcbEventReader : public QThread public: QXcbEventReader(QXcbConnection *connection); - void run(); + void run() Q_DECL_OVERRIDE; QXcbEventArray *lock(); void unlock(); @@ -360,7 +362,7 @@ private: }; class QAbstractEventDispatcher; -class QXcbConnection : public QObject +class Q_XCB_EXPORT QXcbConnection : public QObject { Q_OBJECT public: @@ -395,15 +397,9 @@ public: QXcbWMSupport *wmSupport() const { return m_wmSupport.data(); } xcb_window_t rootWindow(); #ifdef XCB_USE_XLIB - void *xlib_display() const { return m_xlib_display; } + void *xlib_display() const; #endif -#ifdef XCB_USE_EGL - bool hasEgl() const; -#endif -#if defined(XCB_USE_EGL) - void *egl_display() const { return m_egl_display; } -#endif #if defined(XCB_USE_XINPUT2) void xi2Select(xcb_window_t window); #endif @@ -437,7 +433,6 @@ public: inline xcb_timestamp_t netWmUserTime() const { return m_netWmUserTime; } inline void setNetWmUserTime(xcb_timestamp_t t) { if (t > m_netWmUserTime) m_netWmUserTime = t; } - bool hasGLX() const { return has_glx_extension; } bool hasXFixes() const { return xfixes_first_event > 0; } bool hasXShape() const { return has_shape_extension; } bool hasXRandr() const { return has_randr_extension; } @@ -446,6 +441,7 @@ public: bool hasXKB() const { return has_xkb; } bool supportsThreadedRendering() const { return m_reader->isRunning(); } + bool threadedEventHandling() const { return m_reader->isRunning(); } xcb_timestamp_t getTimestamp(); @@ -472,6 +468,8 @@ public: QXcbEventReader *eventReader() const { return m_reader; } bool canGrab() const { return m_canGrabServer; } + + QXcbGlIntegration *glIntegration() const { return m_glIntegration; } protected: bool event(QEvent *e) Q_DECL_OVERRIDE; @@ -484,7 +482,6 @@ private slots: private: void initializeAllAtoms(); void sendConnectionEvent(QXcbAtom::Atom atom, uint id = 0); - void initializeGLX(); void initializeXFixes(); void initializeXRender(); void initializeXRandr(); @@ -580,10 +577,6 @@ private: QHash<int, QWindowSystemInterface::TouchPoint> m_touchPoints; QHash<int, XInput2TouchDeviceData*> m_touchDevices; #endif -#if defined(XCB_USE_EGL) - void *m_egl_display; - bool m_has_egl; -#endif #ifdef Q_XCB_DEBUG struct CallInfo { int sequence; @@ -604,9 +597,7 @@ private: uint32_t xfixes_first_event; uint32_t xrandr_first_event; uint32_t xkb_first_event; - uint32_t glx_first_event; - bool has_glx_extension; bool has_shape_extension; bool has_randr_extension; bool has_input_shape; @@ -619,6 +610,7 @@ private: QByteArray m_startupId; QXcbSystemTrayTracker *m_systemTrayTracker; + QXcbGlIntegration *m_glIntegration; friend class QXcbEventReader; }; @@ -668,11 +660,6 @@ cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, #define Q_XCB_NOOP(c) #endif - -#if defined(XCB_USE_EGL) -#define EGL_DISPLAY_FROM_XCB(object) ((EGLDisplay)(object->connection()->egl_display())) -#endif - QT_END_NAMESPACE #endif diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index 90d323ed34..07303f4e22 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -420,7 +420,7 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id) } if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) { dev->qtTouchDevice = new QTouchDevice; - dev->qtTouchDevice->setName(dev->xiDeviceInfo->name); + dev->qtTouchDevice->setName(QString::fromUtf8(dev->xiDeviceInfo->name)); dev->qtTouchDevice->setType((QTouchDevice::DeviceType)type); dev->qtTouchDevice->setCapabilities(caps); dev->qtTouchDevice->setMaximumTouchPoints(maxTouchPoints); diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h index 8ed23154ed..8f03f01747 100644 --- a/src/plugins/platforms/xcb/qxcbcursor.h +++ b/src/plugins/platforms/xcb/qxcbcursor.h @@ -70,10 +70,10 @@ public: QXcbCursor(QXcbConnection *conn, QXcbScreen *screen); ~QXcbCursor(); #ifndef QT_NO_CURSOR - void changeCursor(QCursor *cursor, QWindow *widget); + void changeCursor(QCursor *cursor, QWindow *widget) Q_DECL_OVERRIDE; #endif - QPoint pos() const; - void setPos(const QPoint &pos); + QPoint pos() const Q_DECL_OVERRIDE; + void setPos(const QPoint &pos) Q_DECL_OVERRIDE; static void queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint *pos, int *keybMask = 0); diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index 7037e102e2..5de5b6bb55 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -117,9 +117,9 @@ public: ~QXcbDropData(); protected: - bool hasFormat_sys(const QString &mimeType) const; - QStringList formats_sys() const; - QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const; + bool hasFormat_sys(const QString &mimeType) const Q_DECL_OVERRIDE; + QStringList formats_sys() const Q_DECL_OVERRIDE; + QVariant retrieveData_sys(const QString &mimeType, QVariant::Type type) const Q_DECL_OVERRIDE; QVariant xdndObtainData(const QByteArray &format, QVariant::Type requestedType) const; diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h index e273492837..1bca9a036f 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.h +++ b/src/plugins/platforms/xcb/qxcbdrag.h @@ -68,14 +68,14 @@ public: QXcbDrag(QXcbConnection *c); ~QXcbDrag(); - virtual QMimeData *platformDropData(); + virtual QMimeData *platformDropData() Q_DECL_OVERRIDE; - void startDrag(); - void cancel(); - void move(const QMouseEvent *me); - void drop(const QMouseEvent *me); - void endDrag(); + void startDrag() Q_DECL_OVERRIDE; + void cancel() Q_DECL_OVERRIDE; + void move(const QMouseEvent *me) Q_DECL_OVERRIDE; + void drop(const QMouseEvent *me) Q_DECL_OVERRIDE; + void endDrag() Q_DECL_OVERRIDE; void handleEnter(QWindow *window, const xcb_client_message_event_t *event); void handlePosition(QWindow *w, const xcb_client_message_event_t *event); @@ -92,7 +92,7 @@ public: xcb_timestamp_t targetTime() { return target_time; } protected: - void timerEvent(QTimerEvent* e); + void timerEvent(QTimerEvent* e) Q_DECL_OVERRIDE; private: friend class QXcbDropData; diff --git a/src/plugins/platforms/xcb/qxcbeglsurface.h b/src/plugins/platforms/xcb/qxcbexport.h index b03a029094..caf5124133 100644 --- a/src/plugins/platforms/xcb/qxcbeglsurface.h +++ b/src/plugins/platforms/xcb/qxcbexport.h @@ -31,34 +31,19 @@ ** ****************************************************************************/ -#ifndef QXCBEGLSURFACE_H -#define QXCBEGLSURFACE_H +#ifndef QXCBEXPORT_H +#define QXCBEXPORT_H -#include <EGL/egl.h> +#include <QtCore/qglobal.h> QT_BEGIN_NAMESPACE -class QXcbEGLSurface -{ -public: - QXcbEGLSurface(EGLDisplay display, EGLSurface surface) - : m_display(display) - , m_surface(surface) - { - } - - ~QXcbEGLSurface() - { - eglDestroySurface(m_display, m_surface); - } - - EGLSurface surface() const { return m_surface; } - -private: - EGLDisplay m_display; - EGLSurface m_surface; -}; +# if defined(QT_BUILD_XCB_PLUGIN) +# define Q_XCB_EXPORT Q_DECL_EXPORT +# else +# define Q_XCB_EXPORT Q_DECL_IMPORT +# endif QT_END_NAMESPACE +#endif //QXCBEXPORT_H -#endif diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp index f0c4a7f691..352d3255e4 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.cpp +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -41,6 +41,7 @@ #include "qxcbnativeinterface.h" #include "qxcbclipboard.h" #include "qxcbdrag.h" +#include "qxcbglintegration.h" #ifndef QT_NO_SESSIONMANAGER #include "qxcbsessionmanager.h" @@ -69,15 +70,6 @@ #include <private/qgenericunixthemes_p.h> #include <qpa/qplatforminputcontext.h> -#if defined(XCB_USE_GLX) -#include "qglxintegration.h" -#elif defined(XCB_USE_EGL) -#include "qxcbeglsurface.h" -#include <QtPlatformSupport/private/qeglplatformcontext_p.h> -#include <QtPlatformSupport/private/qeglpbuffer_p.h> -#include <QtPlatformHeaders/QEGLNativeContext> -#endif - #include <QtGui/QOpenGLContext> #include <QtGui/QScreen> #include <QtGui/QOffscreenSurface> @@ -177,7 +169,7 @@ QXcbIntegration::QXcbIntegration(const QStringList ¶meters, int &argc, char #ifdef Q_XCB_DEBUG qDebug() << "QXcbIntegration: Connecting to additional display: " << parameters.at(i) << parameters.at(i+1); #endif - QString display = parameters.at(i) + ':' + parameters.at(i+1); + QString display = parameters.at(i) + QLatin1Char(':') + parameters.at(i+1); m_connections << new QXcbConnection(m_nativeInterface.data(), display.toLatin1().constData()); } @@ -191,82 +183,32 @@ QXcbIntegration::~QXcbIntegration() QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const { - return new QXcbWindow(window); -} - -#if defined(XCB_USE_EGL) -class QEGLXcbPlatformContext : public QEGLPlatformContext -{ -public: - QEGLXcbPlatformContext(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<QXcbWindow *>(surface)->eglSurface()->surface(); - else - return static_cast<QEGLPbuffer *>(surface)->pbuffer(); - } - - QVariant nativeHandle() const { - return QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(eglContext(), eglDisplay())); + if (window->type() != Qt::Desktop) { + QXcbScreen *screen = static_cast<QXcbScreen *>(window->screen()->handle()); + QXcbGlIntegration *glIntegration = screen->connection()->glIntegration(); + if (glIntegration) { + QXcbWindow *xcbWindow = glIntegration->createWindow(window); + xcbWindow->create(); + return xcbWindow; + } } -private: - QXcbConnection *m_connection; -}; -#endif + Q_ASSERT(window->type() == Qt::Desktop || !window->supportsOpenGL()); + QXcbWindow *xcbWindow = new QXcbWindow(window); + xcbWindow->create(); + return xcbWindow; +} #ifndef QT_NO_OPENGL QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const { QXcbScreen *screen = static_cast<QXcbScreen *>(context->screen()->handle()); -#if defined(XCB_USE_GLX) - QGLXContext *platformContext = new QGLXContext(screen, context->format(), - context->shareHandle(), context->nativeHandle()); - context->setNativeHandle(platformContext->nativeHandle()); - return platformContext; -#elif defined(XCB_USE_EGL) - QEGLXcbPlatformContext *platformContext = new QEGLXcbPlatformContext(context->format(), - context->shareHandle(), - screen->connection()->egl_display(), - screen->connection(), - context->nativeHandle()); - context->setNativeHandle(platformContext->nativeHandle()); - return platformContext; -#else - Q_UNUSED(screen); - qWarning("QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enabled"); - return 0; -#endif + QXcbGlIntegration *glIntegration = screen->connection()->glIntegration(); + if (!glIntegration) { + qWarning("QXcbIntegration: Cannot create platform OpenGL context, neither GLX nor EGL are enabled"); + return Q_NULLPTR; + } + return glIntegration->createPlatformOpenGLContext(context); } #endif @@ -277,45 +219,23 @@ QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *wind QPlatformOffscreenSurface *QXcbIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const { -#if defined(XCB_USE_GLX) - 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 -#elif defined(XCB_USE_EGL) QXcbScreen *screen = static_cast<QXcbScreen *>(surface->screen()->handle()); - return new QEGLPbuffer(screen->connection()->egl_display(), surface->requestedFormat(), surface); -#else - Q_UNUSED(surface); - qWarning("QXcbIntegration: Cannot create platform offscreen surface, neither GLX nor EGL are enabled"); - return 0; -#endif + QXcbGlIntegration *glIntegration = screen->connection()->glIntegration(); + if (!glIntegration) { + qWarning("QXcbIntegration: Cannot create platform offscreen surface, neither GLX nor EGL are enabled"); + return Q_NULLPTR; + } + return glIntegration->createPlatformOffscreenSurface(surface); } bool QXcbIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { case ThreadedPixmaps: return true; -#if defined(XCB_USE_GLX) - case OpenGL: return m_connections.at(0)->hasGLX(); -#elif defined(XCB_USE_EGL) - case OpenGL: return true; -#else - case OpenGL: return false; -#endif -#if defined(XCB_USE_GLX) - case ThreadedOpenGL: return m_connections.at(0)->supportsThreadedRendering() && QGLXContext::supportsThreading(); -#else - case ThreadedOpenGL: return m_connections.at(0)->supportsThreadedRendering(); -#endif + case OpenGL: return m_connections.first()->glIntegration(); + case ThreadedOpenGL: return m_connections.at(0)->threadedEventHandling() + && m_connections.at(0)->glIntegration() + && m_connections.at(0)->glIntegration()->supportsThreadedOpenGL(); case WindowMasks: return true; case MultipleWindows: return true; case ForeignWindows: return true; diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h index db6ad541ea..150e3d57cb 100644 --- a/src/plugins/platforms/xcb/qxcbintegration.h +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -37,6 +37,8 @@ #include <qpa/qplatformintegration.h> #include <qpa/qplatformscreen.h> +#include "qxcbexport.h" + QT_BEGIN_NAMESPACE class QXcbConnection; @@ -44,51 +46,51 @@ class QAbstractEventDispatcher; class QXcbNativeInterface; class QXcbScreen; -class QXcbIntegration : public QPlatformIntegration +class Q_XCB_EXPORT QXcbIntegration : public QPlatformIntegration { public: QXcbIntegration(const QStringList ¶meters, int &argc, char **argv); ~QXcbIntegration(); - QPlatformWindow *createPlatformWindow(QWindow *window) const; + QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; #ifndef QT_NO_OPENGL - QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; #endif - QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const; + QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; - QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const; + QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; - bool hasCapability(Capability cap) const; - QAbstractEventDispatcher *createEventDispatcher() const; - void initialize(); + bool hasCapability(Capability cap) const Q_DECL_OVERRIDE; + QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; + void initialize() Q_DECL_OVERRIDE; void moveToScreen(QWindow *window, int screen); - QPlatformFontDatabase *fontDatabase() const; + QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; - QPlatformNativeInterface *nativeInterface()const; + QPlatformNativeInterface *nativeInterface()const Q_DECL_OVERRIDE; #ifndef QT_NO_CLIPBOARD - QPlatformClipboard *clipboard() const; + QPlatformClipboard *clipboard() const Q_DECL_OVERRIDE; #endif #ifndef QT_NO_DRAGANDDROP - QPlatformDrag *drag() const; + QPlatformDrag *drag() const Q_DECL_OVERRIDE; #endif - QPlatformInputContext *inputContext() const; + QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE; #ifndef QT_NO_ACCESSIBILITY - QPlatformAccessibility *accessibility() const; + QPlatformAccessibility *accessibility() const Q_DECL_OVERRIDE; #endif - QPlatformServices *services() const; + QPlatformServices *services() const Q_DECL_OVERRIDE; - Qt::KeyboardModifiers queryKeyboardModifiers() const; - QList<int> possibleKeys(const QKeyEvent *e) const; + Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE; + QList<int> possibleKeys(const QKeyEvent *e) const Q_DECL_OVERRIDE; - QStringList themeNames() const; - QPlatformTheme *createPlatformTheme(const QString &name) const; - QVariant styleHint(StyleHint hint) const; + QStringList themeNames() const Q_DECL_OVERRIDE; + QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE; + QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE; QXcbConnection *defaultConnection() const { return m_connections.first(); } @@ -98,7 +100,7 @@ public: QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const Q_DECL_OVERRIDE; #endif - void sync(); + void sync() Q_DECL_OVERRIDE; private: QList<QXcbConnection *> m_connections; diff --git a/src/plugins/platforms/xcb/qxcbmain.cpp b/src/plugins/platforms/xcb/qxcbmain.cpp index 80de5ba6f1..921c71711e 100644 --- a/src/plugins/platforms/xcb/qxcbmain.cpp +++ b/src/plugins/platforms/xcb/qxcbmain.cpp @@ -41,7 +41,7 @@ class QXcbIntegrationPlugin : public QPlatformIntegrationPlugin Q_OBJECT Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPA.QPlatformIntegrationFactoryInterface.5.2" FILE "xcb.json") public: - QPlatformIntegration *create(const QString&, const QStringList&, int &, char **); + QPlatformIntegration *create(const QString&, const QStringList&, int &, char **) Q_DECL_OVERRIDE; }; QPlatformIntegration* QXcbIntegrationPlugin::create(const QString& system, const QStringList& parameters, int &argc, char **argv) diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 31dedd40a2..05035a5b1e 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -46,12 +46,6 @@ #include <QtGui/qopenglcontext.h> #include <QtGui/qscreen.h> -#if defined(XCB_USE_EGL) -#include "QtPlatformSupport/private/qeglplatformcontext_p.h" -#elif defined (XCB_USE_GLX) -#include "qglxintegration.h" -#endif - #include <QtPlatformHeaders/qxcbwindowfunctions.h> #ifdef XCB_USE_XLIB @@ -62,18 +56,17 @@ #include <algorithm> +#include "qxcbnativeinterfacehandler.h" + QT_BEGIN_NAMESPACE // return QXcbNativeInterface::ResourceType for the key. static int resourceType(const QByteArray &key) { static const QByteArray names[] = { // match QXcbNativeInterface::ResourceType - QByteArrayLiteral("display"), QByteArrayLiteral("egldisplay"), + QByteArrayLiteral("display"), QByteArrayLiteral("connection"), QByteArrayLiteral("screen"), - QByteArrayLiteral("eglcontext"), - QByteArrayLiteral("eglconfig"), - QByteArrayLiteral("glxconfig"), - QByteArrayLiteral("glxcontext"), QByteArrayLiteral("apptime"), + QByteArrayLiteral("apptime"), QByteArrayLiteral("appusertime"), QByteArrayLiteral("hintstyle"), QByteArrayLiteral("startupid"), QByteArrayLiteral("traywindow"), QByteArrayLiteral("gettimestamp"), QByteArrayLiteral("x11screen"), @@ -83,8 +76,6 @@ static int resourceType(const QByteArray &key) }; const QByteArray *end = names + sizeof(names) / sizeof(names[0]); const QByteArray *result = std::find(names, end, key); - if (result == end) - result = std::find(names, end, key.toLower()); return int(result - names); } @@ -209,10 +200,26 @@ void QXcbNativeInterface::clearRegion(const QWindow *qwindow, const QRect& rect) } } +void QXcbNativeInterface::setParentRelativeBackPixmap(const QWindow *qwindow) +{ + if (const QPlatformWindow *platformWindow = qwindow->handle()) { + const QXcbWindow *qxwindow = static_cast<const QXcbWindow *>(platformWindow); + xcb_connection_t *xcb_conn = qxwindow->xcb_connection(); + + const quint32 mask = XCB_CW_BACK_PIXMAP; + const quint32 values[] = { XCB_BACK_PIXMAP_PARENT_RELATIVE }; + Q_XCB_CALL(xcb_change_window_attributes(xcb_conn, qxwindow->xcb_window(), mask, values)); + } +} + void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString) { - void *result = 0; - switch (resourceType(resourceString)) { + QByteArray lowerCaseResource = resourceString.toLower(); + void *result = handlerNativeResourceForIntegration(lowerCaseResource); + if (result) + return result; + + switch (resourceType(lowerCaseResource)) { case StartupId: result = startupId(); break; @@ -222,6 +229,9 @@ void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resour case RootWindow: result = rootWindow(); break; + case Display: + result = display(); + break; default: break; } @@ -231,32 +241,20 @@ void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resour void *QXcbNativeInterface::nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) { - void *result = 0; - switch (resourceType(resourceString)) { - case EglContext: - result = eglContextForContext(context); - break; - case EglConfig: - result = eglConfigForContext(context); - break; - case GLXConfig: - result = glxConfigForContext(context); - break; - case GLXContext: - result = glxContextForContext(context); - break; - default: - break; - } - + QByteArray lowerCaseResource = resourceString.toLower(); + void *result = handlerNativeResourceForContext(lowerCaseResource, context); return result; } -void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resource, QScreen *screen) +void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resourceString, QScreen *screen) { - void *result = 0; + QByteArray lowerCaseResource = resourceString.toLower(); + void *result = handlerNativeResourceForScreen(lowerCaseResource ,screen); + if (result) + return result; + const QXcbScreen *xcbScreen = static_cast<QXcbScreen *>(screen->handle()); - switch (resourceType(resource)) { + switch (resourceType(lowerCaseResource)) { case Display: #ifdef XCB_USE_XLIB result = xcbScreen->connection()->xlib_display(); @@ -295,14 +293,15 @@ void *QXcbNativeInterface::nativeResourceForScreen(const QByteArray &resource, Q void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) { - void *result = 0; - switch (resourceType(resourceString)) { + QByteArray lowerCaseResource = resourceString.toLower(); + void *result = handlerNativeResourceForWindow(lowerCaseResource, window); + if (result) + return result; + + switch (resourceType(lowerCaseResource)) { case Display: result = displayForWindow(window); break; - case EglDisplay: - result = eglDisplayForWindow(window); - break; case Connection: result = connectionForWindow(window); break; @@ -316,17 +315,42 @@ void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceStr return result; } +void *QXcbNativeInterface::nativeResourceForBackingStore(const QByteArray &resourceString, QBackingStore *backingStore) +{ + const QByteArray lowerCaseResource = resourceString.toLower(); + void *result = handlerNativeResourceForBackingStore(lowerCaseResource,backingStore); + return result; +} + + QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterface::nativeResourceFunctionForIntegration(const QByteArray &resource) { - QByteArray lowerCaseResource = resource.toLower(); + const QByteArray lowerCaseResource = resource.toLower(); + QPlatformNativeInterface::NativeResourceForIntegrationFunction func = handlerNativeResourceFunctionForIntegration(lowerCaseResource); + if (func) + return func; + if (lowerCaseResource == "setstartupid") return NativeResourceForIntegrationFunction(setStartupId); return 0; } +QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource) +{ + const QByteArray lowerCaseResource = resource.toLower(); + QPlatformNativeInterface::NativeResourceForContextFunction func = handlerNativeResourceFunctionForContext(lowerCaseResource); + if (func) + return func; + return Q_NULLPTR; +} + QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::nativeResourceFunctionForScreen(const QByteArray &resource) { const QByteArray lowerCaseResource = resource.toLower(); + NativeResourceForScreenFunction func = handlerNativeResourceFunctionForScreen(lowerCaseResource); + if (func) + return func; + if (lowerCaseResource == "setapptime") return NativeResourceForScreenFunction(setAppTime); else if (lowerCaseResource == "setappusertime") @@ -334,8 +358,28 @@ QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::n return 0; } +QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterface::nativeResourceFunctionForWindow(const QByteArray &resource) +{ + const QByteArray lowerCaseResource = resource.toLower(); + NativeResourceForWindowFunction func = handlerNativeResourceFunctionForWindow(lowerCaseResource); + return func; +} + +QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterface::nativeResourceFunctionForBackingStore(const QByteArray &resource) +{ + const QByteArray lowerCaseResource = resource.toLower(); + NativeResourceForBackingStoreFunction func = handlerNativeResourceFunctionForBackingStore(resource); + return func; +} + QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &function) const { + const QByteArray lowerCaseFunction = function.toLower(); + QFunctionPointer func = handlerPlatformFunction(lowerCaseFunction); + if (func) + return func; + + //case sensitive if (function == QXcbWindowFunctions::setWmWindowTypeIdentifier()) { return QFunctionPointer(QXcbWindow::setWmWindowTypeStatic); } @@ -384,6 +428,17 @@ void *QXcbNativeInterface::rootWindow() return 0; } +void *QXcbNativeInterface::display() +{ +#ifdef XCB_USE_XLIB + QXcbIntegration *integration = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration()); + QXcbConnection *defaultConnection = integration->defaultConnection(); + return defaultConnection->xlib_display(); +#else + return 0; +#endif +} + void QXcbNativeInterface::setAppTime(QScreen* screen, xcb_timestamp_t time) { static_cast<QXcbScreen *>(screen->handle())->connection()->setTime(time); @@ -403,15 +458,6 @@ void QXcbNativeInterface::setStartupId(const char *data) defaultConnection->setStartupId(startupId); } -QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::nativeResourceFunctionForContext(const QByteArray &resource) -{ - QByteArray lowerCaseResource = resource.toLower(); - if (lowerCaseResource == "get_egl_context") { - return eglContextForContext; - } - return 0; -} - QXcbScreen *QXcbNativeInterface::qPlatformScreenForWindow(QWindow *window) { QXcbScreen *screen; @@ -434,17 +480,6 @@ void *QXcbNativeInterface::displayForWindow(QWindow *window) #endif } -void *QXcbNativeInterface::eglDisplayForWindow(QWindow *window) -{ -#if defined(XCB_USE_EGL) - QXcbScreen *screen = qPlatformScreenForWindow(window); - return screen->connection()->egl_display(); -#else - Q_UNUSED(window) - return 0; -#endif -} - void *QXcbNativeInterface::connectionForWindow(QWindow *window) { QXcbScreen *screen = qPlatformScreenForWindow(window); @@ -457,54 +492,121 @@ void *QXcbNativeInterface::screenForWindow(QWindow *window) return screen->screen(); } -void * QXcbNativeInterface::eglContextForContext(QOpenGLContext *context) +void QXcbNativeInterface::addHandler(QXcbNativeInterfaceHandler *handler) { - Q_ASSERT(context); -#if defined(XCB_USE_EGL) - QEGLPlatformContext *eglPlatformContext = static_cast<QEGLPlatformContext *>(context->handle()); - return eglPlatformContext->eglContext(); -#else - Q_UNUSED(context); - return 0; -#endif + m_handlers.removeAll(handler); + m_handlers.prepend(handler); } -void * QXcbNativeInterface::eglConfigForContext(QOpenGLContext *context) +void QXcbNativeInterface::removeHandler(QXcbNativeInterfaceHandler *handler) { - Q_ASSERT(context); -#if defined(XCB_USE_EGL) - QEGLPlatformContext *eglPlatformContext = static_cast<QEGLPlatformContext *>(context->handle()); - return eglPlatformContext->eglConfig(); -#else - Q_UNUSED(context); - return 0; -#endif + m_handlers.removeAll(handler); } -void *QXcbNativeInterface::glxContextForContext(QOpenGLContext *context) +QPlatformNativeInterface::NativeResourceForIntegrationFunction QXcbNativeInterface::handlerNativeResourceFunctionForIntegration(const QByteArray &resource) const { - Q_ASSERT(context); -#if defined(XCB_USE_GLX) - QGLXContext *glxPlatformContext = static_cast<QGLXContext *>(context->handle()); - return glxPlatformContext->glxContext(); -#else - Q_UNUSED(context); - return 0; -#endif + for (int i = 0; i < m_handlers.size(); i++) { + QXcbNativeInterfaceHandler *handler = m_handlers.at(i); + NativeResourceForIntegrationFunction result = handler->nativeResourceFunctionForIntegration(resource); + if (result) + return result; + } + return Q_NULLPTR; +} +QPlatformNativeInterface::NativeResourceForContextFunction QXcbNativeInterface::handlerNativeResourceFunctionForContext(const QByteArray &resource) const +{ + for (int i = 0; i < m_handlers.size(); i++) { + QXcbNativeInterfaceHandler *handler = m_handlers.at(i); + NativeResourceForContextFunction result = handler->nativeResourceFunctionForContext(resource); + if (result) + return result; + } + return Q_NULLPTR; } -void *QXcbNativeInterface::glxConfigForContext(QOpenGLContext *context) +QPlatformNativeInterface::NativeResourceForScreenFunction QXcbNativeInterface::handlerNativeResourceFunctionForScreen(const QByteArray &resource) const { - Q_ASSERT(context); -#if defined(XCB_USE_GLX) - QGLXContext *glxPlatformContext = static_cast<QGLXContext *>(context->handle()); - return glxPlatformContext->glxConfig(); -#else - Q_UNUSED(context); - return 0; -#endif + for (int i = 0; i < m_handlers.size(); i++) { + QXcbNativeInterfaceHandler *handler = m_handlers.at(i); + NativeResourceForScreenFunction result = handler->nativeResourceFunctionForScreen(resource); + if (result) + return result; + } + return Q_NULLPTR; +} + +QPlatformNativeInterface::NativeResourceForWindowFunction QXcbNativeInterface::handlerNativeResourceFunctionForWindow(const QByteArray &resource) const +{ + for (int i = 0; i < m_handlers.size(); i++) { + QXcbNativeInterfaceHandler *handler = m_handlers.at(i); + NativeResourceForWindowFunction result = handler->nativeResourceFunctionForWindow(resource); + if (result) + return result; + } + return Q_NULLPTR; +} + +QPlatformNativeInterface::NativeResourceForBackingStoreFunction QXcbNativeInterface::handlerNativeResourceFunctionForBackingStore(const QByteArray &resource) const +{ + for (int i = 0; i < m_handlers.size(); i++) { + QXcbNativeInterfaceHandler *handler = m_handlers.at(i); + NativeResourceForBackingStoreFunction result = handler->nativeResourceFunctionForBackingStore(resource); + if (result) + return result; + } + return Q_NULLPTR; +} +QFunctionPointer QXcbNativeInterface::handlerPlatformFunction(const QByteArray &function) const +{ + for (int i = 0; i < m_handlers.size(); i++) { + QXcbNativeInterfaceHandler *handler = m_handlers.at(i); + QFunctionPointer func = handler->platformFunction(function); + if (func) + return func; + } + return Q_NULLPTR; +} + +void *QXcbNativeInterface::handlerNativeResourceForIntegration(const QByteArray &resource) const +{ + NativeResourceForIntegrationFunction func = handlerNativeResourceFunctionForIntegration(resource); + if (func) + return func(); + return Q_NULLPTR; +} + +void *QXcbNativeInterface::handlerNativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) const +{ + NativeResourceForContextFunction func = handlerNativeResourceFunctionForContext(resource); + if (func) + return func(context); + return Q_NULLPTR; +} + +void *QXcbNativeInterface::handlerNativeResourceForScreen(const QByteArray &resource, QScreen *screen) const +{ + NativeResourceForScreenFunction func = handlerNativeResourceFunctionForScreen(resource); + if (func) + return func(screen); + return Q_NULLPTR; +} + +void *QXcbNativeInterface::handlerNativeResourceForWindow(const QByteArray &resource, QWindow *window) const +{ + NativeResourceForWindowFunction func = handlerNativeResourceFunctionForWindow(resource); + if (func) + return func(window); + return Q_NULLPTR; +} + +void *QXcbNativeInterface::handlerNativeResourceForBackingStore(const QByteArray &resource, QBackingStore *backingStore) const +{ + NativeResourceForBackingStoreFunction func = handlerNativeResourceFunctionForBackingStore(resource); + if (func) + return func(backingStore); + return Q_NULLPTR; } QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h index 330dd008c4..1db2d1cf83 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.h +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -39,25 +39,23 @@ #include <QtCore/QRect> +#include "qxcbexport.h" + QT_BEGIN_NAMESPACE class QWidget; class QXcbScreen; class QXcbConnection; +class QXcbNativeInterfaceHandler; -class QXcbNativeInterface : public QPlatformNativeInterface +class Q_XCB_EXPORT QXcbNativeInterface : public QPlatformNativeInterface { Q_OBJECT public: enum ResourceType { Display, - EglDisplay, Connection, Screen, - EglContext, - EglConfig, - GLXConfig, - GLXContext, AppTime, AppUserTime, ScreenHintStyle, @@ -77,17 +75,19 @@ public: void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) Q_DECL_OVERRIDE; void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen) Q_DECL_OVERRIDE; void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE; + void *nativeResourceForBackingStore(const QByteArray &resource, QBackingStore *backingStore) Q_DECL_OVERRIDE; NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE; NativeResourceForContextFunction nativeResourceFunctionForContext(const QByteArray &resource) Q_DECL_OVERRIDE; NativeResourceForScreenFunction nativeResourceFunctionForScreen(const QByteArray &resource) Q_DECL_OVERRIDE; + NativeResourceForWindowFunction nativeResourceFunctionForWindow(const QByteArray &resource) Q_DECL_OVERRIDE; + NativeResourceForBackingStoreFunction nativeResourceFunctionForBackingStore(const QByteArray &resource) Q_DECL_OVERRIDE; QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE; inline const QByteArray &genericEventFilterType() const { return m_genericEventFilterType; } void *displayForWindow(QWindow *window); - void *eglDisplayForWindow(QWindow *window); void *connectionForWindow(QWindow *window); void *screenForWindow(QWindow *window); void *appTime(const QXcbScreen *screen); @@ -96,21 +96,21 @@ public: void *startupId(); void *x11Screen(); void *rootWindow(); + void *display(); static void setStartupId(const char *); static void setAppTime(QScreen *screen, xcb_timestamp_t time); static void setAppUserTime(QScreen *screen, xcb_timestamp_t time); - static void *eglContextForContext(QOpenGLContext *context); - static void *eglConfigForContext(QOpenGLContext *context); - static void *glxContextForContext(QOpenGLContext *context); - static void *glxConfigForContext(QOpenGLContext *context); Q_INVOKABLE void beep(); Q_INVOKABLE bool systemTrayAvailable(const QScreen *screen) const; Q_INVOKABLE void clearRegion(const QWindow *qwindow, const QRect& rect); + Q_INVOKABLE void setParentRelativeBackPixmap(const QWindow *window); Q_INVOKABLE bool systrayVisualHasAlphaChannel(); Q_INVOKABLE bool requestSystemTrayWindowDock(const QWindow *window); Q_INVOKABLE QRect systemTrayWindowGlobalGeometry(const QWindow *window); + void addHandler(QXcbNativeInterfaceHandler *handler); + void removeHandler(QXcbNativeInterfaceHandler *handler); signals: void systemTrayWindowChanged(QScreen *screen); @@ -123,6 +123,19 @@ private: xcb_visualid_t m_systrayVisualId; static QXcbScreen *qPlatformScreenForWindow(QWindow *window); + + QList<QXcbNativeInterfaceHandler *> m_handlers; + NativeResourceForIntegrationFunction handlerNativeResourceFunctionForIntegration(const QByteArray &resource) const; + NativeResourceForContextFunction handlerNativeResourceFunctionForContext(const QByteArray &resource) const; + NativeResourceForScreenFunction handlerNativeResourceFunctionForScreen(const QByteArray &resource) const; + NativeResourceForWindowFunction handlerNativeResourceFunctionForWindow(const QByteArray &resource) const; + NativeResourceForBackingStoreFunction handlerNativeResourceFunctionForBackingStore(const QByteArray &resource) const; + QFunctionPointer handlerPlatformFunction(const QByteArray &function) const; + void *handlerNativeResourceForIntegration(const QByteArray &resource) const; + void *handlerNativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) const; + void *handlerNativeResourceForScreen(const QByteArray &resource, QScreen *screen) const; + void *handlerNativeResourceForWindow(const QByteArray &resource, QWindow *window) const; + void *handlerNativeResourceForBackingStore(const QByteArray &resource, QBackingStore *backingStore) const; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 7136455754..0f25d10aac 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -337,7 +337,7 @@ QDpi QXcbScreen::logicalDpi() const qreal QXcbScreen::devicePixelRatio() const { - static int override_dpr = qgetenv("QT_DEVICE_PIXEL_RATIO").toInt(); + static int override_dpr = qEnvironmentVariableIntValue("QT_DEVICE_PIXEL_RATIO"); static bool auto_dpr = qgetenv("QT_DEVICE_PIXEL_RATIO").toLower() == "auto"; if (override_dpr > 0) return override_dpr; diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index e9ab2edaa0..652d64c105 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -41,6 +41,7 @@ #include <xcb/randr.h> #include "qxcbobject.h" +#include "qxcbscreen.h" #include <private/qfontengine_p.h> @@ -50,29 +51,29 @@ class QXcbConnection; class QXcbCursor; class QXcbXSettings; -class QXcbScreen : public QXcbObject, public QPlatformScreen +class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen { public: QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, xcb_randr_get_output_info_reply_t *output, QString outputName, int number); ~QXcbScreen(); - QPixmap grabWindow(WId window, int x, int y, int width, int height) const; + QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE; - QWindow *topLevelAt(const QPoint &point) const; + QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE; - QRect geometry() const { return m_geometry; } + QRect geometry() const Q_DECL_OVERRIDE { return m_geometry; } QRect nativeGeometry() const { return m_nativeGeometry; } - QRect availableGeometry() const {return m_availableGeometry;} - int depth() const { return m_screen->root_depth; } - QImage::Format format() const; - QSizeF physicalSize() const { return m_sizeMillimeters; } - QDpi logicalDpi() const; - qreal devicePixelRatio() const; - QPlatformCursor *cursor() const; - qreal refreshRate() const { return m_refreshRate; } - Qt::ScreenOrientation orientation() const { return m_orientation; } - QList<QPlatformScreen *> virtualSiblings() const { return m_siblings; } + QRect availableGeometry() const Q_DECL_OVERRIDE {return m_availableGeometry;} + int depth() const Q_DECL_OVERRIDE { return m_screen->root_depth; } + QImage::Format format() const Q_DECL_OVERRIDE; + QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_sizeMillimeters; } + QDpi logicalDpi() const Q_DECL_OVERRIDE; + qreal devicePixelRatio() const Q_DECL_OVERRIDE; + QPlatformCursor *cursor() const Q_DECL_OVERRIDE; + qreal refreshRate() const Q_DECL_OVERRIDE { return m_refreshRate; } + Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_orientation; } + QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; } void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; } int screenNumber() const { return m_number; } @@ -89,7 +90,7 @@ public: const xcb_visualtype_t *visualForId(xcb_visualid_t) const; quint8 depthOfVisual(xcb_visualid_t) const; - QString name() const { return m_outputName; } + QString name() const Q_DECL_OVERRIDE { return m_outputName; } void handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event); void updateGeometry(xcb_timestamp_t timestamp); diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.h b/src/plugins/platforms/xcb/qxcbsystemtraytracker.h index 2e297c4ae5..2f364d3e55 100644 --- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.h +++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.h @@ -55,7 +55,7 @@ public: void notifyManagerClientMessageEvent(const xcb_client_message_event_t *); - void handleDestroyNotifyEvent(const xcb_destroy_notify_event_t *); + void handleDestroyNotifyEvent(const xcb_destroy_notify_event_t *) Q_DECL_OVERRIDE; signals: void systemTrayWindowChanged(QScreen *screen); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 4fd71f1635..4676133777 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -97,15 +97,6 @@ #include <X11/extensions/XInput2.h> #endif -#if defined(XCB_USE_GLX) -#include "qglxintegration.h" -#include <QtPlatformSupport/private/qglxconvenience_p.h> -#elif defined(XCB_USE_EGL) -#include "qxcbeglsurface.h" -#include <QtPlatformSupport/private/qeglconvenience_p.h> -#include <QtPlatformSupport/private/qxlibeglintegration_p.h> -#endif - #define XCOORD_MAX 16383 enum { defaultWindowWidth = 160, @@ -238,9 +229,6 @@ QXcbWindow::QXcbWindow(QWindow *window) , m_alertState(false) , m_netWmUserTimeWindow(XCB_NONE) , m_dirtyFrameMargins(false) -#if defined(XCB_USE_EGL) - , m_eglSurface(0) -#endif , m_lastWindowStateEvent(-1) , m_syncState(NoSyncNeeded) , m_pendingSyncRequest(0) @@ -248,11 +236,6 @@ QXcbWindow::QXcbWindow(QWindow *window) m_screen = static_cast<QXcbScreen *>(window->screen()->handle()); setConnection(m_screen->connection()); - - if (window->type() != Qt::ForeignWindow) - create(); - else - m_window = window->winId(); } #ifdef Q_COMPILER_CLASS_ENUM @@ -278,6 +261,11 @@ enum { void QXcbWindow::create() { + if (window()->type() == Qt::ForeignWindow) { + m_window = window()->winId(); + return; + } + destroy(); m_deferredExpose = false; @@ -341,27 +329,12 @@ void QXcbWindow::create() window()->setFormat(parentFormat); } } - m_format = window()->requestedFormat(); -#if (defined(XCB_USE_GLX) || defined(XCB_USE_EGL)) && defined(XCB_USE_XLIB) + resolveFormat(); + +#ifdef XCB_USE_XLIB if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) { -#if defined(XCB_USE_GLX) - XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), &m_format); -#elif defined(XCB_USE_EGL) - EGLDisplay eglDisplay = connection()->egl_display(); - EGLConfig eglConfig = q_configFromGLFormat(eglDisplay, m_format, true); - m_format = q_glFormatFromConfig(eglDisplay, eglConfig, m_format); - - VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this), eglDisplay, eglConfig); - - XVisualInfo visualInfoTemplate; - memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); - visualInfoTemplate.visualid = id; - - XVisualInfo *visualInfo; - int matchingCount = 0; - visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount); -#endif //XCB_USE_GLX + XVisualInfo *visualInfo = static_cast<XVisualInfo *>(createVisual()); if (!visualInfo && window()->surfaceType() == QSurface::OpenGLSurface) qFatal("Could not initialize OpenGL"); @@ -369,6 +342,7 @@ void QXcbWindow::create() qWarning("Could not initialize OpenGL for RasterGLSurface, reverting to RasterSurface."); window()->setSurfaceType(QSurface::RasterSurface); } + if (visualInfo) { m_depth = visualInfo->depth; m_imageFormat = imageFormatForVisual(visualInfo->depth, visualInfo->red_mask, visualInfo->blue_mask); @@ -390,9 +364,9 @@ void QXcbWindow::create() XFree(visualInfo); } } +#endif if (!m_window) -#endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL) { m_window = xcb_generate_id(xcb_connection()); m_visualId = m_screen->screen()->root_visual; @@ -453,12 +427,10 @@ void QXcbWindow::create() properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); - m_usingSyncProtocol = m_screen->syncRequestSupported(); -#if !defined(XCB_USE_GLX) - // synced resize only implemented on GLX - if (window()->supportsOpenGL()) + if (m_screen->syncRequestSupported()) + m_usingSyncProtocol = supportsSyncProtocol(); + else m_usingSyncProtocol = false; -#endif if (m_usingSyncProtocol) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST); @@ -580,11 +552,6 @@ void QXcbWindow::destroy() } m_mapped = false; -#if defined(XCB_USE_EGL) - delete m_eglSurface; - m_eglSurface = 0; -#endif - if (m_pendingSyncRequest) m_pendingSyncRequest->invalidate(); } @@ -1561,21 +1528,6 @@ QSurfaceFormat QXcbWindow::format() const return m_format; } -#if defined(XCB_USE_EGL) -QXcbEGLSurface *QXcbWindow::eglSurface() const -{ - if (!m_eglSurface) { - EGLDisplay display = connection()->egl_display(); - EGLConfig config = q_configFromGLFormat(display, window()->requestedFormat(), true); - EGLSurface surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)m_window, 0); - - m_eglSurface = new QXcbEGLSurface(display, surface); - } - - return m_eglSurface; -} -#endif - void QXcbWindow::setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes) { if (window->handle()) diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 254421e57d..b78bf779d0 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -48,11 +48,10 @@ QT_BEGIN_NAMESPACE class QXcbScreen; -class QXcbEGLSurface; class QXcbSyncWindowRequest; class QIcon; -class QXcbWindow : public QXcbObject, public QXcbWindowEventListener, public QPlatformWindow +class Q_XCB_EXPORT QXcbWindow : public QXcbObject, public QXcbWindowEventListener, public QPlatformWindow { public: enum NetWmState { @@ -71,45 +70,45 @@ public: QXcbWindow(QWindow *window); ~QXcbWindow(); - void setGeometry(const QRect &rect); + void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; - QMargins frameMargins() const; + QMargins frameMargins() const Q_DECL_OVERRIDE; - void setVisible(bool visible); - void setWindowFlags(Qt::WindowFlags flags); - void setWindowState(Qt::WindowState state); - WId winId() const; - void setParent(const QPlatformWindow *window); + void setVisible(bool visible) Q_DECL_OVERRIDE; + void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE; + void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE; + WId winId() const Q_DECL_OVERRIDE; + void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE; - bool isExposed() const; - bool isEmbedded(const QPlatformWindow *parentWindow) const; - QPoint mapToGlobal(const QPoint &pos) const; - QPoint mapFromGlobal(const QPoint &pos) const; + bool isExposed() const Q_DECL_OVERRIDE; + bool isEmbedded(const QPlatformWindow *parentWindow) const Q_DECL_OVERRIDE; + QPoint mapToGlobal(const QPoint &pos) const Q_DECL_OVERRIDE; + QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE; - void setWindowTitle(const QString &title); - void setWindowIcon(const QIcon &icon); - void raise(); - void lower(); - void propagateSizeHints(); + void setWindowTitle(const QString &title) Q_DECL_OVERRIDE; + void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE; + void raise() Q_DECL_OVERRIDE; + void lower() Q_DECL_OVERRIDE; + void propagateSizeHints() Q_DECL_OVERRIDE; - void requestActivateWindow(); + void requestActivateWindow() Q_DECL_OVERRIDE; - bool setKeyboardGrabEnabled(bool grab); - bool setMouseGrabEnabled(bool grab); + bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE; + bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE; void setCursor(xcb_cursor_t cursor); - QSurfaceFormat format() const; + QSurfaceFormat format() const Q_DECL_OVERRIDE; - void windowEvent(QEvent *event); + void windowEvent(QEvent *event) Q_DECL_OVERRIDE; - bool startSystemResize(const QPoint &pos, Qt::Corner corner); + bool startSystemResize(const QPoint &pos, Qt::Corner corner) Q_DECL_OVERRIDE; - void setOpacity(qreal level); - void setMask(const QRegion ®ion); + void setOpacity(qreal level) Q_DECL_OVERRIDE; + void setMask(const QRegion ®ion) Q_DECL_OVERRIDE; - void setAlertState(bool enabled); - bool isAlertState() const { return m_alertState; } + void setAlertState(bool enabled) Q_DECL_OVERRIDE; + bool isAlertState() const Q_DECL_OVERRIDE { return m_alertState; } xcb_window_t xcb_window() const { return m_window; } uint depth() const { return m_depth; } @@ -138,10 +137,6 @@ public: void updateNetWmUserTime(xcb_timestamp_t timestamp); -#if defined(XCB_USE_EGL) - QXcbEGLSurface *eglSurface() const; -#endif - static void setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes); QXcbWindowFunctions::WmWindowTypes wmWindowTypes() const; @@ -152,14 +147,20 @@ public: void postSyncWindowRequest(); void clearSyncWindowRequest() { m_pendingSyncRequest = 0; } - qreal devicePixelRatio() const; + qreal devicePixelRatio() const Q_DECL_OVERRIDE; + virtual void create(); + virtual void destroy(); QPlatformScreen *screenForNativeGeometry(const QRect &newGeometry) const; public Q_SLOTS: void updateSyncRequestCounter(); -private: +protected: + virtual void resolveFormat() { m_format = window()->requestedFormat(); } + virtual void *createVisual() { return Q_NULLPTR; } + virtual bool supportsSyncProtocol() { return !window()->supportsOpenGL(); } + void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0); NetWmStates netWmStates(); void setNetWmStates(NetWmStates); @@ -178,9 +179,6 @@ private: quint32 detail = 0, quint32 data1 = 0, quint32 data2 = 0); void handleXEmbedMessage(const xcb_client_message_event_t *event); - void create(); - void destroy(); - void show(); void hide(); @@ -217,10 +215,6 @@ private: mutable bool m_dirtyFrameMargins; mutable QMargins m_frameMargins; -#if defined(XCB_USE_EGL) - mutable QXcbEGLSurface *m_eglSurface; -#endif - QRegion m_exposeRegion; xcb_visualid_t m_visualId; diff --git a/src/plugins/platforms/xcb/xcb-plugin.pro b/src/plugins/platforms/xcb/xcb-plugin.pro index 129076c916..09ab1ad77a 100644 --- a/src/plugins/platforms/xcb/xcb-plugin.pro +++ b/src/plugins/platforms/xcb/xcb-plugin.pro @@ -5,117 +5,9 @@ PLUGIN_CLASS_NAME = QXcbIntegrationPlugin !equals(TARGET, $$QT_DEFAULT_QPA_PLUGIN): PLUGIN_EXTENDS = - load(qt_plugin) -QT += core-private gui-private platformsupport-private +QT += core-private gui-private platformsupport-private xcb_qpa_lib-private SOURCES = \ - qxcbclipboard.cpp \ - qxcbconnection.cpp \ - qxcbintegration.cpp \ - qxcbkeyboard.cpp \ - qxcbmime.cpp \ - qxcbdrag.cpp \ - qxcbscreen.cpp \ - qxcbwindow.cpp \ - qxcbbackingstore.cpp \ - qxcbwmsupport.cpp \ - qxcbmain.cpp \ - qxcbnativeinterface.cpp \ - qxcbcursor.cpp \ - qxcbimage.cpp \ - qxcbxsettings.cpp \ - qxcbsystemtraytracker.cpp - -HEADERS = \ - qxcbclipboard.h \ - qxcbconnection.h \ - qxcbintegration.h \ - qxcbkeyboard.h \ - qxcbdrag.h \ - qxcbmime.h \ - qxcbobject.h \ - qxcbscreen.h \ - qxcbwindow.h \ - qxcbbackingstore.h \ - qxcbwmsupport.h \ - qxcbnativeinterface.h \ - qxcbcursor.h \ - qxcbimage.h \ - qxcbxsettings.h \ - qxcbsystemtraytracker.h - -LIBS += $$QMAKE_LIBS_DYNLOAD - -# needed by GLX, Xcursor ... -contains(QT_CONFIG, xcb-xlib) { - DEFINES += XCB_USE_XLIB - LIBS += -lX11 -lX11-xcb - - contains(QT_CONFIG, xinput2) { - DEFINES += XCB_USE_XINPUT2 - SOURCES += qxcbconnection_xi2.cpp - LIBS += -lXi - } -} - -# to support custom cursors with depth > 1 -contains(QT_CONFIG, xcb-render) { - DEFINES += XCB_USE_RENDER - LIBS += -lxcb-render -lxcb-render-util -} - -# build with session management support -contains(QT_CONFIG, xcb-sm) { - DEFINES += XCB_USE_SM - LIBS += -lSM -lICE - SOURCES += qxcbsessionmanager.cpp - HEADERS += qxcbsessionmanager.h -} - -contains(QT_CONFIG, opengl) { - contains(QT_CONFIG, xcb-xlib):!contains(QT_CONFIG, opengles2) { - DEFINES += XCB_USE_GLX - HEADERS += qglxintegration.h - SOURCES += qglxintegration.cpp - LIBS += $$QMAKE_LIBS_DYNLOAD - contains(QT_CONFIG, xcb-glx) { - DEFINES += XCB_HAS_XCB_GLX - LIBS += -lxcb-glx - } - } else:contains(QT_CONFIG, egl):contains(QT_CONFIG, egl_x11) { - DEFINES += XCB_USE_EGL - CONFIG += egl - HEADERS += qxcbeglsurface.h - - # EGL on MeeGo 1.2 Harmattan needs this macro to map EGLNativeDisplayType - # and other types to the correct X11 types - DEFINES += SUPPORT_X11 - } -} - -DEFINES += $$QMAKE_DEFINES_XCB -LIBS += $$QMAKE_LIBS_XCB -QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB -QMAKE_CFLAGS += $$QMAKE_CFLAGS_XCB - -CONFIG += qpa/genericunixfontdatabase - + qxcbmain.cpp OTHER_FILES += xcb.json README -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 -} - -# libxkbcommon -contains(QT_CONFIG, xkbcommon-qt): { - QT_CONFIG += use-xkbcommon-x11support - include(../../../3rdparty/xkbcommon.pri) -} else { - LIBS += $$QMAKE_LIBS_XKBCOMMON - QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON -} diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro index dab0d8cb14..5915a59c0b 100644 --- a/src/plugins/platforms/xcb/xcb.pro +++ b/src/plugins/platforms/xcb/xcb.pro @@ -2,4 +2,7 @@ TEMPLATE = subdirs CONFIG += ordered contains(QT_CONFIG, xcb-qt):SUBDIRS+=xcb-static + +SUBDIRS += xcb_qpa_lib.pro SUBDIRS += xcb-plugin.pro +SUBDIRS += gl_integrations diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro new file mode 100644 index 0000000000..770236acc7 --- /dev/null +++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro @@ -0,0 +1,111 @@ +TARGET = QtXcbQpa +CONFIG += no_module_headers internal_module + +MODULE_INCLUDES = \ + \$\$QT_MODULE_INCLUDE_BASE \ + \$\$QT_MODULE_INCLUDE_BASE/QtQGui +MODULE_PRIVATE_INCLUDES = \ + \$\$QT_MODULE_INCLUDE_BASE/QtGui/$$QT.gui.VERSION \ + \$\$QT_MODULE_INCLUDE_BASE/QtGui/$$QT.gui.VERSION/QtGui + +load(qt_module) + +QT += core-private gui-private platformsupport-private + +SOURCES = \ + qxcbclipboard.cpp \ + qxcbconnection.cpp \ + qxcbintegration.cpp \ + qxcbkeyboard.cpp \ + qxcbmime.cpp \ + qxcbdrag.cpp \ + qxcbscreen.cpp \ + qxcbwindow.cpp \ + qxcbbackingstore.cpp \ + qxcbwmsupport.cpp \ + qxcbnativeinterface.cpp \ + qxcbcursor.cpp \ + qxcbimage.cpp \ + qxcbxsettings.cpp \ + qxcbsystemtraytracker.cpp + +HEADERS = \ + qxcbclipboard.h \ + qxcbconnection.h \ + qxcbintegration.h \ + qxcbkeyboard.h \ + qxcbdrag.h \ + qxcbmime.h \ + qxcbobject.h \ + qxcbscreen.h \ + qxcbwindow.h \ + qxcbbackingstore.h \ + qxcbwmsupport.h \ + qxcbnativeinterface.h \ + qxcbcursor.h \ + qxcbimage.h \ + qxcbxsettings.h \ + qxcbsystemtraytracker.h + +LIBS += $$QMAKE_LIBS_DYNLOAD + +DEFINES += QT_BUILD_XCB_PLUGIN +# needed by Xcursor ... +contains(QT_CONFIG, xcb-xlib) { + DEFINES += XCB_USE_XLIB + LIBS += -lX11 -lX11-xcb + + contains(QT_CONFIG, xinput2) { + DEFINES += XCB_USE_XINPUT2 + SOURCES += qxcbconnection_xi2.cpp + LIBS += -lXi + } +} + +# to support custom cursors with depth > 1 +contains(QT_CONFIG, xcb-render) { + DEFINES += XCB_USE_RENDER + LIBS += -lxcb-render -lxcb-render-util +} + +# build with session management support +contains(QT_CONFIG, xcb-sm) { + DEFINES += XCB_USE_SM + LIBS += -lSM -lICE + SOURCES += qxcbsessionmanager.cpp + HEADERS += qxcbsessionmanager.h +} + +include(gl_integrations/gl_integrations.pri) + +DEFINES += $$QMAKE_DEFINES_XCB +LIBS += $$QMAKE_LIBS_XCB +QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XCB +QMAKE_CFLAGS += $$QMAKE_CFLAGS_XCB + +CONFIG += qpa/genericunixfontdatabase + +contains(QT_CONFIG, dbus) { + QT += dbus + LIBS += -ldbus-1 +} + +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 +} + +# libxkbcommon +contains(QT_CONFIG, xkbcommon-qt) { + QT_CONFIG += use-xkbcommon-x11support + include(../../../3rdparty/xkbcommon.pri) +} else { + LIBS += $$QMAKE_LIBS_XKBCOMMON + QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_XKBCOMMON +} + |