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
qoffscreensurface.cpp
Go to the documentation of this file.
1
// Copyright (C) 2020 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
"qoffscreensurface.h"
6
7
#
include
"qguiapplication_p.h"
8
#
include
"qscreen.h"
9
#
include
"qplatformintegration.h"
10
#
include
"qoffscreensurface_p.h"
11
#
include
"qwindow.h"
12
#
include
"qplatformwindow.h"
13
14
#
include
<
private
/
qwindow_p
.
h
>
15
16
QT_BEGIN_NAMESPACE
17
18
using
namespace
Qt::StringLiterals;
19
20
/*!
21
\class QOffscreenSurface
22
\inmodule QtGui
23
\since 5.1
24
\brief The QOffscreenSurface class represents an offscreen surface in the underlying platform.
25
26
QOffscreenSurface is intended to be used with QOpenGLContext to allow rendering with OpenGL in
27
an arbitrary thread without the need to create a QWindow.
28
29
Even though the surface is typically renderable, the surface's pixels are not accessible.
30
QOffscreenSurface should only be used to create OpenGL resources such as textures
31
or framebuffer objects.
32
33
An application will typically use QOffscreenSurface to perform some time-consuming tasks in a
34
separate thread in order to avoid stalling the main rendering thread. Resources created in the
35
QOffscreenSurface's context can be shared with the main OpenGL context. Some common use cases
36
are asynchronous texture uploads or rendering into a QOpenGLFramebufferObject.
37
38
How the offscreen surface is implemented depends on the underlying platform, but it will
39
typically use a pixel buffer (pbuffer). If the platform doesn't implement or support
40
offscreen surfaces, QOffscreenSurface will use an invisible QWindow internally.
41
42
\note Due to the fact that QOffscreenSurface is backed by a QWindow on some platforms,
43
cross-platform applications must ensure that create() is only called on the main (GUI)
44
thread. The QOffscreenSurface is then safe to be used with
45
\l{QOpenGLContext::makeCurrent()}{makeCurrent()} on other threads, but the
46
initialization and destruction must always happen on the main (GUI) thread.
47
48
\note In order to create an offscreen surface that is guaranteed to be compatible with
49
a given context and window, make sure to set the format to the context's or the
50
window's actual format, that is, the QSurfaceFormat returned from
51
QOpenGLContext::format() or QWindow::format() \e{after the context or window has been
52
created}. Passing the format returned from QWindow::requestedFormat() to setFormat()
53
may result in an incompatible offscreen surface since the underlying windowing system
54
interface may offer a different set of configurations for window and pbuffer surfaces.
55
56
\note Some platforms may utilize a surfaceless context extension (for example
57
EGL_KHR_surfaceless_context) when available. In this case there will be no underlying
58
native surface. For the use cases of QOffscreenSurface (rendering to FBOs, texture
59
upload) this is not a problem.
60
*/
61
62
/*!
63
\since 5.10
64
65
Creates an offscreen surface for the \a targetScreen with the given \a parent.
66
67
The underlying platform surface is not created until create() is called.
68
69
\sa setScreen(), create()
70
*/
71
QOffscreenSurface::QOffscreenSurface(QScreen *targetScreen, QObject *parent)
72
: QObject(*
new
QOffscreenSurfacePrivate(), parent)
73
, QSurface(Offscreen)
74
{
75
Q_D(QOffscreenSurface);
76
d->screen = targetScreen;
77
if
(!d->screen)
78
d->screen = QGuiApplication::primaryScreen();
79
80
//if your applications aborts here, then chances are your creating a QOffscreenSurface before
81
//the screen list is populated.
82
Q_ASSERT(d->screen);
83
84
connect(d->screen, SIGNAL(destroyed(QObject*)),
this
, SLOT(screenDestroyed(QObject*)));
85
}
86
87
/*!
88
Destroys the offscreen surface.
89
*/
90
QOffscreenSurface::~QOffscreenSurface()
91
{
92
destroy();
93
}
94
95
/*!
96
Returns the surface type of the offscreen surface.
97
98
The surface type of an offscreen surface is always QSurface::OpenGLSurface.
99
*/
100
QOffscreenSurface::SurfaceType QOffscreenSurface::surfaceType()
const
101
{
102
Q_D(
const
QOffscreenSurface);
103
return
d->surfaceType;
104
}
105
106
/*!
107
Allocates the platform resources associated with the offscreen surface.
108
109
It is at this point that the surface format set using setFormat() gets resolved
110
into an actual native surface.
111
112
Call destroy() to free the platform resources if necessary.
113
114
\note Some platforms require this function to be called on the main (GUI) thread.
115
116
\sa destroy()
117
*/
118
void
QOffscreenSurface::create()
119
{
120
Q_D(QOffscreenSurface);
121
if
(!d->platformOffscreenSurface && !d->offscreenWindow) {
122
d->platformOffscreenSurface = QGuiApplicationPrivate::platformIntegration()->createPlatformOffscreenSurface(
this
);
123
// No platform offscreen surface, fallback to an invisible window
124
if
(!d->platformOffscreenSurface) {
125
if
(!QThread::isMainThread())
126
qWarning(
"Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures."
);
127
d->offscreenWindow =
new
QWindow(d->screen);
128
// Make the window frameless to prevent Windows from enlarging it, should it
129
// violate the minimum title bar width on the platform.
130
d->offscreenWindow->setFlags(d->offscreenWindow->flags()
131
| Qt::CustomizeWindowHint | Qt::FramelessWindowHint);
132
d->offscreenWindow->setObjectName(
"QOffscreenSurface"_L1
);
133
// Remove this window from the global list since we do not want it to be destroyed when closing the app.
134
// The QOffscreenSurface has to be usable even after exiting the event loop.
135
QGuiApplicationPrivate::window_list.removeOne(d->offscreenWindow);
136
d->offscreenWindow->setSurfaceType(QWindow::OpenGLSurface);
137
d->offscreenWindow->setFormat(d->requestedFormat);
138
// Prevent QPlatformWindow::initialGeometry() and platforms from setting a default geometry.
139
qt_window_private(d->offscreenWindow)->setAutomaticPositionAndResizeEnabled(
false
);
140
d->offscreenWindow->setGeometry(0, 0, d->size.width(), d->size.height());
141
d->offscreenWindow->create();
142
}
143
144
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated);
145
QGuiApplication::sendEvent(
this
, &e);
146
}
147
}
148
149
/*!
150
Releases the native platform resources associated with this offscreen surface.
151
152
\sa create()
153
*/
154
void
QOffscreenSurface::destroy()
155
{
156
Q_D(QOffscreenSurface);
157
158
QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed);
159
QGuiApplication::sendEvent(
this
, &e);
160
161
delete
d->platformOffscreenSurface;
162
d->platformOffscreenSurface =
nullptr
;
163
if
(d->offscreenWindow) {
164
d->offscreenWindow->destroy();
165
delete
d->offscreenWindow;
166
d->offscreenWindow =
nullptr
;
167
}
168
}
169
170
/*!
171
Returns \c true if this offscreen surface is valid; otherwise returns \c false.
172
173
The offscreen surface is valid if the platform resources have been successfully allocated.
174
175
\sa create()
176
*/
177
bool
QOffscreenSurface::isValid()
const
178
{
179
Q_D(
const
QOffscreenSurface);
180
return
(d->platformOffscreenSurface && d->platformOffscreenSurface->isValid())
181
|| (d->offscreenWindow && d->offscreenWindow->handle());
182
}
183
184
/*!
185
Sets the offscreen surface \a format.
186
187
The surface format will be resolved in the create() function. Calling
188
this function after create() will not re-resolve the surface format of the native surface.
189
190
\sa create(), destroy()
191
*/
192
void
QOffscreenSurface::setFormat(
const
QSurfaceFormat &format)
193
{
194
Q_D(QOffscreenSurface);
195
d->requestedFormat = format;
196
}
197
198
/*!
199
Returns the requested surfaceformat of this offscreen surface.
200
201
If the requested format was not supported by the platform implementation,
202
the requestedFormat will differ from the actual offscreen surface format.
203
204
This is the value set with setFormat().
205
206
\sa setFormat(), format()
207
*/
208
QSurfaceFormat QOffscreenSurface::requestedFormat()
const
209
{
210
Q_D(
const
QOffscreenSurface);
211
return
d->requestedFormat;
212
}
213
214
/*!
215
Returns the actual format of this offscreen surface.
216
217
After the offscreen surface has been created, this function will return the actual
218
surface format of the surface. It might differ from the requested format if the requested
219
format could not be fulfilled by the platform.
220
221
\sa create(), requestedFormat()
222
*/
223
QSurfaceFormat QOffscreenSurface::format()
const
224
{
225
Q_D(
const
QOffscreenSurface);
226
if
(d->platformOffscreenSurface)
227
return
d->platformOffscreenSurface->format();
228
if
(d->offscreenWindow)
229
return
d->offscreenWindow->format();
230
return
d->requestedFormat;
231
}
232
233
/*!
234
Returns the size of the offscreen surface.
235
*/
236
QSize QOffscreenSurface::size()
const
237
{
238
Q_D(
const
QOffscreenSurface);
239
return
d->size;
240
}
241
242
/*!
243
Returns the screen to which the offscreen surface is connected.
244
245
\sa setScreen()
246
*/
247
QScreen *QOffscreenSurface::screen()
const
248
{
249
Q_D(
const
QOffscreenSurface);
250
return
d->screen;
251
}
252
253
/*!
254
Sets the screen to which the offscreen surface is connected.
255
256
If the offscreen surface has been created, it will be recreated on the \a newScreen.
257
258
\sa screen()
259
*/
260
void
QOffscreenSurface::setScreen(QScreen *newScreen)
261
{
262
Q_D(QOffscreenSurface);
263
if
(!newScreen)
264
newScreen = QCoreApplication::instance() ? QGuiApplication::primaryScreen() :
nullptr
;
265
if
(newScreen != d->screen) {
266
const
bool
wasCreated = d->platformOffscreenSurface !=
nullptr
|| d->offscreenWindow !=
nullptr
;
267
if
(wasCreated)
268
destroy();
269
if
(d->screen)
270
disconnect(d->screen, SIGNAL(destroyed(QObject*)),
this
, SLOT(screenDestroyed(QObject*)));
271
d->screen = newScreen;
272
if
(newScreen) {
273
connect(d->screen, SIGNAL(destroyed(QObject*)),
this
, SLOT(screenDestroyed(QObject*)));
274
if
(wasCreated)
275
create();
276
}
277
emit screenChanged(newScreen);
278
}
279
}
280
281
/*!
282
Called when the offscreen surface's screen is destroyed.
283
284
\internal
285
*/
286
void
QOffscreenSurface::screenDestroyed(QObject *object)
287
{
288
Q_D(QOffscreenSurface);
289
if
(object ==
static_cast
<QObject *>(d->screen))
290
setScreen(
nullptr
);
291
}
292
293
/*!
294
\fn QOffscreenSurface::screenChanged(QScreen *screen)
295
296
This signal is emitted when an offscreen surface's \a screen changes, either
297
by being set explicitly with setScreen(), or automatically when
298
the window's screen is removed.
299
*/
300
301
/*!
302
Returns the platform offscreen surface corresponding to the offscreen surface.
303
304
\internal
305
*/
306
QPlatformOffscreenSurface *QOffscreenSurface::handle()
const
307
{
308
Q_D(
const
QOffscreenSurface);
309
return
d->platformOffscreenSurface;
310
}
311
312
/*!
313
\fn template <typename QNativeInterface> QNativeInterface *QOffscreenSurface::nativeInterface() const
314
315
Returns a native interface of the given type for the surface.
316
317
This function provides access to platform specific functionality
318
of QOffScreenSurface, as defined in the QNativeInterface namespace:
319
320
\annotatedlist native-interfaces-qoffscreensurface
321
322
If the requested interface is not available a \nullptr is returned.
323
*/
324
325
/*!
326
Returns the platform surface corresponding to the offscreen surface.
327
328
\internal
329
*/
330
QPlatformSurface *QOffscreenSurface::surfaceHandle()
const
331
{
332
Q_D(
const
QOffscreenSurface);
333
if
(d->offscreenWindow)
334
return
d->offscreenWindow->handle();
335
336
return
d->platformOffscreenSurface;
337
}
338
339
using
namespace
QNativeInterface;
340
341
void
*QOffscreenSurface::resolveInterface(
const
char
*name,
int
revision)
const
342
{
343
Q_UNUSED(name); Q_UNUSED(revision);
344
345
Q_D(
const
QOffscreenSurface);
346
Q_UNUSED(d);
347
348
#
if
defined
(
Q_OS_ANDROID
)
349
QT_NATIVE_INTERFACE_RETURN_IF(QAndroidOffscreenSurface, d->platformOffscreenSurface);
350
#
endif
351
352
return
nullptr
;
353
}
354
355
QT_END_NAMESPACE
356
357
#
include
"moc_qoffscreensurface.cpp"
QT_BEGIN_NAMESPACE
Combined button and popup list for selecting options.
Definition
qsequentialanimationgroup.cpp:47
qtbase
src
gui
kernel
qoffscreensurface.cpp
Generated on
for Qt by
1.18.0