1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Copyright (C) 2016 Pelagicore AG
5** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
6** Contact: https://www.qt.io/licensing/
7**
8** This file is part of the plugins of the Qt Toolkit.
9**
10** $QT_BEGIN_LICENSE:LGPL$
11** Commercial License Usage
12** Licensees holding valid commercial Qt licenses may use this file in
13** accordance with the commercial license agreement provided with the
14** Software or, alternatively, in accordance with the terms contained in
15** a written agreement between you and The Qt Company. For licensing terms
16** and conditions see https://www.qt.io/terms-conditions. For further
17** information use the contact form at https://www.qt.io/contact-us.
18**
19** GNU Lesser General Public License Usage
20** Alternatively, this file may be used under the terms of the GNU Lesser
21** General Public License version 3 as published by the Free Software
22** Foundation and appearing in the file LICENSE.LGPL3 included in the
23** packaging of this file. Please review the following information to
24** ensure the GNU Lesser General Public License version 3 requirements
25** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
26**
27** GNU General Public License Usage
28** Alternatively, this file may be used under the terms of the GNU
29** General Public License version 2.0 or (at your option) the GNU General
30** Public license version 3 or any later version approved by the KDE Free
31** Qt Foundation. The licenses are as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
33** included in the packaging of this file. Please review the following
34** information to ensure the GNU General Public License requirements will
35** be met: https://www.gnu.org/licenses/gpl-2.0.html and
36** https://www.gnu.org/licenses/gpl-3.0.html.
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#ifndef QKMSDEVICE_P_H
43#define QKMSDEVICE_P_H
44
45//
46// W A R N I N G
47// -------------
48//
49// This file is not part of the Qt API. It exists purely as an
50// implementation detail. This header file may change from version to
51// version without notice, or even be removed.
52//
53// We mean it.
54//
55
56#include <QtGui/private/qtguiglobal_p.h>
57#include <qpa/qplatformscreen.h>
58#include <QtCore/QMap>
59#include <QtCore/QVariant>
60#include <QtCore/QThreadStorage>
61
62#include <xf86drm.h>
63#include <xf86drmMode.h>
64#include <drm_fourcc.h>
65
66#include <functional>
67
68// In less fortunate cases one may need to build on a system with dev headers
69// from the dark ages. Let's pull a GL and define the missing stuff outselves.
70
71#ifndef DRM_PLANE_TYPE_OVERLAY
72#define DRM_PLANE_TYPE_OVERLAY 0
73#endif
74#ifndef DRM_PLANE_TYPE_PRIMARY
75#define DRM_PLANE_TYPE_PRIMARY 1
76#endif
77#ifndef DRM_PLANE_TYPE_CURSOR
78#define DRM_PLANE_TYPE_CURSOR 2
79#endif
80
81#ifndef DRM_CLIENT_CAP_UNIVERSAL_PLANES
82#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
83#endif
84#ifndef DRM_CLIENT_CAP_ATOMIC
85#define DRM_CLIENT_CAP_ATOMIC 3
86#endif
87
88#ifndef DRM_MODE_PROP_EXTENDED_TYPE
89#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0
90#endif
91#ifndef DRM_MODE_PROP_TYPE
92#define DRM_MODE_PROP_TYPE(n) ((n) << 6)
93#endif
94#ifndef DRM_MODE_PROP_OBJECT
95#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1)
96#endif
97#ifndef DRM_MODE_PROP_SIGNED_RANGE
98#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2)
99#endif
100
101QT_BEGIN_NAMESPACE
102
103class QKmsDevice;
104
105class QKmsScreenConfig
106{
107public:
108 enum VirtualDesktopLayout {
109 VirtualDesktopLayoutHorizontal,
110 VirtualDesktopLayoutVertical
111 };
112
113 QKmsScreenConfig();
114
115 QString devicePath() const { return m_devicePath; }
116
117 bool headless() const { return m_headless; }
118 QSize headlessSize() const { return m_headlessSize; }
119 bool hwCursor() const { return m_hwCursor; }
120 bool separateScreens() const { return m_separateScreens; }
121 bool supportsPBuffers() const { return m_pbuffers; }
122 VirtualDesktopLayout virtualDesktopLayout() const { return m_virtualDesktopLayout; }
123
124 QMap<QString, QVariantMap> outputSettings() const { return m_outputSettings; }
125
126private:
127 void loadConfig();
128
129 QString m_devicePath;
130 bool m_headless;
131 QSize m_headlessSize;
132 bool m_hwCursor;
133 bool m_separateScreens;
134 bool m_pbuffers;
135 VirtualDesktopLayout m_virtualDesktopLayout;
136 QMap<QString, QVariantMap> m_outputSettings;
137};
138
139// NB! QKmsPlane does not store the current state and offers no functions to
140// change object properties. Any such functionality belongs to subclasses since
141// in some cases atomic operations will be desired where a mere
142// drmModeObjectSetProperty would not be acceptable.
143struct QKmsPlane
144{
145 enum Type {
146 OverlayPlane = DRM_PLANE_TYPE_OVERLAY,
147 PrimaryPlane = DRM_PLANE_TYPE_PRIMARY,
148 CursorPlane = DRM_PLANE_TYPE_CURSOR
149 };
150
151 enum Rotation {
152 Rotation0 = 1 << 0,
153 Rotation90 = 1 << 1,
154 Rotation180 = 1 << 2,
155 Rotation270 = 1 << 3,
156 RotationReflectX = 1 << 4,
157 RotationReflectY = 1 << 5
158 };
159 Q_DECLARE_FLAGS(Rotations, Rotation)
160
161 uint32_t id = 0;
162 Type type = OverlayPlane;
163
164 int possibleCrtcs = 0;
165
166 QVector<uint32_t> supportedFormats;
167
168 Rotations initialRotation = Rotation0;
169 Rotations availableRotations = Rotation0;
170 uint32_t rotationPropertyId = 0;
171 uint32_t crtcPropertyId = 0;
172 uint32_t framebufferPropertyId = 0;
173 uint32_t srcXPropertyId = 0;
174 uint32_t srcYPropertyId = 0;
175 uint32_t crtcXPropertyId = 0;
176 uint32_t crtcYPropertyId = 0;
177 uint32_t srcwidthPropertyId = 0;
178 uint32_t srcheightPropertyId = 0;
179 uint32_t crtcwidthPropertyId = 0;
180 uint32_t crtcheightPropertyId = 0;
181 uint32_t zposPropertyId = 0;
182 uint32_t blendOpPropertyId = 0;
183
184 uint32_t activeCrtcId = 0;
185};
186
187Q_DECLARE_OPERATORS_FOR_FLAGS(QKmsPlane::Rotations)
188
189struct QKmsOutput
190{
191 QString name;
192 uint32_t connector_id = 0;
193 uint32_t crtc_index = 0;
194 uint32_t crtc_id = 0;
195 QSizeF physical_size;
196 int preferred_mode = -1; // index of preferred mode in list below
197 int mode = -1; // index of selected mode in list below
198 bool mode_set = false;
199 drmModeCrtcPtr saved_crtc = nullptr;
200 QList<drmModeModeInfo> modes;
201 int subpixel = DRM_MODE_SUBPIXEL_UNKNOWN;
202 drmModePropertyPtr dpms_prop = nullptr;
203 drmModePropertyBlobPtr edid_blob = nullptr;
204 bool wants_forced_plane = false;
205 uint32_t forced_plane_id = 0;
206 bool forced_plane_set = false;
207 uint32_t drm_format = DRM_FORMAT_XRGB8888;
208 bool drm_format_requested_by_user = false;
209 QString clone_source;
210 QVector<QKmsPlane> available_planes;
211 struct QKmsPlane *eglfs_plane = nullptr;
212 QSize size;
213 uint32_t crtcIdPropertyId = 0;
214 uint32_t modeIdPropertyId = 0;
215 uint32_t activePropertyId = 0;
216
217 uint32_t mode_blob_id = 0;
218
219 void restoreMode(QKmsDevice *device);
220 void cleanup(QKmsDevice *device);
221 QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const;
222 void setPowerState(QKmsDevice *device, QPlatformScreen::PowerState state);
223};
224
225class QKmsDevice
226{
227public:
228 struct ScreenInfo {
229 int virtualIndex = 0;
230 QPoint virtualPos;
231 bool isPrimary = false;
232 QKmsOutput output;
233 };
234
235 QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path = QString());
236 virtual ~QKmsDevice();
237
238 virtual bool open() = 0;
239 virtual void close() = 0;
240 virtual void *nativeDisplay() const = 0;
241
242 bool hasAtomicSupport();
243
244#if QT_CONFIG(drm_atomic)
245 drmModeAtomicReq *threadLocalAtomicRequest();
246 bool threadLocalAtomicCommit(void *user_data);
247 void threadLocalAtomicReset();
248#endif
249 void createScreens();
250
251 int fd() const;
252 QString devicePath() const;
253
254 QKmsScreenConfig *screenConfig() const;
255
256protected:
257 virtual QPlatformScreen *createScreen(const QKmsOutput &output) = 0;
258 virtual QPlatformScreen *createHeadlessScreen();
259 virtual void registerScreenCloning(QPlatformScreen *screen,
260 QPlatformScreen *screenThisScreenClones,
261 const QVector<QPlatformScreen *> &screensCloningThisScreen);
262 virtual void registerScreen(QPlatformScreen *screen,
263 bool isPrimary,
264 const QPoint &virtualPos,
265 const QList<QPlatformScreen *> &virtualSiblings) = 0;
266
267 void setFd(int fd);
268 int crtcForConnector(drmModeResPtr resources, drmModeConnectorPtr connector);
269 QPlatformScreen *createScreenForConnector(drmModeResPtr resources,
270 drmModeConnectorPtr connector,
271 ScreenInfo *vinfo);
272 drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
273 drmModePropertyBlobPtr connectorPropertyBlob(drmModeConnectorPtr connector, const QByteArray &name);
274 typedef std::function<void(drmModePropertyPtr, quint64)> PropCallback;
275 void enumerateProperties(drmModeObjectPropertiesPtr objProps, PropCallback callback);
276 void discoverPlanes();
277 void parseConnectorProperties(uint32_t connectorId, QKmsOutput *output);
278 void parseCrtcProperties(uint32_t crtcId, QKmsOutput *output);
279
280 QKmsScreenConfig *m_screenConfig;
281 QString m_path;
282 int m_dri_fd;
283
284 bool m_has_atomic_support;
285
286#if QT_CONFIG(drm_atomic)
287 struct AtomicReqs {
288 drmModeAtomicReq *request = nullptr;
289 drmModeAtomicReq *previous_request = nullptr;
290 };
291 QThreadStorage<AtomicReqs> m_atomicReqs;
292#endif
293 quint32 m_crtc_allocator;
294
295 QVector<QKmsPlane> m_planes;
296
297private:
298 Q_DISABLE_COPY(QKmsDevice)
299};
300
301QT_END_NAMESPACE
302
303#endif
304

source code of qtbase/src/platformsupport/kmsconvenience/qkmsdevice_p.h