Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/quick/items/qquickframebufferobject.cpp |
Source code | Switch to Preprocessed file |
Line | Source | Count | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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 QtQuick 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 "qquickframebufferobject.h" | - | ||||||||||||||||||||||||
41 | - | |||||||||||||||||||||||||
42 | #include <QtGui/QOpenGLFramebufferObject> | - | ||||||||||||||||||||||||
43 | #include <QtGui/QOpenGLFunctions> | - | ||||||||||||||||||||||||
44 | #include <private/qquickitem_p.h> | - | ||||||||||||||||||||||||
45 | #include <private/qsgadaptationlayer_p.h> | - | ||||||||||||||||||||||||
46 | #include <qsgtextureprovider.h> | - | ||||||||||||||||||||||||
47 | - | |||||||||||||||||||||||||
48 | #include <QSGSimpleTextureNode> | - | ||||||||||||||||||||||||
49 | #include <QSGRendererInterface> | - | ||||||||||||||||||||||||
50 | - | |||||||||||||||||||||||||
51 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||||||||
52 | - | |||||||||||||||||||||||||
53 | class QQuickFramebufferObjectPrivate : public QQuickItemPrivate | - | ||||||||||||||||||||||||
54 | { | - | ||||||||||||||||||||||||
55 | Q_DECLARE_PUBLIC(QQuickFramebufferObject) | - | ||||||||||||||||||||||||
56 | public: | - | ||||||||||||||||||||||||
57 | QQuickFramebufferObjectPrivate() | - | ||||||||||||||||||||||||
58 | : followsItemSize(true) | - | ||||||||||||||||||||||||
59 | , mirrorVertically(false) | - | ||||||||||||||||||||||||
60 | , node(nullptr) | - | ||||||||||||||||||||||||
61 | { | - | ||||||||||||||||||||||||
62 | } executed 10 times by 1 test: end of block Executed by:
| 10 | ||||||||||||||||||||||||
63 | - | |||||||||||||||||||||||||
64 | bool followsItemSize; | - | ||||||||||||||||||||||||
65 | bool mirrorVertically; | - | ||||||||||||||||||||||||
66 | mutable QSGFramebufferObjectNode *node; | - | ||||||||||||||||||||||||
67 | }; | - | ||||||||||||||||||||||||
68 | - | |||||||||||||||||||||||||
69 | /*! | - | ||||||||||||||||||||||||
70 | * \class QQuickFramebufferObject | - | ||||||||||||||||||||||||
71 | * \inmodule QtQuick | - | ||||||||||||||||||||||||
72 | * \since 5.2 | - | ||||||||||||||||||||||||
73 | * | - | ||||||||||||||||||||||||
74 | * \brief The QQuickFramebufferObject class is a convenience class | - | ||||||||||||||||||||||||
75 | * for integrating OpenGL rendering using a framebuffer object (FBO) | - | ||||||||||||||||||||||||
76 | * with Qt Quick. | - | ||||||||||||||||||||||||
77 | * | - | ||||||||||||||||||||||||
78 | * On most platforms, the rendering will occur on a \l {Scene Graph and Rendering}{dedicated thread}. | - | ||||||||||||||||||||||||
79 | * For this reason, the QQuickFramebufferObject class enforces a strict | - | ||||||||||||||||||||||||
80 | * separation between the item implementation and the FBO rendering. All | - | ||||||||||||||||||||||||
81 | * item logic, such as properties and UI-related helper functions needed by | - | ||||||||||||||||||||||||
82 | * QML should be located in a QQuickFramebufferObject class subclass. | - | ||||||||||||||||||||||||
83 | * Everything that relates to rendering must be located in the | - | ||||||||||||||||||||||||
84 | * QQuickFramebufferObject::Renderer class. | - | ||||||||||||||||||||||||
85 | * | - | ||||||||||||||||||||||||
86 | * To avoid race conditions and read/write issues from two threads | - | ||||||||||||||||||||||||
87 | * it is important that the renderer and the item never read or | - | ||||||||||||||||||||||||
88 | * write shared variables. Communication between the item and the renderer | - | ||||||||||||||||||||||||
89 | * should primarily happen via the | - | ||||||||||||||||||||||||
90 | * QQuickFramebufferObject::Renderer::synchronize() function. This function | - | ||||||||||||||||||||||||
91 | * will be called on the render thread while the GUI thread is blocked. | - | ||||||||||||||||||||||||
92 | * | - | ||||||||||||||||||||||||
93 | * Using queued connections or events for communication between item | - | ||||||||||||||||||||||||
94 | * and renderer is also possible. | - | ||||||||||||||||||||||||
95 | * | - | ||||||||||||||||||||||||
96 | * Both the Renderer and the FBO are memory managed internally. | - | ||||||||||||||||||||||||
97 | * | - | ||||||||||||||||||||||||
98 | * To render into the FBO, the user should subclass the Renderer class | - | ||||||||||||||||||||||||
99 | * and reimplement its Renderer::render() function. The Renderer subclass | - | ||||||||||||||||||||||||
100 | * is returned from createRenderer(). | - | ||||||||||||||||||||||||
101 | * | - | ||||||||||||||||||||||||
102 | * The size of the FBO will by default adapt to the size of | - | ||||||||||||||||||||||||
103 | * the item. If a fixed size is preferred, set textureFollowsItemSize | - | ||||||||||||||||||||||||
104 | * to \c false and return a texture of your choosing from | - | ||||||||||||||||||||||||
105 | * QQuickFramebufferObject::Renderer::createFramebufferObject(). | - | ||||||||||||||||||||||||
106 | * | - | ||||||||||||||||||||||||
107 | * Starting Qt 5.4, the QQuickFramebufferObject class is a | - | ||||||||||||||||||||||||
108 | * \l{QSGTextureProvider}{texture provider} | - | ||||||||||||||||||||||||
109 | * and can be used directly in \l {ShaderEffect}{ShaderEffects} and other | - | ||||||||||||||||||||||||
110 | * classes that consume texture providers. | - | ||||||||||||||||||||||||
111 | * | - | ||||||||||||||||||||||||
112 | * \sa {Scene Graph - Rendering FBOs}, {Scene Graph and Rendering} | - | ||||||||||||||||||||||||
113 | */ | - | ||||||||||||||||||||||||
114 | - | |||||||||||||||||||||||||
115 | /*! | - | ||||||||||||||||||||||||
116 | * Constructs a new QQuickFramebufferObject with parent \a parent. | - | ||||||||||||||||||||||||
117 | */ | - | ||||||||||||||||||||||||
118 | QQuickFramebufferObject::QQuickFramebufferObject(QQuickItem *parent) : | - | ||||||||||||||||||||||||
119 | QQuickItem(*new QQuickFramebufferObjectPrivate, parent) | - | ||||||||||||||||||||||||
120 | { | - | ||||||||||||||||||||||||
121 | setFlag(ItemHasContents); | - | ||||||||||||||||||||||||
122 | } executed 10 times by 1 test: end of block Executed by:
| 10 | ||||||||||||||||||||||||
123 | - | |||||||||||||||||||||||||
124 | /*! | - | ||||||||||||||||||||||||
125 | * \property QQuickFramebufferObject::textureFollowsItemSize | - | ||||||||||||||||||||||||
126 | * | - | ||||||||||||||||||||||||
127 | * This property controls if the size of the FBO's texture should follow | - | ||||||||||||||||||||||||
128 | * the dimensions of the QQuickFramebufferObject item. When this property | - | ||||||||||||||||||||||||
129 | * is false, the FBO will be created once the first time it is displayed. | - | ||||||||||||||||||||||||
130 | * If it is set to true, the FBO will be recreated every time the dimensions | - | ||||||||||||||||||||||||
131 | * of the item change. | - | ||||||||||||||||||||||||
132 | * | - | ||||||||||||||||||||||||
133 | * The default value is \c {true}. | - | ||||||||||||||||||||||||
134 | */ | - | ||||||||||||||||||||||||
135 | - | |||||||||||||||||||||||||
136 | void QQuickFramebufferObject::setTextureFollowsItemSize(bool follows) | - | ||||||||||||||||||||||||
137 | { | - | ||||||||||||||||||||||||
138 | Q_D(QQuickFramebufferObject); | - | ||||||||||||||||||||||||
139 | if (d->followsItemSize == follows)
| 0-6 | ||||||||||||||||||||||||
140 | return; never executed: return; | 0 | ||||||||||||||||||||||||
141 | d->followsItemSize = follows; | - | ||||||||||||||||||||||||
142 | emit textureFollowsItemSizeChanged(d->followsItemSize); | - | ||||||||||||||||||||||||
143 | } executed 6 times by 1 test: end of block Executed by:
| 6 | ||||||||||||||||||||||||
144 | - | |||||||||||||||||||||||||
145 | bool QQuickFramebufferObject::textureFollowsItemSize() const | - | ||||||||||||||||||||||||
146 | { | - | ||||||||||||||||||||||||
147 | Q_D(const QQuickFramebufferObject); | - | ||||||||||||||||||||||||
148 | return d->followsItemSize; never executed: return d->followsItemSize; | 0 | ||||||||||||||||||||||||
149 | } | - | ||||||||||||||||||||||||
150 | - | |||||||||||||||||||||||||
151 | /*! | - | ||||||||||||||||||||||||
152 | * \property QQuickFramebufferObject::mirrorVertically | - | ||||||||||||||||||||||||
153 | * | - | ||||||||||||||||||||||||
154 | * This property controls if the size of the FBO's contents should be mirrored | - | ||||||||||||||||||||||||
155 | * vertically when drawing. This allows easy integration of third-party | - | ||||||||||||||||||||||||
156 | * rendering code that does not follow the standard expectations. | - | ||||||||||||||||||||||||
157 | * | - | ||||||||||||||||||||||||
158 | * The default value is \c {false}. | - | ||||||||||||||||||||||||
159 | * | - | ||||||||||||||||||||||||
160 | * \since 5.6 | - | ||||||||||||||||||||||||
161 | */ | - | ||||||||||||||||||||||||
162 | - | |||||||||||||||||||||||||
163 | void QQuickFramebufferObject::setMirrorVertically(bool enable) | - | ||||||||||||||||||||||||
164 | { | - | ||||||||||||||||||||||||
165 | Q_D(QQuickFramebufferObject); | - | ||||||||||||||||||||||||
166 | if (d->mirrorVertically == enable)
| 0 | ||||||||||||||||||||||||
167 | return; never executed: return; | 0 | ||||||||||||||||||||||||
168 | d->mirrorVertically = enable; | - | ||||||||||||||||||||||||
169 | emit mirrorVerticallyChanged(d->mirrorVertically); | - | ||||||||||||||||||||||||
170 | update(); | - | ||||||||||||||||||||||||
171 | } never executed: end of block | 0 | ||||||||||||||||||||||||
172 | - | |||||||||||||||||||||||||
173 | bool QQuickFramebufferObject::mirrorVertically() const | - | ||||||||||||||||||||||||
174 | { | - | ||||||||||||||||||||||||
175 | Q_D(const QQuickFramebufferObject); | - | ||||||||||||||||||||||||
176 | return d->mirrorVertically; never executed: return d->mirrorVertically; | 0 | ||||||||||||||||||||||||
177 | } | - | ||||||||||||||||||||||||
178 | - | |||||||||||||||||||||||||
179 | /*! | - | ||||||||||||||||||||||||
180 | * \internal | - | ||||||||||||||||||||||||
181 | */ | - | ||||||||||||||||||||||||
182 | void QQuickFramebufferObject::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) | - | ||||||||||||||||||||||||
183 | { | - | ||||||||||||||||||||||||
184 | QQuickItem::geometryChanged(newGeometry, oldGeometry); | - | ||||||||||||||||||||||||
185 | - | |||||||||||||||||||||||||
186 | Q_D(QQuickFramebufferObject); | - | ||||||||||||||||||||||||
187 | if (newGeometry.size() != oldGeometry.size() && d->followsItemSize)
| 0-28 | ||||||||||||||||||||||||
188 | update(); executed 24 times by 1 test: update(); Executed by:
| 24 | ||||||||||||||||||||||||
189 | } executed 28 times by 1 test: end of block Executed by:
| 28 | ||||||||||||||||||||||||
190 | - | |||||||||||||||||||||||||
191 | class QSGFramebufferObjectNode : public QSGTextureProvider, public QSGSimpleTextureNode | - | ||||||||||||||||||||||||
192 | { | - | ||||||||||||||||||||||||
193 | Q_OBJECT | - | ||||||||||||||||||||||||
194 | - | |||||||||||||||||||||||||
195 | public: | - | ||||||||||||||||||||||||
196 | QSGFramebufferObjectNode() | - | ||||||||||||||||||||||||
197 | : window(nullptr) | - | ||||||||||||||||||||||||
198 | , fbo(nullptr) | - | ||||||||||||||||||||||||
199 | , msDisplayFbo(nullptr) | - | ||||||||||||||||||||||||
200 | , renderer(nullptr) | - | ||||||||||||||||||||||||
201 | , renderPending(true) | - | ||||||||||||||||||||||||
202 | , invalidatePending(false) | - | ||||||||||||||||||||||||
203 | , devicePixelRatio(1) | - | ||||||||||||||||||||||||
204 | { | - | ||||||||||||||||||||||||
205 | qsgnode_set_description(this, QStringLiteral("fbonode")); executed 10 times by 1 test: return qstring_literal_temp; Executed by:
| 10 | ||||||||||||||||||||||||
206 | } executed 10 times by 1 test: end of block Executed by:
| 10 | ||||||||||||||||||||||||
207 | - | |||||||||||||||||||||||||
208 | ~QSGFramebufferObjectNode() | - | ||||||||||||||||||||||||
209 | { | - | ||||||||||||||||||||||||
210 | delete renderer; | - | ||||||||||||||||||||||||
211 | delete texture(); | - | ||||||||||||||||||||||||
212 | delete fbo; | - | ||||||||||||||||||||||||
213 | delete msDisplayFbo; | - | ||||||||||||||||||||||||
214 | } executed 10 times by 1 test: end of block Executed by:
| 10 | ||||||||||||||||||||||||
215 | - | |||||||||||||||||||||||||
216 | void scheduleRender() | - | ||||||||||||||||||||||||
217 | { | - | ||||||||||||||||||||||||
218 | renderPending = true; | - | ||||||||||||||||||||||||
219 | window->update(); | - | ||||||||||||||||||||||||
220 | } executed 20 times by 1 test: end of block Executed by:
| 20 | ||||||||||||||||||||||||
221 | - | |||||||||||||||||||||||||
222 | QSGTexture *texture() const override | - | ||||||||||||||||||||||||
223 | { | - | ||||||||||||||||||||||||
224 | return QSGSimpleTextureNode::texture(); executed 20 times by 1 test: return QSGSimpleTextureNode::texture(); Executed by:
| 20 | ||||||||||||||||||||||||
225 | } | - | ||||||||||||||||||||||||
226 | - | |||||||||||||||||||||||||
227 | public Q_SLOTS: | - | ||||||||||||||||||||||||
228 | void render() | - | ||||||||||||||||||||||||
229 | { | - | ||||||||||||||||||||||||
230 | if (renderPending) {
| 20-30 | ||||||||||||||||||||||||
231 | renderPending = false; | - | ||||||||||||||||||||||||
232 | fbo->bind(); | - | ||||||||||||||||||||||||
233 | QOpenGLContext::currentContext()->functions()->glViewport(0, 0, fbo->width(), fbo->height()); | - | ||||||||||||||||||||||||
234 | renderer->render(); | - | ||||||||||||||||||||||||
235 | fbo->bindDefault(); | - | ||||||||||||||||||||||||
236 | - | |||||||||||||||||||||||||
237 | if (msDisplayFbo)
| 0-20 | ||||||||||||||||||||||||
238 | QOpenGLFramebufferObject::blitFramebuffer(msDisplayFbo, fbo); never executed: QOpenGLFramebufferObject::blitFramebuffer(msDisplayFbo, fbo); | 0 | ||||||||||||||||||||||||
239 | - | |||||||||||||||||||||||||
240 | markDirty(QSGNode::DirtyMaterial); | - | ||||||||||||||||||||||||
241 | emit textureChanged(); | - | ||||||||||||||||||||||||
242 | } executed 20 times by 1 test: end of block Executed by:
| 20 | ||||||||||||||||||||||||
243 | } executed 50 times by 1 test: end of block Executed by:
| 50 | ||||||||||||||||||||||||
244 | - | |||||||||||||||||||||||||
245 | void handleScreenChange() | - | ||||||||||||||||||||||||
246 | { | - | ||||||||||||||||||||||||
247 | if (window->effectiveDevicePixelRatio() != devicePixelRatio) {
| 0 | ||||||||||||||||||||||||
248 | renderer->invalidateFramebufferObject(); | - | ||||||||||||||||||||||||
249 | quickFbo->update(); | - | ||||||||||||||||||||||||
250 | } never executed: end of block | 0 | ||||||||||||||||||||||||
251 | } never executed: end of block | 0 | ||||||||||||||||||||||||
252 | - | |||||||||||||||||||||||||
253 | public: | - | ||||||||||||||||||||||||
254 | QQuickWindow *window; | - | ||||||||||||||||||||||||
255 | QOpenGLFramebufferObject *fbo; | - | ||||||||||||||||||||||||
256 | QOpenGLFramebufferObject *msDisplayFbo; | - | ||||||||||||||||||||||||
257 | QQuickFramebufferObject::Renderer *renderer; | - | ||||||||||||||||||||||||
258 | QQuickFramebufferObject *quickFbo; | - | ||||||||||||||||||||||||
259 | - | |||||||||||||||||||||||||
260 | bool renderPending; | - | ||||||||||||||||||||||||
261 | bool invalidatePending; | - | ||||||||||||||||||||||||
262 | - | |||||||||||||||||||||||||
263 | qreal devicePixelRatio; | - | ||||||||||||||||||||||||
264 | }; | - | ||||||||||||||||||||||||
265 | - | |||||||||||||||||||||||||
266 | static inline bool isOpenGL(QSGRenderContext *rc) | - | ||||||||||||||||||||||||
267 | { | - | ||||||||||||||||||||||||
268 | QSGRendererInterface *rif = rc->sceneGraphContext()->rendererInterface(rc); | - | ||||||||||||||||||||||||
269 | return !rif || rif->graphicsApi() == QSGRendererInterface::OpenGL; executed 10 times by 1 test: return !rif || rif->graphicsApi() == QSGRendererInterface::OpenGL; Executed by:
| 10 | ||||||||||||||||||||||||
270 | } | - | ||||||||||||||||||||||||
271 | - | |||||||||||||||||||||||||
272 | /*! | - | ||||||||||||||||||||||||
273 | * \internal | - | ||||||||||||||||||||||||
274 | */ | - | ||||||||||||||||||||||||
275 | QSGNode *QQuickFramebufferObject::updatePaintNode(QSGNode *node, UpdatePaintNodeData *) | - | ||||||||||||||||||||||||
276 | { | - | ||||||||||||||||||||||||
277 | QSGFramebufferObjectNode *n = static_cast<QSGFramebufferObjectNode *>(node); | - | ||||||||||||||||||||||||
278 | - | |||||||||||||||||||||||||
279 | // We only abort if we never had a node before. This is so that we | - | ||||||||||||||||||||||||
280 | // don't recreate the renderer object if the thing becomes tiny. In | - | ||||||||||||||||||||||||
281 | // terms of API it would be horrible if the renderer would go away | - | ||||||||||||||||||||||||
282 | // that easily so with this logic, the renderer only goes away when | - | ||||||||||||||||||||||||
283 | // the scenegraph is invalidated or it is removed from the scene. | - | ||||||||||||||||||||||||
284 | if (!n && (width() <= 0 || height() <= 0))
| 0-10 | ||||||||||||||||||||||||
285 | return nullptr; never executed: return nullptr; | 0 | ||||||||||||||||||||||||
286 | - | |||||||||||||||||||||||||
287 | Q_D(QQuickFramebufferObject); | - | ||||||||||||||||||||||||
288 | - | |||||||||||||||||||||||||
289 | if (!n) {
| 10 | ||||||||||||||||||||||||
290 | if (!isOpenGL(d->sceneGraphRenderContext()))
| 0-10 | ||||||||||||||||||||||||
291 | return nullptr; never executed: return nullptr; | 0 | ||||||||||||||||||||||||
292 | if (!d->node)
| 0-10 | ||||||||||||||||||||||||
293 | d->node = new QSGFramebufferObjectNode; executed 10 times by 1 test: d->node = new QSGFramebufferObjectNode; Executed by:
| 10 | ||||||||||||||||||||||||
294 | n = d->node; | - | ||||||||||||||||||||||||
295 | } executed 10 times by 1 test: end of block Executed by:
| 10 | ||||||||||||||||||||||||
296 | - | |||||||||||||||||||||||||
297 | if (!n->renderer) {
| 10 | ||||||||||||||||||||||||
298 | n->window = window(); | - | ||||||||||||||||||||||||
299 | n->renderer = createRenderer(); | - | ||||||||||||||||||||||||
300 | n->renderer->data = n; | - | ||||||||||||||||||||||||
301 | n->quickFbo = this; | - | ||||||||||||||||||||||||
302 | connect(window(), SIGNAL(beforeRendering()), n, SLOT(render())); | - | ||||||||||||||||||||||||
303 | connect(window(), SIGNAL(screenChanged(QScreen*)), n, SLOT(handleScreenChange())); | - | ||||||||||||||||||||||||
304 | } executed 10 times by 1 test: end of block Executed by:
| 10 | ||||||||||||||||||||||||
305 | - | |||||||||||||||||||||||||
306 | n->renderer->synchronize(this); | - | ||||||||||||||||||||||||
307 | - | |||||||||||||||||||||||||
308 | QSize minFboSize = d->sceneGraphContext()->minimumFBOSize(); | - | ||||||||||||||||||||||||
309 | QSize desiredFboSize(qMax<int>(minFboSize.width(), width()), | - | ||||||||||||||||||||||||
310 | qMax<int>(minFboSize.height(), height())); | - | ||||||||||||||||||||||||
311 | - | |||||||||||||||||||||||||
312 | n->devicePixelRatio = window()->effectiveDevicePixelRatio(); | - | ||||||||||||||||||||||||
313 | desiredFboSize *= n->devicePixelRatio; | - | ||||||||||||||||||||||||
314 | - | |||||||||||||||||||||||||
315 | if (n->fbo && ((d->followsItemSize && n->fbo->size() != desiredFboSize) || n->invalidatePending)) {
| 0-10 | ||||||||||||||||||||||||
316 | delete n->texture(); | - | ||||||||||||||||||||||||
317 | delete n->fbo; | - | ||||||||||||||||||||||||
318 | n->fbo = nullptr; | - | ||||||||||||||||||||||||
319 | delete n->msDisplayFbo; | - | ||||||||||||||||||||||||
320 | n->msDisplayFbo = nullptr; | - | ||||||||||||||||||||||||
321 | n->invalidatePending = false; | - | ||||||||||||||||||||||||
322 | } executed 10 times by 1 test: end of block Executed by:
| 10 | ||||||||||||||||||||||||
323 | - | |||||||||||||||||||||||||
324 | if (!n->fbo) {
| 0-20 | ||||||||||||||||||||||||
325 | n->fbo = n->renderer->createFramebufferObject(desiredFboSize); | - | ||||||||||||||||||||||||
326 | - | |||||||||||||||||||||||||
327 | GLuint displayTexture = n->fbo->texture(); | - | ||||||||||||||||||||||||
328 | - | |||||||||||||||||||||||||
329 | if (n->fbo->format().samples() > 0) {
| 0-20 | ||||||||||||||||||||||||
330 | n->msDisplayFbo = new QOpenGLFramebufferObject(n->fbo->size()); | - | ||||||||||||||||||||||||
331 | displayTexture = n->msDisplayFbo->texture(); | - | ||||||||||||||||||||||||
332 | } never executed: end of block | 0 | ||||||||||||||||||||||||
333 | - | |||||||||||||||||||||||||
334 | n->setTexture(window()->createTextureFromId(displayTexture, | - | ||||||||||||||||||||||||
335 | n->fbo->size(), | - | ||||||||||||||||||||||||
336 | QQuickWindow::TextureHasAlphaChannel)); | - | ||||||||||||||||||||||||
337 | } executed 20 times by 1 test: end of block Executed by:
| 20 | ||||||||||||||||||||||||
338 | - | |||||||||||||||||||||||||
339 | n->setTextureCoordinatesTransform(d->mirrorVertically ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform); | - | ||||||||||||||||||||||||
340 | n->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest); | - | ||||||||||||||||||||||||
341 | n->setRect(0, 0, width(), height()); | - | ||||||||||||||||||||||||
342 | - | |||||||||||||||||||||||||
343 | n->scheduleRender(); | - | ||||||||||||||||||||||||
344 | - | |||||||||||||||||||||||||
345 | return n; executed 20 times by 1 test: return n; Executed by:
| 20 | ||||||||||||||||||||||||
346 | } | - | ||||||||||||||||||||||||
347 | - | |||||||||||||||||||||||||
348 | /*! | - | ||||||||||||||||||||||||
349 | \reimp | - | ||||||||||||||||||||||||
350 | */ | - | ||||||||||||||||||||||||
351 | bool QQuickFramebufferObject::isTextureProvider() const | - | ||||||||||||||||||||||||
352 | { | - | ||||||||||||||||||||||||
353 | return true; never executed: return true; | 0 | ||||||||||||||||||||||||
354 | } | - | ||||||||||||||||||||||||
355 | - | |||||||||||||||||||||||||
356 | /*! | - | ||||||||||||||||||||||||
357 | \reimp | - | ||||||||||||||||||||||||
358 | */ | - | ||||||||||||||||||||||||
359 | QSGTextureProvider *QQuickFramebufferObject::textureProvider() const | - | ||||||||||||||||||||||||
360 | { | - | ||||||||||||||||||||||||
361 | // When Item::layer::enabled == true, QQuickItem will be a texture | - | ||||||||||||||||||||||||
362 | // provider. In this case we should prefer to return the layer rather | - | ||||||||||||||||||||||||
363 | // than the fbo texture. | - | ||||||||||||||||||||||||
364 | if (QQuickItem::isTextureProvider())
| 0 | ||||||||||||||||||||||||
365 | return QQuickItem::textureProvider(); never executed: return QQuickItem::textureProvider(); | 0 | ||||||||||||||||||||||||
366 | - | |||||||||||||||||||||||||
367 | Q_D(const QQuickFramebufferObject); | - | ||||||||||||||||||||||||
368 | QQuickWindow *w = window(); | - | ||||||||||||||||||||||||
369 | if (!w || !w->openglContext() || QThread::currentThread() != w->openglContext()->thread()) {
| 0 | ||||||||||||||||||||||||
370 | qWarning("QQuickFramebufferObject::textureProvider: can only be queried on the rendering thread of an exposed window"); | - | ||||||||||||||||||||||||
371 | return nullptr; never executed: return nullptr; | 0 | ||||||||||||||||||||||||
372 | } | - | ||||||||||||||||||||||||
373 | if (!isOpenGL(d->sceneGraphRenderContext()))
| 0 | ||||||||||||||||||||||||
374 | return nullptr; never executed: return nullptr; | 0 | ||||||||||||||||||||||||
375 | if (!d->node)
| 0 | ||||||||||||||||||||||||
376 | d->node = new QSGFramebufferObjectNode; never executed: d->node = new QSGFramebufferObjectNode; | 0 | ||||||||||||||||||||||||
377 | return d->node; never executed: return d->node; | 0 | ||||||||||||||||||||||||
378 | } | - | ||||||||||||||||||||||||
379 | - | |||||||||||||||||||||||||
380 | /*! | - | ||||||||||||||||||||||||
381 | \reimp | - | ||||||||||||||||||||||||
382 | */ | - | ||||||||||||||||||||||||
383 | void QQuickFramebufferObject::releaseResources() | - | ||||||||||||||||||||||||
384 | { | - | ||||||||||||||||||||||||
385 | // When release resources is called on the GUI thread, we only need to | - | ||||||||||||||||||||||||
386 | // forget about the node. Since it is the node we returned from updatePaintNode | - | ||||||||||||||||||||||||
387 | // it will be managed by the scene graph. | - | ||||||||||||||||||||||||
388 | Q_D(QQuickFramebufferObject); | - | ||||||||||||||||||||||||
389 | d->node = nullptr; | - | ||||||||||||||||||||||||
390 | } executed 10 times by 1 test: end of block Executed by:
| 10 | ||||||||||||||||||||||||
391 | - | |||||||||||||||||||||||||
392 | void QQuickFramebufferObject::invalidateSceneGraph() | - | ||||||||||||||||||||||||
393 | { | - | ||||||||||||||||||||||||
394 | Q_D(QQuickFramebufferObject); | - | ||||||||||||||||||||||||
395 | d->node = nullptr; | - | ||||||||||||||||||||||||
396 | } never executed: end of block | 0 | ||||||||||||||||||||||||
397 | - | |||||||||||||||||||||||||
398 | /*! | - | ||||||||||||||||||||||||
399 | * \class QQuickFramebufferObject::Renderer | - | ||||||||||||||||||||||||
400 | * \inmodule QtQuick | - | ||||||||||||||||||||||||
401 | * \since 5.2 | - | ||||||||||||||||||||||||
402 | * | - | ||||||||||||||||||||||||
403 | * The QQuickFramebufferObject::Renderer class is used to implement the | - | ||||||||||||||||||||||||
404 | * rendering logic of a QQuickFramebufferObject. | - | ||||||||||||||||||||||||
405 | */ | - | ||||||||||||||||||||||||
406 | - | |||||||||||||||||||||||||
407 | /*! | - | ||||||||||||||||||||||||
408 | * Constructs a new renderer. | - | ||||||||||||||||||||||||
409 | * | - | ||||||||||||||||||||||||
410 | * This function is called during the scene graph sync phase when the | - | ||||||||||||||||||||||||
411 | * GUI thread is blocked. | - | ||||||||||||||||||||||||
412 | */ | - | ||||||||||||||||||||||||
413 | QQuickFramebufferObject::Renderer::Renderer() | - | ||||||||||||||||||||||||
414 | : data(nullptr) | - | ||||||||||||||||||||||||
415 | { | - | ||||||||||||||||||||||||
416 | } executed 10 times by 1 test: end of block Executed by:
| 10 | ||||||||||||||||||||||||
417 | - | |||||||||||||||||||||||||
418 | /*! | - | ||||||||||||||||||||||||
419 | * \fn QQuickFramebufferObject::Renderer *QQuickFramebufferObject::createRenderer() const | - | ||||||||||||||||||||||||
420 | * | - | ||||||||||||||||||||||||
421 | * Reimplement this function to create a renderer used to render into the FBO. | - | ||||||||||||||||||||||||
422 | * | - | ||||||||||||||||||||||||
423 | * This function will be called on the rendering thread while the GUI thread is | - | ||||||||||||||||||||||||
424 | * blocked. | - | ||||||||||||||||||||||||
425 | */ | - | ||||||||||||||||||||||||
426 | - | |||||||||||||||||||||||||
427 | /*! | - | ||||||||||||||||||||||||
428 | * The Renderer is automatically deleted when the scene graph resources | - | ||||||||||||||||||||||||
429 | * for the QQuickFramebufferObject item is cleaned up. | - | ||||||||||||||||||||||||
430 | * | - | ||||||||||||||||||||||||
431 | * This function is called on the rendering thread. | - | ||||||||||||||||||||||||
432 | */ | - | ||||||||||||||||||||||||
433 | QQuickFramebufferObject::Renderer::~Renderer() | - | ||||||||||||||||||||||||
434 | { | - | ||||||||||||||||||||||||
435 | } | - | ||||||||||||||||||||||||
436 | - | |||||||||||||||||||||||||
437 | /*! | - | ||||||||||||||||||||||||
438 | * Returns the framebuffer object currently being rendered to. | - | ||||||||||||||||||||||||
439 | */ | - | ||||||||||||||||||||||||
440 | QOpenGLFramebufferObject *QQuickFramebufferObject::Renderer::framebufferObject() const | - | ||||||||||||||||||||||||
441 | { | - | ||||||||||||||||||||||||
442 | return data ? ((QSGFramebufferObjectNode *) data)->fbo : nullptr; executed 20 times by 1 test: return data ? ((QSGFramebufferObjectNode *) data)->fbo : nullptr; Executed by:
| 20 | ||||||||||||||||||||||||
443 | } | - | ||||||||||||||||||||||||
444 | - | |||||||||||||||||||||||||
445 | /*! | - | ||||||||||||||||||||||||
446 | * \fn void QQuickFramebufferObject::Renderer::render() | - | ||||||||||||||||||||||||
447 | * | - | ||||||||||||||||||||||||
448 | * This function is called when the FBO should be rendered into. The framebuffer | - | ||||||||||||||||||||||||
449 | * is bound at this point and the \c glViewport has been set up to match | - | ||||||||||||||||||||||||
450 | * the FBO size. | - | ||||||||||||||||||||||||
451 | * | - | ||||||||||||||||||||||||
452 | * The FBO will be automatically unbound after the function returns. | - | ||||||||||||||||||||||||
453 | * | - | ||||||||||||||||||||||||
454 | * \note Do not assume that the OpenGL state is all set to the defaults when | - | ||||||||||||||||||||||||
455 | * this function is invoked, or that it is maintained between calls. Both the Qt | - | ||||||||||||||||||||||||
456 | * Quick renderer and the custom rendering code uses the same OpenGL | - | ||||||||||||||||||||||||
457 | * context. This means that the state might have been modified by Quick before | - | ||||||||||||||||||||||||
458 | * invoking this function. | - | ||||||||||||||||||||||||
459 | * | - | ||||||||||||||||||||||||
460 | * \note It is recommended to call QQuickWindow::resetOpenGLState() before | - | ||||||||||||||||||||||||
461 | * returning. This resets OpenGL state used by the Qt Quick renderer and thus | - | ||||||||||||||||||||||||
462 | * avoids interference from the state changes made by the rendering code in this | - | ||||||||||||||||||||||||
463 | * function. | - | ||||||||||||||||||||||||
464 | */ | - | ||||||||||||||||||||||||
465 | - | |||||||||||||||||||||||||
466 | /*! | - | ||||||||||||||||||||||||
467 | * This function is called as a result of QQuickFramebufferObject::update(). | - | ||||||||||||||||||||||||
468 | * | - | ||||||||||||||||||||||||
469 | * Use this function to update the renderer with changes that have occurred | - | ||||||||||||||||||||||||
470 | * in the item. \a item is the item that instantiated this renderer. The function | - | ||||||||||||||||||||||||
471 | * is called once before the FBO is created. | - | ||||||||||||||||||||||||
472 | * | - | ||||||||||||||||||||||||
473 | * \e {For instance, if the item has a color property which is controlled by | - | ||||||||||||||||||||||||
474 | * QML, one should call QQuickFramebufferObject::update() and use | - | ||||||||||||||||||||||||
475 | * synchronize() to copy the new color into the renderer so that it can be | - | ||||||||||||||||||||||||
476 | * used to render the next frame.} | - | ||||||||||||||||||||||||
477 | * | - | ||||||||||||||||||||||||
478 | * This function is the only place when it is safe for the renderer and the | - | ||||||||||||||||||||||||
479 | * item to read and write each others members. | - | ||||||||||||||||||||||||
480 | */ | - | ||||||||||||||||||||||||
481 | void QQuickFramebufferObject::Renderer::synchronize(QQuickFramebufferObject *item) | - | ||||||||||||||||||||||||
482 | { | - | ||||||||||||||||||||||||
483 | Q_UNUSED(item); | - | ||||||||||||||||||||||||
484 | } never executed: end of block | 0 | ||||||||||||||||||||||||
485 | - | |||||||||||||||||||||||||
486 | /*! | - | ||||||||||||||||||||||||
487 | * Call this function during synchronize() to invalidate the current FBO. This | - | ||||||||||||||||||||||||
488 | * will result in a new FBO being created with createFramebufferObject(). | - | ||||||||||||||||||||||||
489 | */ | - | ||||||||||||||||||||||||
490 | void QQuickFramebufferObject::Renderer::invalidateFramebufferObject() | - | ||||||||||||||||||||||||
491 | { | - | ||||||||||||||||||||||||
492 | if (data)
| 0-8 | ||||||||||||||||||||||||
493 | ((QSGFramebufferObjectNode *) data)->invalidatePending = true; executed 8 times by 1 test: ((QSGFramebufferObjectNode *) data)->invalidatePending = true; Executed by:
| 8 | ||||||||||||||||||||||||
494 | } executed 8 times by 1 test: end of block Executed by:
| 8 | ||||||||||||||||||||||||
495 | - | |||||||||||||||||||||||||
496 | /*! | - | ||||||||||||||||||||||||
497 | * This function is called when a new FBO is needed. This happens on the | - | ||||||||||||||||||||||||
498 | * initial frame. If QQuickFramebufferObject::textureFollowsItemSize is set to true, | - | ||||||||||||||||||||||||
499 | * it is called again every time the dimensions of the item changes. | - | ||||||||||||||||||||||||
500 | * | - | ||||||||||||||||||||||||
501 | * The returned FBO can have any attachment. If the QOpenGLFramebufferObjectFormat | - | ||||||||||||||||||||||||
502 | * indicates that the FBO should be multisampled, the internal implementation | - | ||||||||||||||||||||||||
503 | * of the Renderer will allocate a second FBO and blit the multisampled FBO | - | ||||||||||||||||||||||||
504 | * into the FBO used to display the texture. | - | ||||||||||||||||||||||||
505 | * | - | ||||||||||||||||||||||||
506 | * \note Some hardware has issues with small FBO sizes. \a size takes that into account, so | - | ||||||||||||||||||||||||
507 | * be cautious when overriding the size with a fixed size. A minimal size of 64x64 should | - | ||||||||||||||||||||||||
508 | * always work. | - | ||||||||||||||||||||||||
509 | * | - | ||||||||||||||||||||||||
510 | * \note \a size takes the device pixel ratio into account, meaning that it is | - | ||||||||||||||||||||||||
511 | * already multiplied by the correct scale factor. When moving the window | - | ||||||||||||||||||||||||
512 | * containing the QQuickFramebufferObject item to a screen with different | - | ||||||||||||||||||||||||
513 | * settings, the FBO is automatically recreated and this function is invoked | - | ||||||||||||||||||||||||
514 | * with the correct size. | - | ||||||||||||||||||||||||
515 | */ | - | ||||||||||||||||||||||||
516 | QOpenGLFramebufferObject *QQuickFramebufferObject::Renderer::createFramebufferObject(const QSize &size) | - | ||||||||||||||||||||||||
517 | { | - | ||||||||||||||||||||||||
518 | return new QOpenGLFramebufferObject(size); never executed: return new QOpenGLFramebufferObject(size); | 0 | ||||||||||||||||||||||||
519 | } | - | ||||||||||||||||||||||||
520 | - | |||||||||||||||||||||||||
521 | /*! | - | ||||||||||||||||||||||||
522 | * Call this function when the FBO should be rendered again. | - | ||||||||||||||||||||||||
523 | * | - | ||||||||||||||||||||||||
524 | * This function can be called from render() to force the FBO to be rendered | - | ||||||||||||||||||||||||
525 | * again before the next frame. | - | ||||||||||||||||||||||||
526 | * | - | ||||||||||||||||||||||||
527 | * \note This function should be used from inside the renderer. To update | - | ||||||||||||||||||||||||
528 | * the item on the GUI thread, use QQuickFramebufferObject::update(). | - | ||||||||||||||||||||||||
529 | */ | - | ||||||||||||||||||||||||
530 | void QQuickFramebufferObject::Renderer::update() | - | ||||||||||||||||||||||||
531 | { | - | ||||||||||||||||||||||||
532 | if (data)
| 0 | ||||||||||||||||||||||||
533 | ((QSGFramebufferObjectNode *) data)->scheduleRender(); never executed: ((QSGFramebufferObjectNode *) data)->scheduleRender(); | 0 | ||||||||||||||||||||||||
534 | } never executed: end of block | 0 | ||||||||||||||||||||||||
535 | - | |||||||||||||||||||||||||
536 | - | |||||||||||||||||||||||||
537 | #include "qquickframebufferobject.moc" | - | ||||||||||||||||||||||||
538 | #include "moc_qquickframebufferobject.cpp" | - | ||||||||||||||||||||||||
539 | - | |||||||||||||||||||||||||
540 | QT_END_NAMESPACE | - | ||||||||||||||||||||||||
Source code | Switch to Preprocessed file |