OpenCoverage

qquickgenericshadereffect.cpp

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/quick/items/qquickgenericshadereffect.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
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-
45QT_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-
53QQuickGenericShaderEffect::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)
i < NShaderDescription
TRUEnever evaluated
FALSEnever evaluated
0
68 m_inProgress[i] = nullptr;
never executed: m_inProgress[i] = nullptr;
0
69}
never executed: end of block
0
70-
71QQuickGenericShaderEffect::~QQuickGenericShaderEffect()-
72{-
73 for (int i = 0; i < NShader; ++i) {
i < NShaderDescription
TRUEnever evaluated
FALSEnever evaluated
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-
82void 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)
m_fragShader == srcDescription
TRUEnever evaluated
FALSEnever evaluated
0
89 return;
never executed: return;
0
90-
91 m_fragShader = src;-
92-
93 m_fragNeedsUpdate = true;-
94 if (m_item->isComponentComplete())
m_item->isComponentComplete()Description
TRUEnever evaluated
FALSEnever evaluated
0
95 maybeUpdateShaders();
never executed: maybeUpdateShaders();
0
96-
97 emit m_item->fragmentShaderChanged();-
98}
never executed: end of block
0
99-
100void QQuickGenericShaderEffect::setVertexShader(const QByteArray &src)-
101{-
102 if (m_vertShader == src)
m_vertShader == srcDescription
TRUEnever evaluated
FALSEnever evaluated
0
103 return;
never executed: return;
0
104-
105 m_vertShader = src;-
106-
107 m_vertNeedsUpdate = true;-
108 if (m_item->isComponentComplete())
m_item->isComponentComplete()Description
TRUEnever evaluated
FALSEnever evaluated
0
109 maybeUpdateShaders();
never executed: maybeUpdateShaders();
0
110-
111 emit m_item->vertexShaderChanged();-
112}
never executed: end of block
0
113-
114void QQuickGenericShaderEffect::setBlending(bool enable)-
115{-
116 if (m_blending == enable)
m_blending == enableDescription
TRUEnever evaluated
FALSEnever evaluated
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-
124QVariant 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-
130void QQuickGenericShaderEffect::setMesh(const QVariant &mesh)-
131{-
132 QQuickShaderEffectMesh *newMesh = qobject_cast<QQuickShaderEffectMesh *>(qvariant_cast<QObject *>(mesh));-
133 if (newMesh && newMesh == m_mesh)
newMeshDescription
TRUEnever evaluated
FALSEnever evaluated
newMesh == m_meshDescription
TRUEnever evaluated
FALSEnever evaluated
0
134 return;
never executed: return;
0
135-
136 if (m_mesh)
m_meshDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
m_meshDescription
TRUEnever evaluated
FALSEnever evaluated
0
142 connect(m_mesh, SIGNAL(geometryChanged()), this, SLOT(markGeometryDirtyAndUpdate()));-
143 } else {
never executed: end of block
0
144 if (mesh.canConvert<QSize>()) {
mesh.canConvert<QSize>()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
okDescription
TRUEnever evaluated
FALSEnever evaluated
0
150 int w = res.at(0).toInt(&ok);-
151 if (ok) {
okDescription
TRUEnever evaluated
FALSEnever evaluated
0
152 int h = res.at(1).toInt(&ok);-
153 if (ok)
okDescription
TRUEnever evaluated
FALSEnever evaluated
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)
!okDescription
TRUEnever evaluated
FALSEnever evaluated
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-
169void QQuickGenericShaderEffect::setCullMode(QQuickShaderEffect::CullMode face)-
170{-
171 if (m_cullMode == face)
m_cullMode == faceDescription
TRUEnever evaluated
FALSEnever evaluated
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-
179void QQuickGenericShaderEffect::setSupportsAtlasTextures(bool supports)-
180{-
181 if (m_supportsAtlasTextures == supports)
m_supportsAtla...es == supportsDescription
TRUEnever evaluated
FALSEnever evaluated
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-
189QString QQuickGenericShaderEffect::parseLog()-
190{-
191 maybeUpdateShaders();-
192 return log();
never executed: return log();
0
193}-
194-
195QString QQuickGenericShaderEffect::log() const-
196{-
197 QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager();-
198 if (!mgr)
!mgrDescription
TRUEnever evaluated
FALSEnever evaluated
0
199 return QString();
never executed: return QString();
0
200-
201 return mgr->log();
never executed: return mgr->log();
0
202}-
203-
204QQuickShaderEffect::Status QQuickGenericShaderEffect::status() const-
205{-
206 QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager();-
207 if (!mgr)
!mgrDescription
TRUEnever evaluated
FALSEnever evaluated
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-
213void QQuickGenericShaderEffect::handleEvent(QEvent *event)-
214{-
215 if (event->type() == QEvent::DynamicPropertyChange) {
event->type() ...PropertyChangeDescription
TRUEnever evaluated
FALSEevaluated 108 times by 5 tests
Evaluated by:
  • tst_examples
  • tst_qquickborderimage
  • tst_qquickitemlayer
  • tst_qquickshadereffect
  • tst_scenegraph
0-108
216 QDynamicPropertyChangeEvent *e = static_cast<QDynamicPropertyChangeEvent *>(event);-
217 for (int shaderType = 0; shaderType < NShader; ++shaderType) {
shaderType < NShaderDescription
TRUEnever evaluated
FALSEnever evaluated
0
218 const auto &vars(m_shaders[shaderType].shaderInfo.variables);-
219 for (int idx = 0; idx < vars.count(); ++idx) {
idx < vars.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
220 if (vars[idx].name == e->propertyName()) {
vars[idx].name...propertyName()Description
TRUEnever evaluated
FALSEnever evaluated
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 block
Executed by:
  • tst_examples
  • tst_qquickborderimage
  • tst_qquickitemlayer
  • tst_qquickshadereffect
  • tst_scenegraph
108
228-
229void QQuickGenericShaderEffect::handleGeometryChanged(const QRectF &, const QRectF &)-
230{-
231 m_dirty |= QSGShaderEffectNode::DirtyShaderGeometry;-
232}
never executed: end of block
0
233-
234QSGNode *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) {
m_item->width() <= 0Description
TRUEnever evaluated
FALSEnever evaluated
m_item->height() <= 0Description
TRUEnever evaluated
FALSEnever evaluated
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])
m_inProgress[Vertex]Description
TRUEnever evaluated
FALSEnever evaluated
m_inProgress[Fragment]Description
TRUEnever evaluated
FALSEnever evaluated
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) {
!mgrDescription
TRUEnever evaluated
FALSEnever evaluated
0
250 delete node;-
251 return nullptr;
never executed: return nullptr;
0
252 }-
253-
254 if (!node) {
!nodeDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
m_dirty & QSGS...irtyShaderMeshDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
m_dirty & QSGS...ShaderGeometryDescription
TRUEnever evaluated
FALSEnever evaluated
0
279 const QRectF rect(0, 0, m_item->width(), m_item->height());-
280 QQuickShaderEffectMesh *mesh = m_mesh ? m_mesh : &m_defaultMesh;
m_meshDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
i < NShaderDescription
TRUEnever evaluated
FALSEnever evaluated
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-
302void QQuickGenericShaderEffect::maybeUpdateShaders()-
303{-
304 if (m_vertNeedsUpdate)
m_vertNeedsUpdateDescription
TRUEnever evaluated
FALSEnever evaluated
0
305 m_vertNeedsUpdate = !updateShader(Vertex, m_vertShader);
never executed: m_vertNeedsUpdate = !updateShader(Vertex, m_vertShader);
0
306 if (m_fragNeedsUpdate)
m_fragNeedsUpdateDescription
TRUEnever evaluated
FALSEnever evaluated
0
307 m_fragNeedsUpdate = !updateShader(Fragment, m_fragShader);
never executed: m_fragNeedsUpdate = !updateShader(Fragment, m_fragShader);
0
308 if (m_vertNeedsUpdate || m_fragNeedsUpdate) {
m_vertNeedsUpdateDescription
TRUEnever evaluated
FALSEnever evaluated
m_fragNeedsUpdateDescription
TRUEnever evaluated
FALSEnever evaluated
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())
!m_item->window()Description
TRUEnever evaluated
FALSEnever evaluated
!m_item->windo...hInitialized()Description
TRUEnever evaluated
FALSEnever evaluated
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-
320void QQuickGenericShaderEffect::handleItemChange(QQuickItem::ItemChange change, const QQuickItem::ItemChangeData &value)-
321{-
322 // Move the window ref.-
323 if (change == QQuickItem::ItemSceneChange) {
change == QQui...temSceneChangeDescription
TRUEnever evaluated
FALSEnever evaluated
0
324 for (int shaderType = 0; shaderType < NShader; ++shaderType) {
shaderType < NShaderDescription
TRUEnever evaluated
FALSEnever evaluated
0
325 for (const auto &vd : qAsConst(m_shaders[shaderType].varData)) {-
326 if (vd.specialType == QSGShaderEffectNode::VariableData::Source) {
vd.specialType...leData::SourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
327 QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value));-
328 if (source) {
sourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
329 if (value.window)
value.windowDescription
TRUEnever evaluated
FALSEnever evaluated
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-
340QSGGuiThreadShaderEffectManager *QQuickGenericShaderEffect::shaderEffectManager() const-
341{-
342 if (!m_mgr) {
!m_mgrDescription
TRUEnever evaluated
FALSEnever evaluated
0
343 // return null if this is not the gui thread and not already created-
344 if (QThread::currentThread() != m_item->thread())
QThread::curre...item->thread()Description
TRUEnever evaluated
FALSEnever evaluated
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
wDescription
TRUEnever evaluated
FALSEnever evaluated
0
348 m_mgr = QQuickWindowPrivate::get(w)->context->sceneGraphContext()->createGuiThreadShaderEffectManager();-
349 if (m_mgr) {
m_mgrDescription
TRUEnever evaluated
FALSEnever evaluated
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-
361void QQuickGenericShaderEffect::disconnectSignals(Shader shaderType)-
362{-
363 for (auto &sm : m_signalMappers[shaderType]) {-
364 if (sm.active) {
sm.activeDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
vd.specialType...leData::SourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
372 QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value));-
373 if (source) {
sourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
374 if (m_item->window())
m_item->window()Description
TRUEnever evaluated
FALSEnever evaluated
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-
382struct 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-
402Q_GLOBAL_STATIC(ShaderInfoCache, shaderInfoCache)
never executed: end of block
never executed: guard.store(QtGlobalStatic::Destroyed);
never executed: return &holder.value;
guard.load() =...c::InitializedDescription
TRUEnever evaluated
FALSEnever evaluated
0
403-
404bool QQuickGenericShaderEffect::updateShader(Shader shaderType, const QByteArray &src)-
405{-
406 QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager();-
407 if (!mgr)
!mgrDescription
TRUEnever evaluated
FALSEnever evaluated
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()) {
!src.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
418 if (shaderInfoCache()->contains(src)) {
shaderInfoCach...>contains(src)Description
TRUEnever evaluated
FALSEnever evaluated
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
shaderType == VertexDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
shaderType == FragmentDescription
TRUEnever evaluated
FALSEnever evaluated
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
texturesSeparateDescription
TRUEnever evaluated
FALSEnever evaluated
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-
461void 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;
typeHint == QS...fo::TypeVertexDescription
TRUEnever evaluated
FALSEnever evaluated
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]) {
result != m_in...ss[shaderType]Description
TRUEnever evaluated
FALSEnever evaluated
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) {
!okDescription
TRUEnever evaluated
FALSEnever evaluated
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-
490void QQuickGenericShaderEffect::updateShaderVars(Shader shaderType)-
491{-
492 QSGGuiThreadShaderEffectManager *mgr = shaderEffectManager();-
493 if (!mgr)
!mgrDescription
TRUEnever evaluated
FALSEnever evaluated
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)
m_signalMapper...t() < varCountDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
i < varCountDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
isSpecialDescription
TRUEnever evaluated
FALSEnever evaluated
0
513 if (v.name == "qt_Opacity")
v.name == "qt_Opacity"Description
TRUEnever evaluated
FALSEnever evaluated
0
514 vd.specialType = QSGShaderEffectNode::VariableData::Opacity;
never executed: vd.specialType = QSGShaderEffectNode::VariableData::Opacity;
0
515 else if (v.name == "qt_Matrix")
v.name == "qt_Matrix"Description
TRUEnever evaluated
FALSEnever evaluated
0
516 vd.specialType = QSGShaderEffectNode::VariableData::Matrix;
never executed: vd.specialType = QSGShaderEffectNode::VariableData::Matrix;
0
517 else if (v.name.startsWith("qt_SubRect_"))
v.name.startsW..."qt_SubRect_")Description
TRUEnever evaluated
FALSEnever evaluated
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) {
v.type == QSGG...rInfo::SamplerDescription
TRUEnever evaluated
FALSEnever evaluated
0
526 if (texturesSeparate) {
texturesSeparateDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
v.type == QSGG...rInfo::TextureDescription
TRUEnever evaluated
FALSEnever evaluated
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) {
propIdx >= 0Description
TRUEnever evaluated
FALSEnever evaluated
0
542 QMetaProperty mp = m_item->metaObject()->property(propIdx);-
543 if (!mp.hasNotifySignal())
!mp.hasNotifySignal()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
!sm.mapperDescription
TRUEnever evaluated
FALSEnever evaluated
0
549QT_WARNING_PUSH-
550QT_WARNING_DISABLE_DEPRECATED-
551 sm.mapper = new QSignalMapper;-
552QT_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())
!m_item->prope...a()).isValid()Description
TRUEnever evaluated
FALSEnever evaluated
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) {
vd.specialType...leData::SourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
568 QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value));-
569 if (source) {
sourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
570 if (m_item->window())
m_item->window()Description
TRUEnever evaluated
FALSEnever evaluated
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-
578bool QQuickGenericShaderEffect::sourceIsUnique(QQuickItem *source, Shader typeToSkip, int indexToSkip) const-
579{-
580 for (int shaderType = 0; shaderType < NShader; ++shaderType) {
shaderType < NShaderDescription
TRUEnever evaluated
FALSEnever evaluated
0
581 for (int idx = 0; idx < m_shaders[shaderType].varData.count(); ++idx) {
idx < m_shader...arData.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
582 if (shaderType != typeToSkip || idx != indexToSkip) {
shaderType != typeToSkipDescription
TRUEnever evaluated
FALSEnever evaluated
idx != indexToSkipDescription
TRUEnever evaluated
FALSEnever evaluated
0
583 const auto &vd(m_shaders[shaderType].varData[idx]);-
584 if (vd.specialType == QSGShaderEffectNode::VariableData::Source && qvariant_cast<QObject *>(vd.value) == source)
vd.specialType...leData::SourceDescription
TRUEnever evaluated
FALSEnever evaluated
qvariant_cast<...lue) == sourceDescription
TRUEnever evaluated
FALSEnever evaluated
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-
592void 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) {
vd.specialType...leData::SourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
600 QQuickItem *source = qobject_cast<QQuickItem *>(qvariant_cast<QObject *>(vd.value));-
601 if (source) {
sourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
602 if (m_item->window())
m_item->window()Description
TRUEnever evaluated
FALSEnever evaluated
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))
sourceIsUnique...ce, type, idx)Description
TRUEnever evaluated
FALSEnever evaluated
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) {
sourceDescription
TRUEnever evaluated
FALSEnever evaluated
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())
m_item->window()Description
TRUEnever evaluated
FALSEnever evaluated
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-
637void QQuickGenericShaderEffect::sourceDestroyed(QObject *object)-
638{-
639 for (int shaderType = 0; shaderType < NShader; ++shaderType) {
shaderType < NShaderDescription
TRUEnever evaluated
FALSEnever evaluated
0
640 for (auto &vd : m_shaders[shaderType].varData) {-
641 if (vd.specialType == QSGShaderEffectNode::VariableData::Source && vd.value.canConvert<QObject *>()) {
vd.specialType...leData::SourceDescription
TRUEnever evaluated
FALSEnever evaluated
vd.value.canCo...t<QObject *>()Description
TRUEnever evaluated
FALSEnever evaluated
0
642 if (qvariant_cast<QObject *>(vd.value) == object)
qvariant_cast<...lue) == objectDescription
TRUEnever evaluated
FALSEnever evaluated
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-
649void QQuickGenericShaderEffect::markGeometryDirtyAndUpdate()-
650{-
651 m_dirty |= QSGShaderEffectNode::DirtyShaderGeometry;-
652 m_item->update();-
653}
never executed: end of block
0
654-
655void QQuickGenericShaderEffect::markGeometryDirtyAndUpdateIfSupportsAtlas()-
656{-
657 if (m_supportsAtlasTextures)
m_supportsAtlasTexturesDescription
TRUEnever evaluated
FALSEnever evaluated
0
658 markGeometryDirtyAndUpdate();
never executed: markGeometryDirtyAndUpdate();
0
659}
never executed: end of block
0
660-
661QT_END_NAMESPACE-
662-
663#include "moc_qquickgenericshadereffect_p.cpp"-
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.2.0