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
qeglfsdeviceintegration.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
7#ifndef QT_NO_OPENGL
8# include "qeglfscursor_p.h"
9#endif
10#include "qeglfswindow_p.h"
11#include "qeglfsscreen_p.h"
12#include "qeglfshooks_p.h"
13
14#include <QtGui/private/qeglconvenience_p.h>
15#include <QGuiApplication>
16#include <private/qguiapplication_p.h>
17#include <QScreen>
18#include <QDir>
19#if QT_CONFIG(regularexpression)
20# include <QFileInfo>
21# include <QRegularExpression>
22#endif
23#include <QLoggingCategory>
24
25#if defined(Q_OS_LINUX)
26#include <fcntl.h>
27#include <unistd.h>
28#include <linux/fb.h>
29#include <sys/ioctl.h>
30#endif
31
32#if defined(Q_OS_VXWORKS)
33#include <fbdev.h>
34#endif
35
36#include <private/qfactoryloader_p.h>
37#include <private/qcore_unix_p.h>
38
40
41using namespace Qt::StringLiterals;
42
43Q_LOGGING_CATEGORY(qLcEglDevDebug, "qt.qpa.egldeviceintegration")
44
45Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
46 (QEglFSDeviceIntegrationFactoryInterface_iid, "/egldeviceintegrations"_L1, Qt::CaseInsensitive))
47
48QStringList QEglFSDeviceIntegrationFactory::keys()
49{
50 QStringList list;
51 list.append(loader()->keyMap().values());
52 qCDebug(qLcEglDevDebug) << "EGL device integration plugin keys:" << list;
53 return list;
54}
55
56QEglFSDeviceIntegration *QEglFSDeviceIntegrationFactory::create(const QString &key)
57{
58 QEglFSDeviceIntegration *integration = nullptr;
59 if (!integration)
60 integration = qLoadPlugin<QEglFSDeviceIntegration, QEglFSDeviceIntegrationPlugin>(loader(), key);
61 if (integration)
62 qCDebug(qLcEglDevDebug) << "Using EGL device integration" << key;
63 else
64 qCWarning(qLcEglDevDebug) << "Failed to load EGL device integration" << key;
65
66 return integration;
67}
68
69static int framebuffer = -1;
70
71QByteArray QEglFSDeviceIntegration::fbDeviceName() const
72{
73#if defined(Q_OS_LINUX) || defined(Q_OS_VXWORKS)
74 QByteArray fbDev = qgetenv("QT_QPA_EGLFS_FB");
75 if (fbDev.isEmpty())
76 fbDev = QByteArrayLiteral("/dev/fb0");
77
78 return fbDev;
79#else
80 return QByteArray();
81#endif
82}
83
84int QEglFSDeviceIntegration::framebufferIndex() const
85{
86 int fbIndex = 0;
87#if QT_CONFIG(regularexpression)
88 QRegularExpression fbIndexRx("fb(\\d+)"_L1);
89 QFileInfo fbinfo(QString::fromLocal8Bit(fbDeviceName()));
90 QRegularExpressionMatch match;
91 if (fbinfo.isSymLink())
92 match = fbIndexRx.match(fbinfo.symLinkTarget());
93 else
94 match = fbIndexRx.match(fbinfo.fileName());
95 if (match.hasMatch())
96 fbIndex = match.captured(1).toInt();
97#endif
98 return fbIndex;
99}
100
101void QEglFSDeviceIntegration::platformInit()
102{
103#if defined(Q_OS_LINUX) || defined(Q_OS_VXWORKS)
104 QByteArray fbDev = fbDeviceName();
105
106 framebuffer = qt_safe_open(fbDev, O_RDONLY);
107
108 if (Q_UNLIKELY(framebuffer == -1)) {
109 qWarning("EGLFS: Failed to open %s", fbDev.constData());
110 qFatal("EGLFS: Can't continue without a display");
111 }
112
113#ifdef FBIOBLANK
114 ioctl(framebuffer, FBIOBLANK, VESA_NO_BLANKING);
115#endif
116#endif
117}
118
119void QEglFSDeviceIntegration::platformDestroy()
120{
121#if defined(Q_OS_LINUX) || defined(Q_OS_VXWORKS)
122 if (framebuffer != -1)
123 close(framebuffer);
124#endif
125}
126
127EGLNativeDisplayType QEglFSDeviceIntegration::platformDisplay() const
128{
129 bool displayOk;
130 const int defaultDisplay = qEnvironmentVariableIntValue("QT_QPA_EGLFS_DEFAULT_DISPLAY", &displayOk);
131 return displayOk ? EGLNativeDisplayType(quintptr(defaultDisplay)) : EGL_DEFAULT_DISPLAY;
132}
133
134EGLDisplay QEglFSDeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay)
135{
136 return eglGetDisplay(nativeDisplay);
137}
138
139bool QEglFSDeviceIntegration::usesDefaultScreen()
140{
141 return true;
142}
143
144void QEglFSDeviceIntegration::screenInit()
145{
146 // Nothing to do here. Called only when usesDefaultScreen is false.
147}
148
149void QEglFSDeviceIntegration::screenDestroy()
150{
151 QGuiApplication *app = qGuiApp;
152 while (!app->screens().isEmpty())
153 QWindowSystemInterface::handleScreenRemoved(app->screens().constLast()->handle());
154}
155
156QSizeF QEglFSDeviceIntegration::physicalScreenSize() const
157{
158 return q_physicalScreenSizeFromFb(framebuffer, screenSize());
159}
160
161QSize QEglFSDeviceIntegration::screenSize() const
162{
163 return q_screenSizeFromFb(framebuffer);
164}
165
166QDpi QEglFSDeviceIntegration::logicalDpi() const
167{
168 return QDpi(100, 100);
169}
170
171QDpi QEglFSDeviceIntegration::logicalBaseDpi() const
172{
173 return QDpi(100, 100);
174}
175
176Qt::ScreenOrientation QEglFSDeviceIntegration::nativeOrientation() const
177{
178 return Qt::PrimaryOrientation;
179}
180
181Qt::ScreenOrientation QEglFSDeviceIntegration::orientation() const
182{
183 return Qt::PrimaryOrientation;
184}
185
186int QEglFSDeviceIntegration::screenDepth() const
187{
188 return q_screenDepthFromFb(framebuffer);
189}
190
191QImage::Format QEglFSDeviceIntegration::screenFormat() const
192{
193 return screenDepth() == 16 ? QImage::Format_RGB16 : QImage::Format_RGB32;
194}
195
196qreal QEglFSDeviceIntegration::refreshRate() const
197{
198 return q_refreshRateFromFb(framebuffer);
199}
200
201EGLint QEglFSDeviceIntegration::surfaceType() const
202{
203 return EGL_WINDOW_BIT;
204}
205
206QSurfaceFormat QEglFSDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const
207{
208 QSurfaceFormat format = inputFormat;
209
210 static const bool force888 = qEnvironmentVariableIntValue("QT_QPA_EGLFS_FORCE888");
211 if (force888) {
212 format.setRedBufferSize(8);
213 format.setGreenBufferSize(8);
214 format.setBlueBufferSize(8);
215 }
216
217 return format;
218}
219
220bool QEglFSDeviceIntegration::filterConfig(EGLDisplay, EGLConfig) const
221{
222 return true;
223}
224
225QEglFSWindow *QEglFSDeviceIntegration::createWindow(QWindow *window) const
226{
227 return new QEglFSWindow(window);
228}
229
230EGLNativeWindowType QEglFSDeviceIntegration::createNativeWindow(QPlatformWindow *platformWindow,
231 const QSize &size,
232 const QSurfaceFormat &format)
233{
234 Q_UNUSED(platformWindow);
235 Q_UNUSED(size);
236 Q_UNUSED(format);
237 return 0;
238}
239
240EGLNativeWindowType QEglFSDeviceIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format)
241{
242 Q_UNUSED(format);
243 return 0;
244}
245
246void QEglFSDeviceIntegration::destroyNativeWindow(EGLNativeWindowType window)
247{
248 Q_UNUSED(window);
249}
250
251bool QEglFSDeviceIntegration::hasCapability(QPlatformIntegration::Capability cap) const
252{
253 Q_UNUSED(cap);
254 return false;
255}
256
257QPlatformCursor *QEglFSDeviceIntegration::createCursor(QPlatformScreen *screen) const
258{
259#ifndef QT_NO_OPENGL
260 return new QEglFSCursor(static_cast<QEglFSScreen *>(screen));
261#else
262 Q_UNUSED(screen);
263 return nullptr;
264#endif
265}
266
267void QEglFSDeviceIntegration::waitForVSync(QPlatformSurface *surface) const
268{
269 Q_UNUSED(surface);
270
271#if defined(Q_OS_LINUX) && defined(FBIO_WAITFORVSYNC)
272 static const bool forceSync = qEnvironmentVariableIntValue("QT_QPA_EGLFS_FORCEVSYNC");
273 if (forceSync && framebuffer != -1) {
274 int arg = 0;
275 if (ioctl(framebuffer, FBIO_WAITFORVSYNC, &arg) == -1)
276 qWarning("Could not wait for vsync.");
277 }
278#elif defined(Q_OS_VXWORKS) && defined(FB_IOCTL_VSYNC)
279 static const bool forceSync = qEnvironmentVariableIntValue("QT_QPA_EGLFS_FORCEVSYNC");
280 if (forceSync && framebuffer != -1) {
281 int arg = 0;
282 if (ioctl(framebuffer, FB_IOCTL_VSYNC, &arg) == -1)
283 qWarning("Could not wait for vsync.");
284 }
285#endif
286}
287
288void QEglFSDeviceIntegration::presentBuffer(QPlatformSurface *surface)
289{
290 Q_UNUSED(surface);
291}
292
293bool QEglFSDeviceIntegration::supportsPBuffers() const
294{
295 return true;
296}
297
298bool QEglFSDeviceIntegration::supportsSurfacelessContexts() const
299{
300 return true;
301}
302
303QFunctionPointer QEglFSDeviceIntegration::platformFunction(const QByteArray &function) const
304{
305 Q_UNUSED(function);
306 return nullptr;
307}
308
309void *QEglFSDeviceIntegration::nativeResourceForIntegration(const QByteArray &name)
310{
311 Q_UNUSED(name);
312 return nullptr;
313}
314
315void *QEglFSDeviceIntegration::nativeResourceForScreen(const QByteArray &resource, QScreen *screen)
316{
317 Q_UNUSED(resource);
318 Q_UNUSED(screen);
319 return nullptr;
320}
321
322void *QEglFSDeviceIntegration::wlDisplay() const
323{
324 return nullptr;
325}
326
327EGLConfig QEglFSDeviceIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format)
328{
329 class Chooser : public QEglConfigChooser {
330 public:
331 Chooser(EGLDisplay display)
332 : QEglConfigChooser(display) { }
333 bool filterConfig(EGLConfig config) const override {
334 return qt_egl_device_integration()->filterConfig(display(), config)
335 && QEglConfigChooser::filterConfig(config);
336 }
337 };
338
339 Chooser chooser(display);
340 chooser.setSurfaceType(qt_egl_device_integration()->surfaceType());
341 chooser.setSurfaceFormat(format);
342 return chooser.chooseConfig();
343}
344
345QT_END_NAMESPACE
346
347#include "moc_qeglfsdeviceintegration_p.cpp"
Combined button and popup list for selecting options.
static int framebuffer
#define QEglFSDeviceIntegrationFactoryInterface_iid
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")