| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/quick/items/qquickgenericshadereffect.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 <private/qquickgenericshadereffect_p.h> | - | ||||||||||||
| 41 | #include <private/qquickwindow_p.h> | - | ||||||||||||
| 42 | #include <private/qquickitem_p.h> | - | ||||||||||||
| 43 | #include <QSignalMapper> | - | ||||||||||||
| 44 | - | |||||||||||||
| 45 | QT_BEGIN_NAMESPACE | - | ||||||||||||
| 46 | - | |||||||||||||
| 47 | // The generic shader effect is used when the scenegraph backend indicates | - | ||||||||||||
| 48 | // SupportsShaderEffectNode. This, unlike the monolithic and interconnected (e.g. | - | ||||||||||||
| 49 | // with particles) OpenGL variant, passes most of the work to a scenegraph node | - | ||||||||||||
| 50 | // created via the adaptation layer, thus allowing different implementation in | - | ||||||||||||
| 51 | // the backends. | - | ||||||||||||
| 52 | - | |||||||||||||
| 53 | QQuickGenericShaderEffect::QQuickGenericShaderEffect(QQuickShaderEffect *item, QObject *parent) | - | ||||||||||||
| 54 | : QObject(parent) | - | ||||||||||||
| 55 | , m_item(item) | - | ||||||||||||
| 56 | , m_meshResolution(1, 1) | - | ||||||||||||
| 57 | , m_mesh(nullptr) | - | ||||||||||||
| 58 | , m_cullMode(QQuickShaderEffect::NoCulling) | - | ||||||||||||
| 59 | , m_blending(true) | - | ||||||||||||
| 60 | , m_supportsAtlasTextures(false) | - | ||||||||||||
| 61 | , m_mgr(nullptr) | - | ||||||||||||
| 62 | , m_fragNeedsUpdate(true) | - | ||||||||||||
| 63 | , m_vertNeedsUpdate(true) | - | ||||||||||||
| 64 | , m_dirty(nullptr) | - | ||||||||||||
| 65 | { | - | ||||||||||||
| 66 | qRegisterMetaType<QSGGuiThreadShaderEffectManager::ShaderInfo::Type>("ShaderInfo::Type"); | - | ||||||||||||
| 67 | for (int i = 0; i < NShader; ++i)
| 0 | ||||||||||||
| 68 | m_inProgress[i] = nullptr; never executed: m_inProgress[i] = nullptr; | 0 | ||||||||||||
| 69 | } never executed: end of block | 0 | ||||||||||||
| 70 | - | |||||||||||||
| 71 | QQuickGenericShaderEffect::~QQuickGenericShaderEffect() | - | ||||||||||||
| 72 | { | - | ||||||||||||
| 73 | for (int i = 0; i < NShader; ++i) {
| 0 | ||||||||||||
| 74 | disconnectSignals(Shader(i)); | - | ||||||||||||
| 75 | for (const auto &sm : qAsConst(m_signalMappers[i])) | - | ||||||||||||
| 76 | delete sm.mapper; never executed: delete sm.mapper; | 0 | ||||||||||||
| 77 | } never executed: end of block | 0 | ||||||||||||
| 78 | - | |||||||||||||
| 79 | delete m_mgr; | - | ||||||||||||
| 80 | } never executed: end of block | 0 | ||||||||||||
| 81 | - | |||||||||||||
| 82 | void QQuickGenericShaderEffect::setFragmentShader(const QByteArray &src) | - | ||||||||||||
| 83 | { | - | ||||||||||||
| 84 | // Compare the actual values since they are often just filenames. | - | ||||||||||||
| 85 | // Optimizing by comparing constData() is a bad idea since seemingly static | - | ||||||||||||
| 86 | // strings in QML may in fact have different addresses when a binding | - | ||||||||||||
| 87 | // triggers assigning the "same" value to the property. | - | ||||||||||||
| 88 | if (m_fragShader == src)
| 0 | ||||||||||||
| 89 | return; never executed: return; | 0 | ||||||||||||
| 90 | - | |||||||||||||
| 91 | m_fragShader = src; | - | ||||||||||||
| 92 | - | |||||||||||||
| 93 | m_fragNeedsUpdate = true; | - | ||||||||||||
| 94 | if (m_item->isComponentComplete())
| 0 | ||||||||||||
| 95 | maybeUpdateShaders(); never executed: maybeUpdateShaders(); | 0 | ||||||||||||
| 96 | - | |||||||||||||
| 97 | emit m_item->fragmentShaderChanged(); | - | ||||||||||||
| 98 | } never executed: end of block | 0 | ||||||||||||
| 99 | - | |||||||||||||
| 100 | void QQuickGenericShaderEffect::setVertexShader(const QByteArray &src) | - | ||||||||||||
| 101 | { | - | ||||||||||||
| 102 | if (m_vertShader == src)
| 0 | ||||||||||||
| 103 | return; never executed: return; | 0 | ||||||||||||
| 104 | - | |||||||||||||
| 105 | m_vertShader = src; | - | ||||||||||||
| 106 | - | |||||||||||||
| 107 | m_vertNeedsUpdate = true; | - | ||||||||||||
| 108 | if (m_item->isComponentComplete())
| 0 | ||||||||||||
| 109 | maybeUpdateShaders(); never executed: maybeUpdateShaders(); | 0 | ||||||||||||
| 110 | - | |||||||||||||
| 111 | emit m_item->vertexShaderChanged(); | - | ||||||||||||
| 112 | } never executed: end of block | 0 | ||||||||||||
| 113 | - | |||||||||||||
| 114 | void QQuickGenericShaderEffect::setBlending(bool enable) | - | ||||||||||||
| 115 | { | - | ||||||||||||
| 116 | if (m_blending == enable)
| 0 | ||||||||||||
| 117 | return; never executed: return; | 0 | ||||||||||||
| 118 | - | |||||||||||||
| 119 | m_blending = enable; | - | ||||||||||||
| 120 | m_item->update(); | - | ||||||||||||
| 121 | emit m_item->blendingChanged(); | - | ||||||||||||
| 122 | } never executed: end of block | 0 | ||||||||||||
| 123 | - | |||||||||||||
| 124 | QVariant QQuickGenericShaderEffect::mesh() const | - | ||||||||||||
| 125 | { | - | ||||||||||||
| 126 | return m_mesh ? qVariantFromValue(static_cast<QObject *>(m_mesh)) never executed: return m_mesh ? qVariantFromValue(static_cast<QObject *>(m_mesh)) : qVariantFromValue(m_meshResolution); | 0 | ||||||||||||
| 127 | : qVariantFromValue(m_meshResolution); never executed: return m_mesh ? qVariantFromValue(static_cast<QObject *>(m_mesh)) : qVariantFromValue(m_meshResolution); | 0 | ||||||||||||
| 128 | } | - | ||||||||||||
| 129 | - | |||||||||||||
| 130 | void QQuickGenericShaderEffect::setMesh(const QVariant &mesh) | - | ||||||||||||
| 131 | { | - | ||||||||||||
| 132 | QQuickShaderEffectMesh *newMesh = qobject_cast<QQuickShaderEffectMesh *>(qvariant_cast<QObject *>(mesh)); | - | ||||||||||||
| 133 | if (newMesh && newMesh == m_mesh)
| 0 | ||||||||||||
| 134 | return; never executed: return; | 0 | ||||||||||||
| 135 | - | |||||||||||||
| 136 | if (m_mesh)
| 0 | ||||||||||||
| 137 | disconnect(m_mesh, SIGNAL(geometryChanged()), this, nullptr); never executed: disconnect(m_mesh, qFlagLocation("2""geometryChanged()" "\0" __FILE__ ":" "137"), this, nullptr); | 0 | ||||||||||||
| 138 | - | |||||||||||||
| 139 | m_mesh = newMesh; | - | ||||||||||||
| 140 | - | |||||||||||||
| 141 | if (m_mesh) {
| 0 | ||||||||||||
| 142 | connect(m_mesh, SIGNAL(geometryChanged()), this, SLOT(markGeometryDirtyAndUpdate())); | - | ||||||||||||
| 143 | } else { never executed: end of block | 0 | ||||||||||||
| 144 | if (mesh.canConvert<QSize>()) {
| 0 | ||||||||||||
| 145 | m_meshResolution = mesh.toSize(); | - | ||||||||||||
| 146 | } else { never executed: end of block | 0 | ||||||||||||
| 147 | QList<QByteArray> res = mesh.toByteArray().split('x'); | - | ||||||||||||
| 148 | bool ok = res.size() == 2; | - | ||||||||||||
| 149 | if (ok) {
| 0 | ||||||||||||
| 150 | int w = res.at(0).toInt(&ok); | - | ||||||||||||
| 151 | if (ok) {
| 0 | ||||||||||||
| 152 | int h = res.at(1).toInt(&ok); | - | ||||||||||||
| 153 | if (ok)
| 0 | ||||||||||||
| 154 | m_meshResolution = QSize(w, h); never executed: m_meshResolution = QSize(w, h); | 0 | ||||||||||||
| 155 | } never executed: end of block | 0 | ||||||||||||
| 156 | } never executed: end of block | 0 | ||||||||||||
| 157 | if (!ok)
| 0 | ||||||||||||
| 158 | qWarning("ShaderEffect: mesh property must be a size or an object deriving from QQuickShaderEffectMesh"); never executed: QMessageLogger(__FILE__, 158, __PRETTY_FUNCTION__).warning("ShaderEffect: mesh property must be a size or an object deriving from QQuickShaderEffectMesh"); | 0 | ||||||||||||
| 159 | } never executed: end of block | 0 | ||||||||||||
| 160 | m_defaultMesh.setResolution(m_meshResolution); | - | ||||||||||||
| 161 | } never executed: end of block | 0 | ||||||||||||
| 162 | - | |||||||||||||
| 163 | m_dirty |= QSGShaderEffectNode::DirtyShaderMesh; | - | ||||||||||||
| 164 | m_item->update(); | - | ||||||||||||
| 165 | - | |||||||||||||
| 166 | emit m_item->meshChanged(); | - | ||||||||||||
| 167 | } never executed: end of block | 0 | ||||||||||||
| 168 | - | |||||||||||||
| 169 | void QQuickGenericShaderEffect::setCullMode(QQuickShaderEffect::CullMode face) | - | ||||||||||||
| 170 | { | - | ||||||||||||
| 171 | if (m_cullMode == face)
| 0 | ||||||||||||
| 172 | return; never executed: return; | 0 | ||||||||||||
| 173 | - | |||||||||||||
| 174 | m_cullMode = face; | - | ||||||||||||
| 175 | m_item->update(); | - | ||||||||||||
| 176 | emit m_item->cullModeChanged(); | - | ||||||||||||
| 177 | } never executed: end of block | 0 | ||||||||||||
| 178 | - | |||||||||||||
| 179 | void QQuickGenericShaderEffect::setSupportsAtlasTextures(bool supports) | - | ||||||||||||
| 180 | { | - | ||||||||||||
| 181 | if (m_supportsAtlasTextures == supports)
| 0 | ||||||||||||
| 182 | return; never executed: return; | 0 | ||||||||||||
| 183 | - | |||||||||||||
| 184 | m_supportsAtlasTextures = supports; | - | ||||||||||||
| 185 | markGeometryDirtyAndUpdate(); | - | ||||||||||||
| 186 | emit m_item->supportsAtlasTexturesChanged(); | - | ||||||||||||
| 187 | } never executed: end of block | 0 | ||||||||||||
| 188 | - | |||||||||||||
| 189 | QString QQuickGenericShaderEffect::parseLog() | - | ||||||||||||
| 190 | { | - | ||||||||||||
| 191 | maybeUpdateShaders(); | - | ||||||||||||
| 192 | return log(); never executed: return log(); | 0 | ||||||||||||
| 193 | } | - | ||||||||||||
| 194 | - | |||||||||||||
| 195 | QString QQuickGenericShaderEffect::log() const | - | ||||||||||||
| 196 | { | - | ||||||||||||
| 197 | QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); | - | ||||||||||||
| 198 | if (!mgr)
| 0 | ||||||||||||
| 199 | return QString(); never executed: return QString(); | 0 | ||||||||||||
| 200 | - | |||||||||||||
| 201 | return mgr->log(); never executed: return mgr->log(); | 0 | ||||||||||||
| 202 | } | - | ||||||||||||
| 203 | - | |||||||||||||
| 204 | QQuickShaderEffect::Status QQuickGenericShaderEffect::status() const | - | ||||||||||||
| 205 | { | - | ||||||||||||
| 206 | QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); | - | ||||||||||||
| 207 | if (!mgr)
| 0 | ||||||||||||
| 208 | return QQuickShaderEffect::Uncompiled; never executed: return QQuickShaderEffect::Uncompiled; | 0 | ||||||||||||
| 209 | - | |||||||||||||
| 210 | return QQuickShaderEffect::Status(mgr->status()); never executed: return QQuickShaderEffect::Status(mgr->status()); | 0 | ||||||||||||
| 211 | } | - | ||||||||||||
| 212 | - | |||||||||||||
| 213 | void QQuickGenericShaderEffect::handleEvent(QEvent *event) | - | ||||||||||||
| 214 | { | - | ||||||||||||
| 215 | if (event->type() == QEvent::DynamicPropertyChange) {
| 0-108 | ||||||||||||
| 216 | QDynamicPropertyChangeEvent *e = static_cast<QDynamicPropertyChangeEvent *>(event); | - | ||||||||||||
| 217 | for (int shaderType = 0; shaderType < NShader; ++shaderType) {
| 0 | ||||||||||||
| 218 | const auto &vars(m_shaders[shaderType].shaderInfo.variables); | - | ||||||||||||
| 219 | for (int idx = 0; idx < vars.count(); ++idx) {
| 0 | ||||||||||||
| 220 | if (vars[idx].name == e->propertyName()) {
| 0 | ||||||||||||
| 221 | propertyChanged((shaderType << 16) | idx); | - | ||||||||||||
| 222 | break; never executed: break; | 0 | ||||||||||||
| 223 | } | - | ||||||||||||
| 224 | } never executed: end of block | 0 | ||||||||||||
| 225 | } never executed: end of block | 0 | ||||||||||||
| 226 | } never executed: end of block | 0 | ||||||||||||
| 227 | } executed 108 times by 5 tests: end of blockExecuted by:
| 108 | ||||||||||||
| 228 | - | |||||||||||||
| 229 | void QQuickGenericShaderEffect::handleGeometryChanged(const QRectF &, const QRectF &) | - | ||||||||||||
| 230 | { | - | ||||||||||||
| 231 | m_dirty |= QSGShaderEffectNode::DirtyShaderGeometry; | - | ||||||||||||
| 232 | } never executed: end of block | 0 | ||||||||||||
| 233 | - | |||||||||||||
| 234 | QSGNode *QQuickGenericShaderEffect::handleUpdatePaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *) | - | ||||||||||||
| 235 | { | - | ||||||||||||
| 236 | QSGShaderEffectNode *node = static_cast<QSGShaderEffectNode *>(oldNode); | - | ||||||||||||
| 237 | - | |||||||||||||
| 238 | if (m_item->width() <= 0 || m_item->height() <= 0) {
| 0 | ||||||||||||
| 239 | delete node; | - | ||||||||||||
| 240 | return nullptr; never executed: return nullptr; | 0 | ||||||||||||
| 241 | } | - | ||||||||||||
| 242 | - | |||||||||||||
| 243 | // Do not change anything while a new shader is being reflected or compiled. | - | ||||||||||||
| 244 | if (m_inProgress[Vertex] || m_inProgress[Fragment])
| 0 | ||||||||||||
| 245 | return node; never executed: return node; | 0 | ||||||||||||
| 246 | - | |||||||||||||
| 247 | // The manager should be already created on the gui thread. Just take that instance. | - | ||||||||||||
| 248 | QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); | - | ||||||||||||
| 249 | if (!mgr) {
| 0 | ||||||||||||
| 250 | delete node; | - | ||||||||||||
| 251 | return nullptr; never executed: return nullptr; | 0 | ||||||||||||
| 252 | } | - | ||||||||||||
| 253 | - | |||||||||||||
| 254 | if (!node) {
| 0 | ||||||||||||
| 255 | QSGRenderContext *rc = QQuickWindowPrivate::get(m_item->window())->context; | - | ||||||||||||
| 256 | node = rc->sceneGraphContext()->createShaderEffectNode(rc, mgr); | - | ||||||||||||
| 257 | m_dirty = QSGShaderEffectNode::DirtyShaderAll; | - | ||||||||||||
| 258 | } never executed: end of block | 0 | ||||||||||||
| 259 | - | |||||||||||||
| 260 | QSGShaderEffectNode::SyncData sd; | - | ||||||||||||
| 261 | sd.dirty = m_dirty; | - | ||||||||||||
| 262 | sd.cullMode = QSGShaderEffectNode::CullMode(m_cullMode); | - | ||||||||||||
| 263 | sd.blending = m_blending; | - | ||||||||||||
| 264 | sd.vertex.shader = &m_shaders[Vertex]; | - | ||||||||||||
| 265 | sd.vertex.dirtyConstants = &m_dirtyConstants[Vertex]; | - | ||||||||||||
| 266 | sd.vertex.dirtyTextures = &m_dirtyTextures[Vertex]; | - | ||||||||||||
| 267 | sd.fragment.shader = &m_shaders[Fragment]; | - | ||||||||||||
| 268 | sd.fragment.dirtyConstants = &m_dirtyConstants[Fragment]; | - | ||||||||||||
| 269 | sd.fragment.dirtyTextures = &m_dirtyTextures[Fragment]; | - | ||||||||||||
| 270 | node->syncMaterial(&sd); | - | ||||||||||||
| 271 | - | |||||||||||||
| 272 | if (m_dirty & QSGShaderEffectNode::DirtyShaderMesh) {
| 0 | ||||||||||||
| 273 | node->setGeometry(nullptr); | - | ||||||||||||
| 274 | m_dirty &= ~QSGShaderEffectNode::DirtyShaderMesh; | - | ||||||||||||
| 275 | m_dirty |= QSGShaderEffectNode::DirtyShaderGeometry; | - | ||||||||||||
| 276 | } never executed: end of block | 0 | ||||||||||||
| 277 | - | |||||||||||||
| 278 | if (m_dirty & QSGShaderEffectNode::DirtyShaderGeometry) {
| 0 | ||||||||||||
| 279 | const QRectF rect(0, 0, m_item->width(), m_item->height()); | - | ||||||||||||
| 280 | QQuickShaderEffectMesh *mesh = m_mesh ? m_mesh : &m_defaultMesh;
| 0 | ||||||||||||
| 281 | QSGGeometry *geometry = node->geometry(); | - | ||||||||||||
| 282 | - | |||||||||||||
| 283 | const QRectF srcRect = node->updateNormalizedTextureSubRect(m_supportsAtlasTextures); | - | ||||||||||||
| 284 | geometry = mesh->updateGeometry(geometry, 2, 0, srcRect, rect); | - | ||||||||||||
| 285 | - | |||||||||||||
| 286 | node->setFlag(QSGNode::OwnsGeometry, false); | - | ||||||||||||
| 287 | node->setGeometry(geometry); | - | ||||||||||||
| 288 | node->setFlag(QSGNode::OwnsGeometry, true); | - | ||||||||||||
| 289 | - | |||||||||||||
| 290 | m_dirty &= ~QSGShaderEffectNode::DirtyShaderGeometry; | - | ||||||||||||
| 291 | } never executed: end of block | 0 | ||||||||||||
| 292 | - | |||||||||||||
| 293 | m_dirty = nullptr; | - | ||||||||||||
| 294 | for (int i = 0; i < NShader; ++i) {
| 0 | ||||||||||||
| 295 | m_dirtyConstants[i].clear(); | - | ||||||||||||
| 296 | m_dirtyTextures[i].clear(); | - | ||||||||||||
| 297 | } never executed: end of block | 0 | ||||||||||||
| 298 | - | |||||||||||||
| 299 | return node; never executed: return node; | 0 | ||||||||||||
| 300 | } | - | ||||||||||||
| 301 | - | |||||||||||||
| 302 | void QQuickGenericShaderEffect::maybeUpdateShaders() | - | ||||||||||||
| 303 | { | - | ||||||||||||
| 304 | if (m_vertNeedsUpdate)
| 0 | ||||||||||||
| 305 | m_vertNeedsUpdate = !updateShader(Vertex, m_vertShader); never executed: m_vertNeedsUpdate = !updateShader(Vertex, m_vertShader); | 0 | ||||||||||||
| 306 | if (m_fragNeedsUpdate)
| 0 | ||||||||||||
| 307 | m_fragNeedsUpdate = !updateShader(Fragment, m_fragShader); never executed: m_fragNeedsUpdate = !updateShader(Fragment, m_fragShader); | 0 | ||||||||||||
| 308 | if (m_vertNeedsUpdate || m_fragNeedsUpdate) {
| 0 | ||||||||||||
| 309 | // This function is invoked either from componentComplete or in a | - | ||||||||||||
| 310 | // response to a previous invocation's polish() request. If this is | - | ||||||||||||
| 311 | // case #1 then updateShader can fail due to not having a window or | - | ||||||||||||
| 312 | // scenegraph ready. Schedule the polish to try again later. In case #2 | - | ||||||||||||
| 313 | // the backend probably does not have shadereffect support so there is | - | ||||||||||||
| 314 | // nothing to do for us here. | - | ||||||||||||
| 315 | if (!m_item->window() || !m_item->window()->isSceneGraphInitialized())
| 0 | ||||||||||||
| 316 | m_item->polish(); never executed: m_item->polish(); | 0 | ||||||||||||
| 317 | } never executed: end of block | 0 | ||||||||||||
| 318 | } never executed: end of block | 0 | ||||||||||||
| 319 | - | |||||||||||||
| 320 | void QQuickGenericShaderEffect::handleItemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value) | - | ||||||||||||
| 321 | { | - | ||||||||||||
| 322 | // Move the window ref. | - | ||||||||||||
| 323 | if (change == QQuickItem::ItemSceneChange) {
| 0 | ||||||||||||
| 324 | for (int shaderType = 0; shaderType < NShader; ++shaderType) {
| 0 | ||||||||||||
| 325 | for (const auto &vd : qAsConst(m_shaders[shaderType].varData)) { | - | ||||||||||||
| 326 | if (vd.specialType == QSGShaderEffectNode::VariableData::Source) {
| 0 | ||||||||||||
| 327 | QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value)); | - | ||||||||||||
| 328 | if (source) {
| 0 | ||||||||||||
| 329 | if (value.window)
| 0 | ||||||||||||
| 330 | QQuickItemPrivate::get(source)->refWindow(value.window); never executed: QQuickItemPrivate::get(source)->refWindow(value.window); | 0 | ||||||||||||
| 331 | else | - | ||||||||||||
| 332 | QQuickItemPrivate::get(source)->derefWindow(); never executed: QQuickItemPrivate::get(source)->derefWindow(); | 0 | ||||||||||||
| 333 | } | - | ||||||||||||
| 334 | } never executed: end of block | 0 | ||||||||||||
| 335 | } never executed: end of block | 0 | ||||||||||||
| 336 | } never executed: end of block | 0 | ||||||||||||
| 337 | } never executed: end of block | 0 | ||||||||||||
| 338 | } never executed: end of block | 0 | ||||||||||||
| 339 | - | |||||||||||||
| 340 | QSGGuiThreadShaderEffectManager *QQuickGenericShaderEffect::shaderEffectManager() const | - | ||||||||||||
| 341 | { | - | ||||||||||||
| 342 | if (!m_mgr) {
| 0 | ||||||||||||
| 343 | // return null if this is not the gui thread and not already created | - | ||||||||||||
| 344 | if (QThread::currentThread() != m_item->thread())
| 0 | ||||||||||||
| 345 | return m_mgr; never executed: return m_mgr; | 0 | ||||||||||||
| 346 | QQuickWindow *w = m_item->window(); | - | ||||||||||||
| 347 | if (w) { // note: just the window, don't care about isSceneGraphInitialized() here
| 0 | ||||||||||||
| 348 | m_mgr = QQuickWindowPrivate::get(w)->context->sceneGraphContext()->createGuiThreadShaderEffectManager(); | - | ||||||||||||
| 349 | if (m_mgr) {
| 0 | ||||||||||||
| 350 | connect(m_mgr, SIGNAL(logAndStatusChanged()), m_item, SIGNAL(logChanged())); | - | ||||||||||||
| 351 | connect(m_mgr, SIGNAL(logAndStatusChanged()), m_item, SIGNAL(statusChanged())); | - | ||||||||||||
| 352 | connect(m_mgr, SIGNAL(textureChanged()), this, SLOT(markGeometryDirtyAndUpdateIfSupportsAtlas())); | - | ||||||||||||
| 353 | connect(m_mgr, &QSGGuiThreadShaderEffectManager::shaderCodePrepared, this, &QQuickGenericShaderEffect::shaderCodePrepared); | - | ||||||||||||
| 354 | } never executed: end of block | 0 | ||||||||||||
| 355 | } never executed: end of block | 0 | ||||||||||||
| 356 | } never executed: end of block | 0 | ||||||||||||
| 357 | - | |||||||||||||
| 358 | return m_mgr; never executed: return m_mgr; | 0 | ||||||||||||
| 359 | } | - | ||||||||||||
| 360 | - | |||||||||||||
| 361 | void QQuickGenericShaderEffect::disconnectSignals(Shader shaderType) | - | ||||||||||||
| 362 | { | - | ||||||||||||
| 363 | for (auto &sm : m_signalMappers[shaderType]) { | - | ||||||||||||
| 364 | if (sm.active) {
| 0 | ||||||||||||
| 365 | sm.active = false; | - | ||||||||||||
| 366 | QObject::disconnect(m_item, nullptr, sm.mapper, SLOT(map())); | - | ||||||||||||
| 367 | QObject::disconnect(sm.mapper, SIGNAL(mapped(int)), this, SLOT(propertyChanged(int))); | - | ||||||||||||
| 368 | } never executed: end of block | 0 | ||||||||||||
| 369 | } never executed: end of block | 0 | ||||||||||||
| 370 | for (const auto &vd : qAsConst(m_shaders[shaderType].varData)) { | - | ||||||||||||
| 371 | if (vd.specialType == QSGShaderEffectNode::VariableData::Source) {
| 0 | ||||||||||||
| 372 | QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value)); | - | ||||||||||||
| 373 | if (source) {
| 0 | ||||||||||||
| 374 | if (m_item->window())
| 0 | ||||||||||||
| 375 | QQuickItemPrivate::get(source)->derefWindow(); never executed: QQuickItemPrivate::get(source)->derefWindow(); | 0 | ||||||||||||
| 376 | QObject::disconnect(source, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*))); | - | ||||||||||||
| 377 | } never executed: end of block | 0 | ||||||||||||
| 378 | } never executed: end of block | 0 | ||||||||||||
| 379 | } never executed: end of block | 0 | ||||||||||||
| 380 | } never executed: end of block | 0 | ||||||||||||
| 381 | - | |||||||||||||
| 382 | struct ShaderInfoCache | - | ||||||||||||
| 383 | { | - | ||||||||||||
| 384 | bool contains(const QByteArray &key) const | - | ||||||||||||
| 385 | { | - | ||||||||||||
| 386 | return m_shaderInfoCache.contains(key); never executed: return m_shaderInfoCache.contains(key); | 0 | ||||||||||||
| 387 | } | - | ||||||||||||
| 388 | - | |||||||||||||
| 389 | QSGGuiThreadShaderEffectManager::ShaderInfo value(const QByteArray &key) const | - | ||||||||||||
| 390 | { | - | ||||||||||||
| 391 | return m_shaderInfoCache.value(key); never executed: return m_shaderInfoCache.value(key); | 0 | ||||||||||||
| 392 | } | - | ||||||||||||
| 393 | - | |||||||||||||
| 394 | void insert(const QByteArray &key, const QSGGuiThreadShaderEffectManager::ShaderInfo &value) | - | ||||||||||||
| 395 | { | - | ||||||||||||
| 396 | m_shaderInfoCache.insert(key, value); | - | ||||||||||||
| 397 | } never executed: end of block | 0 | ||||||||||||
| 398 | - | |||||||||||||
| 399 | QHash<QByteArray, QSGGuiThreadShaderEffectManager::ShaderInfo> m_shaderInfoCache; | - | ||||||||||||
| 400 | }; | - | ||||||||||||
| 401 | - | |||||||||||||
| 402 | Q_GLOBAL_STATIC(ShaderInfoCache, shaderInfoCache) never executed: end of blocknever executed: guard.store(QtGlobalStatic::Destroyed);never executed: return &holder.value;
| 0 | ||||||||||||
| 403 | - | |||||||||||||
| 404 | bool QQuickGenericShaderEffect::updateShader(Shader shaderType, const QByteArray &src) | - | ||||||||||||
| 405 | { | - | ||||||||||||
| 406 | QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); | - | ||||||||||||
| 407 | if (!mgr)
| 0 | ||||||||||||
| 408 | return false; never executed: return false; | 0 | ||||||||||||
| 409 | - | |||||||||||||
| 410 | const bool texturesSeparate = mgr->hasSeparateSamplerAndTextureObjects(); | - | ||||||||||||
| 411 | - | |||||||||||||
| 412 | disconnectSignals(shaderType); | - | ||||||||||||
| 413 | - | |||||||||||||
| 414 | m_shaders[shaderType].shaderInfo = QSGGuiThreadShaderEffectManager::ShaderInfo(); | - | ||||||||||||
| 415 | m_shaders[shaderType].varData.clear(); | - | ||||||||||||
| 416 | - | |||||||||||||
| 417 | if (!src.isEmpty()) {
| 0 | ||||||||||||
| 418 | if (shaderInfoCache()->contains(src)) {
| 0 | ||||||||||||
| 419 | m_shaders[shaderType].shaderInfo = shaderInfoCache()->value(src); | - | ||||||||||||
| 420 | m_shaders[shaderType].hasShaderCode = true; | - | ||||||||||||
| 421 | } else { never executed: end of block | 0 | ||||||||||||
| 422 | // Each prepareShaderCode call needs its own work area, hence the | - | ||||||||||||
| 423 | // dynamic alloc. If there are calls in progress, let those run to | - | ||||||||||||
| 424 | // finish, their results can then simply be ignored because | - | ||||||||||||
| 425 | // m_inProgress indicates what we care about. | - | ||||||||||||
| 426 | m_inProgress[shaderType] = new QSGGuiThreadShaderEffectManager::ShaderInfo; | - | ||||||||||||
| 427 | const QSGGuiThreadShaderEffectManager::ShaderInfo::Type typeHint = | - | ||||||||||||
| 428 | shaderType == Vertex ? QSGGuiThreadShaderEffectManager::ShaderInfo::TypeVertex
| 0 | ||||||||||||
| 429 | : QSGGuiThreadShaderEffectManager::ShaderInfo::TypeFragment; | - | ||||||||||||
| 430 | // Figure out what input parameters and variables are used in the | - | ||||||||||||
| 431 | // shader. For file-based shader source/bytecode this is where the data | - | ||||||||||||
| 432 | // is pulled in from the file. Some backends may choose to do | - | ||||||||||||
| 433 | // source->bytecode compilation as well in this step. | - | ||||||||||||
| 434 | mgr->prepareShaderCode(typeHint, src, m_inProgress[shaderType]); | - | ||||||||||||
| 435 | // the rest is handled in shaderCodePrepared() | - | ||||||||||||
| 436 | return true; never executed: return true; | 0 | ||||||||||||
| 437 | } | - | ||||||||||||
| 438 | } else { | - | ||||||||||||
| 439 | m_shaders[shaderType].hasShaderCode = false; | - | ||||||||||||
| 440 | if (shaderType == Fragment) {
| 0 | ||||||||||||
| 441 | // With built-in shaders hasShaderCode is set to false and all | - | ||||||||||||
| 442 | // metadata is empty, as it is left up to the node to provide a | - | ||||||||||||
| 443 | // built-in default shader and its metadata. However, in case of | - | ||||||||||||
| 444 | // the built-in fragment shader the value for 'source' has to be | - | ||||||||||||
| 445 | // provided and monitored like with an application-provided shader. | - | ||||||||||||
| 446 | QSGGuiThreadShaderEffectManager::ShaderInfo::Variable v; | - | ||||||||||||
| 447 | v.name = QByteArrayLiteral("source"); never executed: return ba; | 0 | ||||||||||||
| 448 | v.bindPoint = 0; | - | ||||||||||||
| 449 | v.type = texturesSeparate ? QSGGuiThreadShaderEffectManager::ShaderInfo::Texture
| 0 | ||||||||||||
| 450 | : QSGGuiThreadShaderEffectManager::ShaderInfo::Sampler; | - | ||||||||||||
| 451 | m_shaders[shaderType].shaderInfo.variables.append(v); | - | ||||||||||||
| 452 | } never executed: end of block | 0 | ||||||||||||
| 453 | } never executed: end of block | 0 | ||||||||||||
| 454 | - | |||||||||||||
| 455 | updateShaderVars(shaderType); | - | ||||||||||||
| 456 | m_dirty |= QSGShaderEffectNode::DirtyShaders; | - | ||||||||||||
| 457 | m_item->update(); | - | ||||||||||||
| 458 | return true; never executed: return true; | 0 | ||||||||||||
| 459 | } | - | ||||||||||||
| 460 | - | |||||||||||||
| 461 | void QQuickGenericShaderEffect::shaderCodePrepared(bool ok, QSGGuiThreadShaderEffectManager::ShaderInfo::Type typeHint, | - | ||||||||||||
| 462 | const QByteArray &src, QSGGuiThreadShaderEffectManager::ShaderInfo *result) | - | ||||||||||||
| 463 | { | - | ||||||||||||
| 464 | const Shader shaderType = typeHint == QSGGuiThreadShaderEffectManager::ShaderInfo::TypeVertex ? Vertex : Fragment;
| 0 | ||||||||||||
| 465 | - | |||||||||||||
| 466 | // If another call was made to updateShader() for the same shader type in | - | ||||||||||||
| 467 | // the meantime then our results are useless, just drop them. | - | ||||||||||||
| 468 | if (result != m_inProgress[shaderType]) {
| 0 | ||||||||||||
| 469 | delete result; | - | ||||||||||||
| 470 | return; never executed: return; | 0 | ||||||||||||
| 471 | } | - | ||||||||||||
| 472 | - | |||||||||||||
| 473 | m_shaders[shaderType].shaderInfo = *result; | - | ||||||||||||
| 474 | delete result; | - | ||||||||||||
| 475 | m_inProgress[shaderType] = nullptr; | - | ||||||||||||
| 476 | - | |||||||||||||
| 477 | if (!ok) {
| 0 | ||||||||||||
| 478 | qWarning("ShaderEffect: shader preparation failed for %s\n%s\n", src.constData(), qPrintable(log())); | - | ||||||||||||
| 479 | m_shaders[shaderType].hasShaderCode = false; | - | ||||||||||||
| 480 | return; never executed: return; | 0 | ||||||||||||
| 481 | } | - | ||||||||||||
| 482 | - | |||||||||||||
| 483 | m_shaders[shaderType].hasShaderCode = true; | - | ||||||||||||
| 484 | shaderInfoCache()->insert(src, m_shaders[shaderType].shaderInfo); | - | ||||||||||||
| 485 | updateShaderVars(shaderType); | - | ||||||||||||
| 486 | m_dirty |= QSGShaderEffectNode::DirtyShaders; | - | ||||||||||||
| 487 | m_item->update(); | - | ||||||||||||
| 488 | } never executed: end of block | 0 | ||||||||||||
| 489 | - | |||||||||||||
| 490 | void QQuickGenericShaderEffect::updateShaderVars(Shader shaderType) | - | ||||||||||||
| 491 | { | - | ||||||||||||
| 492 | QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager(); | - | ||||||||||||
| 493 | if (!mgr)
| 0 | ||||||||||||
| 494 | return; never executed: return; | 0 | ||||||||||||
| 495 | - | |||||||||||||
| 496 | const bool texturesSeparate = mgr->hasSeparateSamplerAndTextureObjects(); | - | ||||||||||||
| 497 | - | |||||||||||||
| 498 | const int varCount = m_shaders[shaderType].shaderInfo.variables.count(); | - | ||||||||||||
| 499 | m_shaders[shaderType].varData.resize(varCount); | - | ||||||||||||
| 500 | - | |||||||||||||
| 501 | // Reuse signal mappers as much as possible since the mapping is based on | - | ||||||||||||
| 502 | // the index and shader type which are both constant. | - | ||||||||||||
| 503 | if (m_signalMappers[shaderType].count() < varCount)
| 0 | ||||||||||||
| 504 | m_signalMappers[shaderType].resize(varCount); never executed: m_signalMappers[shaderType].resize(varCount); | 0 | ||||||||||||
| 505 | - | |||||||||||||
| 506 | // Hook up the signals to get notified about changes for properties that | - | ||||||||||||
| 507 | // correspond to variables in the shader. Store also the values. | - | ||||||||||||
| 508 | for (int i = 0; i < varCount; ++i) {
| 0 | ||||||||||||
| 509 | const auto &v(m_shaders[shaderType].shaderInfo.variables.at(i)); | - | ||||||||||||
| 510 | QSGShaderEffectNode::VariableData &vd(m_shaders[shaderType].varData[i]); | - | ||||||||||||
| 511 | const bool isSpecial = v.name.startsWith("qt_"); // special names not mapped to properties | - | ||||||||||||
| 512 | if (isSpecial) {
| 0 | ||||||||||||
| 513 | if (v.name == "qt_Opacity")
| 0 | ||||||||||||
| 514 | vd.specialType = QSGShaderEffectNode::VariableData::Opacity; never executed: vd.specialType = QSGShaderEffectNode::VariableData::Opacity; | 0 | ||||||||||||
| 515 | else if (v.name == "qt_Matrix")
| 0 | ||||||||||||
| 516 | vd.specialType = QSGShaderEffectNode::VariableData::Matrix; never executed: vd.specialType = QSGShaderEffectNode::VariableData::Matrix; | 0 | ||||||||||||
| 517 | else if (v.name.startsWith("qt_SubRect_"))
| 0 | ||||||||||||
| 518 | vd.specialType = QSGShaderEffectNode::VariableData::SubRect; never executed: vd.specialType = QSGShaderEffectNode::VariableData::SubRect; | 0 | ||||||||||||
| 519 | continue; never executed: continue; | 0 | ||||||||||||
| 520 | } | - | ||||||||||||
| 521 | - | |||||||||||||
| 522 | // The value of a property corresponding to a sampler is the source | - | ||||||||||||
| 523 | // item ref, unless there are separate texture objects in which case | - | ||||||||||||
| 524 | // the sampler is ignored (here). | - | ||||||||||||
| 525 | if (v.type == QSGGuiThreadShaderEffectManager::ShaderInfo::Sampler) {
| 0 | ||||||||||||
| 526 | if (texturesSeparate) {
| 0 | ||||||||||||
| 527 | vd.specialType = QSGShaderEffectNode::VariableData::Unused; | - | ||||||||||||
| 528 | continue; never executed: continue; | 0 | ||||||||||||
| 529 | } else { | - | ||||||||||||
| 530 | vd.specialType = QSGShaderEffectNode::VariableData::Source; | - | ||||||||||||
| 531 | } never executed: end of block | 0 | ||||||||||||
| 532 | } else if (v.type == QSGGuiThreadShaderEffectManager::ShaderInfo::Texture) {
| 0 | ||||||||||||
| 533 | Q_ASSERT(texturesSeparate); | - | ||||||||||||
| 534 | vd.specialType = QSGShaderEffectNode::VariableData::Source; | - | ||||||||||||
| 535 | } else { never executed: end of block | 0 | ||||||||||||
| 536 | vd.specialType = QSGShaderEffectNode::VariableData::None; | - | ||||||||||||
| 537 | } never executed: end of block | 0 | ||||||||||||
| 538 | - | |||||||||||||
| 539 | // Find the property on the ShaderEffect item. | - | ||||||||||||
| 540 | const int propIdx = m_item->metaObject()->indexOfProperty(v.name.constData()); | - | ||||||||||||
| 541 | if (propIdx >= 0) {
| 0 | ||||||||||||
| 542 | QMetaProperty mp = m_item->metaObject()->property(propIdx); | - | ||||||||||||
| 543 | if (!mp.hasNotifySignal())
| 0 | ||||||||||||
| 544 | qWarning("ShaderEffect: property '%s' does not have notification method", v.name.constData()); never executed: QMessageLogger(__FILE__, 544, __PRETTY_FUNCTION__).warning("ShaderEffect: property '%s' does not have notification method", v.name.constData()); | 0 | ||||||||||||
| 545 | - | |||||||||||||
| 546 | // Have a QSignalMapper that emits mapped() with an index+type on each property change notify signal. | - | ||||||||||||
| 547 | auto &sm(m_signalMappers[shaderType][i]); | - | ||||||||||||
| 548 | if (!sm.mapper) {
| 0 | ||||||||||||
| 549 | QT_WARNING_PUSH | - | ||||||||||||
| 550 | QT_WARNING_DISABLE_DEPRECATED | - | ||||||||||||
| 551 | sm.mapper = new QSignalMapper; | - | ||||||||||||
| 552 | QT_WARNING_POP | - | ||||||||||||
| 553 | sm.mapper->setMapping(m_item, i | (shaderType << 16)); | - | ||||||||||||
| 554 | } never executed: end of block | 0 | ||||||||||||
| 555 | sm.active = true; | - | ||||||||||||
| 556 | const QByteArray signalName = '2' + mp.notifySignal().methodSignature(); | - | ||||||||||||
| 557 | QObject::connect(m_item, signalName, sm.mapper, SLOT(map())); | - | ||||||||||||
| 558 | QObject::connect(sm.mapper, SIGNAL(mapped(int)), this, SLOT(propertyChanged(int))); | - | ||||||||||||
| 559 | } else { never executed: end of block | 0 | ||||||||||||
| 560 | // Do not warn for dynamic properties. | - | ||||||||||||
| 561 | if (!m_item->property(v.name.constData()).isValid())
| 0 | ||||||||||||
| 562 | qWarning("ShaderEffect: '%s' does not have a matching property!", v.name.constData()); never executed: QMessageLogger(__FILE__, 562, __PRETTY_FUNCTION__).warning("ShaderEffect: '%s' does not have a matching property!", v.name.constData()); | 0 | ||||||||||||
| 563 | } never executed: end of block | 0 | ||||||||||||
| 564 | - | |||||||||||||
| 565 | vd.value = m_item->property(v.name.constData()); | - | ||||||||||||
| 566 | - | |||||||||||||
| 567 | if (vd.specialType == QSGShaderEffectNode::VariableData::Source) {
| 0 | ||||||||||||
| 568 | QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value)); | - | ||||||||||||
| 569 | if (source) {
| 0 | ||||||||||||
| 570 | if (m_item->window())
| 0 | ||||||||||||
| 571 | QQuickItemPrivate::get(source)->refWindow(m_item->window()); never executed: QQuickItemPrivate::get(source)->refWindow(m_item->window()); | 0 | ||||||||||||
| 572 | QObject::connect(source, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*))); | - | ||||||||||||
| 573 | } never executed: end of block | 0 | ||||||||||||
| 574 | } never executed: end of block | 0 | ||||||||||||
| 575 | } never executed: end of block | 0 | ||||||||||||
| 576 | } never executed: end of block | 0 | ||||||||||||
| 577 | - | |||||||||||||
| 578 | bool QQuickGenericShaderEffect::sourceIsUnique(QQuickItem *source, Shader typeToSkip, int indexToSkip) const | - | ||||||||||||
| 579 | { | - | ||||||||||||
| 580 | for (int shaderType = 0; shaderType < NShader; ++shaderType) {
| 0 | ||||||||||||
| 581 | for (int idx = 0; idx < m_shaders[shaderType].varData.count(); ++idx) {
| 0 | ||||||||||||
| 582 | if (shaderType != typeToSkip || idx != indexToSkip) {
| 0 | ||||||||||||
| 583 | const auto &vd(m_shaders[shaderType].varData[idx]); | - | ||||||||||||
| 584 | if (vd.specialType == QSGShaderEffectNode::VariableData::Source && qvariant_cast<QObject *>(vd.value) == source)
| 0 | ||||||||||||
| 585 | return false; never executed: return false; | 0 | ||||||||||||
| 586 | } never executed: end of block | 0 | ||||||||||||
| 587 | } never executed: end of block | 0 | ||||||||||||
| 588 | } never executed: end of block | 0 | ||||||||||||
| 589 | return true; never executed: return true; | 0 | ||||||||||||
| 590 | } | - | ||||||||||||
| 591 | - | |||||||||||||
| 592 | void QQuickGenericShaderEffect::propertyChanged(int mappedId) | - | ||||||||||||
| 593 | { | - | ||||||||||||
| 594 | const Shader type = Shader(mappedId >> 16); | - | ||||||||||||
| 595 | const int idx = mappedId & 0xFFFF; | - | ||||||||||||
| 596 | const auto &v(m_shaders[type].shaderInfo.variables[idx]); | - | ||||||||||||
| 597 | auto &vd(m_shaders[type].varData[idx]); | - | ||||||||||||
| 598 | - | |||||||||||||
| 599 | if (vd.specialType == QSGShaderEffectNode::VariableData::Source) {
| 0 | ||||||||||||
| 600 | QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value)); | - | ||||||||||||
| 601 | if (source) {
| 0 | ||||||||||||
| 602 | if (m_item->window())
| 0 | ||||||||||||
| 603 | QQuickItemPrivate::get(source)->derefWindow(); never executed: QQuickItemPrivate::get(source)->derefWindow(); | 0 | ||||||||||||
| 604 | // QObject::disconnect() will disconnect all matching connections. | - | ||||||||||||
| 605 | // If the same source has been attached to two separate | - | ||||||||||||
| 606 | // textures/samplers, then changing one of them would trigger both | - | ||||||||||||
| 607 | // to be disconnected. So check first. | - | ||||||||||||
| 608 | if (sourceIsUnique(source, type, idx))
| 0 | ||||||||||||
| 609 | QObject::disconnect(source, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*))); never executed: QObject::disconnect(source, qFlagLocation("2""destroyed(QObject*)" "\0" __FILE__ ":" "609"), this, qFlagLocation("1""sourceDestroyed(QObject*)" "\0" __FILE__ ":" "609")); | 0 | ||||||||||||
| 610 | } never executed: end of block | 0 | ||||||||||||
| 611 | - | |||||||||||||
| 612 | vd.value = m_item->property(v.name.constData()); | - | ||||||||||||
| 613 | - | |||||||||||||
| 614 | source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value)); | - | ||||||||||||
| 615 | if (source) {
| 0 | ||||||||||||
| 616 | // 'source' needs a window to get a scene graph node. It usually gets one through its | - | ||||||||||||
| 617 | // parent, but if the source item is "inline" rather than a reference -- i.e. | - | ||||||||||||
| 618 | // "property variant source: Image { }" instead of "property variant source: foo" -- it | - | ||||||||||||
| 619 | // will not get a parent. In those cases, 'source' should get the window from 'item'. | - | ||||||||||||
| 620 | if (m_item->window())
| 0 | ||||||||||||
| 621 | QQuickItemPrivate::get(source)->refWindow(m_item->window()); never executed: QQuickItemPrivate::get(source)->refWindow(m_item->window()); | 0 | ||||||||||||
| 622 | QObject::connect(source, SIGNAL(destroyed(QObject*)), this, SLOT(sourceDestroyed(QObject*))); | - | ||||||||||||
| 623 | } never executed: end of block | 0 | ||||||||||||
| 624 | - | |||||||||||||
| 625 | m_dirty |= QSGShaderEffectNode::DirtyShaderTexture; | - | ||||||||||||
| 626 | m_dirtyTextures[type].insert(idx); | - | ||||||||||||
| 627 | - | |||||||||||||
| 628 | } else { never executed: end of block | 0 | ||||||||||||
| 629 | vd.value = m_item->property(v.name.constData()); | - | ||||||||||||
| 630 | m_dirty |= QSGShaderEffectNode::DirtyShaderConstant; | - | ||||||||||||
| 631 | m_dirtyConstants[type].insert(idx); | - | ||||||||||||
| 632 | } never executed: end of block | 0 | ||||||||||||
| 633 | - | |||||||||||||
| 634 | m_item->update(); | - | ||||||||||||
| 635 | } never executed: end of block | 0 | ||||||||||||
| 636 | - | |||||||||||||
| 637 | void QQuickGenericShaderEffect::sourceDestroyed(QObject *object) | - | ||||||||||||
| 638 | { | - | ||||||||||||
| 639 | for (int shaderType = 0; shaderType < NShader; ++shaderType) {
| 0 | ||||||||||||
| 640 | for (auto &vd : m_shaders[shaderType].varData) { | - | ||||||||||||
| 641 | if (vd.specialType == QSGShaderEffectNode::VariableData::Source && vd.value.canConvert<QObject *>()) {
| 0 | ||||||||||||
| 642 | if (qvariant_cast<QObject *>(vd.value) == object)
| 0 | ||||||||||||
| 643 | vd.value = QVariant(); never executed: vd.value = QVariant(); | 0 | ||||||||||||
| 644 | } never executed: end of block | 0 | ||||||||||||
| 645 | } never executed: end of block | 0 | ||||||||||||
| 646 | } never executed: end of block | 0 | ||||||||||||
| 647 | } never executed: end of block | 0 | ||||||||||||
| 648 | - | |||||||||||||
| 649 | void QQuickGenericShaderEffect::markGeometryDirtyAndUpdate() | - | ||||||||||||
| 650 | { | - | ||||||||||||
| 651 | m_dirty |= QSGShaderEffectNode::DirtyShaderGeometry; | - | ||||||||||||
| 652 | m_item->update(); | - | ||||||||||||
| 653 | } never executed: end of block | 0 | ||||||||||||
| 654 | - | |||||||||||||
| 655 | void QQuickGenericShaderEffect::markGeometryDirtyAndUpdateIfSupportsAtlas() | - | ||||||||||||
| 656 | { | - | ||||||||||||
| 657 | if (m_supportsAtlasTextures)
| 0 | ||||||||||||
| 658 | markGeometryDirtyAndUpdate(); never executed: markGeometryDirtyAndUpdate(); | 0 | ||||||||||||
| 659 | } never executed: end of block | 0 | ||||||||||||
| 660 | - | |||||||||||||
| 661 | QT_END_NAMESPACE | - | ||||||||||||
| 662 | - | |||||||||||||
| 663 | #include "moc_qquickgenericshadereffect_p.cpp" | - | ||||||||||||
| Source code | Switch to Preprocessed file |