Multi-screen handling for the eglfs_kms_egldevice backend
Separates the generic kms classes into a own kms static lib called QtEglFsKmsSupport. The eglfs_kms plugin was changed to use these base classes and got renamed accordingly to QEglFSKmsGbm*. The eglfs_kms_egldevice plugin got extended to also derive from the kms base classed and by this provides multi-screen support Change-Id: I6de6a754e94cb8d52cf8e658b03c6bd6637674a1 Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>
This commit is contained in:
parent
920fc1a523
commit
224f31c0b5
@ -1,9 +1,12 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
contains(QT_CONFIG, egl_x11): SUBDIRS += eglfs_x11
|
||||
contains(QT_CONFIG, eglfs_gbm): SUBDIRS += eglfs_kms
|
||||
contains(QT_CONFIG, eglfs_egldevice): SUBDIRS += eglfs_kms_egldevice
|
||||
contains(QT_CONFIG, eglfs_gbm): SUBDIRS += eglfs_kms_support eglfs_kms
|
||||
contains(QT_CONFIG, eglfs_egldevice): SUBDIRS += eglfs_kms_support eglfs_kms_egldevice
|
||||
contains(QT_CONFIG, eglfs_brcm): SUBDIRS += eglfs_brcm
|
||||
contains(QT_CONFIG, eglfs_mali): SUBDIRS += eglfs_mali
|
||||
contains(QT_CONFIG, eglfs_viv): SUBDIRS += eglfs_viv
|
||||
contains(QT_CONFIG, eglfs_viv_wl): SUBDIRS += eglfs_viv_wl
|
||||
|
||||
eglfs_kms_egldevice.depends = eglfs_kms_support
|
||||
eglfs_kms.depends = eglfs_kms_support
|
||||
|
@ -1,31 +1,35 @@
|
||||
TARGET = qeglfs-kms-integration
|
||||
|
||||
QT += core-private gui-private platformsupport-private eglfs_device_lib-private
|
||||
PLUGIN_TYPE = egldeviceintegrations
|
||||
PLUGIN_CLASS_NAME = QEglFSKmsIntegrationPlugin
|
||||
load(qt_plugin)
|
||||
|
||||
INCLUDEPATH += $$PWD/../..
|
||||
QT += core-private gui-private platformsupport-private eglfs_device_lib-private eglfs_kms_support-private
|
||||
|
||||
INCLUDEPATH += $$PWD/../.. $$PWD/../eglfs_kms_support
|
||||
|
||||
# Avoid X11 header collision
|
||||
DEFINES += MESA_EGL_NO_X11_HEADERS
|
||||
|
||||
CONFIG += link_pkgconfig
|
||||
PKGCONFIG += libdrm gbm
|
||||
!contains(QT_CONFIG, no-pkg-config) {
|
||||
PKGCONFIG += libdrm gbm
|
||||
} else {
|
||||
LIBS += -ldrm -lgbm
|
||||
}
|
||||
|
||||
CONFIG += egl
|
||||
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
|
||||
|
||||
SOURCES += $$PWD/qeglfskmsmain.cpp \
|
||||
$$PWD/qeglfskmsintegration.cpp \
|
||||
$$PWD/qeglfskmsdevice.cpp \
|
||||
$$PWD/qeglfskmsscreen.cpp \
|
||||
$$PWD/qeglfskmscursor.cpp
|
||||
SOURCES += $$PWD/qeglfskmsgbmmain.cpp \
|
||||
$$PWD/qeglfskmsgbmintegration.cpp \
|
||||
$$PWD/qeglfskmsgbmdevice.cpp \
|
||||
$$PWD/qeglfskmsgbmscreen.cpp \
|
||||
$$PWD/qeglfskmsgbmcursor.cpp
|
||||
|
||||
HEADERS += $$PWD/qeglfskmsintegration.h \
|
||||
$$PWD/qeglfskmsdevice.h \
|
||||
$$PWD/qeglfskmsscreen.h \
|
||||
$$PWD/qeglfskmscursor.h
|
||||
HEADERS += $$PWD/qeglfskmsgbmintegration.h \
|
||||
$$PWD/qeglfskmsgbmdevice.h \
|
||||
$$PWD/qeglfskmsgbmscreen.h \
|
||||
$$PWD/qeglfskmsgbmcursor.h
|
||||
|
||||
OTHER_FILES += $$PWD/eglfs_kms.json
|
||||
|
||||
PLUGIN_TYPE = egldeviceintegrations
|
||||
PLUGIN_CLASS_NAME = QEglFSKmsIntegrationPlugin
|
||||
load(qt_plugin)
|
||||
|
@ -2,6 +2,7 @@
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
@ -38,9 +39,9 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfskmscursor.h"
|
||||
#include "qeglfskmsscreen.h"
|
||||
#include "qeglfskmsdevice.h"
|
||||
#include "qeglfskmsgbmcursor.h"
|
||||
#include "qeglfskmsgbmscreen.h"
|
||||
#include "qeglfskmsgbmdevice.h"
|
||||
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonObject>
|
||||
@ -63,7 +64,7 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
|
||||
|
||||
QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen)
|
||||
QEglFSKmsGbmCursor::QEglFSKmsGbmCursor(QEglFSKmsGbmScreen *screen)
|
||||
: m_screen(screen)
|
||||
, m_cursorSize(64, 64) // 64x64 is the old standard size, we now try to query the real size below
|
||||
, m_bo(Q_NULLPTR)
|
||||
@ -83,7 +84,7 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen)
|
||||
m_cursorSize.setHeight(height);
|
||||
}
|
||||
|
||||
m_bo = gbm_bo_create(m_screen->device()->device(), m_cursorSize.width(), m_cursorSize.height(),
|
||||
m_bo = gbm_bo_create(static_cast<QEglFSKmsGbmDevice *>(m_screen->device())->gbmDevice(), m_cursorSize.width(), m_cursorSize.height(),
|
||||
GBM_FORMAT_ARGB8888, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
|
||||
if (!m_bo) {
|
||||
qWarning("Could not create buffer for cursor!");
|
||||
@ -98,7 +99,7 @@ QEglFSKmsCursor::QEglFSKmsCursor(QEglFSKmsScreen *screen)
|
||||
setPos(QPoint(0, 0));
|
||||
}
|
||||
|
||||
QEglFSKmsCursor::~QEglFSKmsCursor()
|
||||
QEglFSKmsGbmCursor::~QEglFSKmsGbmCursor()
|
||||
{
|
||||
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
|
||||
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
|
||||
@ -110,13 +111,13 @@ QEglFSKmsCursor::~QEglFSKmsCursor()
|
||||
m_bo = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void QEglFSKmsCursor::pointerEvent(const QMouseEvent &event)
|
||||
void QEglFSKmsGbmCursor::pointerEvent(const QMouseEvent &event)
|
||||
{
|
||||
setPos(event.screenPos().toPoint());
|
||||
}
|
||||
|
||||
#ifndef QT_NO_CURSOR
|
||||
void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window)
|
||||
void QEglFSKmsGbmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
|
||||
{
|
||||
Q_UNUSED(window);
|
||||
|
||||
@ -171,12 +172,12 @@ void QEglFSKmsCursor::changeCursor(QCursor *windowCursor, QWindow *window)
|
||||
}
|
||||
#endif // QT_NO_CURSOR
|
||||
|
||||
QPoint QEglFSKmsCursor::pos() const
|
||||
QPoint QEglFSKmsGbmCursor::pos() const
|
||||
{
|
||||
return m_pos;
|
||||
}
|
||||
|
||||
void QEglFSKmsCursor::setPos(const QPoint &pos)
|
||||
void QEglFSKmsGbmCursor::setPos(const QPoint &pos)
|
||||
{
|
||||
Q_FOREACH (QPlatformScreen *screen, m_screen->virtualSiblings()) {
|
||||
QEglFSKmsScreen *kmsScreen = static_cast<QEglFSKmsScreen *>(screen);
|
||||
@ -192,7 +193,7 @@ void QEglFSKmsCursor::setPos(const QPoint &pos)
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSKmsCursor::initCursorAtlas()
|
||||
void QEglFSKmsGbmCursor::initCursorAtlas()
|
||||
{
|
||||
static QByteArray json = qgetenv("QT_QPA_EGLFS_CURSOR");
|
||||
if (json.isEmpty())
|
@ -37,8 +37,8 @@
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QEGLFSKMSCURSOR_H
|
||||
#define QEGLFSKMSCURSOR_H
|
||||
#ifndef QEGLFSKMSGBMCURSOR_H
|
||||
#define QEGLFSKMSGBMCURSOR_H
|
||||
|
||||
#include <qpa/qplatformcursor.h>
|
||||
#include <QtCore/QList>
|
||||
@ -48,15 +48,15 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglFSKmsScreen;
|
||||
class QEglFSKmsGbmScreen;
|
||||
|
||||
class QEglFSKmsCursor : public QPlatformCursor
|
||||
class QEglFSKmsGbmCursor : public QPlatformCursor
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QEglFSKmsCursor(QEglFSKmsScreen *screen);
|
||||
~QEglFSKmsCursor();
|
||||
QEglFSKmsGbmCursor(QEglFSKmsGbmScreen *screen);
|
||||
~QEglFSKmsGbmCursor();
|
||||
|
||||
// input methods
|
||||
void pointerEvent(const QMouseEvent & event) Q_DECL_OVERRIDE;
|
||||
@ -69,7 +69,7 @@ public:
|
||||
private:
|
||||
void initCursorAtlas();
|
||||
|
||||
QEglFSKmsScreen *m_screen;
|
||||
QEglFSKmsGbmScreen *m_screen;
|
||||
QSize m_cursorSize;
|
||||
gbm_bo *m_bo;
|
||||
QPoint m_pos;
|
||||
@ -89,4 +89,4 @@ private:
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif
|
||||
#endif // QEGLFSKMSGBMCURSOR_H
|
@ -0,0 +1,158 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfskmsgbmdevice.h"
|
||||
#include "qeglfskmsgbmscreen.h"
|
||||
|
||||
#include "qeglfsintegration.h"
|
||||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/private/qcore_unix_p.h>
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
|
||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
|
||||
|
||||
void QEglFSKmsGbmDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
|
||||
{
|
||||
Q_UNUSED(fd);
|
||||
Q_UNUSED(sequence);
|
||||
Q_UNUSED(tv_sec);
|
||||
Q_UNUSED(tv_usec);
|
||||
|
||||
QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(user_data);
|
||||
screen->flipFinished();
|
||||
}
|
||||
|
||||
QEglFSKmsGbmDevice::QEglFSKmsGbmDevice(QEglFSKmsIntegration *integration, const QString &path)
|
||||
: QEglFSKmsDevice(integration, path)
|
||||
, m_gbm_device(Q_NULLPTR)
|
||||
, m_globalCursor(Q_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
bool QEglFSKmsGbmDevice::open()
|
||||
{
|
||||
Q_ASSERT(fd() == -1);
|
||||
Q_ASSERT(m_gbm_device == Q_NULLPTR);
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug) << "Opening device" << devicePath();
|
||||
int fd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
qErrnoWarning("Could not open DRM device %s", qPrintable(devicePath()));
|
||||
return false;
|
||||
}
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug) << "Creating GBM device for file descriptor" << fd
|
||||
<< "obtained from" << devicePath();
|
||||
m_gbm_device = gbm_create_device(fd);
|
||||
if (!m_gbm_device) {
|
||||
qErrnoWarning("Could not create GBM device");
|
||||
qt_safe_close(fd);
|
||||
fd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
setFd(fd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QEglFSKmsGbmDevice::close()
|
||||
{
|
||||
if (m_gbm_device) {
|
||||
gbm_device_destroy(m_gbm_device);
|
||||
m_gbm_device = Q_NULLPTR;
|
||||
}
|
||||
|
||||
if (fd() != -1) {
|
||||
qt_safe_close(fd());
|
||||
setFd(-1);
|
||||
}
|
||||
|
||||
if (m_globalCursor)
|
||||
m_globalCursor->deleteLater();
|
||||
m_globalCursor = Q_NULLPTR;
|
||||
}
|
||||
|
||||
EGLNativeDisplayType QEglFSKmsGbmDevice::device() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
gbm_device * QEglFSKmsGbmDevice::gbmDevice() const
|
||||
{
|
||||
return m_gbm_device;
|
||||
}
|
||||
|
||||
QPlatformCursor *QEglFSKmsGbmDevice::globalCursor() const
|
||||
{
|
||||
return m_globalCursor;
|
||||
}
|
||||
|
||||
void QEglFSKmsGbmDevice::handleDrmEvent()
|
||||
{
|
||||
drmEventContext drmEvent = {
|
||||
DRM_EVENT_CONTEXT_VERSION,
|
||||
Q_NULLPTR, // vblank handler
|
||||
pageFlipHandler // page flip handler
|
||||
};
|
||||
|
||||
drmHandleEvent(fd(), &drmEvent);
|
||||
}
|
||||
|
||||
QEglFSKmsScreen *QEglFSKmsGbmDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position)
|
||||
{
|
||||
static bool firstScreen = true;
|
||||
QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(integration, device, output, position);
|
||||
|
||||
if (firstScreen && integration->hwCursor()) {
|
||||
m_globalCursor = new QEglFSKmsGbmCursor(screen);
|
||||
firstScreen = false;
|
||||
}
|
||||
|
||||
return screen;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
@ -0,0 +1,90 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QEGLFSKMSGBMDEVICE_H
|
||||
#define QEGLFSKMSGBMDEVICE_H
|
||||
|
||||
#include "qeglfskmsgbmcursor.h"
|
||||
#include "qeglfskmsdevice.h"
|
||||
|
||||
#include <gbm.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglFSKmsScreen;
|
||||
|
||||
class QEglFSKmsGbmDevice: public QEglFSKmsDevice
|
||||
{
|
||||
public:
|
||||
QEglFSKmsGbmDevice(QEglFSKmsIntegration *integration, const QString &path);
|
||||
|
||||
bool open() Q_DECL_OVERRIDE;
|
||||
void close() Q_DECL_OVERRIDE;
|
||||
|
||||
EGLNativeDisplayType device() const Q_DECL_OVERRIDE;
|
||||
gbm_device *gbmDevice() const;
|
||||
|
||||
QPlatformCursor *globalCursor() const;
|
||||
|
||||
void handleDrmEvent();
|
||||
|
||||
virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration,
|
||||
QEglFSKmsDevice *device,
|
||||
QEglFSKmsOutput output,
|
||||
QPoint position) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QEglFSKmsGbmDevice)
|
||||
|
||||
gbm_device *m_gbm_device;
|
||||
|
||||
QEglFSKmsGbmCursor *m_globalCursor;
|
||||
|
||||
static void pageFlipHandler(int fd,
|
||||
unsigned int sequence,
|
||||
unsigned int tv_sec,
|
||||
unsigned int tv_usec,
|
||||
void *user_data);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QEGLFSKMSGBMDEVICE_H
|
@ -0,0 +1,143 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfskmsgbmintegration.h"
|
||||
#include "qeglfskmsgbmdevice.h"
|
||||
#include "qeglfskmsgbmscreen.h"
|
||||
#include "qeglfskmsgbmcursor.h"
|
||||
#include "qeglfscursor.h"
|
||||
|
||||
#include <QtPlatformSupport/private/qdevicediscovery_p.h>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QJsonArray>
|
||||
#include <QtGui/qpa/qplatformwindow.h>
|
||||
#include <QtGui/qpa/qplatformcursor.h>
|
||||
#include <QtGui/QScreen>
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <gbm.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QMutex QEglFSKmsGbmScreen::m_waitForFlipMutex;
|
||||
|
||||
QEglFSKmsGbmIntegration::QEglFSKmsGbmIntegration()
|
||||
: QEglFSKmsIntegration()
|
||||
{}
|
||||
|
||||
EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeWindow(QPlatformWindow *platformWindow,
|
||||
const QSize &size,
|
||||
const QSurfaceFormat &format)
|
||||
{
|
||||
Q_UNUSED(size);
|
||||
Q_UNUSED(format);
|
||||
|
||||
QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(platformWindow->screen());
|
||||
if (screen->surface()) {
|
||||
qWarning("Only single window per screen supported!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<EGLNativeWindowType>(screen->createSurface());
|
||||
}
|
||||
|
||||
EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format)
|
||||
{
|
||||
Q_UNUSED(format);
|
||||
Q_ASSERT(device());
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug) << "Creating native off screen window";
|
||||
gbm_surface *surface = gbm_surface_create(static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(),
|
||||
1, 1,
|
||||
GBM_FORMAT_XRGB8888,
|
||||
GBM_BO_USE_RENDERING);
|
||||
|
||||
return reinterpret_cast<EGLNativeWindowType>(surface);
|
||||
}
|
||||
|
||||
void QEglFSKmsGbmIntegration::destroyNativeWindow(EGLNativeWindowType window)
|
||||
{
|
||||
gbm_surface *surface = reinterpret_cast<gbm_surface *>(window);
|
||||
gbm_surface_destroy(surface);
|
||||
}
|
||||
|
||||
QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen) const
|
||||
{
|
||||
if (hwCursor())
|
||||
return Q_NULLPTR;
|
||||
else
|
||||
return new QEglFSCursor(screen);
|
||||
}
|
||||
|
||||
void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface)
|
||||
{
|
||||
QWindow *window = static_cast<QWindow *>(surface->surface());
|
||||
QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(window->screen()->handle());
|
||||
|
||||
screen->flip();
|
||||
}
|
||||
|
||||
QEglFSKmsDevice *QEglFSKmsGbmIntegration::createDevice(const QString &devicePath)
|
||||
{
|
||||
QString path = devicePath;
|
||||
if (!devicePath.isEmpty()) {
|
||||
qCDebug(qLcEglfsKmsDebug) << "Using DRM device" << path << "specified in config file";
|
||||
} else {
|
||||
|
||||
QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask);
|
||||
QStringList devices = d->scanConnectedDevices();
|
||||
qCDebug(qLcEglfsKmsDebug) << "Found the following video devices:" << devices;
|
||||
d->deleteLater();
|
||||
|
||||
if (Q_UNLIKELY(devices.isEmpty()))
|
||||
qFatal("Could not find DRM device!");
|
||||
|
||||
path = devices.first();
|
||||
qCDebug(qLcEglfsKmsDebug) << "Using" << path;
|
||||
}
|
||||
|
||||
return new QEglFSKmsGbmDevice(this, path);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
@ -0,0 +1,75 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QEGLFSKMSGBMINTEGRATION_H
|
||||
#define QEGLFSKMSGBMINTEGRATION_H
|
||||
|
||||
#include "qeglfskmsintegration.h"
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglFSKmsDevice;
|
||||
|
||||
class QEglFSKmsGbmIntegration : public QEglFSKmsIntegration
|
||||
{
|
||||
public:
|
||||
QEglFSKmsGbmIntegration();
|
||||
|
||||
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;
|
||||
|
||||
QPlatformCursor *createCursor(QPlatformScreen *screen) const Q_DECL_OVERRIDE;
|
||||
void presentBuffer(QPlatformSurface *surface) Q_DECL_OVERRIDE;
|
||||
|
||||
protected:
|
||||
QEglFSKmsDevice *createDevice(const QString &devicePath) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QEGLFSKMSGBMINTEGRATION_H
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the qmake spec of the Qt Toolkit.
|
||||
@ -38,19 +39,19 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfsdeviceintegration.h"
|
||||
#include "qeglfskmsintegration.h"
|
||||
#include "qeglfskmsgbmintegration.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglFSKmsIntegrationPlugin : public QEGLDeviceIntegrationPlugin
|
||||
class QEglFSKmsGbmIntegrationPlugin : public QEGLDeviceIntegrationPlugin
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_kms.json")
|
||||
|
||||
public:
|
||||
QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsIntegration; }
|
||||
QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSKmsGbmIntegration; }
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#include "qeglfskmsmain.moc"
|
||||
#include "qeglfskmsgbmmain.moc"
|
@ -0,0 +1,223 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfskmsgbmscreen.h"
|
||||
#include "qeglfskmsgbmdevice.h"
|
||||
#include "qeglfskmsgbmcursor.h"
|
||||
#include "qeglfsintegration.h"
|
||||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
#include <QtPlatformSupport/private/qfbvthandler_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
|
||||
|
||||
void QEglFSKmsGbmScreen::bufferDestroyedHandler(gbm_bo *bo, void *data)
|
||||
{
|
||||
FrameBuffer *fb = static_cast<FrameBuffer *>(data);
|
||||
|
||||
if (fb->fb) {
|
||||
gbm_device *device = gbm_bo_get_device(bo);
|
||||
drmModeRmFB(gbm_device_get_fd(device), fb->fb);
|
||||
}
|
||||
|
||||
delete fb;
|
||||
}
|
||||
|
||||
QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject(gbm_bo *bo)
|
||||
{
|
||||
{
|
||||
FrameBuffer *fb = static_cast<FrameBuffer *>(gbm_bo_get_user_data(bo));
|
||||
if (fb)
|
||||
return fb;
|
||||
}
|
||||
|
||||
uint32_t width = gbm_bo_get_width(bo);
|
||||
uint32_t height = gbm_bo_get_height(bo);
|
||||
uint32_t stride = gbm_bo_get_stride(bo);
|
||||
uint32_t handle = gbm_bo_get_handle(bo).u32;
|
||||
|
||||
QScopedPointer<FrameBuffer> fb(new FrameBuffer);
|
||||
|
||||
int ret = drmModeAddFB(device()->fd(), width, height, 24, 32,
|
||||
stride, handle, &fb->fb);
|
||||
|
||||
if (ret) {
|
||||
qWarning("Failed to create KMS FB!");
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler);
|
||||
return fb.take();
|
||||
}
|
||||
|
||||
QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration,
|
||||
QEglFSKmsDevice *device,
|
||||
QEglFSKmsOutput output,
|
||||
QPoint position)
|
||||
: QEglFSKmsScreen(integration, device, output, position)
|
||||
, m_gbm_surface(Q_NULLPTR)
|
||||
, m_gbm_bo_current(Q_NULLPTR)
|
||||
, m_gbm_bo_next(Q_NULLPTR)
|
||||
, m_cursor(Q_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
QEglFSKmsGbmScreen::~QEglFSKmsGbmScreen()
|
||||
{
|
||||
}
|
||||
|
||||
QPlatformCursor *QEglFSKmsGbmScreen::cursor() const
|
||||
{
|
||||
if (integration()->hwCursor()) {
|
||||
if (!integration()->separateScreens())
|
||||
return static_cast<QEglFSKmsGbmDevice *>(device())->globalCursor();
|
||||
|
||||
if (m_cursor.isNull()) {
|
||||
QEglFSKmsGbmScreen *that = const_cast<QEglFSKmsGbmScreen *>(this);
|
||||
that->m_cursor.reset(new QEglFSKmsGbmCursor(that));
|
||||
}
|
||||
|
||||
return m_cursor.data();
|
||||
} else {
|
||||
return QEglFSScreen::cursor();
|
||||
}
|
||||
}
|
||||
|
||||
gbm_surface *QEglFSKmsGbmScreen::createSurface()
|
||||
{
|
||||
if (!m_gbm_surface) {
|
||||
qCDebug(qLcEglfsKmsDebug) << "Creating window for screen" << name();
|
||||
m_gbm_surface = gbm_surface_create(static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(),
|
||||
geometry().width(),
|
||||
geometry().height(),
|
||||
GBM_FORMAT_XRGB8888,
|
||||
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
||||
}
|
||||
return m_gbm_surface;
|
||||
}
|
||||
|
||||
void QEglFSKmsGbmScreen::destroySurface()
|
||||
{
|
||||
if (m_gbm_bo_current) {
|
||||
gbm_bo_destroy(m_gbm_bo_current);
|
||||
m_gbm_bo_current = Q_NULLPTR;
|
||||
}
|
||||
|
||||
if (m_gbm_bo_next) {
|
||||
gbm_bo_destroy(m_gbm_bo_next);
|
||||
m_gbm_bo_next = Q_NULLPTR;
|
||||
}
|
||||
|
||||
if (m_gbm_surface) {
|
||||
gbm_surface_destroy(m_gbm_surface);
|
||||
m_gbm_surface = Q_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSKmsGbmScreen::waitForFlip()
|
||||
{
|
||||
// Don't lock the mutex unless we actually need to
|
||||
if (!m_gbm_bo_next)
|
||||
return;
|
||||
|
||||
QMutexLocker lock(&m_waitForFlipMutex);
|
||||
while (m_gbm_bo_next)
|
||||
static_cast<QEglFSKmsGbmDevice *>(device())->handleDrmEvent();
|
||||
}
|
||||
|
||||
void QEglFSKmsGbmScreen::flip()
|
||||
{
|
||||
if (!m_gbm_surface) {
|
||||
qWarning("Cannot sync before platform init!");
|
||||
return;
|
||||
}
|
||||
|
||||
m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface);
|
||||
if (!m_gbm_bo_next) {
|
||||
qWarning("Could not lock GBM surface front buffer!");
|
||||
return;
|
||||
}
|
||||
|
||||
FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next);
|
||||
|
||||
if (!output().mode_set) {
|
||||
int ret = drmModeSetCrtc(device()->fd(),
|
||||
output().crtc_id,
|
||||
fb->fb,
|
||||
0, 0,
|
||||
&output().connector_id, 1,
|
||||
&output().modes[output().mode]);
|
||||
|
||||
if (ret) {
|
||||
qErrnoWarning("Could not set DRM mode!");
|
||||
} else {
|
||||
output().mode_set = true;
|
||||
setPowerState(PowerStateOn);
|
||||
}
|
||||
}
|
||||
|
||||
int ret = drmModePageFlip(device()->fd(),
|
||||
output().crtc_id,
|
||||
fb->fb,
|
||||
DRM_MODE_PAGE_FLIP_EVENT,
|
||||
this);
|
||||
if (ret) {
|
||||
qErrnoWarning("Could not queue DRM page flip!");
|
||||
gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next);
|
||||
m_gbm_bo_next = Q_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSKmsGbmScreen::flipFinished()
|
||||
{
|
||||
if (m_gbm_bo_current)
|
||||
gbm_surface_release_buffer(m_gbm_surface,
|
||||
m_gbm_bo_current);
|
||||
|
||||
m_gbm_bo_current = m_gbm_bo_next;
|
||||
m_gbm_bo_next = Q_NULLPTR;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
@ -0,0 +1,93 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QEGLFSKMSGBMSCREEN_H
|
||||
#define QEGLFSKMSGBMSCREEN_H
|
||||
|
||||
#include "qeglfskmsscreen.h"
|
||||
#include <QtCore/QMutex>
|
||||
|
||||
#include <gbm.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglFSKmsGbmCursor;
|
||||
|
||||
class QEglFSKmsGbmScreen : public QEglFSKmsScreen
|
||||
{
|
||||
public:
|
||||
QEglFSKmsGbmScreen(QEglFSKmsIntegration *integration,
|
||||
QEglFSKmsDevice *device,
|
||||
QEglFSKmsOutput output,
|
||||
QPoint position);
|
||||
~QEglFSKmsGbmScreen();
|
||||
|
||||
QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
|
||||
|
||||
gbm_surface *surface() const { return m_gbm_surface; }
|
||||
gbm_surface *createSurface();
|
||||
void destroySurface();
|
||||
|
||||
void waitForFlip() Q_DECL_OVERRIDE;
|
||||
void flip() Q_DECL_OVERRIDE;
|
||||
void flipFinished() Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
gbm_surface *m_gbm_surface;
|
||||
|
||||
gbm_bo *m_gbm_bo_current;
|
||||
gbm_bo *m_gbm_bo_next;
|
||||
|
||||
QScopedPointer<QEglFSKmsGbmCursor> m_cursor;
|
||||
|
||||
struct FrameBuffer {
|
||||
FrameBuffer() : fb(0) {}
|
||||
uint32_t fb;
|
||||
};
|
||||
static void bufferDestroyedHandler(gbm_bo *bo, void *data);
|
||||
FrameBuffer *framebufferForBufferObject(gbm_bo *bo);
|
||||
|
||||
static QMutex m_waitForFlipMutex;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QEGLFSKMSGBMSCREEN_H
|
@ -1,23 +1,32 @@
|
||||
TARGET = qeglfs-kms-egldevice-integration
|
||||
|
||||
QT += core-private gui-private platformsupport-private eglfs_device_lib-private
|
||||
QT += core-private gui-private platformsupport-private eglfs_device_lib-private eglfs_kms_support-private
|
||||
|
||||
INCLUDEPATH += $$PWD/../..
|
||||
INCLUDEPATH += $$PWD/../.. $$PWD/../eglfs_kms_support
|
||||
|
||||
DEFINES += MESA_EGL_NO_X11_HEADERS
|
||||
|
||||
CONFIG += link_pkgconfig
|
||||
!contains(QT_CONFIG, no-pkg-config) {
|
||||
PKGCONFIG += libdrm
|
||||
} else {
|
||||
LIBS += -ldrm
|
||||
}
|
||||
|
||||
CONFIG += egl
|
||||
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
|
||||
|
||||
SOURCES += $$PWD/qeglfskmsegldevicemain.cpp \
|
||||
$$PWD/qeglfskmsegldeviceintegration.cpp
|
||||
$$PWD/qeglfskmsegldeviceintegration.cpp \
|
||||
qeglfskmsegldevice.cpp \
|
||||
qeglfskmsegldevicescreen.cpp
|
||||
|
||||
HEADERS += $$PWD/qeglfskmsegldeviceintegration.h
|
||||
HEADERS += $$PWD/qeglfskmsegldeviceintegration.h \
|
||||
qeglfskmsegldevice.h \
|
||||
qeglfskmsegldevicescreen.h
|
||||
|
||||
OTHER_FILES += $$PWD/eglfs_kms_egldevice.json
|
||||
|
||||
LIBS += -ldrm
|
||||
|
||||
PLUGIN_TYPE = egldeviceintegrations
|
||||
PLUGIN_CLASS_NAME = QEglFSKmsEglDeviceIntegrationPlugin
|
||||
load(qt_plugin)
|
||||
|
@ -0,0 +1,79 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfskmsegldevice.h"
|
||||
#include "qeglfskmsegldevicescreen.h"
|
||||
|
||||
#include <QtCore/private/qcore_unix_p.h>
|
||||
|
||||
QEglFSKmsEglDevice::QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path)
|
||||
: QEglFSKmsDevice(integration, path)
|
||||
{
|
||||
}
|
||||
|
||||
bool QEglFSKmsEglDevice::open()
|
||||
{
|
||||
Q_ASSERT(fd() == -1);
|
||||
|
||||
int fd = drmOpen(devicePath().toLocal8Bit().constData(), Q_NULLPTR);
|
||||
if (Q_UNLIKELY(fd < 0))
|
||||
qFatal("Could not open DRM device");
|
||||
|
||||
setFd(fd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QEglFSKmsEglDevice::close()
|
||||
{
|
||||
if (qt_safe_close(fd()) == -1)
|
||||
qErrnoWarning("Could not close DRM device");
|
||||
|
||||
setFd(-1);
|
||||
}
|
||||
|
||||
EGLNativeDisplayType QEglFSKmsEglDevice::device() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
QEglFSKmsScreen *QEglFSKmsEglDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position)
|
||||
{
|
||||
return new QEglFSKmsEglDeviceScreen(integration, device, output, position);
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QEGLFSKMSEGLDEVICE_H
|
||||
#define QEGLFSKMSEGLDEVICE_H
|
||||
|
||||
#include <qeglfskmsdevice.h>
|
||||
|
||||
class QEglFSKmsEglDevice: public QEglFSKmsDevice
|
||||
{
|
||||
public:
|
||||
QEglFSKmsEglDevice(QEglFSKmsIntegration *integration, const QString &path);
|
||||
|
||||
virtual bool open() Q_DECL_OVERRIDE;
|
||||
virtual void close() Q_DECL_OVERRIDE;
|
||||
|
||||
virtual EGLNativeDisplayType device() const Q_DECL_OVERRIDE;
|
||||
|
||||
virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration,
|
||||
QEglFSKmsDevice *device,
|
||||
QEglFSKmsOutput output,
|
||||
QPoint position) Q_DECL_OVERRIDE;
|
||||
};
|
||||
|
||||
#endif // QEGLFSKMSEGLDEVICE_H
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
@ -38,60 +39,26 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfskmsegldeviceintegration.h"
|
||||
#include <QtPlatformSupport/private/qeglconvenience_p.h>
|
||||
#include "qeglfswindow.h"
|
||||
#include "qeglfskmsegldevice.h"
|
||||
#include "qeglfskmsscreen.h"
|
||||
#include <QLoggingCategory>
|
||||
#include <private/qmath_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms")
|
||||
|
||||
QEglFSKmsEglDeviceIntegration::QEglFSKmsEglDeviceIntegration()
|
||||
: m_dri_fd(-1)
|
||||
: QEglFSKmsIntegration()
|
||||
, m_egl_device(EGL_NO_DEVICE_EXT)
|
||||
, m_egl_display(EGL_NO_DISPLAY)
|
||||
, m_drm_connector(Q_NULLPTR)
|
||||
, m_drm_encoder(Q_NULLPTR)
|
||||
, m_drm_crtc(0)
|
||||
, m_funcs(Q_NULLPTR)
|
||||
{
|
||||
qCDebug(qLcEglfsKmsDebug, "New DRM/KMS on EGLDevice integration created");
|
||||
}
|
||||
|
||||
void QEglFSKmsEglDeviceIntegration::platformInit()
|
||||
EGLint QEglFSKmsEglDeviceIntegration::surfaceType() const
|
||||
{
|
||||
if (Q_UNLIKELY(!query_egl_device()))
|
||||
qFatal("Could not set up EGL device!");
|
||||
|
||||
const char *deviceName = m_funcs->query_device_string(m_egl_device, EGL_DRM_DEVICE_FILE_EXT);
|
||||
if (Q_UNLIKELY(!deviceName))
|
||||
qFatal("Failed to query device name from EGLDevice");
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug, "Opening %s", deviceName);
|
||||
|
||||
m_dri_fd = drmOpen(deviceName, Q_NULLPTR);
|
||||
if (Q_UNLIKELY(m_dri_fd < 0))
|
||||
qFatal("Could not open DRM device");
|
||||
|
||||
if (Q_UNLIKELY(!setup_kms()))
|
||||
qFatal("Could not set up KMS on device %s!", m_device.constData());
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug, "DRM/KMS initialized");
|
||||
}
|
||||
|
||||
void QEglFSKmsEglDeviceIntegration::platformDestroy()
|
||||
{
|
||||
if (qt_safe_close(m_dri_fd) == -1)
|
||||
qErrnoWarning("Could not close DRM device");
|
||||
|
||||
m_dri_fd = -1;
|
||||
|
||||
delete m_funcs;
|
||||
m_funcs = Q_NULLPTR;
|
||||
}
|
||||
|
||||
EGLNativeDisplayType QEglFSKmsEglDeviceIntegration::platformDisplay() const
|
||||
{
|
||||
return static_cast<EGLNativeDisplayType>(m_egl_device);
|
||||
return EGL_STREAM_BIT_KHR;
|
||||
}
|
||||
|
||||
EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay)
|
||||
@ -120,46 +87,17 @@ EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nat
|
||||
return display;
|
||||
}
|
||||
|
||||
QSizeF QEglFSKmsEglDeviceIntegration::physicalScreenSize() const
|
||||
bool QEglFSKmsEglDeviceIntegration::supportsSurfacelessContexts() const
|
||||
{
|
||||
const int defaultPhysicalDpi = 100;
|
||||
static const int width = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_WIDTH");
|
||||
static const int height = qEnvironmentVariableIntValue("QT_QPA_EGLFS_PHYSICAL_HEIGHT");
|
||||
QSizeF size(width, height);
|
||||
if (size.isEmpty()) {
|
||||
size = QSizeF(m_drm_connector->mmWidth, m_drm_connector->mmHeight);
|
||||
if (size.isEmpty()) {
|
||||
const float pixelsPerMm = Q_MM_PER_INCH / defaultPhysicalDpi;
|
||||
size = QSizeF(screenSize().width() * pixelsPerMm, screenSize().height() * pixelsPerMm);
|
||||
}
|
||||
}
|
||||
return size;
|
||||
// Returning false disables the usage of EGL_KHR_surfaceless_context even when the
|
||||
// extension is available. This is just what we need since, at least with NVIDIA
|
||||
// 352.00 making a null surface current with a context breaks.
|
||||
return false;
|
||||
}
|
||||
|
||||
QSize QEglFSKmsEglDeviceIntegration::screenSize() const
|
||||
bool QEglFSKmsEglDeviceIntegration::supportsPBuffers() const
|
||||
{
|
||||
return QSize(m_drm_mode.hdisplay, m_drm_mode.vdisplay);
|
||||
}
|
||||
|
||||
int QEglFSKmsEglDeviceIntegration::screenDepth() const
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
|
||||
QSurfaceFormat QEglFSKmsEglDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const
|
||||
{
|
||||
QSurfaceFormat format(inputFormat);
|
||||
format.setRenderableType(QSurfaceFormat::OpenGLES);
|
||||
format.setSwapBehavior(QSurfaceFormat::DoubleBuffer);
|
||||
format.setRedBufferSize(8);
|
||||
format.setGreenBufferSize(8);
|
||||
format.setBlueBufferSize(8);
|
||||
return format;
|
||||
}
|
||||
|
||||
EGLint QEglFSKmsEglDeviceIntegration::surfaceType() const
|
||||
{
|
||||
return EGL_STREAM_BIT_KHR;
|
||||
return true;
|
||||
}
|
||||
|
||||
class QEglJetsonTK1Window : public QEglFSWindow
|
||||
@ -216,11 +154,15 @@ void QEglJetsonTK1Window::resetSurface()
|
||||
return;
|
||||
}
|
||||
|
||||
QEglFSKmsScreen *cur_screen = static_cast<QEglFSKmsScreen*>(screen());
|
||||
Q_ASSERT(cur_screen);
|
||||
qCDebug(qLcEglfsKmsDebug, "Searching for id: %d", cur_screen->output().crtc_id);
|
||||
|
||||
for (int i = 0; i < actualCount; ++i) {
|
||||
EGLAttrib id;
|
||||
if (m_integration->m_funcs->query_output_layer_attrib(display, layers[i], EGL_DRM_CRTC_EXT, &id)) {
|
||||
qCDebug(qLcEglfsKmsDebug, " [%d] layer %p - crtc %d", i, layers[i], (int) id);
|
||||
if (id == EGLAttrib(m_integration->m_drm_crtc))
|
||||
if (id == EGLAttrib(cur_screen->output().crtc_id))
|
||||
layer = layers[i];
|
||||
} else if (m_integration->m_funcs->query_output_layer_attrib(display, layers[i], EGL_DRM_PLANE_EXT, &id)) {
|
||||
// Not used yet, just for debugging.
|
||||
@ -251,8 +193,8 @@ void QEglJetsonTK1Window::resetSurface()
|
||||
m_format = q_glFormatFromConfig(display, m_config);
|
||||
qCDebug(qLcEglfsKmsDebug) << "Stream producer format is" << m_format;
|
||||
|
||||
const int w = m_integration->screenSize().width();
|
||||
const int h = m_integration->screenSize().height();
|
||||
const int w = cur_screen->geometry().width();
|
||||
const int h = cur_screen->geometry().height();
|
||||
qCDebug(qLcEglfsKmsDebug, "Creating stream producer surface of size %dx%d", w, h);
|
||||
|
||||
const EGLint stream_producer_attribs[] = {
|
||||
@ -280,133 +222,25 @@ QEglFSWindow *QEglFSKmsEglDeviceIntegration::createWindow(QWindow *window) const
|
||||
return eglWindow;
|
||||
}
|
||||
|
||||
bool QEglFSKmsEglDeviceIntegration::hasCapability(QPlatformIntegration::Capability cap) const
|
||||
bool QEglFSKmsEglDeviceIntegration::separateScreens() const
|
||||
{
|
||||
switch (cap) {
|
||||
case QPlatformIntegration::ThreadedPixmaps:
|
||||
case QPlatformIntegration::OpenGL:
|
||||
case QPlatformIntegration::ThreadedOpenGL:
|
||||
case QPlatformIntegration::BufferQueueingOpenGL:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSKmsEglDeviceIntegration::waitForVSync(QPlatformSurface *) const
|
||||
{
|
||||
static bool mode_set = false;
|
||||
|
||||
if (!mode_set) {
|
||||
mode_set = true;
|
||||
|
||||
drmModeCrtcPtr currentMode = drmModeGetCrtc(m_dri_fd, m_drm_crtc);
|
||||
const bool alreadySet = currentMode
|
||||
&& currentMode->width == m_drm_mode.hdisplay
|
||||
&& currentMode->height == m_drm_mode.vdisplay;
|
||||
if (currentMode)
|
||||
drmModeFreeCrtc(currentMode);
|
||||
if (alreadySet) {
|
||||
// Maybe detecting the DPMS mode could help here, but there are no properties
|
||||
// exposed on the connector apparently. So rely on an env var for now.
|
||||
static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE");
|
||||
if (!alwaysDoSet) {
|
||||
qCDebug(qLcEglfsKmsDebug, "Mode already set");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug, "Setting mode");
|
||||
int ret = drmModeSetCrtc(m_dri_fd, m_drm_crtc,
|
||||
-1, 0, 0,
|
||||
&m_drm_connector->connector_id, 1,
|
||||
const_cast<const drmModeModeInfoPtr>(&m_drm_mode));
|
||||
if (Q_UNLIKELY(ret))
|
||||
qFatal("drmModeSetCrtc failed");
|
||||
}
|
||||
}
|
||||
|
||||
qreal QEglFSKmsEglDeviceIntegration::refreshRate() const
|
||||
{
|
||||
quint32 refresh = m_drm_mode.vrefresh;
|
||||
return refresh > 0 ? refresh : 60;
|
||||
}
|
||||
|
||||
bool QEglFSKmsEglDeviceIntegration::supportsSurfacelessContexts() const
|
||||
{
|
||||
// Returning false disables the usage of EGL_KHR_surfaceless_context even when the
|
||||
// extension is available. This is just what we need since, at least with NVIDIA
|
||||
// 352.00 making a null surface current with a context breaks.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QEglFSKmsEglDeviceIntegration::setup_kms()
|
||||
{
|
||||
drmModeRes *resources;
|
||||
drmModeConnector *connector;
|
||||
drmModeEncoder *encoder;
|
||||
quint32 crtc = 0;
|
||||
int i;
|
||||
|
||||
resources = drmModeGetResources(m_dri_fd);
|
||||
if (!resources) {
|
||||
qWarning("drmModeGetResources failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (i = 0; i < resources->count_connectors; i++) {
|
||||
connector = drmModeGetConnector(m_dri_fd, resources->connectors[i]);
|
||||
if (!connector)
|
||||
continue;
|
||||
|
||||
if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0)
|
||||
break;
|
||||
|
||||
drmModeFreeConnector(connector);
|
||||
}
|
||||
|
||||
if (i == resources->count_connectors) {
|
||||
qWarning("No currently active connector found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug, "Using connector with type %d", connector->connector_type);
|
||||
|
||||
for (i = 0; i < resources->count_encoders; i++) {
|
||||
encoder = drmModeGetEncoder(m_dri_fd, resources->encoders[i]);
|
||||
if (!encoder)
|
||||
continue;
|
||||
|
||||
if (encoder->encoder_id == connector->encoder_id)
|
||||
break;
|
||||
|
||||
drmModeFreeEncoder(encoder);
|
||||
}
|
||||
|
||||
for (int j = 0; j < resources->count_crtcs; j++) {
|
||||
if ((encoder->possible_crtcs & (1 << j))) {
|
||||
crtc = resources->crtcs[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Q_UNLIKELY(crtc == 0))
|
||||
qFatal("No suitable CRTC available");
|
||||
|
||||
m_drm_connector = connector;
|
||||
m_drm_encoder = encoder;
|
||||
m_drm_mode = connector->modes[0];
|
||||
m_drm_crtc = crtc;
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug).noquote() << "Using crtc" << m_drm_crtc
|
||||
<< "with mode" << m_drm_mode.hdisplay << "x" << m_drm_mode.vdisplay
|
||||
<< "@" << m_drm_mode.vrefresh;
|
||||
|
||||
drmModeFreeResources(resources);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QEglFSKmsDevice *QEglFSKmsEglDeviceIntegration::createDevice(const QString &devicePath)
|
||||
{
|
||||
Q_UNUSED(devicePath)
|
||||
|
||||
if (Q_UNLIKELY(!query_egl_device()))
|
||||
qFatal("Could not set up EGL device!");
|
||||
|
||||
const char *deviceName = m_funcs->query_device_string(m_egl_device, EGL_DRM_DEVICE_FILE_EXT);
|
||||
if (Q_UNLIKELY(!deviceName))
|
||||
qFatal("Failed to query device name from EGLDevice");
|
||||
|
||||
return new QEglFSKmsEglDevice(this, deviceName);
|
||||
}
|
||||
|
||||
bool QEglFSKmsEglDeviceIntegration::query_egl_device()
|
||||
{
|
||||
m_funcs = new QEGLStreamConvenience;
|
||||
|
@ -1,6 +1,7 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
@ -40,17 +41,7 @@
|
||||
#ifndef QEGLFSKMSEGLDEVICEINTEGRATION_H
|
||||
#define QEGLFSKMSEGLDEVICEINTEGRATION_H
|
||||
|
||||
#include "qeglfsdeviceintegration.h"
|
||||
#include "qeglfswindow.h"
|
||||
#include "qeglfsintegration.h"
|
||||
|
||||
#include <QtPlatformSupport/private/qdevicediscovery_p.h>
|
||||
#include <QtPlatformSupport/private/qeglconvenience_p.h>
|
||||
#include <QtCore/private/qcore_unix_p.h>
|
||||
#include <QtCore/QScopedPointer>
|
||||
#include <QtGui/qpa/qplatformwindow.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QDebug>
|
||||
#include <qeglfskmsintegration.h>
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
@ -59,41 +50,28 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglFSKmsEglDeviceIntegration : public QEGLDeviceIntegration
|
||||
class QEglFSKmsEglDeviceIntegration : public QEglFSKmsIntegration
|
||||
{
|
||||
public:
|
||||
QEglFSKmsEglDeviceIntegration();
|
||||
|
||||
void platformInit() Q_DECL_OVERRIDE;
|
||||
void platformDestroy() Q_DECL_OVERRIDE;
|
||||
EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE;
|
||||
EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) Q_DECL_OVERRIDE;
|
||||
QSizeF physicalScreenSize() const Q_DECL_OVERRIDE;
|
||||
QSize screenSize() const Q_DECL_OVERRIDE;
|
||||
int screenDepth() const Q_DECL_OVERRIDE;
|
||||
qreal refreshRate() const Q_DECL_OVERRIDE;
|
||||
QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const Q_DECL_OVERRIDE;
|
||||
EGLint surfaceType() const Q_DECL_OVERRIDE;
|
||||
QEglFSWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE;
|
||||
bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
|
||||
void waitForVSync(QPlatformSurface *surface) const Q_DECL_OVERRIDE;
|
||||
EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) Q_DECL_OVERRIDE;
|
||||
bool supportsSurfacelessContexts() const Q_DECL_OVERRIDE;
|
||||
bool supportsPBuffers() const Q_DECL_OVERRIDE;
|
||||
QEglFSWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE;
|
||||
|
||||
virtual bool separateScreens() const Q_DECL_OVERRIDE;
|
||||
protected:
|
||||
QEglFSKmsDevice *createDevice(const QString &devicePath) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
bool setup_kms();
|
||||
bool query_egl_device();
|
||||
|
||||
// device bits
|
||||
QByteArray m_device;
|
||||
int m_dri_fd;
|
||||
EGLDeviceEXT m_egl_device;
|
||||
EGLDisplay m_egl_display;
|
||||
|
||||
// KMS bits
|
||||
drmModeConnector *m_drm_connector;
|
||||
drmModeEncoder *m_drm_encoder;
|
||||
drmModeModeInfo m_drm_mode;
|
||||
quint32 m_drm_crtc;
|
||||
|
||||
friend class QEglJetsonTK1Window;
|
||||
// EGLStream infrastructure
|
||||
QEGLStreamConvenience *m_funcs;
|
||||
};
|
||||
|
@ -0,0 +1,78 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfskmsegldevicescreen.h"
|
||||
#include "qeglfskmsegldevice.h"
|
||||
|
||||
QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position)
|
||||
: QEglFSKmsScreen(integration, device, output, position)
|
||||
{
|
||||
}
|
||||
|
||||
void QEglFSKmsEglDeviceScreen::waitForFlip()
|
||||
{
|
||||
if (!output().mode_set) {
|
||||
output().mode_set = true;
|
||||
|
||||
drmModeCrtcPtr currentMode = drmModeGetCrtc(device()->fd(), output().crtc_id);
|
||||
const bool alreadySet = currentMode
|
||||
&& currentMode->width == output().modes[output().mode].hdisplay
|
||||
&& currentMode->height == output().modes[output().mode].vdisplay;
|
||||
if (currentMode)
|
||||
drmModeFreeCrtc(currentMode);
|
||||
if (alreadySet) {
|
||||
// Maybe detecting the DPMS mode could help here, but there are no properties
|
||||
// exposed on the connector apparently. So rely on an env var for now.
|
||||
static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE");
|
||||
if (!alwaysDoSet) {
|
||||
qCDebug(qLcEglfsKmsDebug, "Mode already set");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug, "Setting mode");
|
||||
int ret = drmModeSetCrtc(device()->fd(), output().crtc_id,
|
||||
-1, 0, 0,
|
||||
&output().connector_id, 1,
|
||||
&output().modes[output().mode]);
|
||||
if (ret)
|
||||
qFatal("drmModeSetCrtc failed");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** 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 The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/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 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or any later version approved by the KDE Free
|
||||
** Qt Foundation. The licenses are as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QEGLFSKMSEGLDEVICESCREEN_H
|
||||
#define QEGLFSKMSEGLDEVICESCREEN_H
|
||||
|
||||
#include <qeglfskmsscreen.h>
|
||||
|
||||
class QEglFSKmsEglDeviceScreen : public QEglFSKmsScreen
|
||||
{
|
||||
public:
|
||||
QEglFSKmsEglDeviceScreen(QEglFSKmsIntegration *integration,
|
||||
QEglFSKmsDevice *device,
|
||||
QEglFSKmsOutput output,
|
||||
QPoint position);
|
||||
|
||||
void waitForFlip() Q_DECL_OVERRIDE;
|
||||
};
|
||||
|
||||
#endif // QEGLFSKMSEGLDEVICESCREEN_H
|
@ -0,0 +1,28 @@
|
||||
TARGET = QtEglFsKmsSupport
|
||||
CONFIG += no_module_headers internal_module
|
||||
load(qt_module)
|
||||
|
||||
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
|
||||
!contains(QT_CONFIG, no-pkg-config) {
|
||||
PKGCONFIG += libdrm
|
||||
} else {
|
||||
LIBS += -ldrm
|
||||
}
|
||||
|
||||
CONFIG += egl
|
||||
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
|
||||
|
||||
SOURCES += $$PWD/qeglfskmsintegration.cpp \
|
||||
$$PWD/qeglfskmsdevice.cpp \
|
||||
$$PWD/qeglfskmsscreen.cpp \
|
||||
|
||||
HEADERS += $$PWD/qeglfskmsintegration.h \
|
||||
$$PWD/qeglfskmsdevice.h \
|
||||
$$PWD/qeglfskmsscreen.h \
|
@ -2,6 +2,7 @@
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
@ -309,7 +310,7 @@ QEglFSKmsScreen *QEglFSKmsDevice::screenForConnector(drmModeResPtr resources, dr
|
||||
m_crtc_allocator |= (1 << output.crtc_id);
|
||||
m_connector_allocator |= (1 << output.connector_id);
|
||||
|
||||
return new QEglFSKmsScreen(m_integration, this, output, pos);
|
||||
return createScreen(m_integration, this, output, pos);
|
||||
}
|
||||
|
||||
drmModePropertyPtr QEglFSKmsDevice::connectorProperty(drmModeConnectorPtr connector, const QByteArray &name)
|
||||
@ -328,68 +329,17 @@ drmModePropertyPtr QEglFSKmsDevice::connectorProperty(drmModeConnectorPtr connec
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
void QEglFSKmsDevice::pageFlipHandler(int fd, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec, void *user_data)
|
||||
{
|
||||
Q_UNUSED(fd);
|
||||
Q_UNUSED(sequence);
|
||||
Q_UNUSED(tv_sec);
|
||||
Q_UNUSED(tv_usec);
|
||||
|
||||
QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(user_data);
|
||||
screen->flipFinished();
|
||||
}
|
||||
|
||||
QEglFSKmsDevice::QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path)
|
||||
: m_integration(integration)
|
||||
, m_path(path)
|
||||
, m_dri_fd(-1)
|
||||
, m_gbm_device(Q_NULLPTR)
|
||||
, m_crtc_allocator(0)
|
||||
, m_connector_allocator(0)
|
||||
, m_globalCursor(Q_NULLPTR)
|
||||
{
|
||||
}
|
||||
|
||||
bool QEglFSKmsDevice::open()
|
||||
QEglFSKmsDevice::~QEglFSKmsDevice()
|
||||
{
|
||||
Q_ASSERT(m_dri_fd == -1);
|
||||
Q_ASSERT(m_gbm_device == Q_NULLPTR);
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug) << "Opening device" << m_path;
|
||||
m_dri_fd = qt_safe_open(m_path.toLocal8Bit().constData(), O_RDWR | O_CLOEXEC);
|
||||
if (m_dri_fd == -1) {
|
||||
qErrnoWarning("Could not open DRM device %s", qPrintable(m_path));
|
||||
return false;
|
||||
}
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug) << "Creating GBM device for file descriptor" << m_dri_fd
|
||||
<< "obtained from" << m_path;
|
||||
m_gbm_device = gbm_create_device(m_dri_fd);
|
||||
if (!m_gbm_device) {
|
||||
qErrnoWarning("Could not create GBM device");
|
||||
qt_safe_close(m_dri_fd);
|
||||
m_dri_fd = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QEglFSKmsDevice::close()
|
||||
{
|
||||
if (m_gbm_device) {
|
||||
gbm_device_destroy(m_gbm_device);
|
||||
m_gbm_device = Q_NULLPTR;
|
||||
}
|
||||
|
||||
if (m_dri_fd != -1) {
|
||||
qt_safe_close(m_dri_fd);
|
||||
m_dri_fd = -1;
|
||||
}
|
||||
|
||||
if (m_globalCursor)
|
||||
m_globalCursor->deleteLater();
|
||||
m_globalCursor = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void QEglFSKmsDevice::createScreens()
|
||||
@ -428,36 +378,27 @@ void QEglFSKmsDevice::createScreens()
|
||||
if (!m_integration->separateScreens()) {
|
||||
Q_FOREACH (QPlatformScreen *screen, siblings)
|
||||
static_cast<QEglFSKmsScreen *>(screen)->setVirtualSiblings(siblings);
|
||||
|
||||
if (primaryScreen && m_integration->hwCursor())
|
||||
m_globalCursor = new QEglFSKmsCursor(primaryScreen);
|
||||
}
|
||||
}
|
||||
|
||||
gbm_device *QEglFSKmsDevice::device() const
|
||||
{
|
||||
return m_gbm_device;
|
||||
}
|
||||
|
||||
int QEglFSKmsDevice::fd() const
|
||||
{
|
||||
return m_dri_fd;
|
||||
}
|
||||
|
||||
QPlatformCursor *QEglFSKmsDevice::globalCursor() const
|
||||
QString QEglFSKmsDevice::devicePath() const
|
||||
{
|
||||
return m_globalCursor;
|
||||
return m_path;
|
||||
}
|
||||
|
||||
void QEglFSKmsDevice::handleDrmEvent()
|
||||
QEglFSKmsScreen *QEglFSKmsDevice::createScreen(QEglFSKmsIntegration *integration, QEglFSKmsDevice *device, QEglFSKmsOutput output, QPoint position)
|
||||
{
|
||||
drmEventContext drmEvent = {
|
||||
DRM_EVENT_CONTEXT_VERSION,
|
||||
Q_NULLPTR, // vblank handler
|
||||
pageFlipHandler // page flip handler
|
||||
};
|
||||
return new QEglFSKmsScreen(integration, device, output, position);
|
||||
}
|
||||
|
||||
drmHandleEvent(m_dri_fd, &drmEvent);
|
||||
void QEglFSKmsDevice::setFd(int fd)
|
||||
{
|
||||
m_dri_fd = fd;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
@ -2,6 +2,7 @@
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
@ -41,33 +42,35 @@
|
||||
#ifndef QEGLFSKMSDEVICE_H
|
||||
#define QEGLFSKMSDEVICE_H
|
||||
|
||||
#include "qeglfskmscursor.h"
|
||||
#include "qeglfskmsintegration.h"
|
||||
#include "qeglfskmsscreen.h"
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <gbm.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglFSKmsScreen;
|
||||
|
||||
class QEglFSKmsDevice
|
||||
class Q_EGLFS_EXPORT QEglFSKmsDevice
|
||||
{
|
||||
public:
|
||||
QEglFSKmsDevice(QEglFSKmsIntegration *integration, const QString &path);
|
||||
virtual ~QEglFSKmsDevice();
|
||||
|
||||
bool open();
|
||||
void close();
|
||||
virtual bool open() = 0;
|
||||
virtual void close() = 0;
|
||||
|
||||
void createScreens();
|
||||
virtual void createScreens();
|
||||
|
||||
gbm_device *device() const;
|
||||
virtual EGLNativeDisplayType device() const = 0;
|
||||
int fd() const;
|
||||
QString devicePath() const;
|
||||
|
||||
QPlatformCursor *globalCursor() const;
|
||||
|
||||
void handleDrmEvent();
|
||||
protected:
|
||||
virtual QEglFSKmsScreen *createScreen(QEglFSKmsIntegration *integration,
|
||||
QEglFSKmsDevice *device,
|
||||
QEglFSKmsOutput output,
|
||||
QPoint position);
|
||||
void setFd(int fd);
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(QEglFSKmsDevice)
|
||||
@ -75,13 +78,10 @@ private:
|
||||
QEglFSKmsIntegration *m_integration;
|
||||
QString m_path;
|
||||
int m_dri_fd;
|
||||
gbm_device *m_gbm_device;
|
||||
|
||||
quint32 m_crtc_allocator;
|
||||
quint32 m_connector_allocator;
|
||||
|
||||
QEglFSKmsCursor *m_globalCursor;
|
||||
|
||||
int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
|
||||
QEglFSKmsScreen *screenForConnector(drmModeResPtr resources, drmModeConnectorPtr connector, QPoint pos);
|
||||
drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
|
@ -2,6 +2,7 @@
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
@ -41,11 +42,10 @@
|
||||
#include "qeglfskmsintegration.h"
|
||||
#include "qeglfskmsdevice.h"
|
||||
#include "qeglfskmsscreen.h"
|
||||
#include "qeglfskmscursor.h"
|
||||
#include "qeglfswindow.h"
|
||||
#include "qeglfscursor.h"
|
||||
|
||||
#include <QtPlatformSupport/private/qdevicediscovery_p.h>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
#include <QtPlatformSupport/private/qeglconvenience_p.h>
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QJsonObject>
|
||||
#include <QtCore/QJsonArray>
|
||||
@ -55,17 +55,14 @@
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <gbm.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms")
|
||||
|
||||
QMutex QEglFSKmsScreen::m_waitForFlipMutex;
|
||||
|
||||
QEglFSKmsIntegration::QEglFSKmsIntegration()
|
||||
: m_device(Q_NULLPTR)
|
||||
, m_hwCursor(true)
|
||||
, m_hwCursor(false)
|
||||
, m_pbuffers(false)
|
||||
, m_separateScreens(false)
|
||||
{}
|
||||
@ -76,21 +73,9 @@ void QEglFSKmsIntegration::platformInit()
|
||||
|
||||
if (!m_devicePath.isEmpty()) {
|
||||
qCDebug(qLcEglfsKmsDebug) << "Using DRM device" << m_devicePath << "specified in config file";
|
||||
} else {
|
||||
|
||||
QDeviceDiscovery *d = QDeviceDiscovery::create(QDeviceDiscovery::Device_VideoMask);
|
||||
QStringList devices = d->scanConnectedDevices();
|
||||
qCDebug(qLcEglfsKmsDebug) << "Found the following video devices:" << devices;
|
||||
d->deleteLater();
|
||||
|
||||
if (Q_UNLIKELY(devices.isEmpty()))
|
||||
qFatal("Could not find DRM device!");
|
||||
|
||||
m_devicePath = devices.first();
|
||||
qCDebug(qLcEglfsKmsDebug) << "Using" << m_devicePath;
|
||||
}
|
||||
|
||||
m_device = new QEglFSKmsDevice(this, m_devicePath);
|
||||
m_device = createDevice(m_devicePath);
|
||||
if (Q_UNLIKELY(!m_device->open()))
|
||||
qFatal("Could not open device %s - aborting!", qPrintable(m_devicePath));
|
||||
}
|
||||
@ -129,42 +114,6 @@ QSurfaceFormat QEglFSKmsIntegration::surfaceFormatFor(const QSurfaceFormat &inpu
|
||||
return format;
|
||||
}
|
||||
|
||||
EGLNativeWindowType QEglFSKmsIntegration::createNativeWindow(QPlatformWindow *platformWindow,
|
||||
const QSize &size,
|
||||
const QSurfaceFormat &format)
|
||||
{
|
||||
Q_UNUSED(size);
|
||||
Q_UNUSED(format);
|
||||
|
||||
QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(platformWindow->screen());
|
||||
if (screen->surface()) {
|
||||
qWarning("Only single window per screen supported!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reinterpret_cast<EGLNativeWindowType>(screen->createSurface());
|
||||
}
|
||||
|
||||
EGLNativeWindowType QEglFSKmsIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format)
|
||||
{
|
||||
Q_UNUSED(format);
|
||||
Q_ASSERT(m_device);
|
||||
|
||||
qCDebug(qLcEglfsKmsDebug) << "Creating native off screen window";
|
||||
gbm_surface *surface = gbm_surface_create(m_device->device(),
|
||||
1, 1,
|
||||
GBM_FORMAT_XRGB8888,
|
||||
GBM_BO_USE_RENDERING);
|
||||
|
||||
return reinterpret_cast<EGLNativeWindowType>(surface);
|
||||
}
|
||||
|
||||
void QEglFSKmsIntegration::destroyNativeWindow(EGLNativeWindowType window)
|
||||
{
|
||||
gbm_surface *surface = reinterpret_cast<gbm_surface *>(window);
|
||||
gbm_surface_destroy(surface);
|
||||
}
|
||||
|
||||
bool QEglFSKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const
|
||||
{
|
||||
switch (cap) {
|
||||
@ -177,14 +126,6 @@ bool QEglFSKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) c
|
||||
}
|
||||
}
|
||||
|
||||
QPlatformCursor *QEglFSKmsIntegration::createCursor(QPlatformScreen *screen) const
|
||||
{
|
||||
if (m_hwCursor)
|
||||
return Q_NULLPTR;
|
||||
else
|
||||
return new QEglFSCursor(screen);
|
||||
}
|
||||
|
||||
void QEglFSKmsIntegration::waitForVSync(QPlatformSurface *surface) const
|
||||
{
|
||||
QWindow *window = static_cast<QWindow *>(surface->surface());
|
||||
@ -193,14 +134,6 @@ void QEglFSKmsIntegration::waitForVSync(QPlatformSurface *surface) const
|
||||
screen->waitForFlip();
|
||||
}
|
||||
|
||||
void QEglFSKmsIntegration::presentBuffer(QPlatformSurface *surface)
|
||||
{
|
||||
QWindow *window = static_cast<QWindow *>(surface->surface());
|
||||
QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(window->screen()->handle());
|
||||
|
||||
screen->flip();
|
||||
}
|
||||
|
||||
bool QEglFSKmsIntegration::supportsPBuffers() const
|
||||
{
|
||||
return m_pbuffers;
|
||||
@ -221,6 +154,11 @@ QMap<QString, QVariantMap> QEglFSKmsIntegration::outputSettings() const
|
||||
return m_outputSettings;
|
||||
}
|
||||
|
||||
QEglFSKmsDevice *QEglFSKmsIntegration::device() const
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
void QEglFSKmsIntegration::loadConfig()
|
||||
{
|
||||
static QByteArray json = qgetenv("QT_QPA_EGLFS_KMS_CONFIG");
|
@ -2,6 +2,7 @@
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
@ -44,12 +45,15 @@
|
||||
#include "qeglfsdeviceintegration.h"
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglFSKmsDevice;
|
||||
|
||||
class QEglFSKmsIntegration : public QEGLDeviceIntegration
|
||||
Q_EGLFS_EXPORT Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
|
||||
|
||||
class Q_EGLFS_EXPORT QEglFSKmsIntegration : public QEGLDeviceIntegration
|
||||
{
|
||||
public:
|
||||
QEglFSKmsIntegration();
|
||||
@ -60,21 +64,19 @@ public:
|
||||
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;
|
||||
bool separateScreens() const;
|
||||
virtual bool hwCursor() const;
|
||||
virtual bool separateScreens() const;
|
||||
QMap<QString, QVariantMap> outputSettings() const;
|
||||
|
||||
QEglFSKmsDevice *device() const;
|
||||
|
||||
protected:
|
||||
virtual QEglFSKmsDevice *createDevice(const QString &devicePath) = 0;
|
||||
|
||||
private:
|
||||
void loadConfig();
|
||||
|
@ -2,6 +2,7 @@
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
@ -40,7 +41,6 @@
|
||||
|
||||
#include "qeglfskmsscreen.h"
|
||||
#include "qeglfskmsdevice.h"
|
||||
#include "qeglfskmscursor.h"
|
||||
#include "qeglfsintegration.h"
|
||||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
@ -69,45 +69,6 @@ private:
|
||||
QEglFSKmsScreen *m_screen;
|
||||
};
|
||||
|
||||
void QEglFSKmsScreen::bufferDestroyedHandler(gbm_bo *bo, void *data)
|
||||
{
|
||||
FrameBuffer *fb = static_cast<FrameBuffer *>(data);
|
||||
|
||||
if (fb->fb) {
|
||||
gbm_device *device = gbm_bo_get_device(bo);
|
||||
drmModeRmFB(gbm_device_get_fd(device), fb->fb);
|
||||
}
|
||||
|
||||
delete fb;
|
||||
}
|
||||
|
||||
QEglFSKmsScreen::FrameBuffer *QEglFSKmsScreen::framebufferForBufferObject(gbm_bo *bo)
|
||||
{
|
||||
{
|
||||
FrameBuffer *fb = static_cast<FrameBuffer *>(gbm_bo_get_user_data(bo));
|
||||
if (fb)
|
||||
return fb;
|
||||
}
|
||||
|
||||
uint32_t width = gbm_bo_get_width(bo);
|
||||
uint32_t height = gbm_bo_get_height(bo);
|
||||
uint32_t stride = gbm_bo_get_stride(bo);
|
||||
uint32_t handle = gbm_bo_get_handle(bo).u32;
|
||||
|
||||
QScopedPointer<FrameBuffer> fb(new FrameBuffer);
|
||||
|
||||
int ret = drmModeAddFB(m_device->fd(), width, height, 24, 32,
|
||||
stride, handle, &fb->fb);
|
||||
|
||||
if (ret) {
|
||||
qWarning("Failed to create KMS FB!");
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
|
||||
gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler);
|
||||
return fb.take();
|
||||
}
|
||||
|
||||
QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration,
|
||||
QEglFSKmsDevice *device,
|
||||
QEglFSKmsOutput output,
|
||||
@ -115,12 +76,8 @@ QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration,
|
||||
: QEglFSScreen(eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(device->device())))
|
||||
, m_integration(integration)
|
||||
, m_device(device)
|
||||
, m_gbm_surface(Q_NULLPTR)
|
||||
, m_gbm_bo_current(Q_NULLPTR)
|
||||
, m_gbm_bo_next(Q_NULLPTR)
|
||||
, m_output(output)
|
||||
, m_pos(position)
|
||||
, m_cursor(Q_NULLPTR)
|
||||
, m_powerState(PowerStateOn)
|
||||
, m_interruptHandler(new QEglFSKmsInterruptHandler(this))
|
||||
{
|
||||
@ -191,116 +148,20 @@ QString QEglFSKmsScreen::name() const
|
||||
return m_output.name;
|
||||
}
|
||||
|
||||
QPlatformCursor *QEglFSKmsScreen::cursor() const
|
||||
{
|
||||
if (m_integration->hwCursor()) {
|
||||
if (!m_integration->separateScreens())
|
||||
return m_device->globalCursor();
|
||||
|
||||
if (m_cursor.isNull()) {
|
||||
QEglFSKmsScreen *that = const_cast<QEglFSKmsScreen *>(this);
|
||||
that->m_cursor.reset(new QEglFSKmsCursor(that));
|
||||
}
|
||||
|
||||
return m_cursor.data();
|
||||
} else {
|
||||
return QEglFSScreen::cursor();
|
||||
}
|
||||
}
|
||||
|
||||
gbm_surface *QEglFSKmsScreen::createSurface()
|
||||
{
|
||||
if (!m_gbm_surface) {
|
||||
qCDebug(qLcEglfsKmsDebug) << "Creating window for screen" << name();
|
||||
m_gbm_surface = gbm_surface_create(m_device->device(),
|
||||
geometry().width(),
|
||||
geometry().height(),
|
||||
GBM_FORMAT_XRGB8888,
|
||||
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
|
||||
}
|
||||
return m_gbm_surface;
|
||||
}
|
||||
|
||||
void QEglFSKmsScreen::destroySurface()
|
||||
{
|
||||
if (m_gbm_bo_current) {
|
||||
gbm_bo_destroy(m_gbm_bo_current);
|
||||
m_gbm_bo_current = Q_NULLPTR;
|
||||
}
|
||||
|
||||
if (m_gbm_bo_next) {
|
||||
gbm_bo_destroy(m_gbm_bo_next);
|
||||
m_gbm_bo_next = Q_NULLPTR;
|
||||
}
|
||||
|
||||
if (m_gbm_surface) {
|
||||
gbm_surface_destroy(m_gbm_surface);
|
||||
m_gbm_surface = Q_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSKmsScreen::waitForFlip()
|
||||
{
|
||||
// Don't lock the mutex unless we actually need to
|
||||
if (!m_gbm_bo_next)
|
||||
return;
|
||||
|
||||
QMutexLocker lock(&m_waitForFlipMutex);
|
||||
while (m_gbm_bo_next)
|
||||
m_device->handleDrmEvent();
|
||||
}
|
||||
|
||||
void QEglFSKmsScreen::flip()
|
||||
{
|
||||
if (!m_gbm_surface) {
|
||||
qWarning("Cannot sync before platform init!");
|
||||
return;
|
||||
}
|
||||
|
||||
m_gbm_bo_next = gbm_surface_lock_front_buffer(m_gbm_surface);
|
||||
if (!m_gbm_bo_next) {
|
||||
qWarning("Could not lock GBM surface front buffer!");
|
||||
return;
|
||||
}
|
||||
|
||||
FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next);
|
||||
|
||||
if (!m_output.mode_set) {
|
||||
int ret = drmModeSetCrtc(m_device->fd(),
|
||||
m_output.crtc_id,
|
||||
fb->fb,
|
||||
0, 0,
|
||||
&m_output.connector_id, 1,
|
||||
&m_output.modes[m_output.mode]);
|
||||
|
||||
if (ret) {
|
||||
qErrnoWarning("Could not set DRM mode!");
|
||||
} else {
|
||||
m_output.mode_set = true;
|
||||
setPowerState(PowerStateOn);
|
||||
}
|
||||
}
|
||||
|
||||
int ret = drmModePageFlip(m_device->fd(),
|
||||
m_output.crtc_id,
|
||||
fb->fb,
|
||||
DRM_MODE_PAGE_FLIP_EVENT,
|
||||
this);
|
||||
if (ret) {
|
||||
qErrnoWarning("Could not queue DRM page flip!");
|
||||
gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next);
|
||||
m_gbm_bo_next = Q_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSKmsScreen::flipFinished()
|
||||
{
|
||||
if (m_gbm_bo_current)
|
||||
gbm_surface_release_buffer(m_gbm_surface,
|
||||
m_gbm_bo_current);
|
||||
|
||||
m_gbm_bo_current = m_gbm_bo_next;
|
||||
m_gbm_bo_next = Q_NULLPTR;
|
||||
}
|
||||
|
||||
void QEglFSKmsScreen::restoreMode()
|
@ -2,6 +2,7 @@
|
||||
**
|
||||
** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Copyright (C) 2016 Pelagicore AG
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
@ -48,12 +49,10 @@
|
||||
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <gbm.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglFSKmsDevice;
|
||||
class QEglFSKmsCursor;
|
||||
class QEglFSKmsInterruptHandler;
|
||||
|
||||
struct QEglFSKmsOutput
|
||||
@ -70,7 +69,7 @@ struct QEglFSKmsOutput
|
||||
drmModePropertyPtr dpms_prop;
|
||||
};
|
||||
|
||||
class QEglFSKmsScreen : public QEglFSScreen
|
||||
class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen
|
||||
{
|
||||
public:
|
||||
QEglFSKmsScreen(QEglFSKmsIntegration *integration,
|
||||
@ -90,8 +89,6 @@ public:
|
||||
|
||||
QString name() const Q_DECL_OVERRIDE;
|
||||
|
||||
QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
|
||||
|
||||
qreal refreshRate() const Q_DECL_OVERRIDE;
|
||||
|
||||
QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; }
|
||||
@ -100,13 +97,11 @@ public:
|
||||
QEglFSKmsIntegration *integration() const { return m_integration; }
|
||||
QEglFSKmsDevice *device() const { return m_device; }
|
||||
|
||||
gbm_surface *surface() const { return m_gbm_surface; }
|
||||
gbm_surface *createSurface();
|
||||
void destroySurface();
|
||||
|
||||
void waitForFlip();
|
||||
void flip();
|
||||
void flipFinished();
|
||||
virtual void waitForFlip();
|
||||
virtual void flip();
|
||||
virtual void flipFinished();
|
||||
|
||||
QEglFSKmsOutput &output() { return m_output; }
|
||||
void restoreMode();
|
||||
@ -119,28 +114,14 @@ public:
|
||||
private:
|
||||
QEglFSKmsIntegration *m_integration;
|
||||
QEglFSKmsDevice *m_device;
|
||||
gbm_surface *m_gbm_surface;
|
||||
|
||||
gbm_bo *m_gbm_bo_current;
|
||||
gbm_bo *m_gbm_bo_next;
|
||||
|
||||
QEglFSKmsOutput m_output;
|
||||
QPoint m_pos;
|
||||
QScopedPointer<QEglFSKmsCursor> m_cursor;
|
||||
|
||||
QList<QPlatformScreen *> m_siblings;
|
||||
|
||||
PowerState m_powerState;
|
||||
|
||||
struct FrameBuffer {
|
||||
FrameBuffer() : fb(0) {}
|
||||
uint32_t fb;
|
||||
};
|
||||
static void bufferDestroyedHandler(gbm_bo *bo, void *data);
|
||||
FrameBuffer *framebufferForBufferObject(gbm_bo *bo);
|
||||
|
||||
static QMutex m_waitForFlipMutex;
|
||||
|
||||
QEglFSKmsInterruptHandler *m_interruptHandler;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user