1/****************************************************************************
2**
3** Copyright (C) 2017 The Qt Company Ltd.
4** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
5** Copyright (C) 2016 Pelagicore AG
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#include "qeglfskmsscreen.h"
43#include "qeglfskmsdevice.h"
44#include "qeglfsintegration_p.h"
45
46#include <QtCore/QLoggingCategory>
47
48#include <QtGui/private/qguiapplication_p.h>
49#include <QtFbSupport/private/qfbvthandler_p.h>
50
51QT_BEGIN_NAMESPACE
52
53Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug)
54
55class QEglFSKmsInterruptHandler : public QObject
56{
57public:
58 QEglFSKmsInterruptHandler(QEglFSKmsScreen *screen) : m_screen(screen) {
59 m_vtHandler = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->vtHandler();
60 connect(sender: m_vtHandler, signal: &QFbVtHandler::interrupted, receiver: this, slot: &QEglFSKmsInterruptHandler::restoreVideoMode);
61 connect(sender: m_vtHandler, signal: &QFbVtHandler::aboutToSuspend, receiver: this, slot: &QEglFSKmsInterruptHandler::restoreVideoMode);
62 }
63
64public slots:
65 void restoreVideoMode() { m_screen->restoreMode(); }
66
67private:
68 QFbVtHandler *m_vtHandler;
69 QEglFSKmsScreen *m_screen;
70};
71
72QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsDevice *device, const QKmsOutput &output, bool headless)
73 : QEglFSScreen(static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->display())
74 , m_device(device)
75 , m_output(output)
76 , m_cursorOutOfRange(false)
77 , m_powerState(PowerStateOn)
78 , m_interruptHandler(new QEglFSKmsInterruptHandler(this))
79 , m_headless(headless)
80{
81 m_siblings << this; // gets overridden later
82
83 if (m_output.edid_blob) {
84 QByteArray edid(reinterpret_cast<const char *>(m_output.edid_blob->data), m_output.edid_blob->length);
85 if (m_edid.parse(blob: edid))
86 qCDebug(qLcEglfsKmsDebug, "EDID data for output \"%s\": identifier '%s', manufacturer '%s', model '%s', serial '%s', physical size: %.2fx%.2f",
87 name().toLatin1().constData(),
88 m_edid.identifier.toLatin1().constData(),
89 m_edid.manufacturer.toLatin1().constData(),
90 m_edid.model.toLatin1().constData(),
91 m_edid.serialNumber.toLatin1().constData(),
92 m_edid.physicalSize.width(), m_edid.physicalSize.height());
93 else
94 qCDebug(qLcEglfsKmsDebug) << "Failed to parse EDID data for output" << name(); // keep this debug, not warning
95 } else {
96 qCDebug(qLcEglfsKmsDebug) << "No EDID data for output" << name();
97 }
98}
99
100QEglFSKmsScreen::~QEglFSKmsScreen()
101{
102 m_output.cleanup(device: m_device);
103 delete m_interruptHandler;
104}
105
106void QEglFSKmsScreen::setVirtualPosition(const QPoint &pos)
107{
108 m_pos = pos;
109}
110
111// Reimplement rawGeometry(), not geometry(). The base class implementation of
112// geometry() calls rawGeometry() and may apply additional transforms.
113QRect QEglFSKmsScreen::rawGeometry() const
114{
115 if (m_headless)
116 return QRect(QPoint(0, 0), m_device->screenConfig()->headlessSize());
117
118 return QRect(m_pos.x(), m_pos.y(),
119 m_output.size.width(),
120 m_output.size.height());
121}
122
123int QEglFSKmsScreen::depth() const
124{
125 return format() == QImage::Format_RGB16 ? 16 : 32;
126}
127
128QImage::Format QEglFSKmsScreen::format() const
129{
130 // the result can be slightly incorrect, it won't matter in practice
131 switch (m_output.drm_format) {
132 case DRM_FORMAT_ARGB8888:
133 case DRM_FORMAT_ABGR8888:
134 return QImage::Format_ARGB32;
135 case DRM_FORMAT_RGB565:
136 case DRM_FORMAT_BGR565:
137 return QImage::Format_RGB16;
138 case DRM_FORMAT_XRGB2101010:
139 return QImage::Format_RGB30;
140 case DRM_FORMAT_XBGR2101010:
141 return QImage::Format_BGR30;
142 case DRM_FORMAT_ARGB2101010:
143 return QImage::Format_A2RGB30_Premultiplied;
144 case DRM_FORMAT_ABGR2101010:
145 return QImage::Format_A2BGR30_Premultiplied;
146 default:
147 return QImage::Format_RGB32;
148 }
149}
150
151QSizeF QEglFSKmsScreen::physicalSize() const
152{
153 if (!m_output.physical_size.isEmpty()) {
154 return m_output.physical_size;
155 } else {
156 const QSize s = geometry().size();
157 return QSizeF(0.254 * s.width(), 0.254 * s.height());
158 }
159}
160
161QDpi QEglFSKmsScreen::logicalDpi() const
162{
163 const QSizeF ps = physicalSize();
164 const QSize s = geometry().size();
165
166 if (!ps.isEmpty() && !s.isEmpty())
167 return QDpi(25.4 * s.width() / ps.width(),
168 25.4 * s.height() / ps.height());
169 else
170 return QDpi(100, 100);
171}
172
173Qt::ScreenOrientation QEglFSKmsScreen::nativeOrientation() const
174{
175 return Qt::PrimaryOrientation;
176}
177
178Qt::ScreenOrientation QEglFSKmsScreen::orientation() const
179{
180 return Qt::PrimaryOrientation;
181}
182
183QString QEglFSKmsScreen::name() const
184{
185 return !m_headless ? m_output.name : QStringLiteral("qt_Headless");
186}
187
188QString QEglFSKmsScreen::manufacturer() const
189{
190 return m_edid.manufacturer;
191}
192
193QString QEglFSKmsScreen::model() const
194{
195 return m_edid.model.isEmpty() ? m_edid.identifier : m_edid.model;
196}
197
198QString QEglFSKmsScreen::serialNumber() const
199{
200 return m_edid.serialNumber;
201}
202
203void QEglFSKmsScreen::waitForFlip()
204{
205}
206
207void QEglFSKmsScreen::restoreMode()
208{
209 m_output.restoreMode(device: m_device);
210}
211
212qreal QEglFSKmsScreen::refreshRate() const
213{
214 if (m_headless)
215 return 60;
216
217 quint32 refresh = m_output.modes[m_output.mode].vrefresh;
218 return refresh > 0 ? refresh : 60;
219}
220
221QVector<QPlatformScreen::Mode> QEglFSKmsScreen::modes() const
222{
223 QVector<QPlatformScreen::Mode> list;
224 list.reserve(asize: m_output.modes.size());
225
226 for (const drmModeModeInfo &info : qAsConst(t: m_output.modes))
227 list.append(t: {.size: QSize(info.hdisplay, info.vdisplay),
228 .refreshRate: qreal(info.vrefresh > 0 ? info.vrefresh : 60)});
229
230 return list;
231}
232
233int QEglFSKmsScreen::currentMode() const
234{
235 return m_output.mode;
236}
237
238int QEglFSKmsScreen::preferredMode() const
239{
240 return m_output.preferred_mode;
241}
242
243QPlatformScreen::SubpixelAntialiasingType QEglFSKmsScreen::subpixelAntialiasingTypeHint() const
244{
245 return m_output.subpixelAntialiasingTypeHint();
246}
247
248QPlatformScreen::PowerState QEglFSKmsScreen::powerState() const
249{
250 return m_powerState;
251}
252
253void QEglFSKmsScreen::setPowerState(QPlatformScreen::PowerState state)
254{
255 m_output.setPowerState(device: m_device, state);
256 m_powerState = state;
257}
258
259QT_END_NAMESPACE
260

source code of qtbase/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp