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
4#include "qplatformbackingstore.h"
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
15QT_BEGIN_NAMESPACE
16
17Q_LOGGING_CATEGORY(lcQpaBackingStore, "qt.qpa.backingstore", QtWarningMsg);
18
19class QPlatformBackingStorePrivate
20{
21public:
22 QPlatformBackingStorePrivate(QWindow *w)
23 : window(w)
24 , backingStore(nullptr)
25 {
26 }
27
28 QWindow *window;
29 QBackingStore *backingStore;
30
31 struct SurfaceSupport {
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)
35 QBackingStoreRhiSupport rhiSupport;
36 QBackingStoreDefaultCompositor compositor;
37 };
38 std::unordered_map<QSurface::SurfaceType, SurfaceSupport> surfaceSupport;
39};
40
41struct QBackingstoreTextureInfo
42{
43 void *source; // may be null
44 QRhiTexture *texture;
45 QRhiTexture *textureExtra;
46 QRect rect;
47 QRect clipRect;
48 QPlatformTextureList::Flags flags;
49};
50
51Q_DECLARE_TYPEINFO(QBackingstoreTextureInfo, Q_RELOCATABLE_TYPE);
52
53class QPlatformTextureListPrivate : public QObjectPrivate
54{
55public:
56 QPlatformTextureListPrivate()
57 : locked(false)
58 {
59 }
60
61 QList<QBackingstoreTextureInfo> textures;
62 bool locked;
63};
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(i: index).texture;
84}
85
86QRhiTexture *QPlatformTextureList::textureExtra(int index) const
87{
88 Q_D(const QPlatformTextureList);
89 return d->textures.at(i: index).textureExtra;
90}
91
92void *QPlatformTextureList::source(int index)
93{
94 Q_D(const QPlatformTextureList);
95 return d->textures.at(i: index).source;
96}
97
98QPlatformTextureList::Flags QPlatformTextureList::flags(int index) const
99{
100 Q_D(const QPlatformTextureList);
101 return d->textures.at(i: index).flags;
102}
103
104QRect QPlatformTextureList::geometry(int index) const
105{
106 Q_D(const QPlatformTextureList);
107 return d->textures.at(i: index).rect;
108}
109
110QRect QPlatformTextureList::clipRect(int index) const
111{
112 Q_D(const QPlatformTextureList);
113 return d->textures.at(i: 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(t: 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(t: 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{
218 auto &surfaceSupport = d_ptr->surfaceSupport[window->surfaceType()];
219 return surfaceSupport.compositor.flush(backingStore: this,
220 rhi: surfaceSupport.rhiSupport.rhi(),
221 swapchain: surfaceSupport.rhiSupport.swapChainForWindow(window),
222 window, sourceDevicePixelRatio, region, offset, textures,
223 translucentBackground);
224}
225
226/*!
227 Implemented in subclasses to return the content of the backingstore as a QImage.
228
229 If composition via a 3D graphics API is supported, either this function or
230 toTexture() must be implemented.
231
232 The returned image is only valid until the next operation (resize, paint, scroll,
233 or flush) on the backingstore. The caller must not store the return value between
234 calls, but instead call this function before each use, or make an explicit copy.
235
236 \sa toTexture()
237 */
238QImage QPlatformBackingStore::toImage() const
239{
240 return QImage();
241}
242
243/*!
244 May be reimplemented in subclasses to return the content of the
245 backingstore as an QRhiTexture. \a dirtyRegion is the part of the
246 backingstore which may have changed since the last call to this function. The
247 caller of this function must ensure that there is a current context.
248
249 The ownership of the texture is not transferred. The caller must not store
250 the return value between calls, but instead call this function before each use.
251
252 The default implementation returns a cached texture if \a dirtyRegion is
253 empty and the existing texture's size matches the backingstore size,
254 otherwise it retrieves the content using toImage() and performs a texture
255 upload.
256
257 If the red and blue components have to swapped, \a flags will be set to include \c
258 TextureSwizzle. This allows creating textures from images in formats like
259 QImage::Format_RGB32 without any further image conversion. Instead, the swizzling will
260 be done in the shaders when performing composition. Other formats, that do not need
261 such swizzling due to being already byte ordered RGBA, for example
262 QImage::Format_RGBA8888, must result in having \a needsSwizzle set to false.
263
264 If the image has to be flipped (e.g. because the texture is attached to an FBO), \a
265 flags will be set to include \c TextureFlip.
266
267 \note \a dirtyRegion is relative to the backingstore so no adjustment is needed.
268 */
269QRhiTexture *QPlatformBackingStore::toTexture(QRhiResourceUpdateBatch *resourceUpdates,
270 const QRegion &dirtyRegion,
271 TextureFlags *flags) const
272{
273 auto &surfaceSupport = d_ptr->surfaceSupport[window()->surfaceType()];
274 return surfaceSupport.compositor.toTexture(backingStore: this,
275 rhi: surfaceSupport.rhiSupport.rhi(), resourceUpdates,
276 dirtyRegion, flags);
277}
278
279/*!
280 \fn QPaintDevice* QPlatformBackingStore::paintDevice()
281
282 Implement this function to return the appropriate paint device.
283*/
284
285/*!
286 Constructs an empty surface for the given top-level \a window.
287*/
288QPlatformBackingStore::QPlatformBackingStore(QWindow *window)
289 : d_ptr(new QPlatformBackingStorePrivate(window))
290{
291}
292
293/*!
294 Destroys this surface.
295*/
296QPlatformBackingStore::~QPlatformBackingStore()
297{
298 delete d_ptr;
299}
300
301/*!
302 Returns a pointer to the top-level window associated with this
303 surface.
304*/
305QWindow* QPlatformBackingStore::window() const
306{
307 return d_ptr->window;
308}
309
310/*!
311 Sets the backing store associated with this surface.
312*/
313void QPlatformBackingStore::setBackingStore(QBackingStore *backingStore)
314{
315 d_ptr->backingStore = backingStore;
316}
317
318/*!
319 Returns a pointer to the backing store associated with this
320 surface.
321*/
322QBackingStore *QPlatformBackingStore::backingStore() const
323{
324 return d_ptr->backingStore;
325}
326
327/*!
328 This function is called before painting onto the surface begins,
329 with the \a region in which the painting will occur.
330
331 \sa endPaint(), paintDevice()
332*/
333
334void QPlatformBackingStore::beginPaint(const QRegion &)
335{
336}
337
338/*!
339 This function is called after painting onto the surface has ended.
340
341 \sa beginPaint(), paintDevice()
342*/
343
344void QPlatformBackingStore::endPaint()
345{
346}
347
348/*!
349 Accessor for a backingstores graphics buffer abstraction
350*/
351QPlatformGraphicsBuffer *QPlatformBackingStore::graphicsBuffer() const
352{
353 return nullptr;
354}
355
356/*!
357 Scrolls the given \a area \a dx pixels to the right and \a dy
358 downward; both \a dx and \a dy may be negative.
359
360 Returns \c true if the area was scrolled successfully; false otherwise.
361*/
362bool QPlatformBackingStore::scroll(const QRegion &area, int dx, int dy)
363{
364 Q_UNUSED(area);
365 Q_UNUSED(dx);
366 Q_UNUSED(dy);
367
368 return false;
369}
370
371void QPlatformBackingStore::createRhi(QWindow *window, QPlatformBackingStoreRhiConfig config)
372{
373 if (!config.isEnabled())
374 return;
375
376 qCDebug(lcQpaBackingStore) << "Setting up RHI support in" << this
377 << "for" << window << "with" << window->surfaceType()
378 << "and requested API" << config.api();
379
380 auto &support = d_ptr->surfaceSupport[window->surfaceType()];
381 if (!support.rhiSupport.rhi()) {
382 support.rhiSupport.setConfig(config);
383 support.rhiSupport.setWindow(window);
384 support.rhiSupport.setFormat(window->format());
385 support.rhiSupport.create();
386 } else {
387 qCDebug(lcQpaBackingStore) << "Window already has RHI support"
388 << "with backend" << support.rhiSupport.rhi()->backendName();
389 }
390}
391
392QRhi *QPlatformBackingStore::rhi(QWindow *window) const
393{
394 // Returning null is valid, and means this is not a QRhi-capable backingstore.
395 return d_ptr->surfaceSupport[window->surfaceType()].rhiSupport.rhi();
396}
397
398void QPlatformBackingStore::graphicsDeviceReportedLost(QWindow *window)
399{
400 auto &surfaceSupport = d_ptr->surfaceSupport[window->surfaceType()];
401 if (!surfaceSupport.rhiSupport.rhi())
402 return;
403
404 qWarning(msg: "Rhi backingstore: graphics device lost, attempting to reinitialize");
405 surfaceSupport.compositor.reset();
406 surfaceSupport.rhiSupport.reset();
407 surfaceSupport.rhiSupport.create();
408 if (!surfaceSupport.rhiSupport.rhi())
409 qWarning(msg: "Rhi backingstore: failed to reinitialize after losing the device");
410}
411
412QT_END_NAMESPACE
413
414#include "moc_qplatformbackingstore.cpp"
415

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtbase/src/gui/painting/qplatformbackingstore.cpp