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
qplatformbackingstore.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
6#include <qwindow.h>
7#include <qpixmap.h>
8#include <private/qbackingstorerhisupport_p.h>
9#include <private/qbackingstoredefaultcompositor_p.h>
10#include <private/qwindow_p.h>
11
12#include <QtCore/private/qobject_p.h>
13
14#include <unordered_map>
15
17
18Q_LOGGING_CATEGORY(lcQpaBackingStore, "qt.qpa.backingstore", QtWarningMsg);
19
21{
22public:
24 : window(w)
25 , backingStore(nullptr)
26 {
27 }
28
30 QBackingStore *backingStore;
31
33 // The order matters. if it needs to be rearranged in the future, call
34 // reset() explicitly from the dtor in the correct order.
35 // (first the compositor, then the rhiSupport)
38 };
40};
41
43{
44 void *source; // may be null
45 QRhiTexture *texture;
46 QRhiTexture *textureExtra;
47 QRect rect;
48 QRect clipRect;
50};
51
53
65
66QPlatformTextureList::QPlatformTextureList(QObject *parent)
67: QObject(*new QPlatformTextureListPrivate, parent)
68{
69}
70
71QPlatformTextureList::~QPlatformTextureList()
72{
73}
74
75int QPlatformTextureList::count() const
76{
77 Q_D(const QPlatformTextureList);
78 return d->textures.size();
79}
80
81QRhiTexture *QPlatformTextureList::texture(int index) const
82{
83 Q_D(const QPlatformTextureList);
84 return d->textures.at(index).texture;
85}
86
87QRhiTexture *QPlatformTextureList::textureExtra(int index) const
88{
89 Q_D(const QPlatformTextureList);
90 return d->textures.at(index).textureExtra;
91}
92
93void *QPlatformTextureList::source(int index)
94{
95 Q_D(const QPlatformTextureList);
96 return d->textures.at(index).source;
97}
98
99QPlatformTextureList::Flags QPlatformTextureList::flags(int index) const
100{
101 Q_D(const QPlatformTextureList);
102 return d->textures.at(index).flags;
103}
104
105QRect QPlatformTextureList::geometry(int index) const
106{
107 Q_D(const QPlatformTextureList);
108 return d->textures.at(index).rect;
109}
110
111QRect QPlatformTextureList::clipRect(int index) const
112{
113 Q_D(const QPlatformTextureList);
114 return d->textures.at(index).clipRect;
115}
116
117void QPlatformTextureList::lock(bool on)
118{
119 Q_D(QPlatformTextureList);
120 if (on != d->locked) {
121 d->locked = on;
122 emit locked(on);
123 }
124}
125
126bool QPlatformTextureList::isLocked() const
127{
128 Q_D(const QPlatformTextureList);
129 return d->locked;
130}
131
132void QPlatformTextureList::appendTexture(void *source, QRhiTexture *texture, const QRect &geometry,
133 const QRect &clipRect, Flags flags)
134{
135 Q_D(QPlatformTextureList);
136 QBackingstoreTextureInfo bi;
137 bi.source = source;
138 bi.texture = texture;
139 bi.textureExtra = nullptr;
140 bi.rect = geometry;
141 bi.clipRect = clipRect;
142 bi.flags = flags;
143 d->textures.append(bi);
144}
145
146void QPlatformTextureList::appendTexture(void *source, QRhiTexture *textureLeft, QRhiTexture *textureRight, const QRect &geometry,
147 const QRect &clipRect, Flags flags)
148{
149 Q_D(QPlatformTextureList);
150
151 QBackingstoreTextureInfo bi;
152 bi.source = source;
153 bi.texture = textureLeft;
154 bi.textureExtra = textureRight;
155 bi.rect = geometry;
156 bi.clipRect = clipRect;
157 bi.flags = flags;
158 d->textures.append(bi);
159}
160
161void QPlatformTextureList::clear()
162{
163 Q_D(QPlatformTextureList);
164 d->textures.clear();
165}
166
167/*!
168 \class QPlatformBackingStore
169 \since 5.0
170 \internal
171 \preliminary
172 \ingroup qpa
173
174 \brief The QPlatformBackingStore class provides the drawing area for top-level
175 windows.
176*/
177
178/*!
179 Flushes the given \a region from the specified \a window.
180
181 \note \a region is relative to the window which may not be top-level in case
182 \a window corresponds to a native child widget. \a offset is the position of
183 the native child relative to the top-level window.
184
185 Unlike rhiFlush(), this function's default implementation does nothing. It
186 is expected that subclasses provide a platform-specific (non-QRhi-based)
187 implementation, if applicable on the given platform.
188
189 \sa rhiFlush()
190 */
191void QPlatformBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
192{
193 Q_UNUSED(window);
194 Q_UNUSED(region);
195 Q_UNUSED(offset);
196}
197
198/*!
199 Flushes the given \a region from the specified \a window, and compositing
200 it with the specified \a textures list.
201
202 The default implementation retrieves the contents using toTexture() and
203 composes using QRhi with OpenGL, Metal, Vulkan, or Direct 3D underneath.
204 May be reimplemented in subclasses if customization is desired.
205
206 \note \a region is relative to the window which may not be top-level in case
207 \a window corresponds to a native child widget. \a offset is the position of
208 the native child relative to the top-level window.
209
210 \sa flush()
211 */
212QPlatformBackingStore::FlushResult QPlatformBackingStore::rhiFlush(QWindow *window,
213 qreal sourceDevicePixelRatio,
214 const QRegion &region,
215 const QPoint &offset,
216 QPlatformTextureList *textures,
217 bool translucentBackground,
218 qreal sourceTransformFactor)
219{
220 auto &surfaceSupport = d_ptr->surfaceSupport[window->surfaceType()];
221 return surfaceSupport.compositor.flush(this,
222 surfaceSupport.rhiSupport.rhi(),
223 surfaceSupport.rhiSupport.swapChainForWindow(window),
224 window, sourceDevicePixelRatio, region, offset, textures,
225 translucentBackground, sourceTransformFactor);
226}
227
228/*!
229 Implemented in subclasses to return the content of the backingstore as a QImage.
230
231 If composition via a 3D graphics API is supported, either this function or
232 toTexture() must be implemented.
233
234 The returned image is only valid until the next operation (resize, paint, scroll,
235 or flush) on the backingstore. The caller must not store the return value between
236 calls, but instead call this function before each use, or make an explicit copy.
237
238 \sa toTexture()
239 */
240QImage QPlatformBackingStore::toImage() const
241{
242 return QImage();
243}
244
245/*!
246 May be reimplemented in subclasses to return the content of the
247 backingstore as an QRhiTexture. \a dirtyRegion is the part of the
248 backingstore which may have changed since the last call to this function. The
249 caller of this function must ensure that there is a current context.
250
251 The ownership of the texture is not transferred. The caller must not store
252 the return value between calls, but instead call this function before each use.
253
254 The default implementation returns a cached texture if \a dirtyRegion is
255 empty and the existing texture's size matches the backingstore size,
256 otherwise it retrieves the content using toImage() and performs a texture
257 upload.
258
259 If the red and blue components have to swapped, \a flags will be set to include \c
260 TextureSwizzle. This allows creating textures from images in formats like
261 QImage::Format_RGB32 without any further image conversion. Instead, the swizzling will
262 be done in the shaders when performing composition. Other formats, that do not need
263 such swizzling due to being already byte ordered RGBA, for example
264 QImage::Format_RGBA8888, must result in having \a needsSwizzle set to false.
265
266 If the image has to be flipped (e.g. because the texture is attached to an FBO), \a
267 flags will be set to include \c TextureFlip.
268
269 \note \a dirtyRegion is relative to the backingstore so no adjustment is needed.
270 */
271QRhiTexture *QPlatformBackingStore::toTexture(QRhiResourceUpdateBatch *resourceUpdates,
272 const QRegion &dirtyRegion,
273 TextureFlags *flags) const
274{
275 auto &surfaceSupport = d_ptr->surfaceSupport[window()->surfaceType()];
276 return surfaceSupport.compositor.toTexture(this,
277 surfaceSupport.rhiSupport.rhi(), resourceUpdates,
278 dirtyRegion, flags);
279}
280
281/*!
282 \fn QPaintDevice* QPlatformBackingStore::paintDevice()
283
284 Implement this function to return the appropriate paint device.
285*/
286
287/*!
288 Constructs an empty surface for the given top-level \a window.
289*/
290QPlatformBackingStore::QPlatformBackingStore(QWindow *window)
291 : d_ptr(new QPlatformBackingStorePrivate(window))
292{
293}
294
295/*!
296 Destroys this surface.
297*/
298QPlatformBackingStore::~QPlatformBackingStore()
299{
300 delete d_ptr;
301}
302
303/*!
304 Returns a pointer to the top-level window associated with this
305 surface.
306*/
307QWindow* QPlatformBackingStore::window() const
308{
309 return d_ptr->window;
310}
311
312/*!
313 Sets the backing store associated with this surface.
314*/
315void QPlatformBackingStore::setBackingStore(QBackingStore *backingStore)
316{
317 d_ptr->backingStore = backingStore;
318}
319
320/*!
321 Returns a pointer to the backing store associated with this
322 surface.
323*/
324QBackingStore *QPlatformBackingStore::backingStore() const
325{
326 return d_ptr->backingStore;
327}
328
329/*!
330 This function is called before painting onto the surface begins,
331 with the \a region in which the painting will occur.
332
333 \sa endPaint(), paintDevice()
334*/
335
336void QPlatformBackingStore::beginPaint(const QRegion &)
337{
338}
339
340/*!
341 This function is called after painting onto the surface has ended.
342
343 \sa beginPaint(), paintDevice()
344*/
345
346void QPlatformBackingStore::endPaint()
347{
348}
349
350/*!
351 Accessor for a backingstores graphics buffer abstraction
352*/
353QPlatformGraphicsBuffer *QPlatformBackingStore::graphicsBuffer() const
354{
355 return nullptr;
356}
357
358/*!
359 Scrolls the given \a area \a dx pixels to the right and \a dy
360 downward; both \a dx and \a dy may be negative.
361
362 Returns \c true if the area was scrolled successfully; false otherwise.
363*/
364bool QPlatformBackingStore::scroll(const QRegion &area, int dx, int dy)
365{
366 Q_UNUSED(area);
367 Q_UNUSED(dx);
368 Q_UNUSED(dy);
369
370 return false;
371}
372
373void QPlatformBackingStore::createRhi(QWindow *window, QPlatformBackingStoreRhiConfig config)
374{
375 if (!config.isEnabled())
376 return;
377
378 qCDebug(lcQpaBackingStore) << "Setting up RHI support in" << this
379 << "for" << window << "with" << window->surfaceType()
380 << "and requested API" << config.api();
381
382 auto &support = d_ptr->surfaceSupport[window->surfaceType()];
383 if (!support.rhiSupport.rhi()) {
384 support.rhiSupport.setConfig(config);
385 support.rhiSupport.setWindow(window);
386 support.rhiSupport.setFormat(window->format());
387 support.rhiSupport.create();
388 } else {
389 qCDebug(lcQpaBackingStore) << "Window already has RHI support"
390 << "with backend" << support.rhiSupport.rhi()->backendName();
391 }
392}
393
394QRhi *QPlatformBackingStore::rhi(QWindow *window) const
395{
396 // Returning null is valid, and means this is not a QRhi-capable backingstore.
397 return d_ptr->surfaceSupport[window->surfaceType()].rhiSupport.rhi();
398}
399
400void QPlatformBackingStore::graphicsDeviceReportedLost(QWindow *window)
401{
402 auto &surfaceSupport = d_ptr->surfaceSupport[window->surfaceType()];
403 if (!surfaceSupport.rhiSupport.rhi())
404 return;
405
406 qWarning("Rhi backingstore: graphics device lost, attempting to reinitialize");
407 surfaceSupport.compositor.reset();
408 surfaceSupport.rhiSupport.reset();
409 surfaceSupport.rhiSupport.create();
410 if (!surfaceSupport.rhiSupport.rhi())
411 qWarning("Rhi backingstore: failed to reinitialize after losing the device");
412}
413
414QT_END_NAMESPACE
415
416#include "moc_qplatformbackingstore.cpp"
std::unordered_map< QSurface::SurfaceType, SurfaceSupport > surfaceSupport
QList< QBackingstoreTextureInfo > textures
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")
Q_DECLARE_TYPEINFO(QBackingstoreTextureInfo, Q_RELOCATABLE_TYPE)
QPlatformTextureList::Flags flags