Pluginize the eglfs hooks

Following the principle of device integrations in QtWayland and soon
xcb, a plugin interface is being introduced to gradually replace the
statically compiled-in hooks.

The interface is same as before for the time being, for compatibility
with the existing device-specific hooks.

QEglFSHooks is now just a dummy subclass for QEGLDeviceIntegration to
support the legacy, compiled-in, device-specific hooks. When -device
is not used with configure and so there is no hook active, the new
plugin-based approach kicks in.

The environment variable QT_QPA_EGLFS_INTEGRATION can be set to
indicate the preferred integration name (e.g. eglfs_x11, eglfs_kms).

It can also be set to "none", indicating that no plugins should be
considered and the default, non-specialized integration is to be used.
(this is for devices, like Beagleboard|bone, that do not need any special
code to set up EGL)

Device makespecs can set EGLFS_DEVICE_INTEGRATION. The value is then used
as the default, preferred plugin name when QT_QPA_EGLFS_INTEGRATION is not
set. In the future device makespecs are expected to set a plugin name instead
of relying on the traditional EGLFS_PLATFORM_HOOKS_*.

When neither the QT_QPA_EGLFS_INTEGRATION nor EGLFS_DEVICE_INTEGRATION are
set, all plugins will be tried in an unspecified order. The first one that
succeeds to load is used. If all fails or there are no plugins, the built-in,
non-specialized integration is used.

To debug what integration is being used, enable the logging category
qt.qpa.egldeviceintegration.

There is some built-in logic for desktop/Mesa based systems: Under X,
eglfs_x11 is preferred, otherwise eglfs_kms is prioritized. This, assuming
sufficient permissions to video and input devices, allows simply launching
apps with -platform eglfs. No more editing of eglfs.pri.

[ChangeLog][QtGui] Added support for device-specific backend plugins in eglfs.

Change-Id: Ia2ddcddac014c25817171dc140cd8cf913784ac6
Reviewed-by: Louai Al-Khanji <louai.al-khanji@theqtcompany.com>
This commit is contained in:
Laszlo Agocs 2014-10-10 16:03:36 +02:00 committed by Laszlo Agocs
parent fec53bf5ed
commit b7f0583f31
34 changed files with 1163 additions and 534 deletions

View File

@ -47,6 +47,10 @@ QMAKE_LIBS_EGL = -lEGL -lIMGegl -lsrv_um
QMAKE_LIBS_OPENGL_ES2 = -lGLESv2 $${QMAKE_LIBS_EGL}
QMAKE_LIBS_OPENVG = -lOpenVG $${QMAKE_LIBS_EGL}
# No need for any special EGL device integration.
# Prioritize the default, compiled-in integration over any plugins.
EGLFS_DEVICE_INTEGRATION = none
# Sanity check
deviceSanityCheckCompiler()

View File

@ -13,7 +13,8 @@ MODULE_PLUGIN_TYPES = \
platforminputcontexts \
generic \
iconengines \
imageformats
imageformats \
egldeviceintegrations
# This is here only because the platform plugin is no module, obviously.
win32:contains(QT_CONFIG, angle)|contains(QT_CONFIG, dynamicgl) {

View File

@ -0,0 +1,4 @@
TEMPLATE = subdirs
contains(QT_CONFIG, egl_x11): SUBDIRS += eglfs_x11
contains(QT_CONFIG, kms): SUBDIRS += eglfs_kms

View File

@ -0,0 +1,3 @@
{
"Keys": [ "eglfs_kms" ]
}

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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"

View File

@ -0,0 +1,3 @@
{
"Keys": [ "eglfs_x11" ]
}

View File

@ -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

View File

@ -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>
/* 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. */
QT_BEGIN_NAMESPACE
class QEglFSX11Hooks;
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

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
{
Chooser(EGLDisplay display)
: QEglConfigChooser(display) { }
bool filterConfig(EGLConfig config) const Q_DECL_OVERRIDE {
return qt_egl_device_integration()->filterConfig(display(), config)
&& QEglConfigChooser::filterConfig(config);
}
protected:
bool filterConfig(EGLConfig config) const Q_DECL_OVERRIDE
{
return m_hooks->filterConfig(display(), config) && QEglConfigChooser::filterConfig(config);
}
private:
QEglFSHooks *m_hooks;
};
Chooser chooser(display, QEglFSHooks::hooks());
Chooser chooser(display);
chooser.setSurfaceFormat(format);
return chooser.chooseConfig();
}

View File

@ -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();

View File

@ -55,4 +55,4 @@ QPlatformIntegration* QEglFSIntegrationPlugin::create(const QString& system, con
QT_END_NAMESPACE
#include "main.moc"
#include "qeglfsmain.moc"

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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);