| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/particles/qquickcustomparticle.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 QtQml 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 "qquickcustomparticle_p.h" | - | ||||||||||||||||||
| 41 | #include <QtCore/qrandom.h> | - | ||||||||||||||||||
| 42 | #include <QtQuick/private/qquickshadereffectmesh_p.h> | - | ||||||||||||||||||
| 43 | #include <QtQuick/private/qsgshadersourcebuilder_p.h> | - | ||||||||||||||||||
| 44 | #include <QtQml/qqmlinfo.h> | - | ||||||||||||||||||
| 45 | - | |||||||||||||||||||
| 46 | QT_BEGIN_NAMESPACE | - | ||||||||||||||||||
| 47 | - | |||||||||||||||||||
| 48 | static QSGGeometry::Attribute PlainParticle_Attributes[] = { | - | ||||||||||||||||||
| 49 | QSGGeometry::Attribute::create(0, 2, GL_FLOAT, true), // Position | - | ||||||||||||||||||
| 50 | QSGGeometry::Attribute::create(1, 2, GL_FLOAT), // TexCoord | - | ||||||||||||||||||
| 51 | QSGGeometry::Attribute::create(2, 4, GL_FLOAT), // Data | - | ||||||||||||||||||
| 52 | QSGGeometry::Attribute::create(3, 4, GL_FLOAT), // Vectors | - | ||||||||||||||||||
| 53 | QSGGeometry::Attribute::create(4, 1, GL_FLOAT) // r | - | ||||||||||||||||||
| 54 | }; | - | ||||||||||||||||||
| 55 | - | |||||||||||||||||||
| 56 | static QSGGeometry::AttributeSet PlainParticle_AttributeSet = | - | ||||||||||||||||||
| 57 | { | - | ||||||||||||||||||
| 58 | 5, // Attribute Count | - | ||||||||||||||||||
| 59 | (2 + 2 + 4 + 4 + 1) * sizeof(float), | - | ||||||||||||||||||
| 60 | PlainParticle_Attributes | - | ||||||||||||||||||
| 61 | }; | - | ||||||||||||||||||
| 62 | - | |||||||||||||||||||
| 63 | struct PlainVertex { | - | ||||||||||||||||||
| 64 | float x; | - | ||||||||||||||||||
| 65 | float y; | - | ||||||||||||||||||
| 66 | float tx; | - | ||||||||||||||||||
| 67 | float ty; | - | ||||||||||||||||||
| 68 | float t; | - | ||||||||||||||||||
| 69 | float lifeSpan; | - | ||||||||||||||||||
| 70 | float size; | - | ||||||||||||||||||
| 71 | float endSize; | - | ||||||||||||||||||
| 72 | float vx; | - | ||||||||||||||||||
| 73 | float vy; | - | ||||||||||||||||||
| 74 | float ax; | - | ||||||||||||||||||
| 75 | float ay; | - | ||||||||||||||||||
| 76 | float r; | - | ||||||||||||||||||
| 77 | }; | - | ||||||||||||||||||
| 78 | - | |||||||||||||||||||
| 79 | struct PlainVertices { | - | ||||||||||||||||||
| 80 | PlainVertex v1; | - | ||||||||||||||||||
| 81 | PlainVertex v2; | - | ||||||||||||||||||
| 82 | PlainVertex v3; | - | ||||||||||||||||||
| 83 | PlainVertex v4; | - | ||||||||||||||||||
| 84 | }; | - | ||||||||||||||||||
| 85 | - | |||||||||||||||||||
| 86 | /*! | - | ||||||||||||||||||
| 87 | \qmltype CustomParticle | - | ||||||||||||||||||
| 88 | \instantiates QQuickCustomParticle | - | ||||||||||||||||||
| 89 | \inqmlmodule QtQuick.Particles | - | ||||||||||||||||||
| 90 | \inherits ParticlePainter | - | ||||||||||||||||||
| 91 | \brief For specifying shaders to paint particles. | - | ||||||||||||||||||
| 92 | \ingroup qtquick-particles | - | ||||||||||||||||||
| 93 | - | |||||||||||||||||||
| 94 | \note The maximum number of custom particles is limited to 16383. | - | ||||||||||||||||||
| 95 | */ | - | ||||||||||||||||||
| 96 | - | |||||||||||||||||||
| 97 | QQuickCustomParticle::QQuickCustomParticle(QQuickItem* parent) | - | ||||||||||||||||||
| 98 | : QQuickParticlePainter(parent) | - | ||||||||||||||||||
| 99 | , m_common(this, [this](int mappedId){this->propertyChanged(mappedId);}) | - | ||||||||||||||||||
| 100 | , m_myMetaObject(nullptr) | - | ||||||||||||||||||
| 101 | , m_dirtyUniforms(true) | - | ||||||||||||||||||
| 102 | , m_dirtyUniformValues(true) | - | ||||||||||||||||||
| 103 | , m_dirtyTextureProviders(true) | - | ||||||||||||||||||
| 104 | , m_dirtyProgram(true) | - | ||||||||||||||||||
| 105 | { | - | ||||||||||||||||||
| 106 | setFlag(QQuickItem::ItemHasContents); | - | ||||||||||||||||||
| 107 | } executed 10 times by 2 tests:  end of blockExecuted by: 
  | 10 | ||||||||||||||||||
