summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/eglfs
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/eglfs')
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp16
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h2
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration.cpp5
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfswindow_p.h2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp50
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h12
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp56
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp240
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h34
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp80
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h67
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp10
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp10
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp12
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp47
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h8
20 files changed, 462 insertions, 204 deletions
diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
index e411ea55e9..0fc4cc54e0 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
@@ -103,7 +103,7 @@ QStringList QEglFSDeviceIntegrationFactory::keys(const QString &pluginPath)
QEglFSDeviceIntegration *QEglFSDeviceIntegrationFactory::create(const QString &key, const QString &pluginPath)
{
- QEglFSDeviceIntegration *integration = Q_NULLPTR;
+ QEglFSDeviceIntegration *integration = nullptr;
#if QT_CONFIG(library)
if (!pluginPath.isEmpty()) {
QCoreApplication::addLibraryPath(pluginPath);
@@ -351,9 +351,21 @@ bool QEglFSDeviceIntegration::supportsSurfacelessContexts() const
return true;
}
+QFunctionPointer QEglFSDeviceIntegration::platformFunction(const QByteArray &function) const
+{
+ Q_UNUSED(function);
+ return nullptr;
+}
+
+void *QEglFSDeviceIntegration::nativeResourceForIntegration(const QByteArray &name)
+{
+ Q_UNUSED(name);
+ return nullptr;
+}
+
void *QEglFSDeviceIntegration::wlDisplay() const
{
- return Q_NULLPTR;
+ return nullptr;
}
EGLConfig QEglFSDeviceIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format)
diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h
index 4335554912..d927bc9bc6 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration_p.h
@@ -103,6 +103,8 @@ public:
virtual int framebufferIndex() const;
virtual bool supportsPBuffers() const;
virtual bool supportsSurfacelessContexts() const;
+ virtual QFunctionPointer platformFunction(const QByteArray &function) const;
+ virtual void *nativeResourceForIntegration(const QByteArray &name);
virtual void *wlDisplay() const;
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
index 9a0be489a8..c0ecfd235f 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
@@ -324,6 +324,7 @@ void *QEglFSIntegration::nativeResourceForIntegration(const QByteArray &resource
result = qt_egl_device_integration()->wlDisplay();
break;
default:
+ result = qt_egl_device_integration()->nativeResourceForIntegration(resource);
break;
}
@@ -427,11 +428,9 @@ QFunctionPointer QEglFSIntegration::platformFunction(const QByteArray &function)
#if QT_CONFIG(evdev)
if (function == QEglFSFunctions::loadKeymapTypeIdentifier())
return QFunctionPointer(loadKeymapStatic);
-#else
- Q_UNUSED(function)
#endif
- return 0;
+ return qt_egl_device_integration()->platformFunction(function);
}
void QEglFSIntegration::loadKeymapStatic(const QString &filename)
diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h
index 6bda262523..c61f04f569 100644
--- a/src/plugins/platforms/eglfs/api/qeglfswindow_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfswindow_p.h
@@ -95,7 +95,7 @@ public:
EGLNativeWindowType eglWindow() const;
EGLSurface surface() const;
- QEglFSScreen *screen() const;
+ QEglFSScreen *screen() const override;
bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); }
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
index 27c0af1f08..43170a3875 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
@@ -19,11 +19,13 @@ SOURCES += $$PWD/qeglfskmsgbmmain.cpp \
$$PWD/qeglfskmsgbmintegration.cpp \
$$PWD/qeglfskmsgbmdevice.cpp \
$$PWD/qeglfskmsgbmscreen.cpp \
- $$PWD/qeglfskmsgbmcursor.cpp
+ $$PWD/qeglfskmsgbmcursor.cpp \
+ $$PWD/qeglfskmsgbmwindow.cpp
HEADERS += $$PWD/qeglfskmsgbmintegration.h \
$$PWD/qeglfskmsgbmdevice.h \
$$PWD/qeglfskmsgbmscreen.h \
- $$PWD/qeglfskmsgbmcursor.h
+ $$PWD/qeglfskmsgbmcursor.h \
+ $$PWD/qeglfskmsgbmwindow.h
OTHER_FILES += $$PWD/eglfs_kms.json
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
index 800118362d..9bd7fee1fb 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
@@ -68,7 +68,7 @@ Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
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)
+ , m_bo(nullptr)
, m_cursorImage(0, 0, 0, 0, 0, 0)
, m_state(CursorPendingVisible)
{
@@ -118,7 +118,7 @@ QEglFSKmsGbmCursor::~QEglFSKmsGbmCursor()
if (m_bo) {
gbm_bo_destroy(m_bo);
- m_bo = Q_NULLPTR;
+ m_bo = nullptr;
}
}
@@ -132,7 +132,7 @@ void QEglFSKmsGbmCursor::updateMouseStatus()
m_state = visible ? CursorPendingVisible : CursorPendingHidden;
#ifndef QT_NO_CURSOR
- changeCursor(Q_NULLPTR, m_screen->topLevelAt(pos()));
+ changeCursor(nullptr, m_screen->topLevelAt(pos()));
#endif
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
index e218d580a2..20127ae7f7 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.cpp
@@ -53,28 +53,17 @@ 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(QKmsScreenConfig *screenConfig, const QString &path)
: QEglFSKmsDevice(screenConfig, path)
- , m_gbm_device(Q_NULLPTR)
- , m_globalCursor(Q_NULLPTR)
+ , m_gbm_device(nullptr)
+ , m_globalCursor(nullptr)
{
}
bool QEglFSKmsGbmDevice::open()
{
Q_ASSERT(fd() == -1);
- Q_ASSERT(m_gbm_device == Q_NULLPTR);
+ Q_ASSERT(m_gbm_device == nullptr);
int fd = qt_safe_open(devicePath().toLocal8Bit().constData(), O_RDWR | O_CLOEXEC);
if (fd == -1) {
@@ -103,7 +92,7 @@ void QEglFSKmsGbmDevice::close()
if (m_gbm_device) {
gbm_device_destroy(m_gbm_device);
- m_gbm_device = Q_NULLPTR;
+ m_gbm_device = nullptr;
}
if (fd() != -1) {
@@ -134,24 +123,13 @@ void QEglFSKmsGbmDevice::destroyGlobalCursor()
if (m_globalCursor) {
qCDebug(qLcEglfsKmsDebug, "Destroying global GBM mouse cursor");
delete m_globalCursor;
- m_globalCursor = Q_NULLPTR;
+ m_globalCursor = nullptr;
}
}
-void QEglFSKmsGbmDevice::handleDrmEvent()
-{
- drmEventContext drmEvent;
- memset(&drmEvent, 0, sizeof(drmEvent));
- drmEvent.version = 2;
- drmEvent.vblank_handler = nullptr;
- drmEvent.page_flip_handler = pageFlipHandler;
-
- drmHandleEvent(fd(), &drmEvent);
-}
-
QPlatformScreen *QEglFSKmsGbmDevice::createScreen(const QKmsOutput &output)
{
- QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(this, output);
+ QEglFSKmsGbmScreen *screen = new QEglFSKmsGbmScreen(this, output, false);
if (!m_globalCursor && screenConfig()->hwCursor()) {
qCDebug(qLcEglfsKmsDebug, "Creating new global GBM mouse cursor");
@@ -161,4 +139,20 @@ QPlatformScreen *QEglFSKmsGbmDevice::createScreen(const QKmsOutput &output)
return screen;
}
+QPlatformScreen *QEglFSKmsGbmDevice::createHeadlessScreen()
+{
+ return new QEglFSKmsGbmScreen(this, QKmsOutput(), true);
+}
+
+void QEglFSKmsGbmDevice::registerScreenCloning(QPlatformScreen *screen,
+ QPlatformScreen *screenThisScreenClones,
+ const QVector<QPlatformScreen *> &screensCloningThisScreen)
+{
+ if (!screenThisScreenClones && screensCloningThisScreen.isEmpty())
+ return;
+
+ QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen);
+ gbmScreen->initCloning(screenThisScreenClones, screensCloningThisScreen);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
index 08ca28d48e..518e2ce58b 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmdevice.h
@@ -65,9 +65,11 @@ public:
QPlatformCursor *globalCursor() const;
void destroyGlobalCursor();
- void handleDrmEvent();
-
QPlatformScreen *createScreen(const QKmsOutput &output) override;
+ QPlatformScreen *createHeadlessScreen() override;
+ void registerScreenCloning(QPlatformScreen *screen,
+ QPlatformScreen *screenThisScreenClones,
+ const QVector<QPlatformScreen *> &screensCloningThisScreen) override;
private:
Q_DISABLE_COPY(QEglFSKmsGbmDevice)
@@ -75,12 +77,6 @@ private:
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
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
index 058791e473..402338197d 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
@@ -43,21 +43,13 @@
#include "qeglfskmsgbmdevice.h"
#include "qeglfskmsgbmscreen.h"
#include "qeglfskmsgbmcursor.h"
-#include "private/qeglfswindow_p.h"
+#include "qeglfskmsgbmwindow.h"
#include "private/qeglfscursor_p.h"
-#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
-#include <QtEglSupport/private/qeglconvenience_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 <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
-#include <xf86drm.h>
-#include <xf86drmMode.h>
#include <gbm.h>
QT_BEGIN_NAMESPACE
@@ -105,7 +97,6 @@ EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeOffscreenWindow(const Q
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,
@@ -134,8 +125,7 @@ QPlatformCursor *QEglFSKmsGbmIntegration::createCursor(QPlatformScreen *screen)
void QEglFSKmsGbmIntegration::presentBuffer(QPlatformSurface *surface)
{
QWindow *window = static_cast<QWindow *>(surface->surface());
- QEglFSKmsScreen *screen = static_cast<QEglFSKmsScreen *>(window->screen()->handle());
-
+ QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(window->screen()->handle());
screen->flip();
}
@@ -160,46 +150,6 @@ QKmsDevice *QEglFSKmsGbmIntegration::createDevice()
return new QEglFSKmsGbmDevice(screenConfig(), path);
}
-class QEglFSKmsGbmWindow : public QEglFSWindow
-{
-public:
- QEglFSKmsGbmWindow(QWindow *w, const QEglFSKmsGbmIntegration *integration)
- : QEglFSWindow(w)
- , m_integration(integration)
- {}
- void resetSurface() override;
- const QEglFSKmsGbmIntegration *m_integration;
-};
-
-void QEglFSKmsGbmWindow::resetSurface()
-{
- QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen());
- if (gbmScreen->surface()) {
- qWarning("Only single window per screen supported!");
- return;
- }
-
- EGLDisplay display = gbmScreen->display();
- QSurfaceFormat platformFormat = m_integration->surfaceFormatFor(window()->requestedFormat());
- m_config = QEglFSDeviceIntegration::chooseConfig(display, platformFormat);
- m_format = q_glFormatFromConfig(display, m_config, platformFormat);
- m_window = reinterpret_cast<EGLNativeWindowType>(gbmScreen->createSurface());
-
- PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = nullptr;
- const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
- if (extensions && (strstr(extensions, "EGL_KHR_platform_gbm") || strstr(extensions, "EGL_MESA_platform_gbm"))) {
- createPlatformWindowSurface = reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(
- eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
- }
-
- if (createPlatformWindowSurface) {
- m_surface = createPlatformWindowSurface(display, m_config, reinterpret_cast<void *>(m_window), nullptr);
- } else {
- qCDebug(qLcEglfsKmsDebug, "No eglCreatePlatformWindowSurface for GBM, falling back to eglCreateWindowSurface");
- m_surface = eglCreateWindowSurface(display, m_config, m_window, nullptr);
- }
-}
-
QEglFSWindow *QEglFSKmsGbmIntegration::createWindow(QWindow *window) const
{
return new QEglFSKmsGbmWindow(window, this);
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
index 87fb3146c7..4742143121 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
+** Copyright (C) 2017 The Qt Company Ltd.
** 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/
**
@@ -55,6 +55,18 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
+static inline uint32_t drmFormatToGbmFormat(uint32_t drmFormat)
+{
+ Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
+ return drmFormat;
+}
+
+static inline uint32_t gbmFormatToDrmFormat(uint32_t gbmFormat)
+{
+ Q_ASSERT(DRM_FORMAT_XRGB8888 == GBM_FORMAT_XRGB8888);
+ return gbmFormat;
+}
+
void QEglFSKmsGbmScreen::bufferDestroyedHandler(gbm_bo *bo, void *data)
{
FrameBuffer *fb = static_cast<FrameBuffer *>(data);
@@ -77,29 +89,34 @@ QEglFSKmsGbmScreen::FrameBuffer *QEglFSKmsGbmScreen::framebufferForBufferObject(
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;
+ uint32_t handles[4] = { gbm_bo_get_handle(bo).u32 };
+ uint32_t strides[4] = { gbm_bo_get_stride(bo) };
+ uint32_t offsets[4] = { 0 };
+ uint32_t pixelFormat = gbmFormatToDrmFormat(gbm_bo_get_format(bo));
QScopedPointer<FrameBuffer> fb(new FrameBuffer);
+ qCDebug(qLcEglfsKmsDebug, "Adding FB, size %ux%u, DRM format 0x%x", width, height, pixelFormat);
- int ret = drmModeAddFB(device()->fd(), width, height, 24, 32,
- stride, handle, &fb->fb);
+ int ret = drmModeAddFB2(device()->fd(), width, height, pixelFormat,
+ handles, strides, offsets, &fb->fb, 0);
if (ret) {
qWarning("Failed to create KMS FB!");
- return Q_NULLPTR;
+ return nullptr;
}
gbm_bo_set_user_data(bo, fb.data(), bufferDestroyedHandler);
return fb.take();
}
-QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output)
- : QEglFSKmsScreen(device, output)
- , m_gbm_surface(Q_NULLPTR)
- , m_gbm_bo_current(Q_NULLPTR)
- , m_gbm_bo_next(Q_NULLPTR)
- , m_cursor(Q_NULLPTR)
+QEglFSKmsGbmScreen::QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output, bool headless)
+ : QEglFSKmsScreen(device, output, headless)
+ , m_gbm_surface(nullptr)
+ , m_gbm_bo_current(nullptr)
+ , m_gbm_bo_next(nullptr)
+ , m_flipPending(false)
+ , m_cursor(nullptr)
+ , m_cloneSource(nullptr)
{
}
@@ -114,6 +131,8 @@ QEglFSKmsGbmScreen::~QEglFSKmsGbmScreen()
QPlatformCursor *QEglFSKmsGbmScreen::cursor() const
{
QKmsScreenConfig *config = device()->screenConfig();
+ if (config->headless())
+ return nullptr;
if (config->hwCursor()) {
if (!config->separateScreens())
return static_cast<QEglFSKmsGbmDevice *>(device())->globalCursor();
@@ -132,47 +151,112 @@ QPlatformCursor *QEglFSKmsGbmScreen::cursor() const
gbm_surface *QEglFSKmsGbmScreen::createSurface()
{
if (!m_gbm_surface) {
- qCDebug(qLcEglfsKmsDebug) << "Creating window for screen" << name();
+ uint32_t gbmFormat = drmFormatToGbmFormat(m_output.drm_format);
+ qCDebug(qLcEglfsKmsDebug, "Creating gbm_surface for screen %s with format 0x%x", qPrintable(name()), gbmFormat);
m_gbm_surface = gbm_surface_create(static_cast<QEglFSKmsGbmDevice *>(device())->gbmDevice(),
rawGeometry().width(),
rawGeometry().height(),
- GBM_FORMAT_XRGB8888,
+ gbmFormat,
GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
}
- return m_gbm_surface;
+ return m_gbm_surface; // not owned, gets destroyed in QEglFSKmsGbmIntegration::destroyNativeWindow() via QEglFSKmsGbmWindow::invalidateSurface()
}
-void QEglFSKmsGbmScreen::destroySurface()
+void QEglFSKmsGbmScreen::resetSurface()
{
- if (m_gbm_bo_current) {
- gbm_bo_destroy(m_gbm_bo_current);
- m_gbm_bo_current = Q_NULLPTR;
- }
+ m_gbm_surface = nullptr;
+}
- if (m_gbm_bo_next) {
- gbm_bo_destroy(m_gbm_bo_next);
- m_gbm_bo_next = Q_NULLPTR;
+void QEglFSKmsGbmScreen::initCloning(QPlatformScreen *screenThisScreenClones,
+ const QVector<QPlatformScreen *> &screensCloningThisScreen)
+{
+ // clone destinations need to know the clone source
+ const bool clonesAnother = screenThisScreenClones != nullptr;
+ if (clonesAnother && !screensCloningThisScreen.isEmpty()) {
+ qWarning("QEglFSKmsGbmScreen %s cannot be clone source and destination at the same time", qPrintable(name()));
+ return;
}
+ if (clonesAnother)
+ m_cloneSource = static_cast<QEglFSKmsGbmScreen *>(screenThisScreenClones);
+
+ // clone sources need to know their additional destinations
+ for (QPlatformScreen *s : screensCloningThisScreen) {
+ CloneDestination d;
+ d.screen = static_cast<QEglFSKmsGbmScreen *>(s);
+ m_cloneDests.append(d);
+ }
+}
+
+void QEglFSKmsGbmScreen::ensureModeSet(uint32_t fb)
+{
+ QKmsOutput &op(output());
+ const int fd = device()->fd();
+
+ if (!op.mode_set) {
+ op.mode_set = true;
+
+ bool doModeSet = true;
+ drmModeCrtcPtr currentMode = drmModeGetCrtc(fd, op.crtc_id);
+ const bool alreadySet = currentMode && !memcmp(&currentMode->mode, &op.modes[op.mode], sizeof(drmModeModeInfo));
+ if (currentMode)
+ drmModeFreeCrtc(currentMode);
+ if (alreadySet) {
+ static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE");
+ if (!alwaysDoSet) {
+ qCDebug(qLcEglfsKmsDebug, "Mode already set, skipping modesetting for screen %s", qPrintable(name()));
+ doModeSet = false;
+ }
+ }
- if (m_gbm_surface) {
- gbm_surface_destroy(m_gbm_surface);
- m_gbm_surface = Q_NULLPTR;
+ if (doModeSet) {
+ qCDebug(qLcEglfsKmsDebug, "Setting mode for screen %s", qPrintable(name()));
+ int ret = drmModeSetCrtc(fd,
+ op.crtc_id,
+ fb,
+ 0, 0,
+ &op.connector_id, 1,
+ &op.modes[op.mode]);
+
+ if (ret == 0)
+ setPowerState(PowerStateOn);
+ else
+ qErrnoWarning(errno, "Could not set DRM mode for screen %s", qPrintable(name()));
+ }
}
}
void QEglFSKmsGbmScreen::waitForFlip()
{
+ if (m_headless || m_cloneSource)
+ return;
+
// 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();
+ while (m_gbm_bo_next) {
+ drmEventContext drmEvent;
+ memset(&drmEvent, 0, sizeof(drmEvent));
+ drmEvent.version = 2;
+ drmEvent.vblank_handler = nullptr;
+ drmEvent.page_flip_handler = pageFlipHandler;
+ drmHandleEvent(device()->fd(), &drmEvent);
+ }
}
void QEglFSKmsGbmScreen::flip()
{
+ // For headless screen just return silently. It is not necessarily an error
+ // to end up here, so show no warnings.
+ if (m_headless)
+ return;
+
+ if (m_cloneSource) {
+ qWarning("Screen %s clones another screen. swapBuffers() not allowed.", qPrintable(name()));
+ return;
+ }
+
if (!m_gbm_surface) {
qWarning("Cannot sync before platform init!");
return;
@@ -185,60 +269,92 @@ void QEglFSKmsGbmScreen::flip()
}
FrameBuffer *fb = framebufferForBufferObject(m_gbm_bo_next);
+ ensureModeSet(fb->fb);
QKmsOutput &op(output());
const int fd = device()->fd();
- const uint32_t w = op.modes[op.mode].hdisplay;
- const uint32_t h = op.modes[op.mode].vdisplay;
-
- if (!op.mode_set) {
- int ret = drmModeSetCrtc(fd,
- op.crtc_id,
- fb->fb,
- 0, 0,
- &op.connector_id, 1,
- &op.modes[op.mode]);
-
- if (ret == -1) {
- qErrnoWarning(errno, "Could not set DRM mode!");
- } else {
- op.mode_set = true;
- setPowerState(PowerStateOn);
-
- if (!op.plane_set) {
- op.plane_set = true;
- if (op.wants_plane) {
- int ret = drmModeSetPlane(fd, op.plane_id, op.crtc_id,
- uint32_t(-1), 0,
- 0, 0, w, h,
- 0 << 16, 0 << 16, w << 16, h << 16);
- if (ret == -1)
- qErrnoWarning(errno, "drmModeSetPlane failed");
- }
- }
- }
- }
-
+ m_flipPending = true;
int ret = drmModePageFlip(fd,
op.crtc_id,
fb->fb,
DRM_MODE_PAGE_FLIP_EVENT,
this);
if (ret) {
- qErrnoWarning("Could not queue DRM page flip!");
+ qErrnoWarning("Could not queue DRM page flip on screen %s", qPrintable(name()));
+ m_flipPending = false;
gbm_surface_release_buffer(m_gbm_surface, m_gbm_bo_next);
- m_gbm_bo_next = Q_NULLPTR;
+ m_gbm_bo_next = nullptr;
+ return;
+ }
+
+ for (CloneDestination &d : m_cloneDests) {
+ if (d.screen != this) {
+ d.screen->ensureModeSet(fb->fb);
+ d.cloneFlipPending = true;
+ int ret = drmModePageFlip(fd,
+ d.screen->output().crtc_id,
+ fb->fb,
+ DRM_MODE_PAGE_FLIP_EVENT,
+ d.screen);
+ if (ret) {
+ qErrnoWarning("Could not queue DRM page flip for clone screen %s", qPrintable(name()));
+ d.cloneFlipPending = false;
+ }
+ }
}
}
+void QEglFSKmsGbmScreen::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);
+
+ QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(user_data);
+ screen->flipFinished();
+}
+
void QEglFSKmsGbmScreen::flipFinished()
{
+ if (m_cloneSource) {
+ m_cloneSource->cloneDestFlipFinished(this);
+ return;
+ }
+
+ m_flipPending = false;
+ updateFlipStatus();
+}
+
+void QEglFSKmsGbmScreen::cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen)
+{
+ for (CloneDestination &d : m_cloneDests) {
+ if (d.screen == cloneDestScreen) {
+ d.cloneFlipPending = false;
+ break;
+ }
+ }
+ updateFlipStatus();
+}
+
+void QEglFSKmsGbmScreen::updateFlipStatus()
+{
+ Q_ASSERT(!m_cloneSource);
+
+ if (m_flipPending)
+ return;
+
+ for (const CloneDestination &d : m_cloneDests) {
+ if (d.cloneFlipPending)
+ return;
+ }
+
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;
+ m_gbm_bo_next = nullptr;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
index 341cc95bbe..f5a2122723 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmscreen.h
@@ -54,34 +54,54 @@ class QEglFSKmsGbmCursor;
class QEglFSKmsGbmScreen : public QEglFSKmsScreen
{
public:
- QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output);
+ QEglFSKmsGbmScreen(QKmsDevice *device, const QKmsOutput &output, bool headless);
~QEglFSKmsGbmScreen();
QPlatformCursor *cursor() const override;
- gbm_surface *surface() const { return m_gbm_surface; }
gbm_surface *createSurface();
- void destroySurface();
+ void resetSurface();
+
+ void initCloning(QPlatformScreen *screenThisScreenClones,
+ const QVector<QPlatformScreen *> &screensCloningThisScreen);
void waitForFlip() override;
- void flip() override;
- void flipFinished() override;
+
+ void flip();
private:
+ void flipFinished();
+ void ensureModeSet(uint32_t fb);
+ void cloneDestFlipFinished(QEglFSKmsGbmScreen *cloneDestScreen);
+ void updateFlipStatus();
+
+ static void pageFlipHandler(int fd,
+ unsigned int sequence,
+ unsigned int tv_sec,
+ unsigned int tv_usec,
+ void *user_data);
+
gbm_surface *m_gbm_surface;
gbm_bo *m_gbm_bo_current;
gbm_bo *m_gbm_bo_next;
+ bool m_flipPending;
QScopedPointer<QEglFSKmsGbmCursor> m_cursor;
struct FrameBuffer {
- FrameBuffer() : fb(0) {}
- uint32_t fb;
+ uint32_t fb = 0;
};
static void bufferDestroyedHandler(gbm_bo *bo, void *data);
FrameBuffer *framebufferForBufferObject(gbm_bo *bo);
+ QEglFSKmsGbmScreen *m_cloneSource;
+ struct CloneDestination {
+ QEglFSKmsGbmScreen *screen = nullptr;
+ bool cloneFlipPending = false;
+ };
+ QVector<CloneDestination> m_cloneDests;
+
static QMutex m_waitForFlipMutex;
};
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp
new file mode 100644
index 0000000000..110a592dec
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** 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 "qeglfskmsgbmwindow.h"
+#include "qeglfskmsgbmintegration.h"
+#include "qeglfskmsgbmscreen.h"
+
+#include <QtEglSupport/private/qeglconvenience_p.h>
+
+QT_BEGIN_NAMESPACE
+
+void QEglFSKmsGbmWindow::resetSurface()
+{
+ QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen());
+ EGLDisplay display = gbmScreen->display();
+ QSurfaceFormat platformFormat = m_integration->surfaceFormatFor(window()->requestedFormat());
+ m_config = QEglFSDeviceIntegration::chooseConfig(display, platformFormat);
+ m_format = q_glFormatFromConfig(display, m_config, platformFormat);
+ // One fullscreen window per screen -> the native window is simply the gbm_surface the screen created.
+ m_window = reinterpret_cast<EGLNativeWindowType>(gbmScreen->createSurface());
+
+ PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = nullptr;
+ const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (extensions && (strstr(extensions, "EGL_KHR_platform_gbm") || strstr(extensions, "EGL_MESA_platform_gbm"))) {
+ createPlatformWindowSurface = reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(
+ eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
+ }
+
+ if (createPlatformWindowSurface) {
+ m_surface = createPlatformWindowSurface(display, m_config, reinterpret_cast<void *>(m_window), nullptr);
+ } else {
+ qCDebug(qLcEglfsKmsDebug, "No eglCreatePlatformWindowSurface for GBM, falling back to eglCreateWindowSurface");
+ m_surface = eglCreateWindowSurface(display, m_config, m_window, nullptr);
+ }
+}
+
+void QEglFSKmsGbmWindow::invalidateSurface()
+{
+ QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen());
+ QEglFSWindow::invalidateSurface();
+ gbmScreen->resetSurface();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h
new file mode 100644
index 0000000000..a19cf7e8bc
--- /dev/null
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** 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 QEGLFSKMSGBMWINDOW_H
+#define QEGLFSKMSGBMWINDOW_H
+
+#include "private/qeglfswindow_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEglFSKmsGbmIntegration;
+
+class QEglFSKmsGbmWindow : public QEglFSWindow
+{
+public:
+ QEglFSKmsGbmWindow(QWindow *w, const QEglFSKmsGbmIntegration *integration)
+ : QEglFSWindow(w),
+ m_integration(integration)
+ { }
+ void resetSurface() override;
+ void invalidateSurface() override;
+
+private:
+ const QEglFSKmsGbmIntegration *m_integration;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEGLFSKMSGBMWINDOW_H
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
index cca413ff2d..8c8e6260f1 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
@@ -58,7 +58,7 @@ bool QEglFSKmsEglDevice::open()
{
Q_ASSERT(fd() == -1);
- int fd = drmOpen(devicePath().toLocal8Bit().constData(), Q_NULLPTR);
+ int fd = drmOpen(devicePath().toLocal8Bit().constData(), nullptr);
if (Q_UNLIKELY(fd < 0))
qFatal("Could not open DRM (NV) device");
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
index 3af21d768e..a67457a6a5 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -51,7 +51,7 @@ QT_BEGIN_NAMESPACE
QEglFSKmsEglDeviceIntegration::QEglFSKmsEglDeviceIntegration()
: m_egl_device(EGL_NO_DEVICE_EXT)
- , m_funcs(Q_NULLPTR)
+ , m_funcs(nullptr)
{
qCDebug(qLcEglfsKmsDebug, "New DRM/KMS on EGLDevice integration created");
}
@@ -75,7 +75,7 @@ EGLDisplay QEglFSKmsEglDeviceIntegration::createDisplay(EGLNativeDisplayType nat
EGLDisplay display;
if (m_funcs->has_egl_platform_device) {
- display = m_funcs->get_platform_display(EGL_PLATFORM_DEVICE_EXT, nativeDisplay, Q_NULLPTR);
+ display = m_funcs->get_platform_display(EGL_PLATFORM_DEVICE_EXT, nativeDisplay, nullptr);
} else {
qWarning("EGL_EXT_platform_device not available, falling back to legacy path!");
display = eglGetDisplay(nativeDisplay);
@@ -162,7 +162,7 @@ void QEglFSKmsEglDeviceWindow::resetSurface()
qCDebug(qLcEglfsKmsDebug, "Could not query number of EGLStream FIFO frames");
}
- if (!m_integration->m_funcs->get_output_layers(display, Q_NULLPTR, Q_NULLPTR, 0, &count) || count == 0) {
+ if (!m_integration->m_funcs->get_output_layers(display, nullptr, nullptr, 0, &count) || count == 0) {
qWarning("No output layers found");
return;
}
@@ -172,7 +172,7 @@ void QEglFSKmsEglDeviceWindow::resetSurface()
QVector<EGLOutputLayerEXT> layers;
layers.resize(count);
EGLint actualCount;
- if (!m_integration->m_funcs->get_output_layers(display, Q_NULLPTR, layers.data(), count, &actualCount)) {
+ if (!m_integration->m_funcs->get_output_layers(display, nullptr, layers.data(), count, &actualCount)) {
qWarning("Failed to get layers");
return;
}
@@ -180,7 +180,7 @@ void QEglFSKmsEglDeviceWindow::resetSurface()
QEglFSKmsEglDeviceScreen *cur_screen = static_cast<QEglFSKmsEglDeviceScreen *>(screen());
Q_ASSERT(cur_screen);
QKmsOutput &output(cur_screen->output());
- const uint32_t wantedId = !output.wants_plane ? output.crtc_id : output.plane_id;
+ const uint32_t wantedId = !output.wants_forced_plane ? output.crtc_id : output.forced_plane_id;
qCDebug(qLcEglfsKmsDebug, "Searching for id: %d", wantedId);
EGLOutputLayerEXT layer = EGL_NO_OUTPUT_LAYER_EXT;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
index a27c89faab..531b73d1dc 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp
@@ -105,12 +105,12 @@ void QEglFSKmsEglDeviceScreen::waitForFlip()
qErrnoWarning(errno, "drmModeSetCrtc failed");
}
- if (!op.plane_set) {
- op.plane_set = true;
+ if (!op.forced_plane_set) {
+ op.forced_plane_set = true;
- if (op.wants_plane) {
- qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.plane_id);
- int ret = drmModeSetPlane(fd, op.plane_id, op.crtc_id, uint32_t(-1), 0,
+ if (op.wants_forced_plane) {
+ qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.forced_plane_id);
+ int ret = drmModeSetPlane(fd, op.forced_plane_id, op.crtc_id, uint32_t(-1), 0,
0, 0, w, h,
0 << 16, 0 << 16, w << 16, h << 16);
if (ret == -1)
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
index c77151181e..975b1947bf 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.cpp
@@ -55,7 +55,7 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(qLcEglfsKmsDebug, "qt.qpa.eglfs.kms")
QEglFSKmsIntegration::QEglFSKmsIntegration()
- : m_device(Q_NULLPTR),
+ : m_device(nullptr),
m_screenConfig(new QKmsScreenConfig)
{
}
@@ -78,7 +78,7 @@ void QEglFSKmsIntegration::platformDestroy()
qCDebug(qLcEglfsKmsDebug, "platformDestroy: Closing DRM device");
m_device->close();
delete m_device;
- m_device = Q_NULLPTR;
+ m_device = nullptr;
}
EGLNativeDisplayType QEglFSKmsIntegration::platformDisplay() const
@@ -133,6 +133,14 @@ bool QEglFSKmsIntegration::supportsPBuffers() const
return m_screenConfig->supportsPBuffers();
}
+void *QEglFSKmsIntegration::nativeResourceForIntegration(const QByteArray &name)
+{
+ if (name == QByteArrayLiteral("dri_fd") && m_device)
+ return (void *) (qintptr) m_device->fd();
+
+ return nullptr;
+}
+
QKmsDevice *QEglFSKmsIntegration::device() const
{
return m_device;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
index 9955616919..26ba2fdaec 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsintegration.h
@@ -69,6 +69,7 @@ public:
bool hasCapability(QPlatformIntegration::Capability cap) const override;
void waitForVSync(QPlatformSurface *surface) const override;
bool supportsPBuffers() const override;
+ void *nativeResourceForIntegration(const QByteArray &name) override;
QKmsDevice *device() const;
QKmsScreenConfig *screenConfig() const;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
index 734f5cd611..5e45b42abe 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
+** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2017 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/
**
@@ -68,12 +68,13 @@ private:
QEglFSKmsScreen *m_screen;
};
-QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output)
+QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output, bool headless)
: QEglFSScreen(static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->display())
, m_device(device)
, m_output(output)
, m_powerState(PowerStateOn)
, m_interruptHandler(new QEglFSKmsInterruptHandler(this))
+ , m_headless(headless)
{
m_siblings << this; // gets overridden later
@@ -109,6 +110,9 @@ void QEglFSKmsScreen::setVirtualPosition(const QPoint &pos)
// geometry() calls rawGeometry() and may apply additional transforms.
QRect QEglFSKmsScreen::rawGeometry() const
{
+ if (m_headless)
+ return QRect(QPoint(0, 0), m_device->screenConfig()->headlessSize());
+
const int mode = m_output.mode;
return QRect(m_pos.x(), m_pos.y(),
m_output.modes[mode].hdisplay,
@@ -117,12 +121,30 @@ QRect QEglFSKmsScreen::rawGeometry() const
int QEglFSKmsScreen::depth() const
{
- return 32;
+ return format() == QImage::Format_RGB16 ? 16 : 32;
}
QImage::Format QEglFSKmsScreen::format() const
{
- return QImage::Format_RGB32;
+ // the result can be slightly incorrect, it won't matter in practice
+ switch (m_output.drm_format) {
+ case DRM_FORMAT_ARGB8888:
+ case DRM_FORMAT_ABGR8888:
+ return QImage::Format_ARGB32;
+ case DRM_FORMAT_RGB565:
+ case DRM_FORMAT_BGR565:
+ return QImage::Format_RGB16;
+ case DRM_FORMAT_XRGB2101010:
+ return QImage::Format_RGB30;
+ case DRM_FORMAT_XBGR2101010:
+ return QImage::Format_BGR30;
+ case DRM_FORMAT_ARGB2101010:
+ return QImage::Format_A2RGB30_Premultiplied;
+ case DRM_FORMAT_ABGR2101010:
+ return QImage::Format_A2BGR30_Premultiplied;
+ default:
+ return QImage::Format_RGB32;
+ }
}
QSizeF QEglFSKmsScreen::physicalSize() const
@@ -159,7 +181,7 @@ Qt::ScreenOrientation QEglFSKmsScreen::orientation() const
QString QEglFSKmsScreen::name() const
{
- return m_output.name;
+ return !m_headless ? m_output.name : QStringLiteral("qt_Headless");
}
QString QEglFSKmsScreen::manufacturer() const
@@ -177,22 +199,10 @@ QString QEglFSKmsScreen::serialNumber() const
return m_edid.serialNumber;
}
-void QEglFSKmsScreen::destroySurface()
-{
-}
-
void QEglFSKmsScreen::waitForFlip()
{
}
-void QEglFSKmsScreen::flip()
-{
-}
-
-void QEglFSKmsScreen::flipFinished()
-{
-}
-
void QEglFSKmsScreen::restoreMode()
{
m_output.restoreMode(m_device);
@@ -200,6 +210,9 @@ void QEglFSKmsScreen::restoreMode()
qreal QEglFSKmsScreen::refreshRate() const
{
+ if (m_headless)
+ return 60;
+
quint32 refresh = m_output.modes[m_output.mode].vrefresh;
return refresh > 0 ? refresh : 60;
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
index 4e09929189..7f395aacb7 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
@@ -56,7 +56,7 @@ class QEglFSKmsInterruptHandler;
class Q_EGLFS_EXPORT QEglFSKmsScreen : public QEglFSScreen
{
public:
- QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output);
+ QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output, bool headless = false);
~QEglFSKmsScreen();
void setVirtualPosition(const QPoint &pos);
@@ -89,11 +89,7 @@ public:
QKmsDevice *device() const { return m_device; }
- void destroySurface();
-
virtual void waitForFlip();
- virtual void flip();
- virtual void flipFinished();
QKmsOutput &output() { return m_output; }
void restoreMode();
@@ -115,6 +111,8 @@ protected:
PowerState m_powerState;
QEglFSKmsInterruptHandler *m_interruptHandler;
+
+ bool m_headless;
};
QT_END_NAMESPACE