1// Copyright (C) 2016 Pelagicore AG
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qeglfskmsegldevicescreen.h"
5#include "qeglfskmsegldevice.h"
6#include <QGuiApplication>
7#include <QLoggingCategory>
8#include <errno.h>
9
10QT_BEGIN_NAMESPACE
11
12Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
13
14QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsDevice *device, const QKmsOutput &output)
15 : QEglFSKmsScreen(device, output)
16{
17}
18
19QEglFSKmsEglDeviceScreen::~QEglFSKmsEglDeviceScreen()
20{
21 const int remainingScreenCount = qGuiApp->screens().size();
22 qCDebug(qLcEglfsKmsDebug, "Screen dtor. Remaining screens: %d", remainingScreenCount);
23 if (!remainingScreenCount && !device()->screenConfig()->separateScreens())
24 static_cast<QEglFSKmsEglDevice *>(device())->destroyGlobalCursor();
25}
26
27QPlatformCursor *QEglFSKmsEglDeviceScreen::cursor() const
28{
29 // The base class creates a cursor via integration->createCursor()
30 // in its ctor. With separateScreens just use that. Otherwise
31 // there's a virtual desktop and the device has a global cursor
32 // and the base class has no dedicated cursor at all.
33 // config->hwCursor() is ignored for now, just use the standard OpenGL cursor.
34 return device()->screenConfig()->separateScreens()
35 ? QEglFSScreen::cursor()
36 : static_cast<QEglFSKmsEglDevice *>(device())->globalCursor();
37}
38
39void QEglFSKmsEglDeviceScreen::waitForFlip()
40{
41 QKmsOutput &op(output());
42 const int fd = device()->fd();
43 const uint32_t w = op.modes[op.mode].hdisplay;
44 const uint32_t h = op.modes[op.mode].vdisplay;
45
46 if (!op.mode_set) {
47 op.mode_set = true;
48
49 drmModeCrtcPtr currentMode = drmModeGetCrtc(fd, crtcId: op.crtc_id);
50 const bool alreadySet = currentMode && currentMode->width == w && currentMode->height == h;
51 if (currentMode)
52 drmModeFreeCrtc(ptr: currentMode);
53 if (alreadySet) {
54 // Maybe detecting the DPMS mode could help here, but there are no properties
55 // exposed on the connector apparently. So rely on an env var for now.
56 static bool alwaysDoSet = qEnvironmentVariableIntValue(varName: "QT_QPA_EGLFS_ALWAYS_SET_MODE");
57 if (!alwaysDoSet) {
58 qCDebug(qLcEglfsKmsDebug, "Mode already set");
59 return;
60 }
61 }
62
63 qCDebug(qLcEglfsKmsDebug, "Setting mode");
64 int ret = drmModeSetCrtc(fd, crtcId: op.crtc_id,
65 bufferId: uint32_t(-1), x: 0, y: 0,
66 connectors: &op.connector_id, count: 1,
67 mode: &op.modes[op.mode]);
68 if (ret)
69 qErrnoWarning(errno, msg: "drmModeSetCrtc failed");
70 }
71
72 if (!op.forced_plane_set) {
73 op.forced_plane_set = true;
74
75 if (op.wants_forced_plane) {
76 qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.forced_plane_id);
77 int ret = drmModeSetPlane(fd, plane_id: op.forced_plane_id, crtc_id: op.crtc_id, fb_id: uint32_t(-1), flags: 0,
78 crtc_x: 0, crtc_y: 0, crtc_w: w, crtc_h: h,
79 src_x: 0 << 16, src_y: 0 << 16, src_w: op.size.width() << 16, src_h: op.size.height() << 16);
80 if (ret == -1)
81 qErrnoWarning(errno, msg: "drmModeSetPlane failed");
82 }
83 }
84}
85
86QT_END_NAMESPACE
87

source code of qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevicescreen.cpp