| 108 | - | |||||||||||||||||||
| 109 | void QQuickCustomParticle::sceneGraphInvalidated() | - | ||||||||||||||||||
| 110 | { | - | ||||||||||||||||||
| 111 | m_nodes.clear(); | - | ||||||||||||||||||
| 112 | } never executed:  end of block | 0 | ||||||||||||||||||
| 113 | - | |||||||||||||||||||
| 114 | QQuickCustomParticle::~QQuickCustomParticle() | - | ||||||||||||||||||
| 115 | { | - | ||||||||||||||||||
| 116 | } | - | ||||||||||||||||||
| 117 | - | |||||||||||||||||||
| 118 | void QQuickCustomParticle::componentComplete() | - | ||||||||||||||||||
| 119 | { | - | ||||||||||||||||||
| 120 |     if (!m_myMetaObject)
  | 0-10 | ||||||||||||||||||
| 121 |         m_myMetaObject = metaObject(); executed 10 times by 2 tests:  m_myMetaObject = metaObject();Executed by: 
  | 10 | ||||||||||||||||||
| 122 | - | |||||||||||||||||||
| 123 | m_common.updateShader(this, m_myMetaObject, Key::FragmentShader); | - | ||||||||||||||||||
| 124 | updateVertexShader(); | - | ||||||||||||||||||
| 125 | reset(); | - | ||||||||||||||||||
| 126 | QQuickParticlePainter::componentComplete(); | - | ||||||||||||||||||
| 127 | } executed 10 times by 2 tests:  end of blockExecuted by: 
  | 10 | ||||||||||||||||||
| 128 | - | |||||||||||||||||||
| 129 | - | |||||||||||||||||||
| 130 | //Trying to keep the shader conventions the same as in qsgshadereffectitem | - | ||||||||||||||||||
| 131 | /*! | - | ||||||||||||||||||
| 132 | \qmlproperty string QtQuick.Particles::CustomParticle::fragmentShader | - | ||||||||||||||||||
| 133 | - | |||||||||||||||||||
| 134 | This property holds the fragment shader's GLSL source code. | - | ||||||||||||||||||
| 135 | The default shader expects the texture coordinate to be passed from the | - | ||||||||||||||||||
| 136 | vertex shader as "varying highp vec2 qt_TexCoord0", and it samples from a | - | ||||||||||||||||||
| 137 | sampler2D named "source". | - | ||||||||||||||||||
| 138 | */ | - | ||||||||||||||||||
| 139 | - | |||||||||||||||||||
| 140 | void QQuickCustomParticle::setFragmentShader(const QByteArray &code) | - | ||||||||||||||||||
| 141 | { | - | ||||||||||||||||||
| 142 |     if (m_common.source.sourceCode[Key::FragmentShader].constData() == code.constData())
  | 0-6 | ||||||||||||||||||
| 143 |         return; never executed:  return; | 0 | ||||||||||||||||||
| 144 | m_common.source.sourceCode[Key::FragmentShader] = code; | - | ||||||||||||||||||
| 145 | m_dirtyProgram = true; | - | ||||||||||||||||||
| 146 |     if (isComponentComplete()) {
  | 0-6 | ||||||||||||||||||
| 147 | m_common.updateShader(this, m_myMetaObject, Key::FragmentShader); | - | ||||||||||||||||||
| 148 | reset(); | - | ||||||||||||||||||
| 149 |     } never executed:  end of block | 0 | ||||||||||||||||||
| 150 | emit fragmentShaderChanged(); | - | ||||||||||||||||||
| 151 | } executed 6 times by 1 test:  end of blockExecuted by: 
  | 6 | ||||||||||||||||||
