diff options
Diffstat (limited to 'src/plugins/platforms/eglfs')
32 files changed, 1157 insertions, 533 deletions
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..2eb46f8427 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro @@ -0,0 +1,26 @@ +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 + +HEADERS += $$PWD/qeglfskmsintegration.h + +OTHER_FILES += $$PWD/eglfs_kms.json diff --git a/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp index 4c430964a3..5a9d3db236 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks_kms.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.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:LGPL$ ** Commercial License Usage @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qeglfshooks.h" +#include "qeglfskmsintegration.h" #include "qeglfsintegration.h" #include "qeglfsscreen.h" @@ -70,7 +70,7 @@ #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) -QT_USE_NAMESPACE +QT_BEGIN_NAMESPACE Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms") @@ -100,6 +100,7 @@ class QEglFSKmsDevice { Q_DISABLE_COPY(QEglFSKmsDevice) + QEglFSKmsIntegration *m_integration; QString m_path; int m_dri_fd; gbm_device *m_gbm_device; @@ -116,7 +117,7 @@ class QEglFSKmsDevice unsigned int tv_usec, void *user_data); public: - QEglFSKmsDevice(const QString &path); + QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path); bool open(); void close(); @@ -131,6 +132,7 @@ public: class QEglFSKmsScreen : public QEglFSScreen { + QEglFSKmsIntegration *m_integration; QEglFSKmsDevice *m_device; gbm_surface *m_gbm_surface; @@ -151,7 +153,10 @@ class QEglFSKmsScreen : public QEglFSScreen static QMutex m_waitForFlipMutex; public: - QEglFSKmsScreen(QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position); + QEglFSKmsScreen(QEglFSKmsIntegration *integration, + QEglFSKmsDevice *device, + QEglFSKmsOutput output, + QPoint position); ~QEglFSKmsScreen(); QRect geometry() const Q_DECL_OVERRIDE; @@ -219,51 +224,13 @@ private: } m_cursorAtlas; }; -class QEglKmsHooks : public QEglFSHooks -{ -public: - QEglKmsHooks(); - - void platformInit() Q_DECL_OVERRIDE; - void platformDestroy() Q_DECL_OVERRIDE; - EGLNativeDisplayType platformDisplay() const 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; -}; - -static QEglKmsHooks kms_hooks; -QEglFSHooks *platformHooks = &kms_hooks; - -QEglKmsHooks::QEglKmsHooks() +QEglFSKmsIntegration::QEglFSKmsIntegration() : m_device(Q_NULLPTR) , m_hwCursor(true) , m_pbuffers(false) {} -void QEglKmsHooks::platformInit() +void QEglFSKmsIntegration::platformInit() { loadConfig(); @@ -283,30 +250,35 @@ void QEglKmsHooks::platformInit() qCDebug(qLcEglfsKmsDebug) << "Using" << m_devicePath; } - m_device = new QEglFSKmsDevice(m_devicePath); + m_device = new QEglFSKmsDevice(this, m_devicePath); if (!m_device->open()) qFatal("Could not open device %s - aborting!", qPrintable(m_devicePath)); } -void QEglKmsHooks::platformDestroy() +void QEglFSKmsIntegration::platformDestroy() { m_device->close(); delete m_device; m_device = Q_NULLPTR; } -EGLNativeDisplayType QEglKmsHooks::platformDisplay() const +EGLNativeDisplayType QEglFSKmsIntegration::platformDisplay() const { Q_ASSERT(m_device); return reinterpret_cast<EGLNativeDisplayType>(m_device->device()); } -void QEglKmsHooks::screenInit() +bool QEglFSKmsIntegration::usesDefaultScreen() +{ + return false; +} + +void QEglFSKmsIntegration::screenInit() { m_device->createScreens(); } -QSurfaceFormat QEglKmsHooks::surfaceFormatFor(const QSurfaceFormat &inputFormat) const +QSurfaceFormat QEglFSKmsIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const { QSurfaceFormat format(inputFormat); format.setRenderableType(QSurfaceFormat::OpenGLES); @@ -317,7 +289,7 @@ QSurfaceFormat QEglKmsHooks::surfaceFormatFor(const QSurfaceFormat &inputFormat) return format; } -EGLNativeWindowType QEglKmsHooks::createNativeWindow(QPlatformWindow *platformWindow, +EGLNativeWindowType QEglFSKmsIntegration::createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format) { @@ -333,7 +305,7 @@ EGLNativeWindowType QEglKmsHooks::createNativeWindow(QPlatformWindow *platformWi return reinterpret_cast<EGLNativeWindowType>(screen->createSurface()); } -EGLNativeWindowType QEglKmsHooks::createNativeOffscreenWindow(const QSurfaceFormat &format) +EGLNativeWindowType QEglFSKmsIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format) { Q_UNUSED(format); Q_ASSERT(m_device); @@ -347,13 +319,13 @@ EGLNativeWindowType QEglKmsHooks::createNativeOffscreenWindow(const QSurfaceForm return reinterpret_cast<EGLNativeWindowType>(surface); } -void QEglKmsHooks::destroyNativeWindow(EGLNativeWindowType window) +void QEglFSKmsIntegration::destroyNativeWindow(EGLNativeWindowType window) { gbm_surface *surface = reinterpret_cast<gbm_surface *>(window); gbm_surface_destroy(surface); } -bool QEglKmsHooks::hasCapability(QPlatformIntegration::Capability cap) const +bool QEglFSKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const { switch (cap) { case QPlatformIntegration::ThreadedPixmaps: @@ -365,7 +337,7 @@ bool QEglKmsHooks::hasCapability(QPlatformIntegration::Capability cap) const } } -QPlatformCursor *QEglKmsHooks::createCursor(QPlatformScreen *screen) const +QPlatformCursor *QEglFSKmsIntegration::createCursor(QPlatformScreen *screen) const { if (m_hwCursor) return Q_NULLPTR; @@ -373,7 +345,7 @@ QPlatformCursor *QEglKmsHooks::createCursor(QPlatformScreen *screen) const return new QEGLPlatformCursor(screen); } -void QEglKmsHooks::waitForVSync(QPlatformSurface *surface) const +void QEglFSKmsIntegration::waitForVSync(QPlatformSurface *surface) const { QWindow *window = static_cast<QWindow *>(surface->surface()); QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(window->screen()->handle()); @@ -381,7 +353,7 @@ void QEglKmsHooks::waitForVSync(QPlatformSurface *surface) const screen->waitForFlip(); } -void QEglKmsHooks::presentBuffer(QPlatformSurface *surface) +void QEglFSKmsIntegration::presentBuffer(QPlatformSurface *surface) { QWindow *window = static_cast<QWindow *>(surface->surface()); QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(window->screen()->handle()); @@ -389,22 +361,22 @@ void QEglKmsHooks::presentBuffer(QPlatformSurface *surface) screen->flip(); } -bool QEglKmsHooks::supportsPBuffers() const +bool QEglFSKmsIntegration::supportsPBuffers() const { return m_pbuffers; } -bool QEglKmsHooks::hwCursor() const +bool QEglFSKmsIntegration::hwCursor() const { return m_hwCursor; } -QMap<QString, QVariantMap> QEglKmsHooks::outputSettings() const +QMap<QString, QVariantMap> QEglFSKmsIntegration::outputSettings() const { return m_outputSettings; } -void QEglKmsHooks::loadConfig() +void QEglFSKmsIntegration::loadConfig() { static QByteArray json = qgetenv("QT_QPA_EGLFS_KMS_CONFIG"); if (json.isEmpty()) @@ -640,8 +612,12 @@ QEglFSKmsScreen::FrameBuffer *QEglFSKmsScreen::framebufferForBufferObject(gbm_bo } -QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position) +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) @@ -709,7 +685,7 @@ QString QEglFSKmsScreen::name() const QPlatformCursor *QEglFSKmsScreen::cursor() const { - if (kms_hooks.hwCursor()) { + if (m_integration->hwCursor()) { if (m_cursor.isNull()) { QEglFSKmsScreen *that = const_cast<QEglFSKmsScreen *>(this); that->m_cursor.reset(new QEglFSKmsCursor(that)); @@ -942,7 +918,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr QSize configurationSize; drmModeModeInfo configurationModeline; - const QString mode = kms_hooks.outputSettings().value(connectorName).value("mode", "preferred").toString().toLower(); + const QString mode = m_integration->outputSettings().value(connectorName).value("mode", "preferred").toString().toLower(); if (mode == "off") { configuration = OutputConfigOff; } else if (mode == "preferred") { @@ -1063,7 +1039,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr m_crtc_allocator |= (1 << output.crtc_id); m_connector_allocator |= (1 << output.connector_id); - return new QEglFSKmsScreen(this, output, pos); + 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) @@ -1077,8 +1053,9 @@ void QEglFSKmsDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned in screen->flipFinished(); } -QEglFSKmsDevice::QEglFSKmsDevice(const QString &path) - : m_path(path) +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) @@ -1173,4 +1150,6 @@ void QEglFSKmsDevice::handleDrmEvent() drmHandleEvent(m_dri_fd, &drmEvent); } -#include "qeglfshooks_kms.moc" +QT_END_NAMESPACE + +#include "qeglfskmsintegration.moc" 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..44414a2eed --- /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 <QMap> +#include <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_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 c026546ced..0ce5e341bf 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,17 +202,17 @@ 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'); @@ -271,7 +226,7 @@ QSize QEglFSX11Hooks::screenSize() const return m_screenSize; } -EGLNativeWindowType QEglFSX11Hooks::createNativeWindow(QPlatformWindow *platformWindow, +EGLNativeWindowType QEglFSX11Integration::createNativeWindow(QPlatformWindow *platformWindow, const QSize &size, const QSurfaceFormat &format) { @@ -325,18 +280,15 @@ EGLNativeWindowType QEglFSX11Hooks::createNativeWindow(QPlatformWindow *platform 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 182539d8fe..0000000000 --- a/src/plugins/platforms/eglfs/eglfs.pri +++ /dev/null @@ -1,46 +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 \ - $$PWD/qeglfsoffscreenwindow.cpp - -HEADERS += $$PWD/qeglfsintegration.h \ - $$PWD/qeglfswindow.h \ - $$PWD/qeglfsscreen.h \ - $$PWD/qeglfshooks.h \ - $$PWD/qeglfscontext.h \ - $$PWD/qeglfsoffscreenwindow.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 00778373ae..7054c90521 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.cpp +++ b/src/plugins/platforms/eglfs/qeglfscontext.cpp @@ -60,11 +60,11 @@ EGLSurface QEglFSContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface EGLSurface QEglFSContext::createTemporaryOffscreenSurface() { - if (QEglFSHooks::hooks()->supportsPBuffers()) + if (qt_egl_device_integration()->supportsPBuffers()) return QEGLPlatformContext::createTemporaryOffscreenSurface(); if (!m_tempWindow) { - m_tempWindow = QEglFSHooks::hooks()->createNativeOffscreenWindow(format()); + m_tempWindow = qt_egl_device_integration()->createNativeOffscreenWindow(format()); if (!m_tempWindow) { qWarning("QEglFSContext: Failed to create temporary native window"); return EGL_NO_SURFACE; @@ -76,11 +76,11 @@ EGLSurface QEglFSContext::createTemporaryOffscreenSurface() void QEglFSContext::destroyTemporaryOffscreenSurface(EGLSurface surface) { - if (QEglFSHooks::hooks()->supportsPBuffers()) { + if (qt_egl_device_integration()->supportsPBuffers()) { QEGLPlatformContext::destroyTemporaryOffscreenSurface(surface); } else { eglDestroySurface(eglDisplay(), surface); - QEglFSHooks::hooks()->destroyNativeWindow(m_tempWindow); + qt_egl_device_integration()->destroyNativeWindow(m_tempWindow); m_tempWindow = 0; } } @@ -94,9 +94,9 @@ void QEglFSContext::swapBuffers(QPlatformSurface *surface) cursor->paintOnScreen(); } - QEglFSHooks::hooks()->waitForVSync(surface); + qt_egl_device_integration()->waitForVSync(surface); QEGLPlatformContext::swapBuffers(surface); - QEglFSHooks::hooks()->presentBuffer(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 a656a50e2f..245f690822 100644 --- a/src/plugins/platforms/eglfs/qeglfscontext.h +++ b/src/plugins/platforms/eglfs/qeglfscontext.h @@ -36,10 +36,11 @@ #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, diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp new file mode 100644 index 0000000000..a2e1ac3832 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp @@ -0,0 +1,306 @@ +/**************************************************************************** +** +** 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 <QtPlatformSupport/private/qeglconvenience_p.h> +#include <QtPlatformSupport/private/qeglplatformcursor_p.h> +#include <QGuiApplication> +#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() +{ + while (!qApp->screens().isEmpty()) + delete qApp->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 b2b8d46741..1fcfc5bd08 100644 --- a/src/plugins/platforms/eglfs/qeglfshooks.h +++ b/src/plugins/platforms/eglfs/qeglfshooks.h @@ -34,63 +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 QEglFSScreen; -class QEglFSIntegration; -class QPlatformSurface; - -class QEglFSHooks +class QEglFSHooks : public QEGLDeviceIntegration { -public: - virtual ~QEglFSHooks() {} - virtual void platformInit(); - virtual void platformDestroy(); - virtual EGLNativeDisplayType platformDisplay() const; - 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; - - 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_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp deleted file mode 100644 index 1b042a0743..0000000000 --- a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp +++ /dev/null @@ -1,233 +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 "qeglfsintegration.h" -#include "qeglfsscreen.h" - -#include <QtPlatformSupport/private/qeglplatformcursor_p.h> -#include <QtPlatformSupport/private/qeglconvenience_p.h> -#include <QtCore/QRegularExpression> -#include <QtGui/private/qguiapplication_p.h> - -#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; -} - -void QEglFSHooks::screenInit() -{ - QEglFSIntegration *integration = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration()); - integration->addScreen(new QEglFSScreen(integration->display())); -} - -void QEglFSHooks::screenDestroy() -{ - while (!qApp->screens().isEmpty()) - delete qApp->screens().last()->handle(); -} - -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 = qEnvironmentVariableIntValue("QT_QPA_EGLFS_FORCE888"); - 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; -} - -EGLNativeWindowType QEglFSHooks::createNativeOffscreenWindow(const QSurfaceFormat &format) -{ - 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; -} - -QPlatformCursor *QEglFSHooks::createCursor(QPlatformScreen *screen) const -{ - return new QEGLPlatformCursor(screen); -} - -void QEglFSHooks::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 QEglFSHooks::presentBuffer(QPlatformSurface *surface) -{ - Q_UNUSED(surface); -} - -bool QEglFSHooks::supportsPBuffers() const -{ - return true; -} - -#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 125e4e1bf9..8cb23f2c09 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -71,7 +71,7 @@ QEglFSIntegration::QEglFSIntegration() 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); @@ -84,26 +84,29 @@ void QEglFSIntegration::addScreen(QPlatformScreen *screen) void QEglFSIntegration::initialize() { - QEglFSHooks::hooks()->platformInit(); + qt_egl_device_integration()->platformInit(); QEGLPlatformIntegration::initialize(); if (!mDisableInputHandlers) createInputHandlers(); - QEglFSHooks::hooks()->screenInit(); + if (qt_egl_device_integration()->usesDefaultScreen()) + addScreen(new QEglFSScreen(display())); + else + qt_egl_device_integration()->screenInit(); } void QEglFSIntegration::destroy() { - QEglFSHooks::hooks()->screenDestroy(); + qt_egl_device_integration()->screenDestroy(); QEGLPlatformIntegration::destroy(); - QEglFSHooks::hooks()->platformDestroy(); + qt_egl_device_integration()->platformDestroy(); } EGLNativeDisplayType QEglFSIntegration::nativeDisplay() const { - return QEglFSHooks::hooks()->platformDisplay(); + return qt_egl_device_integration()->platformDisplay(); } QEGLPlatformWindow *QEglFSIntegration::createWindow(QWindow *window) const @@ -117,7 +120,7 @@ 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()); @@ -132,8 +135,8 @@ QPlatformOffscreenSurface *QEglFSIntegration::createOffscreenSurface(EGLDisplay const QSurfaceFormat &format, QOffscreenSurface *surface) const { - QSurfaceFormat fmt = QEglFSHooks::hooks()->surfaceFormatFor(format); - if (QEglFSHooks::hooks()->supportsPBuffers()) + 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); @@ -145,23 +148,15 @@ EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceForm { class Chooser : public QEglConfigChooser { public: - Chooser(EGLDisplay display, QEglFSHooks *hooks) - : QEglConfigChooser(display) - , m_hooks(hooks) - { - } - - protected: - bool filterConfig(EGLConfig config) const Q_DECL_OVERRIDE - { - 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 86038910ca..b75dc240bb 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -37,10 +37,11 @@ #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(); diff --git a/src/plugins/platforms/eglfs/main.cpp b/src/plugins/platforms/eglfs/qeglfsmain.cpp index 985fccb7af..2c5e79534d 100644 --- a/src/plugins/platforms/eglfs/main.cpp +++ b/src/plugins/platforms/eglfs/qeglfsmain.cpp @@ -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 index 0e8e3957d0..7bf53ef351 100644 --- a/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.cpp @@ -63,7 +63,7 @@ QEglFSOffscreenWindow::QEglFSOffscreenWindow(EGLDisplay display, const QSurfaceF , m_surface(EGL_NO_SURFACE) , m_window(0) { - m_window = QEglFSHooks::hooks()->createNativeOffscreenWindow(format); + m_window = qt_egl_device_integration()->createNativeOffscreenWindow(format); if (!m_window) { qWarning("QEglFSOffscreenWindow: Failed to create native window"); return; @@ -79,7 +79,7 @@ QEglFSOffscreenWindow::~QEglFSOffscreenWindow() if (m_surface != EGL_NO_SURFACE) eglDestroySurface(m_display, m_surface); if (m_window) - QEglFSHooks::hooks()->destroyNativeWindow(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 index 8bd4089c34..128ff56968 100644 --- a/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h +++ b/src/plugins/platforms/eglfs/qeglfsoffscreenwindow.h @@ -44,10 +44,11 @@ #include <EGL/egl.h> #include <qpa/qplatformoffscreensurface.h> +#include "qeglfsglobal.h" QT_BEGIN_NAMESPACE -class QEglFSOffscreenWindow : public QPlatformOffscreenSurface +class Q_EGLFS_EXPORT QEglFSOffscreenWindow : public QPlatformOffscreenSurface { public: QEglFSOffscreenWindow(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface); diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp index a66cff165b..84ea1c6483 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -43,7 +43,7 @@ QEglFSScreen::QEglFSScreen(EGLDisplay dpy) m_surface(EGL_NO_SURFACE), m_cursor(0) { - m_cursor = QEglFSHooks::hooks()->createCursor(this); + m_cursor = qt_egl_device_integration()->createCursor(this); } QEglFSScreen::~QEglFSScreen() @@ -53,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 d109ad9d9b..59f55d33fb 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.h +++ b/src/plugins/platforms/eglfs/qeglfsscreen.h @@ -34,10 +34,8 @@ #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 @@ -45,7 +43,7 @@ QT_BEGIN_NAMESPACE class QEglFSWindow; class QOpenGLContext; -class QEglFSScreen : public QEGLPlatformScreen +class Q_EGLFS_EXPORT QEglFSScreen : public QEGLPlatformScreen { public: QEglFSScreen(EGLDisplay display); diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 0ab19e6065..d568d50e59 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -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); @@ -140,7 +140,7 @@ 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; } @@ -148,7 +148,7 @@ void QEglFSWindow::resetSurface() { QEglFSScreen *nativeScreen = static_cast<QEglFSScreen *>(screen()); EGLDisplay display = nativeScreen->display(); - m_window = QEglFSHooks::hooks()->createNativeWindow(this, nativeScreen->geometry().size(), m_format); + 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(); diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h index 439338f756..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); |