| 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted by:
| 10 | ||||||||||||||||||||||||
| 215 | - | |||||||||||||||||||||||||
| 216 | void scheduleRender() | - | ||||||||||||||||||||||||
| 217 | { | - | ||||||||||||||||||||||||
| 218 | renderPending = true; | - | ||||||||||||||||||||||||
| 219 | window->update(); | - | ||||||||||||||||||||||||
| 220 | } executed 20 times by 1 test: end of blockExecuted 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 blockExecuted by:
| 20 | ||||||||||||||||||||||||
| 243 | } executed 50 times by 1 test: end of blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 blockExecuted 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 |