| 152 | - | |||||||||||||||||||
| 153 | /*! | - | ||||||||||||||||||
| 154 | \qmlproperty string QtQuick.Particles::CustomParticle::vertexShader | - | ||||||||||||||||||
| 155 | - | |||||||||||||||||||
| 156 | This property holds the vertex shader's GLSL source code. | - | ||||||||||||||||||
| 157 | - | |||||||||||||||||||
| 158 | The default shader passes the texture coordinate along to the fragment | - | ||||||||||||||||||
| 159 | shader as "varying highp vec2 qt_TexCoord0". | - | ||||||||||||||||||
| 160 | - | |||||||||||||||||||
| 161 | To aid writing a particle vertex shader, the following GLSL code is prepended | - | ||||||||||||||||||
| 162 | to your vertex shader: | - | ||||||||||||||||||
| 163 | \code | - | ||||||||||||||||||
| 164 | attribute highp vec2 qt_ParticlePos; | - | ||||||||||||||||||
| 165 | attribute highp vec2 qt_ParticleTex; | - | ||||||||||||||||||
| 166 | attribute highp vec4 qt_ParticleData; // x = time, y = lifeSpan, z = size, w = endSize | - | ||||||||||||||||||
| 167 | attribute highp vec4 qt_ParticleVec; // x,y = constant velocity, z,w = acceleration | - | ||||||||||||||||||
| 168 | attribute highp float qt_ParticleR; | - | ||||||||||||||||||
| 169 | uniform highp mat4 qt_Matrix; | - | ||||||||||||||||||
| 170 | uniform highp float qt_Timestamp; | - | ||||||||||||||||||
| 171 | varying highp vec2 qt_TexCoord0; | - | ||||||||||||||||||
| 172 | void defaultMain() { | - | ||||||||||||||||||
| 173 | qt_TexCoord0 = qt_ParticleTex; | - | ||||||||||||||||||
| 174 | highp float size = qt_ParticleData.z; | - | ||||||||||||||||||
| 175 | highp float endSize = qt_ParticleData.w; | - | ||||||||||||||||||
| 176 | highp float t = (qt_Timestamp - qt_ParticleData.x) / qt_ParticleData.y; | - | ||||||||||||||||||
| 177 | highp float currentSize = mix(size, endSize, t * t); | - | ||||||||||||||||||
| 178 | if (t < 0. || t > 1.) | - | ||||||||||||||||||
| 179 | currentSize = 0.; | - | ||||||||||||||||||
| 180 | highp vec2 pos = qt_ParticlePos | - | ||||||||||||||||||
| 181 | - currentSize / 2. + currentSize * qt_ParticleTex // adjust size | - | ||||||||||||||||||
| 182 | + qt_ParticleVec.xy * t * qt_ParticleData.y // apply velocity vector.. | - | ||||||||||||||||||
| 183 | + 0.5 * qt_ParticleVec.zw * pow(t * qt_ParticleData.y, 2.); | - | ||||||||||||||||||
| 184 | gl_Position = qt_Matrix * vec4(pos.x, pos.y, 0, 1); | - | ||||||||||||||||||
| 185 | } | - | ||||||||||||||||||
| 186 | \endcode | - | ||||||||||||||||||
| 187 | - | |||||||||||||||||||
| 188 | defaultMain() is the same code as in the default shader, you can call this for basic | - | ||||||||||||||||||
| 189 | particle functions and then add additional variables for custom effects. Note that | - | ||||||||||||||||||
| 190 | the vertex shader for particles is responsible for simulating the movement of particles | - | ||||||||||||||||||
| 191 | over time, the particle data itself only has the starting position and spawn time. | - | ||||||||||||||||||
| 192 | */ | - | ||||||||||||||||||
| 193 | - | |||||||||||||||||||
| 194 | void QQuickCustomParticle::setVertexShader(const QByteArray &code) | - | ||||||||||||||||||
| 195 | { | - | ||||||||||||||||||
| 196 |     if (m_common.source.sourceCode[Key::VertexShader].constData() == code.constData())
  | 0-6 | ||||||||||||||||||
| 197 |         return; never executed:  return; | 0 | ||||||||||||||||||
| 198 | m_common.source.sourceCode[Key::VertexShader] = code; | - | ||||||||||||||||||
| 199 | - | |||||||||||||||||||
| 200 | m_dirtyProgram = true; | - | ||||||||||||||||||
| 201 |     if (isComponentComplete()) {
  | 0-6 | ||||||||||||||||||
| 202 | updateVertexShader(); | - | ||||||||||||||||||
| 203 | reset(); | - | ||||||||||||||||||
| 204 |     } never executed:  end of block | 0 | ||||||||||||||||||
| 205 | emit vertexShaderChanged(); | - | ||||||||||||||||||
| 206 | } executed 6 times by 1 test:  end of blockExecuted by: 
  | 6 | ||||||||||||||||||
