1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qplatformbackingstore.h"
41#include <qwindow.h>
42#include <qpixmap.h>
43
44#include <QtCore/private/qobject_p.h>
45
46QT_BEGIN_NAMESPACE
47
48Q_LOGGING_CATEGORY(lcQpaBackingStore, "qt.qpa.backingstore", QtWarningMsg);
49
50class QPlatformBackingStorePrivate
51{
52public:
53 QPlatformBackingStorePrivate(QWindow *w)
54 : window(w)
55 , backingStore(nullptr)
56 {
57 }
58
59 ~QPlatformBackingStorePrivate()
60 {
61#ifndef QT_NO_OPENGL
62 delete openGLSupport;
63#endif
64 }
65 QWindow *window;
66 QBackingStore *backingStore;
67#ifndef QT_NO_OPENGL
68 QPlatformBackingStoreOpenGLSupportBase *openGLSupport = nullptr;
69#endif
70};
71
72#ifndef QT_NO_OPENGL
73
74struct QBackingstoreTextureInfo
75{
76 void *source; // may be null
77 GLuint textureId;
78 QRect rect;
79 QRect clipRect;
80 QPlatformTextureList::Flags flags;
81};
82
83Q_DECLARE_TYPEINFO(QBackingstoreTextureInfo, Q_MOVABLE_TYPE);
84
85class QPlatformTextureListPrivate : public QObjectPrivate
86{
87public:
88 QPlatformTextureListPrivate()
89 : locked(false)
90 {
91 }
92
93 QList<QBackingstoreTextureInfo> textures;
94 bool locked;
95};
96
97QPlatformTextureList::QPlatformTextureList(QObject *parent)
98: QObject(*new QPlatformTextureListPrivate, parent)
99{
100}
101
102QPlatformTextureList::~QPlatformTextureList()
103{
104}
105
106int QPlatformTextureList::count() const
107{
108 Q_D(const QPlatformTextureList);
109 return d->textures.count();
110}
111
112GLuint QPlatformTextureList::textureId(int index) const
113{
114 Q_D(const QPlatformTextureList);
115 return d->textures.at(index).textureId;
116}
117
118void *QPlatformTextureList::source(int index)
119{
120 Q_D(const QPlatformTextureList);
121 return d->textures.at(index).source;
122}
123
124QPlatformTextureList::Flags QPlatformTextureList::flags(int index) const
125{
126 Q_D(const QPlatformTextureList);
127 return d->textures.at(index).flags;
128}
129
130QRect QPlatformTextureList::geometry(int index) const
131{
132 Q_D(const QPlatformTextureList);
133 return d->textures.at(index).rect;
134}
135
136QRect QPlatformTextureList::clipRect(int index) const
137{
138 Q_D(const QPlatformTextureList);
139 return d->textures.at(index).clipRect;
140}
141
142void QPlatformTextureList::lock(bool on)
143{
144 Q_D(QPlatformTextureList);
145 if (on != d->locked) {
146 d->locked = on;
147 emit locked(on);
148 }
149}
150
151bool QPlatformTextureList::isLocked() const
152{
153 Q_D(const QPlatformTextureList);
154 return d->locked;
155}
156
157void QPlatformTextureList::appendTexture(void *source, GLuint textureId, const QRect &geometry,
158 const QRect &clipRect, Flags flags)
159{
160 Q_D(QPlatformTextureList);
161 QBackingstoreTextureInfo bi;
162 bi.source = source;
163 bi.textureId = textureId;
164 bi.rect = geometry;
165 bi.clipRect = clipRect;
166 bi.flags = flags;
167 d->textures.append(bi);
168}
169
170void QPlatformTextureList::clear()
171{
172 Q_D(QPlatformTextureList);
173 d->textures.clear();
174}
175#endif // QT_NO_OPENGL
176
177/*!
178 \class QPlatformBackingStore
179 \since 5.0
180 \internal
181 \preliminary
182 \ingroup qpa
183
184 \brief The QPlatformBackingStore class provides the drawing area for top-level
185 windows.
186*/
187
188#ifndef QT_NO_OPENGL
189/*!
190 Flushes the given \a region from the specified \a window onto the
191 screen, and composes it with the specified \a textures.
192
193 The default implementation retrieves the contents using toTexture()
194 and composes using OpenGL. May be reimplemented in subclasses if there
195 is a more efficient native way to do it.
196
197 \note \a region is relative to the window which may not be top-level in case
198 \a window corresponds to a native child widget. \a offset is the position of
199 the native child relative to the top-level window.
200 */
201
202void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &region,
203 const QPoint &offset,
204 QPlatformTextureList *textures,
205 bool translucentBackground)
206{
207 if (auto *c = d_ptr->openGLSupport)
208 c->composeAndFlush(window, region, offset, textures, translucentBackground);
209 else
210 qWarning() << Q_FUNC_INFO << "no opengl support set";
211}
212#endif
213
214/*!
215 Implemented in subclasses to return the content of the backingstore as a QImage.
216
217 If QPlatformIntegration::RasterGLSurface is supported, either this function or
218 toTexture() must be implemented.
219
220 \sa toTexture()
221 */
222QImage QPlatformBackingStore::toImage() const
223{
224 return QImage();
225}
226#ifndef QT_NO_OPENGL
227/*!
228 May be reimplemented in subclasses to return the content of the
229 backingstore as an OpenGL texture. \a dirtyRegion is the part of the
230 backingstore which may have changed since the last call to this function. The
231 caller of this function must ensure that there is a current context.
232
233 The size of the texture is returned in \a textureSize.
234
235 The ownership of the texture is not transferred. The caller must not store
236 the return value between calls, but instead call this function before each use.
237
238 The default implementation returns a cached texture if \a dirtyRegion is empty and
239 \a textureSize matches the backingstore size, otherwise it retrieves the content using
240 toImage() and performs a texture upload. This works only if the value of \a textureSize
241 is preserved between the calls to this function.
242
243 If the red and blue components have to swapped, \a flags will be set to include \c
244 TextureSwizzle. This allows creating textures from images in formats like
245 QImage::Format_RGB32 without any further image conversion. Instead, the swizzling will
246 be done in the shaders when performing composition. Other formats, that do not need
247 such swizzling due to being already byte ordered RGBA, for example
248 QImage::Format_RGBA8888, must result in having \a needsSwizzle set to false.
249
250 If the image has to be flipped (e.g. because the texture is attached to an FBO), \a
251 flags will be set to include \c TextureFlip.
252
253 \note \a dirtyRegion is relative to the backingstore so no adjustment is needed.
254 */
255GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const
256{
257 if (auto *c = d_ptr->openGLSupport)
258 return c->toTexture(dirtyRegion, textureSize, flags);
259 else {
260 qWarning() << Q_FUNC_INFO << "no opengl support set";
261 return 0;
262 }
263}
264#endif // QT_NO_OPENGL
265
266/*!
267 \fn QPaintDevice* QPlatformBackingStore::paintDevice()
268
269 Implement this function to return the appropriate paint device.
270*/
271
272/*!
273 Constructs an empty surface for the given top-level \a window.
274*/
275QPlatformBackingStore::QPlatformBackingStore(QWindow *window)
276 : d_ptr(new QPlatformBackingStorePrivate(window))
277{
278#ifndef QT_NO_OPENGL
279 if (auto createOpenGLSupport = QPlatformBackingStoreOpenGLSupportBase::factoryFunction()) {
280 d_ptr->openGLSupport = createOpenGLSupport();
281 d_ptr->openGLSupport->backingStore = this;
282 }
283#endif
284}
285
286/*!
287 Destroys this surface.
288*/
289QPlatformBackingStore::~QPlatformBackingStore()
290{
291 delete d_ptr;
292}
293
294/*!
295 Returns a pointer to the top-level window associated with this
296 surface.
297*/
298QWindow* QPlatformBackingStore::window() const
299{
300 return d_ptr->window;
301}
302
303/*!
304 Sets the backing store associated with this surface.
305*/
306void QPlatformBackingStore::setBackingStore(QBackingStore *backingStore)
307{
308 d_ptr->backingStore = backingStore;
309}
310
311/*!
312 Returns a pointer to the backing store associated with this
313 surface.
314*/
315QBackingStore *QPlatformBackingStore::backingStore() const
316{
317 return d_ptr->backingStore;
318}
319
320#ifndef QT_NO_OPENGL
321
322using FactoryFunction = QPlatformBackingStoreOpenGLSupportBase::FactoryFunction;
323
324/*!
325 Registers a factory function for OpenGL implementation helper.
326
327 The QtOpenGL library automatically registers a default function,
328 unless already set by the platform plugin in other ways.
329*/
330void QPlatformBackingStoreOpenGLSupportBase::setFactoryFunction(FactoryFunction function)
331{
332 s_factoryFunction = function;
333}
334
335FactoryFunction QPlatformBackingStoreOpenGLSupportBase::factoryFunction()
336{
337 return s_factoryFunction;
338}
339
340FactoryFunction QPlatformBackingStoreOpenGLSupportBase::s_factoryFunction = nullptr;
341
342#endif // QT_NO_OPENGL
343
344/*!
345 This function is called before painting onto the surface begins,
346 with the \a region in which the painting will occur.
347
348 \sa endPaint(), paintDevice()
349*/
350
351void QPlatformBackingStore::beginPaint(const QRegion &)
352{
353}
354
355/*!
356 This function is called after painting onto the surface has ended.
357
358 \sa beginPaint(), paintDevice()
359*/
360
361void QPlatformBackingStore::endPaint()
362{
363}
364
365/*!
366 Accessor for a backingstores graphics buffer abstraction
367*/
368QPlatformGraphicsBuffer *QPlatformBackingStore::graphicsBuffer() const
369{
370 return nullptr;
371}
372
373/*!
374 Scrolls the given \a area \a dx pixels to the right and \a dy
375 downward; both \a dx and \a dy may be negative.
376
377 Returns \c true if the area was scrolled successfully; false otherwise.
378*/
379bool QPlatformBackingStore::scroll(const QRegion &area, int dx, int dy)
380{
381 Q_UNUSED(area);
382 Q_UNUSED(dx);
383 Q_UNUSED(dy);
384
385 return false;
386}
387
388QT_END_NAMESPACE
389