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 | |
10 | QT_BEGIN_NAMESPACE |
11 | |
12 | Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) |
13 | |
14 | QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsDevice *device, const QKmsOutput &output) |
15 | : QEglFSKmsScreen(device, output) |
16 | { |
17 | } |
18 | |
19 | QEglFSKmsEglDeviceScreen::~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 | |
27 | QPlatformCursor *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 | |
39 | void 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 | |
86 | QT_END_NAMESPACE |
87 | |