| 207 | - | |||||||||||||||||||
| 208 | void QQuickCustomParticle::updateVertexShader() | - | ||||||||||||||||||
| 209 | { | - | ||||||||||||||||||
| 210 | m_common.disconnectPropertySignals(this, Key::VertexShader); | - | ||||||||||||||||||
| 211 | m_common.uniformData[Key::VertexShader].clear(); | - | ||||||||||||||||||
| 212 | m_common.clearSignalMappers(Key::VertexShader); | - | ||||||||||||||||||
| 213 | m_common.attributes.clear(); | - | ||||||||||||||||||
| 214 | m_common.attributes.append("qt_ParticlePos"); | - | ||||||||||||||||||
| 215 | m_common.attributes.append("qt_ParticleTex"); | - | ||||||||||||||||||
| 216 | m_common.attributes.append("qt_ParticleData"); | - | ||||||||||||||||||
| 217 | m_common.attributes.append("qt_ParticleVec"); | - | ||||||||||||||||||
| 218 | m_common.attributes.append("qt_ParticleR"); | - | ||||||||||||||||||
| 219 | - | |||||||||||||||||||
| 220 | UniformData d; | - | ||||||||||||||||||
| 221 | d.name = "qt_Matrix"; | - | ||||||||||||||||||
| 222 | d.specialType = UniformData::Matrix; | - | ||||||||||||||||||
| 223 | m_common.uniformData[Key::VertexShader].append(d); | - | ||||||||||||||||||
| 224 | m_common.signalMappers[Key::VertexShader].append(0); | - | ||||||||||||||||||
| 225 | - | |||||||||||||||||||
| 226 | d.name = "qt_Timestamp"; | - | ||||||||||||||||||
| 227 | d.specialType = UniformData::None; | - | ||||||||||||||||||
| 228 | m_common.uniformData[Key::VertexShader].append(d); | - | ||||||||||||||||||
| 229 | m_common.signalMappers[Key::VertexShader].append(0); | - | ||||||||||||||||||
| 230 | - | |||||||||||||||||||
| 231 | const QByteArray &code = m_common.source.sourceCode[Key::VertexShader]; | - | ||||||||||||||||||
| 232 |     if (!code.isEmpty())
  | 4-6 | ||||||||||||||||||
| 233 |         m_common.lookThroughShaderCode(this, m_myMetaObject, Key::VertexShader, code); executed 6 times by 1 test:  m_common.lookThroughShaderCode(this, m_myMetaObject, Key::VertexShader, code);Executed by: 
  | 6 | ||||||||||||||||||
| 234 | - | |||||||||||||||||||
| 235 | m_common.connectPropertySignals(this, m_myMetaObject, Key::VertexShader); | - | ||||||||||||||||||
| 236 | } executed 10 times by 2 tests:  end of blockExecuted by: 
  | 10 | ||||||||||||||||||
| 237 | - | |||||||||||||||||||
| 238 | void QQuickCustomParticle::reset() | - | ||||||||||||||||||
| 239 | { | - | ||||||||||||||||||
| 240 | QQuickParticlePainter::reset(); | - | ||||||||||||||||||
| 241 | update(); | - | ||||||||||||||||||
| 242 | } executed 40 times by 2 tests:  end of blockExecuted by: 
  | 40 | ||||||||||||||||||
