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