Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Toggle main menu visibility
Loading...
Searching...
No Matches
qeglfswindow.cpp
Go to the documentation of this file.
1
// Copyright (C) 2021 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
5
#
include
<
QtCore
/
qtextstream
.
h
>
6
#
include
<
qpa
/
qwindowsysteminterface
.
h
>
7
#
include
<
qpa
/
qplatformintegration
.
h
>
8
#
include
<
private
/
qguiapplication_p
.
h
>
9
#
include
<
private
/
qwindow_p
.
h
>
10
#
ifndef
QT_NO_OPENGL
11
#
include
<
QtGui
/
private
/
qopenglcontext_p
.
h
>
12
#
include
<
QtGui
/
QOpenGLContext
>
13
#
include
<
QtOpenGL
/
private
/
qopenglcompositorbackingstore_p
.
h
>
14
#
endif
15
#
include
<
QtGui
/
private
/
qeglconvenience_p
.
h
>
16
17
#
include
"qeglfswindow_p.h"
18
#
ifndef
QT_NO_OPENGL
19
#
include
"qeglfscursor_p.h"
20
#
endif
21
#
include
"qeglfshooks_p.h"
22
#
include
"qeglfsdeviceintegration_p.h"
23
24
QT_BEGIN_NAMESPACE
25
26
QEglFSWindow::QEglFSWindow(QWindow *w)
27
: QPlatformWindow(w),
28
#
ifndef
QT_NO_OPENGL
29
m_backingStore(
nullptr
),
30
m_rasterCompositingContext(
nullptr
),
31
#
endif
32
m_winId(0),
33
m_surface(EGL_NO_SURFACE),
34
m_window(0)
35
{
36
}
37
38
QEglFSWindow::~QEglFSWindow()
39
{
40
destroy();
41
}
42
43
static
WId
newWId
()
44
{
45
static
WId id = 0;
46
47
if
(id == std::numeric_limits<WId>::max())
48
qWarning(
"QEGLPlatformWindow: Out of window IDs"
);
49
50
return
++id;
51
}
52
53
void
QEglFSWindow::create()
54
{
55
if
(m_flags.testFlag(Created))
56
return
;
57
58
m_winId = newWId();
59
m_flags = Created;
60
61
// Stop if there is already a window backed by a native window and surface. Additional
62
// raster windows will not have their own native window, surface and context. Instead,
63
// they will be composited onto the root window's surface.
64
QEglFSScreen *screen =
this
->screen();
65
#
ifndef
QT_NO_OPENGL
66
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
67
if
(screen->primarySurface() != EGL_NO_SURFACE) {
68
if
(Q_UNLIKELY(isRaster() != (compositor->targetWindow() !=
nullptr
))) {
69
#
ifndef
Q_OS_ANDROID
70
// We can have either a single OpenGL window or multiple raster windows.
71
// Other combinations cannot work.
72
qFatal(
"EGLFS: OpenGL windows cannot be mixed with others."
);
73
#
endif
74
return
;
75
}
76
m_format = compositor->targetWindow()->format();
77
return
;
78
}
79
#
endif
// QT_NO_OPENGL
80
81
m_flags |= HasNativeWindow;
82
setGeometry(QRect());
// will become fullscreen
83
84
resetSurface();
85
86
if
(Q_UNLIKELY(m_surface == EGL_NO_SURFACE)) {
87
EGLint error = eglGetError();
88
eglTerminate(screen->display());
89
qFatal(
"EGL Error : Could not create the egl surface: error = 0x%x\n"
, error);
90
}
91
92
screen->setPrimarySurface(m_surface);
93
94
#
ifndef
QT_NO_OPENGL
95
compositor->setTargetWindow(window(), screen->rawGeometry());
96
compositor->setRotation(qEnvironmentVariableIntValue(
"QT_QPA_EGLFS_ROTATION"
));
97
#
endif
98
}
99
100
void
QEglFSWindow::setBackingStore(QOpenGLCompositorBackingStore *backingStore)
101
{
102
#
ifndef
QT_NO_OPENGL
103
if
(!m_rasterCompositingContext) {
104
m_rasterCompositingContext =
new
QOpenGLContext;
105
m_rasterCompositingContext->setShareContext(QOpenGLContext::globalShareContext());
106
m_rasterCompositingContext->setFormat(m_format);
107
m_rasterCompositingContext->setScreen(window()->screen());
108
if
(Q_UNLIKELY(!m_rasterCompositingContext->create()))
109
qFatal(
"EGLFS: Failed to create compositing context"
);
110
// If there is a "root" window into which raster and QOpenGLWidget content is
111
// composited, all other contexts must share with its context.
112
if
(!QOpenGLContext::globalShareContext())
113
qt_gl_set_global_share_context(m_rasterCompositingContext);
114
}
115
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
116
compositor->setTargetContext(m_rasterCompositingContext);
117
#
endif
118
m_backingStore = backingStore;
119
}
120
121
void
QEglFSWindow::destroy()
122
{
123
if
(!m_flags.testFlag(Created))
124
return
;
// already destroyed
125
126
QEglFSScreen *screen =
this
->screen();
127
#
ifndef
QT_NO_OPENGL
128
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
129
compositor->removeWindow(
this
);
130
if
(compositor->targetWindow() == window()) {
131
QEglFSCursor *cursor = qobject_cast<QEglFSCursor *>(screen->cursor());
132
if
(cursor)
133
cursor->resetResources();
134
135
if
(screen->primarySurface() == m_surface)
136
screen->setPrimarySurface(EGL_NO_SURFACE);
137
138
invalidateSurface();
139
140
if
(compositor->windows().isEmpty()) {
141
compositor->destroy();
142
if
(QOpenGLContext::globalShareContext() == m_rasterCompositingContext)
143
qt_gl_set_global_share_context(
nullptr
);
144
delete
m_rasterCompositingContext;
145
}
else
{
146
auto
windows = compositor->windows();
147
auto
topWindow =
static_cast
<QEglFSWindow *>(windows.last());
148
// Make fullscreen
149
topWindow->setGeometry(screen->rawGeometry());
150
topWindow->resetSurface();
151
screen->setPrimarySurface(topWindow->surface());
152
compositor->setTargetWindow(topWindow->sourceWindow(), screen->rawGeometry());
153
}
154
}
155
#
else
156
if
(m_flags.testFlag(HasNativeWindow)) {
157
if
(screen->primarySurface() == m_surface)
158
screen->setPrimarySurface(EGL_NO_SURFACE);
159
160
invalidateSurface();
161
}
162
#
endif
163
164
m_flags = { };
165
}
166
167
void
QEglFSWindow::invalidateSurface()
168
{
169
if
(m_surface != EGL_NO_SURFACE) {
170
qCDebug(qLcEglDevDebug) << Q_FUNC_INFO <<
" about to destroy EGLSurface: "
<< m_surface;
171
172
bool
ok = eglDestroySurface(screen()->display(), m_surface);
173
174
if
(!ok) {
175
qCWarning(qLcEglDevDebug,
"QEglFSWindow::invalidateSurface() eglDestroySurface failed!"
176
" Follow-up errors or memory leaks are possible."
177
" eglGetError(): %x"
, eglGetError());
178
}
179
180
if
(eglGetCurrentSurface(EGL_READ) == m_surface ||
181
eglGetCurrentSurface(EGL_DRAW) == m_surface) {
182
bool
ok = eglMakeCurrent(eglGetCurrentDisplay(), EGL_NO_DISPLAY, EGL_NO_DISPLAY, EGL_NO_CONTEXT);
183
qCDebug(qLcEglDevDebug) << Q_FUNC_INFO <<
" due to eglDestroySurface on *currently* bound surface"
184
<<
"we just called eglMakeCurrent(..,0,0,0)! It returned: "
<< ok;
185
}
186
187
if
(screen()->primarySurface() == m_surface)
188
screen()->setPrimarySurface(EGL_NO_SURFACE);
189
190
m_surface = EGL_NO_SURFACE;
191
m_flags = m_flags & ~Created;
192
}
193
qt_egl_device_integration()->destroyNativeWindow(m_window);
194
m_window = 0;
195
}
196
197
void
QEglFSWindow::resetSurface()
198
{
199
EGLDisplay display = screen()->display();
200
QSurfaceFormat platformFormat = qt_egl_device_integration()->surfaceFormatFor(window()->requestedFormat());
201
202
m_config = QEglFSDeviceIntegration::chooseConfig(display, platformFormat);
203
m_format = q_glFormatFromConfig(display, m_config, platformFormat);
204
const
QSize surfaceSize = screen()->rawGeometry().size();
205
m_window = qt_egl_device_integration()->createNativeWindow(
this
, surfaceSize, m_format);
206
m_surface = eglCreateWindowSurface(display, m_config, m_window,
nullptr
);
207
}
208
209
void
QEglFSWindow::setVisible(
bool
visible)
210
{
211
#
ifndef
QT_NO_OPENGL
212
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
213
QList<QOpenGLCompositorWindow *> windows = compositor->windows();
214
QWindow *wnd = window();
215
216
if
(visible) {
217
compositor->addWindow(
this
);
218
}
else
{
219
compositor->removeWindow(
this
);
220
windows = compositor->windows();
221
if
(windows.size())
222
windows.last()->sourceWindow()->requestActivate();
223
}
224
#
else
225
QWindow *wnd = window();
226
#
endif
227
QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size()));
228
229
if
(visible)
230
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
231
}
232
233
void
QEglFSWindow::setGeometry(
const
QRect &r)
234
{
235
QRect rect = r;
236
if
(m_flags.testFlag(HasNativeWindow))
237
rect = screen()->availableGeometry();
238
239
QPlatformWindow::setGeometry(rect);
240
241
QWindowSystemInterface::handleGeometryChange(window(), rect);
242
243
const
QRect lastReportedGeometry = qt_window_private(window())->geometry;
244
if
(rect != lastReportedGeometry)
245
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size()));
246
}
247
248
QRect QEglFSWindow::geometry()
const
249
{
250
// For yet-to-become-fullscreen windows report the geometry covering the entire
251
// screen. This is particularly important for Quick where the root object may get
252
// sized to some geometry queried before calling create().
253
if
(!m_flags.testFlag(Created) && screen()->primarySurface() == EGL_NO_SURFACE)
254
return
screen()->availableGeometry();
255
256
return
QPlatformWindow::geometry();
257
}
258
259
void
QEglFSWindow::requestActivateWindow()
260
{
261
#
ifndef
QT_NO_OPENGL
262
QOpenGLCompositor::instance()->moveToTop(
this
);
263
#
endif
264
QWindow *wnd = window();
265
QWindowSystemInterface::handleFocusWindowChanged(wnd, Qt::ActiveWindowFocusReason);
266
QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size()));
267
}
268
269
void
QEglFSWindow::raise()
270
{
271
QWindow *wnd = window();
272
#
ifndef
QT_NO_OPENGL
273
QOpenGLCompositor::instance()->moveToTop(
this
);
274
#
endif
275
QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size()));
276
}
277
278
void
QEglFSWindow::lower()
279
{
280
#
ifndef
QT_NO_OPENGL
281
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
282
QList<QOpenGLCompositorWindow *> windows = compositor->windows();
283
if
(windows.size() > 1) {
284
int
idx = windows.indexOf(
this
);
285
if
(idx > 0) {
286
compositor->changeWindowIndex(
this
, idx - 1);
287
QWindowSystemInterface::handleExposeEvent(windows.last()->sourceWindow(),
288
QRect(QPoint(0, 0), windows.last()->sourceWindow()->geometry().size()));
289
}
290
}
291
#
endif
292
}
293
294
EGLSurface QEglFSWindow::surface()
const
295
{
296
return
m_surface != EGL_NO_SURFACE ? m_surface : screen()->primarySurface();
297
}
298
299
QSurfaceFormat QEglFSWindow::format()
const
300
{
301
return
m_format;
302
}
303
304
EGLNativeWindowType QEglFSWindow::eglWindow()
const
305
{
306
return
m_window;
307
}
308
309
QEglFSScreen *QEglFSWindow::screen()
const
310
{
311
return
static_cast
<QEglFSScreen *>(QPlatformWindow::screen());
312
}
313
314
bool
QEglFSWindow::isRaster()
const
315
{
316
return
window()->surfaceType() == QSurface::RasterSurface;
317
}
318
319
#
ifndef
QT_NO_OPENGL
320
QWindow *QEglFSWindow::sourceWindow()
const
321
{
322
return
window();
323
}
324
325
const
QPlatformTextureList *QEglFSWindow::textures()
const
326
{
327
if
(m_backingStore)
328
return
m_backingStore->textures();
329
330
return
nullptr
;
331
}
332
333
void
QEglFSWindow::endCompositing()
334
{
335
if
(m_backingStore)
336
m_backingStore->notifyComposited();
337
}
338
#
endif
339
340
WId QEglFSWindow::winId()
const
341
{
342
return
m_winId;
343
}
344
345
void
QEglFSWindow::setOpacity(qreal)
346
{
347
if
(!isRaster() && !backingStore())
348
qWarning(
"QEglFSWindow: Cannot set opacity for non-raster windows"
);
349
350
// Nothing to do here. The opacity is stored in the QWindow.
351
}
352
353
QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
newWId
static WId newWId()
Definition
qeglfswindow.cpp:43
qtbase
src
plugins
platforms
eglfs
api
qeglfswindow.cpp
Generated on
for Qt by
1.18.0