| 243 | - | |||||||||||||||||||
| 244 | QSGNode *QQuickCustomParticle::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) | - | ||||||||||||||||||
| 245 | { | - | ||||||||||||||||||
| 246 | QQuickOpenGLShaderEffectNode *rootNode = static_cast<QQuickOpenGLShaderEffectNode *>(oldNode); | - | ||||||||||||||||||
| 247 |     if (m_pleaseReset){
  | 9-278 | ||||||||||||||||||
| 248 | delete rootNode;//Automatically deletes children | - | ||||||||||||||||||
| 249 | rootNode = nullptr; | - | ||||||||||||||||||
| 250 | m_nodes.clear(); | - | ||||||||||||||||||
| 251 | m_pleaseReset = false; | - | ||||||||||||||||||
| 252 | m_dirtyProgram = true; | - | ||||||||||||||||||
| 253 |     } executed 9 times by 2 tests:  end of blockExecuted by: 
  | 9 | ||||||||||||||||||
| 254 | - | |||||||||||||||||||
| 255 |     if (m_system && m_system->isRunning() && !m_system->isPaused()){
 
 
  | 0-287 | ||||||||||||||||||
| 256 | rootNode = prepareNextFrame(rootNode); | - | ||||||||||||||||||
| 257 |         if (rootNode) {
  | 0-287 | ||||||||||||||||||
| 258 |             foreach (QSGGeometryNode* node, m_nodes)
 
 
  | 0-574 | ||||||||||||||||||
| 259 |                 node->markDirty(QSGNode::DirtyGeometry); executed 287 times by 2 tests:  node->markDirty(QSGNode::DirtyGeometry);Executed by: 
  | 287 | ||||||||||||||||||
| 260 | update(); | - | ||||||||||||||||||
| 261 |         } executed 287 times by 2 tests:  end of blockExecuted by: 
  | 287 | ||||||||||||||||||
| 262 |     } executed 287 times by 2 tests:  end of blockExecuted by: 
  | 287 | ||||||||||||||||||
| 263 | - | |||||||||||||||||||
| 264 |     return rootNode; executed 287 times by 2 tests:  return rootNode;Executed by: 
  | 287 | ||||||||||||||||||
| 265 | } | - | ||||||||||||||||||
| 266 | - | |||||||||||||||||||
| 267 | QQuickOpenGLShaderEffectNode *QQuickCustomParticle::prepareNextFrame(QQuickOpenGLShaderEffectNode *rootNode) | - | ||||||||||||||||||
| 268 | { | - | ||||||||||||||||||
| 269 |     if (!rootNode)
  | 9-278 | ||||||||||||||||||
| 270 |         rootNode = buildCustomNodes(); executed 9 times by 2 tests:  rootNode = buildCustomNodes();Executed by: 
  | 9 | ||||||||||||||||||
| 271 | - | |||||||||||||||||||
| 272 |     if (!rootNode)
  | 0-287 | ||||||||||||||||||
| 273 |         return nullptr; never executed:  return nullptr; | 0 | ||||||||||||||||||
| 274 | - | |||||||||||||||||||
| 275 |     if (m_dirtyProgram) {
  | 9-278 | ||||||||||||||||||
| 276 | const bool isES = QOpenGLContext::currentContext()->isOpenGLES(); | - | ||||||||||||||||||
| 277 | - | |||||||||||||||||||
| 278 | QQuickOpenGLShaderEffectMaterial *material = static_cast<QQuickOpenGLShaderEffectMaterial *>(rootNode->material()); | - | ||||||||||||||||||
| 279 | Q_ASSERT(material); | - | ||||||||||||||||||
| 280 | - | |||||||||||||||||||
| 281 | Key s = m_common.source; | - | ||||||||||||||||||
| 282 | QSGShaderSourceBuilder builder; | - | ||||||||||||||||||
| 283 |         if (s.sourceCode[Key::FragmentShader].isEmpty()) {
  | 4-5 | ||||||||||||||||||
| 284 |             builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticle.frag")); executed 4 times by 1 test:  return qstring_literal_temp;Executed by: 
  | 4 | ||||||||||||||||||
| 285 |             if (isES)
  | 0-4 | ||||||||||||||||||
| 286 |                 builder.removeVersion(); never executed:  builder.removeVersion(); | 0 | ||||||||||||||||||
| 287 | s.sourceCode[Key::FragmentShader] = builder.source(); | - | ||||||||||||||||||
| 288 | builder.clear(); | - | ||||||||||||||||||
| 289 |         } executed 4 times by 1 test:  end of blockExecuted by: 
  | 4 | ||||||||||||||||||
| 290 | - | |||||||||||||||||||
| 291 |         builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticletemplate.vert")); executed 9 times by 2 tests:  return qstring_literal_temp;Executed by: 
  | 9 | ||||||||||||||||||
| 292 |         if (isES)
  | 0-9 | ||||||||||||||||||
| 293 |             builder.removeVersion(); never executed:  builder.removeVersion(); | 0 | ||||||||||||||||||
| 294 | - | |||||||||||||||||||
| 295 |         if (s.sourceCode[Key::VertexShader].isEmpty())
  | 4-5 | ||||||||||||||||||
| 296 |             builder.appendSourceFile(QStringLiteral(":/particles/shaders/customparticle.vert")); executed 4 times by 1 test:  builder.appendSourceFile(([]() noexcept -> QString { enum { Size = sizeof(u"" ":/particles/shaders/customparticle.vert")/2 - 1 }; static const QStaticStringData<Size> qstring_literal = { { { { -1 } }, Size, 0, 0, sizeof(QStringData) }, u"" ":/particles/shaders/customparticle.vert" }; QStringDataPtr holder = { qstring_literal.data_ptr() }; const QString qstring_literal_temp(holder); return qstring_literal_temp; }()));Executed by: 
 executed 4 times by 1 test:  return qstring_literal_temp;Executed by: 
  | 4 | ||||||||||||||||||
| 297 | s.sourceCode[Key::VertexShader] = builder.source() + s.sourceCode[Key::VertexShader]; | - | ||||||||||||||||||
| 298 | - | |||||||||||||||||||
| 299 | material->setProgramSource(s); | - | ||||||||||||||||||
| 300 | material->attributes = m_common.attributes; | - | ||||||||||||||||||
| 301 |         foreach (QQuickOpenGLShaderEffectNode* node, m_nodes)
 
 
  | 0-18 | ||||||||||||||||||
| 302 |             node->markDirty(QSGNode::DirtyMaterial); executed 9 times by 2 tests:  node->markDirty(QSGNode::DirtyMaterial);Executed by: 
  | 9 | ||||||||||||||||||
| 303 | - | |||||||||||||||||||
| 304 | m_dirtyProgram = false; | - | ||||||||||||||||||
| 305 | m_dirtyUniforms = true; | - | ||||||||||||||||||
| 306 |     } executed 9 times by 2 tests:  end of blockExecuted by: 
  | 9 | ||||||||||||||||||
| 307 | - | |||||||||||||||||||
| 308 | m_lastTime = m_system->systemSync(this) / 1000.; | - | ||||||||||||||||||
| 309 | if (true) //Currently this is how we update timestamp... potentially over expensive. | - | ||||||||||||||||||
| 310 |         buildData(rootNode); executed 287 times by 2 tests:  buildData(rootNode);Executed by: 
  | 287 | ||||||||||||||||||
| 311 |     return rootNode; executed 287 times by 2 tests:  return rootNode;Executed by: 
  | 287 | ||||||||||||||||||
| 312 | } | - | ||||||||||||||||||
| 313 | - | |||||||||||||||||||
| 314 | QQuickOpenGLShaderEffectNode* QQuickCustomParticle::buildCustomNodes() | - | ||||||||||||||||||
| 315 | { | - | ||||||||||||||||||
| 316 | typedef QHash<int, QQuickOpenGLShaderEffectNode*>::const_iterator NodeHashConstIt; | - | ||||||||||||||||||
| 317 | - | |||||||||||||||||||
| 318 |     if (!QOpenGLContext::currentContext())
  | 0-9 | ||||||||||||||||||
| 319 |         return nullptr; never executed:  return nullptr; | 0 | ||||||||||||||||||
| 320 | - | |||||||||||||||||||
| 321 |     if (m_count * 4 > 0xffff) {
  | 0-9 | ||||||||||||||||||
| 322 | // Index data is ushort. | - | ||||||||||||||||||
| 323 | qmlInfo(this) << "CustomParticle: Too many particles - maximum 16383 per CustomParticle"; | - | ||||||||||||||||||
| 324 |         return nullptr; never executed:  return nullptr; | 0 | ||||||||||||||||||
| 325 | } | - | ||||||||||||||||||
| 326 | - | |||||||||||||||||||
| 327 |     if (m_count <= 0) {
  | 0-9 | ||||||||||||||||||
| 328 | qmlInfo(this) << "CustomParticle: Too few particles"; | - | ||||||||||||||||||
| 329 |         return nullptr; never executed:  return nullptr; | 0 | ||||||||||||||||||
| 330 | } | - | ||||||||||||||||||
| 331 | - | |||||||||||||||||||
| 332 |     if (groups().isEmpty())
  | 0-9 | ||||||||||||||||||
| 333 |         return nullptr; never executed:  return nullptr; | 0 | ||||||||||||||||||
| 334 | - | |||||||||||||||||||
| 335 | QQuickOpenGLShaderEffectNode *rootNode = nullptr; | - | ||||||||||||||||||
| 336 | QQuickOpenGLShaderEffectMaterial *material = new QQuickOpenGLShaderEffectMaterial; | - | ||||||||||||||||||
| 337 | m_dirtyProgram = true; | - | ||||||||||||||||||
| 338 | - | |||||||||||||||||||
| 339 | for (auto groupId : groupIds()) { | - | ||||||||||||||||||
| 340 | int count = m_system->groupData[groupId]->size(); | - | ||||||||||||||||||
| 341 | - | |||||||||||||||||||
| 342 | QQuickOpenGLShaderEffectNode* node = new QQuickOpenGLShaderEffectNode(); | - | ||||||||||||||||||
| 343 | m_nodes.insert(groupId, node); | - | ||||||||||||||||||
| 344 | - | |||||||||||||||||||
| 345 | node->setMaterial(material); | - | ||||||||||||||||||
| 346 | - | |||||||||||||||||||
| 347 | //Create Particle Geometry | - | ||||||||||||||||||
| 348 | int vCount = count * 4; | - | ||||||||||||||||||
| 349 | int iCount = count * 6; | - | ||||||||||||||||||
| 350 | QSGGeometry *g = new QSGGeometry(PlainParticle_AttributeSet, vCount, iCount); | - | ||||||||||||||||||
| 351 | g->setDrawingMode(GL_TRIANGLES); | - | ||||||||||||||||||
| 352 | node->setGeometry(g); | - | ||||||||||||||||||
| 353 | node->setFlag(QSGNode::OwnsGeometry, true); | - | ||||||||||||||||||
| 354 | PlainVertex *vertices = (PlainVertex *) g->vertexData(); | - | ||||||||||||||||||
| 355 |         for (int p=0; p < count; ++p) {
  | 9-16412 | ||||||||||||||||||
| 356 | commit(groupId, p); | - | ||||||||||||||||||
| 357 | vertices[0].tx = 0; | - | ||||||||||||||||||
| 358 | vertices[0].ty = 0; | - | ||||||||||||||||||
| 359 | - | |||||||||||||||||||
| 360 | vertices[1].tx = 1; | - | ||||||||||||||||||
| 361 | vertices[1].ty = 0; | - | ||||||||||||||||||
| 362 | - | |||||||||||||||||||
| 363 | vertices[2].tx = 0; | - | ||||||||||||||||||
| 364 | vertices[2].ty = 1; | - | ||||||||||||||||||
| 365 | - | |||||||||||||||||||
| 366 | vertices[3].tx = 1; | - | ||||||||||||||||||
| 367 | vertices[3].ty = 1; | - | ||||||||||||||||||
| 368 | vertices += 4; | - | ||||||||||||||||||
| 369 |         } executed 16412 times by 2 tests:  end of blockExecuted by: 
  | 16412 | ||||||||||||||||||
| 370 | quint16 *indices = g->indexDataAsUShort(); | - | ||||||||||||||||||
| 371 |         for (int i=0; i < count; ++i) {
  | 9-16412 | ||||||||||||||||||
| 372 | int o = i * 4; | - | ||||||||||||||||||
| 373 | indices[0] = o; | - | ||||||||||||||||||
| 374 | indices[1] = o + 1; | - | ||||||||||||||||||
| 375 | indices[2] = o + 2; | - | ||||||||||||||||||
| 376 | indices[3] = o + 1; | - | ||||||||||||||||||
| 377 | indices[4] = o + 3; | - | ||||||||||||||||||
| 378 | indices[5] = o + 2; | - | ||||||||||||||||||
| 379 | indices += 6; | - | ||||||||||||||||||
| 380 |         } executed 16412 times by 2 tests:  end of blockExecuted by: 
  | 16412 | ||||||||||||||||||
| 381 |     } executed 9 times by 2 tests:  end of blockExecuted by: 
  | 9 | ||||||||||||||||||
| 382 | - | |||||||||||||||||||
| 383 | NodeHashConstIt it = m_nodes.cbegin(); | - | ||||||||||||||||||
| 384 | rootNode = it.value(); | - | ||||||||||||||||||
| 385 | rootNode->setFlag(QSGNode::OwnsMaterial, true); | - | ||||||||||||||||||
| 386 | NodeHashConstIt cend = m_nodes.cend(); | - | ||||||||||||||||||
| 387 |     for (++it; it != cend; ++it)
  | 0-9 | ||||||||||||||||||
| 388 |         rootNode->appendChildNode(it.value()); never executed:  rootNode->appendChildNode(it.value()); | 0 | ||||||||||||||||||
| 389 | - | |||||||||||||||||||
| 390 |     return rootNode; executed 9 times by 2 tests:  return rootNode;Executed by: 
  | 9 | ||||||||||||||||||
| 391 | } | - | ||||||||||||||||||
| 392 | - | |||||||||||||||||||
| 393 | void QQuickCustomParticle::sourceDestroyed(QObject *object) | - | ||||||||||||||||||
| 394 | { | - | ||||||||||||||||||
| 395 | m_common.sourceDestroyed(object); | - | ||||||||||||||||||
| 396 | } executed 2 times by 1 test:  end of blockExecuted by: 
  | 2 | ||||||||||||||||||
