Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qeglfskmsegldevicescreen.cpp
Go to the documentation of this file.
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
6
7#include <private/qeglfskmsintegration_p.h>
8
9#include <QGuiApplication>
10#include <QLoggingCategory>
11#include <errno.h>
12
13QT_BEGIN_NAMESPACE
14
15QEglFSKmsEglDeviceScreen::QEglFSKmsEglDeviceScreen(QEglFSKmsDevice *device, const QKmsOutput &output)
16 : QEglFSKmsScreen(device, output)
17 , m_default_fb_handle(uint32_t(-1))
18 , m_default_fb_id(uint32_t(-1))
19{
20 const int fd = device->fd();
21
22 struct drm_mode_create_dumb createRequest;
23 createRequest.width = output.size.width();
24 createRequest.height = output.size.height();
25 createRequest.bpp = 32;
26 createRequest.flags = 0;
27
28 qCDebug(qLcEglfsKmsDebug, "Creating dumb fb %dx%d", createRequest.width, createRequest.height);
29
30 int ret = drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &createRequest);
31 if (ret < 0)
32 qFatal("Unable to create dumb buffer.\n");
33
34 m_default_fb_handle = createRequest.handle;
35
36 uint32_t handles[4] = { 0, 0, 0, 0 };
37 uint32_t pitches[4] = { 0, 0, 0, 0 };
38 uint32_t offsets[4] = { 0, 0, 0, 0 };
39
40 handles[0] = createRequest.handle;
41 pitches[0] = createRequest.pitch;
42 offsets[0] = 0;
43
44 ret = drmModeAddFB2(fd, createRequest.width, createRequest.height, DRM_FORMAT_ARGB8888, handles,
45 pitches, offsets, &m_default_fb_id, 0);
46 if (ret)
47 qFatal("Unable to add fb\n");
48
49 qCDebug(qLcEglfsKmsDebug, "Added dumb fb %dx%d handle:%u pitch:%d id:%u", createRequest.width, createRequest.height,
50 createRequest.handle, createRequest.pitch, m_default_fb_id);
51}
52
54{
55 int ret;
56 const int fd = device()->fd();
57
58 if (m_default_fb_id != uint32_t(-1)) {
59 ret = drmModeRmFB(fd, m_default_fb_id);
60 if (ret)
61 qErrnoWarning("drmModeRmFB failed");
62 }
63
64 if (m_default_fb_handle != uint32_t(-1)) {
65 struct drm_mode_destroy_dumb destroyRequest;
66 destroyRequest.handle = m_default_fb_handle;
67
68 ret = drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroyRequest);
69 if (ret)
70 qErrnoWarning("DRM_IOCTL_MODE_DESTROY_DUMB failed");
71 }
72
73 const int remainingScreenCount = qGuiApp->screens().size();
74 qCDebug(qLcEglfsKmsDebug, "Screen dtor. %p Remaining screens: %d", this, remainingScreenCount);
75 if (!remainingScreenCount && !device()->screenConfig()->separateScreens())
76 static_cast<QEglFSKmsEglDevice *>(device())->destroyGlobalCursor();
77}
78
79QPlatformCursor *QEglFSKmsEglDeviceScreen::cursor() const
80{
81 // The base class creates a cursor via integration->createCursor()
82 // in its ctor. With separateScreens just use that. Otherwise
83 // there's a virtual desktop and the device has a global cursor
84 // and the base class has no dedicated cursor at all.
85 // config->hwCursor() is ignored for now, just use the standard OpenGL cursor.
86 return device()->screenConfig()->separateScreens()
87 ? QEglFSScreen::cursor()
88 : static_cast<QEglFSKmsEglDevice *>(device())->globalCursor();
89}
90
92{
93 QKmsOutput &op(output());
94 const int fd = device()->fd();
95 const uint32_t w = op.modes[op.mode].hdisplay;
96 const uint32_t h = op.modes[op.mode].vdisplay;
97
98 if (!op.mode_set) {
99 op.mode_set = true;
100
101 drmModeCrtcPtr currentMode = drmModeGetCrtc(fd, op.crtc_id);
102 const bool alreadySet = currentMode && currentMode->width == w && currentMode->height == h;
103 if (currentMode)
104 drmModeFreeCrtc(currentMode);
105 if (alreadySet) {
106 // Maybe detecting the DPMS mode could help here, but there are no properties
107 // exposed on the connector apparently. So rely on an env var for now.
108 // Note that typically, we need to set crtc with the default fb even if the
109 // mode did not change, unless QT_QPA_EGLFS_ALWAYS_SET_MODE is explicitly specified.
110 static bool envVarSet = false;
111 static bool alwaysDoSet = qEnvironmentVariableIntValue("QT_QPA_EGLFS_ALWAYS_SET_MODE", &envVarSet);
112 if (envVarSet && !alwaysDoSet) {
113 qCDebug(qLcEglfsKmsDebug, "Mode already set");
114 return;
115 }
116 }
117
118 qCDebug(qLcEglfsKmsDebug, "Setting mode");
119 int ret = drmModeSetCrtc(fd, op.crtc_id,
120 m_default_fb_id, 0, 0,
121 &op.connector_id, 1,
122 &op.modes[op.mode]);
123 if (ret)
124 qErrnoWarning(errno, "drmModeSetCrtc failed");
125 }
126
127 if (!op.forced_plane_set) {
128 op.forced_plane_set = true;
129
130 if (op.wants_forced_plane) {
131 qCDebug(qLcEglfsKmsDebug, "Setting plane %u", op.forced_plane_id);
132 int ret = drmModeSetPlane(fd, op.forced_plane_id, op.crtc_id, m_default_fb_id, 0,
133 0, 0, w, h,
134 0 << 16, 0 << 16, op.size.width() << 16, op.size.height() << 16);
135 if (ret == -1)
136 qErrnoWarning(errno, "drmModeSetPlane failed");
137 }
138 }
139}
140
141QT_END_NAMESPACE
QPlatformCursor * cursor() const override
Reimplement this function in subclass to return the cursor of the screen.