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