| 397 | - | |||||||||||||||||||
| 398 | void QQuickCustomParticle::propertyChanged(int mappedId) | - | ||||||||||||||||||
| 399 | { | - | ||||||||||||||||||
| 400 | bool textureProviderChanged; | - | ||||||||||||||||||
| 401 | m_common.propertyChanged(this, m_myMetaObject, mappedId, &textureProviderChanged); | - | ||||||||||||||||||
| 402 | m_dirtyTextureProviders |= textureProviderChanged; | - | ||||||||||||||||||
| 403 | m_dirtyUniformValues = true; | - | ||||||||||||||||||
| 404 | update(); | - | ||||||||||||||||||
| 405 | } executed 2 times by 1 test:  end of blockExecuted by: 
  | 2 | ||||||||||||||||||
| 406 | - | |||||||||||||||||||
| 407 | - | |||||||||||||||||||
| 408 | void QQuickCustomParticle::buildData(QQuickOpenGLShaderEffectNode *rootNode) | - | ||||||||||||||||||
| 409 | { | - | ||||||||||||||||||
| 410 |     if (!rootNode)
  | 0-287 | ||||||||||||||||||
| 411 |         return; never executed:  return; | 0 | ||||||||||||||||||
| 412 |     for (int shaderType = 0; shaderType < Key::ShaderTypeCount; ++shaderType) {
  | 287-574 | ||||||||||||||||||
| 413 |         for (int i = 0; i < m_common.uniformData[shaderType].size(); ++i) {
  | 574-1153 | ||||||||||||||||||
| 414 |             if (m_common.uniformData[shaderType].at(i).name == "qt_Timestamp")
  | 287-866 | ||||||||||||||||||
| 415 |                 m_common.uniformData[shaderType][i].value = qVariantFromValue(m_lastTime); executed 287 times by 2 tests:  m_common.uniformData[shaderType][i].value = qVariantFromValue(m_lastTime);Executed by: 
  | 287 | ||||||||||||||||||
| 416 |         } executed 1153 times by 2 tests:  end of blockExecuted by: 
  | 1153 | ||||||||||||||||||
| 417 |     } executed 574 times by 2 tests:  end of blockExecuted by: 
  | 574 | ||||||||||||||||||
| 418 | m_common.updateMaterial(rootNode, static_cast<QQuickOpenGLShaderEffectMaterial *>(rootNode->material()), | - | ||||||||||||||||||
| 419 | m_dirtyUniforms, true, m_dirtyTextureProviders); | - | ||||||||||||||||||
| 420 |     foreach (QQuickOpenGLShaderEffectNode* node, m_nodes)
 
 
  | 0-574 | ||||||||||||||||||
| 421 |         node->markDirty(QSGNode::DirtyMaterial); executed 287 times by 2 tests:  node->markDirty(QSGNode::DirtyMaterial);Executed by: 
  | 287 | ||||||||||||||||||
| 422 | m_dirtyUniforms = m_dirtyUniformValues = m_dirtyTextureProviders = false; | - | ||||||||||||||||||
| 423 | } executed 287 times by 2 tests:  end of blockExecuted by: 
  | 287 | ||||||||||||||||||
| 424 | - | |||||||||||||||||||
| 425 | void QQuickCustomParticle::initialize(int gIdx, int pIdx) | - | ||||||||||||||||||
| 426 | { | - | ||||||||||||||||||
| 427 | QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx]; | - | ||||||||||||||||||
| 428 | datum->r = QRandomGenerator::global()->generateDouble(); | - | ||||||||||||||||||
| 429 | } executed 2512 times by 1 test:  end of blockExecuted by: 
  | 2512 | ||||||||||||||||||
| 430 | - | |||||||||||||||||||
| 431 | void QQuickCustomParticle::commit(int gIdx, int pIdx) | - | ||||||||||||||||||
| 432 | { | - | ||||||||||||||||||
| 433 |     if (m_nodes[gIdx] == 0)
  | 0-18892 | ||||||||||||||||||
| 434 |         return; never executed:  return; | 0 | ||||||||||||||||||
| 435 | - | |||||||||||||||||||
| 436 | QQuickParticleData* datum = m_system->groupData[gIdx]->data[pIdx]; | - | ||||||||||||||||||
| 437 | PlainVertices *particles = (PlainVertices *) m_nodes[gIdx]->geometry()->vertexData(); | - | ||||||||||||||||||
| 438 | PlainVertex *vertices = (PlainVertex *)&particles[pIdx]; | - | ||||||||||||||||||
| 439 |     for (int i=0; i<4; ++i) {
  | 18892-75568 | ||||||||||||||||||
| 440 | vertices[i].x = datum->x - m_systemOffset.x(); | - | ||||||||||||||||||
| 441 | vertices[i].y = datum->y - m_systemOffset.y(); | - | ||||||||||||||||||
| 442 | vertices[i].t = datum->t; | - | ||||||||||||||||||
| 443 | vertices[i].lifeSpan = datum->lifeSpan; | - | ||||||||||||||||||
| 444 | vertices[i].size = datum->size; | - | ||||||||||||||||||
| 445 | vertices[i].endSize = datum->endSize; | - | ||||||||||||||||||
| 446 | vertices[i].vx = datum->vx; | - | ||||||||||||||||||
| 447 | vertices[i].vy = datum->vy; | - | ||||||||||||||||||
| 448 | vertices[i].ax = datum->ax; | - | ||||||||||||||||||
| 449 | vertices[i].ay = datum->ay; | - | ||||||||||||||||||
| 450 | vertices[i].r = datum->r; | - | ||||||||||||||||||
| 451 |     } executed 75568 times by 2 tests:  end of blockExecuted by: 
  | 75568 | ||||||||||||||||||
| 452 | } executed 18892 times by 2 tests:  end of blockExecuted by: 
  | 18892 | ||||||||||||||||||
| 453 | - | |||||||||||||||||||
| 454 | void QQuickCustomParticle::itemChange(ItemChange change, const ItemChangeData &value) | - | ||||||||||||||||||
| 455 | { | - | ||||||||||||||||||
| 456 |     if (change == QQuickItem::ItemSceneChange)
  | 20-28 | ||||||||||||||||||
| 457 |         m_common.updateWindow(value.window); executed 20 times by 2 tests:  m_common.updateWindow(value.window);Executed by: 
  | 20 | ||||||||||||||||||
| 458 | QQuickParticlePainter::itemChange(change, value); | - | ||||||||||||||||||
| 459 | } executed 48 times by 2 tests:  end of blockExecuted by: 
  | 48 | ||||||||||||||||||
| 460 | - | |||||||||||||||||||
| 461 | - | |||||||||||||||||||
| 462 | QT_END_NAMESPACE | - | ||||||||||||||||||
| 463 | - | |||||||||||||||||||
| 464 | #include "moc_qquickcustomparticle_p.cpp" | - | ||||||||||||||||||
| Source code | Switch to Preprocessed file |