QGIS API Documentation 3.99.0-Master (d270888f95f)
Loading...
Searching...
No Matches
qgsframegraphutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsfgutils.cpp
3 --------------------------------------
4 Date : August 2024
5 Copyright : (C) 2024 by Mike Krus / Benoit De Mezzo
6 Email : mike dot krus at kdab dot com / benoit dot de dot mezzo at oslandia dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsframegraphutils.h"
17
18#include <QMetaEnum>
19#include <QString>
20#include <Qt3DExtras/QTextureMaterial>
21#include <Qt3DRender/QAbstractTexture>
22#include <Qt3DRender/QBlendEquation>
23#include <Qt3DRender/QBlendEquationArguments>
24#include <Qt3DRender/QColorMask>
25#include <Qt3DRender/QEffect>
26#include <Qt3DRender/QGeometryRenderer>
27#include <Qt3DRender/QGraphicsApiFilter>
28#include <Qt3DRender/QNoDepthMask>
29#include <Qt3DRender/QNoDraw>
30#include <Qt3DRender/QPointSize>
31#include <Qt3DRender/QSeamlessCubemap>
32#include <Qt3DRender/QSortPolicy>
33#include <Qt3DRender/QTechnique>
34
35using namespace Qt::StringLiterals;
36
37QStringList QgsFrameGraphUtils::dumpSceneGraph( const Qt3DCore::QNode *node, FgDumpContext context )
38{
39 return dumpSG( context, node );
40}
41
42QStringList QgsFrameGraphUtils::dumpFrameGraph( const Qt3DCore::QNode *node, FgDumpContext context )
43{
44 return dumpFG( context, node );
45}
46
47QString QgsFrameGraphUtils::formatIdName( FgDumpContext context, quint64 id, const QString &name )
48{
49 QString fixedName = name.isEmpty() ? "<no_name>"_L1 : name;
50 return "{%1/%2}"_L1.arg( QString::number( id - context.lowestId ) ).arg( fixedName );
51}
52
53QString QgsFrameGraphUtils::formatIdName( FgDumpContext context, const Qt3DRender::QAbstractTexture *texture )
54{
55 QString fixedName = texture->objectName().isEmpty() ? "<no_name>"_L1 : texture->objectName();
56 return "{%1[%2]/%3"_L1
57 .arg( QString::number( texture->id().id() - context.lowestId ), QString( QMetaEnum::fromType<Qt3DRender::QAbstractTexture::TextureFormat>().valueToKey( texture->format() ) ), fixedName );
58}
59
60QString QgsFrameGraphUtils::formatNode( FgDumpContext context, const Qt3DCore::QNode *node )
61{
62 QString res = "(%1%2)"_L1
63 .arg( QLatin1String( node->metaObject()->className() ) )
64 .arg( formatIdName( context, node->id().id(), node->objectName() ) );
65 if ( !node->isEnabled() )
66 res += " [D]"_L1;
67 return res;
68}
69
70QString QgsFrameGraphUtils::formatList( const QStringList &lst )
71{
72 return QString( "[ %1 ]"_L1 ).arg( lst.join( ", "_L1 ) );
73}
74
75QString QgsFrameGraphUtils::formatLongList( const QStringList &lst, int level )
76{
77 QString out = formatList( lst );
78 if ( out.size() < 200 )
79 return out;
80
81 out = QString( "[\n"_L1 );
82 for ( QString item : lst )
83 {
84 item = QString( "-> %1\n" ).arg( item );
85 out += item.rightJustified( item.length() + ( 1 + level ) * 2, ' ' );
86 }
87 QString end( "]"_L1 );
88 return out + end.rightJustified( end.length() + ( 1 + level ) * 2, ' ' );
89}
90
91QString QgsFrameGraphUtils::formatField( const QString &name, const QString &value )
92{
93 if ( value == "<no_value>" )
94 return QString( "(%1)"_L1 ).arg( name );
95 return QString( "(%1:%2)"_L1 ).arg( name, value );
96}
97
98QString QgsFrameGraphUtils::dumpSGEntity( FgDumpContext context, const Qt3DCore::QEntity *node, int level )
99{
100 auto extractTextureParam = []( FgDumpContext context, const QVector<Qt3DRender::QParameter *> &params, QStringList &fl ) {
101 for ( const auto *param : params )
102 {
103 if ( strstr( param->value().typeName(), "QAbstractTexture*" ) )
104 {
105 const Qt3DRender::QAbstractTexture *tex = param->value().value<Qt3DRender::QAbstractTexture *>();
106 fl += formatField( param->name(), formatIdName( context, tex ) );
107 }
108 }
109 };
110
111
112 QString res = formatNode( context, node );
113 const auto &components = node->components();
114 if ( !components.isEmpty() )
115 {
116 QStringList componentNames;
117 for ( const auto &comp : components )
118 {
119 QString res = formatNode( context, comp );
120 QStringList fl;
121 if ( const auto *textMat = qobject_cast<const Qt3DExtras::QTextureMaterial *>( comp ) )
122 {
123 if ( textMat->texture() )
124 {
125 const auto texImages = textMat->texture()->textureImages();
126 for ( const auto *texImg : texImages )
127 {
128 fl += formatField(
129 texImg->metaObject()->className(),
130 formatIdName( context, texImg->id().id(), texImg->objectName() )
131 );
132 }
133 }
134 }
135 if ( const auto *material = qobject_cast<const Qt3DRender::QMaterial *>( comp ) )
136 {
137 if ( material->effect() )
138 {
139 const auto techniques = material->effect()->techniques();
140 for ( const auto *tech : techniques )
141 {
142 extractTextureParam( context, tech->parameters(), fl );
143 const auto passes = tech->renderPasses();
144 for ( const auto *pass : passes )
145 {
146 extractTextureParam( context, pass->parameters(), fl );
147 }
148 }
149 extractTextureParam( context, material->effect()->parameters(), fl );
150 }
151 extractTextureParam( context, material->parameters(), fl );
152 if ( !fl.empty() )
153 res += formatList( fl );
154 }
155
156 componentNames << res;
157 }
158 res += formatLongList( componentNames, level );
159 }
160
161 return res;
162}
163
164QStringList QgsFrameGraphUtils::dumpSG( FgDumpContext context, const Qt3DCore::QNode *node, int level )
165{
166 QStringList reply;
167 const auto *entity = qobject_cast<const Qt3DCore::QEntity *>( node );
168 if ( entity )
169 {
170 QString res = dumpSGEntity( context, entity, level );
171 reply += res.rightJustified( res.length() + level * 2, ' ' );
172 level++;
173 }
174
175 const auto children = node->childNodes();
176 for ( auto *child : children )
177 reply += dumpSG( context, child, level );
178
179 return reply;
180}
181
182QString QgsFrameGraphUtils::dumpFGNode( FgDumpContext context, const Qt3DRender::QFrameGraphNode *node )
183{
184 QString res = formatNode( context, node );
185
186 if ( const auto *lf = qobject_cast<const Qt3DRender::QLayerFilter *>( node ) )
187 {
188 QStringList sl;
189 const auto layers = lf->layers();
190 for ( auto layer : layers )
191 {
192 sl += formatIdName( context, layer->id().id(), layer->objectName() );
193 }
194
195 QStringList fl;
196 fl += formatField( QMetaEnum::fromType<Qt3DRender::QLayerFilter::FilterMode>().valueToKey( lf->filterMode() ), formatList( sl ) );
197 res += QString( " %1" ).arg( formatList( fl ) );
198 }
199
200 else if ( const auto *cs = qobject_cast<const Qt3DRender::QCameraSelector *>( node ) )
201 {
202 QStringList fl;
203 fl += formatField( cs->camera()->metaObject()->className(), formatIdName( context, cs->camera()->id().id(), cs->camera()->objectName() ) );
204 res += QString( " %1" ).arg( formatList( fl ) );
205 }
206
207 else if ( const auto *rss = qobject_cast<const Qt3DRender::QRenderStateSet *>( node ) )
208 {
209 QStringList sl;
210 const auto renderStates = rss->renderStates();
211 for ( auto rs : renderStates )
212 {
213 if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QCullFace *>( rs ) )
214 {
215 sl += formatField( "QCullFace", QMetaEnum::fromType<Qt3DRender::QCullFace::CullingMode>().valueToKey( rs_cast->mode() ) );
216 }
217 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QBlendEquation *>( rs ) )
218 {
219 sl += formatField( "QBlendEquation", QMetaEnum::fromType<Qt3DRender::QBlendEquation::BlendFunction>().valueToKey( rs_cast->blendFunction() ) );
220 }
221 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QBlendEquationArguments *>( rs ) )
222 {
223 QStringList fl;
224 fl += formatField( "sourceRgb", QMetaEnum::fromType<Qt3DRender::QBlendEquationArguments::Blending>().valueToKey( rs_cast->sourceRgb() ) );
225 fl += formatField( "destinationRgb", QMetaEnum::fromType<Qt3DRender::QBlendEquationArguments::Blending>().valueToKey( rs_cast->destinationRgb() ) );
226 fl += formatField( "sourceAlpha", QMetaEnum::fromType<Qt3DRender::QBlendEquationArguments::Blending>().valueToKey( rs_cast->sourceAlpha() ) );
227 fl += formatField( "destinationAlpha", QMetaEnum::fromType<Qt3DRender::QBlendEquationArguments::Blending>().valueToKey( rs_cast->destinationAlpha() ) );
228 fl += formatField( "bufferIndex", QString::number( rs_cast->bufferIndex() ) );
229
230 sl += formatField( "QBlendEquationArguments", formatList( fl ) );
231 }
232 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QColorMask *>( rs ) )
233 {
234 QStringList fl;
235 fl += formatField( "red", ( rs_cast->isRedMasked() ? "true"_L1 : "false"_L1 ) );
236 fl += formatField( "green", ( rs_cast->isGreenMasked() ? "true"_L1 : "false"_L1 ) );
237 fl += formatField( "blue", ( rs_cast->isBlueMasked() ? "true"_L1 : "false"_L1 ) );
238 fl += formatField( "alpha", ( rs_cast->isAlphaMasked() ? "true"_L1 : "false"_L1 ) );
239 sl += formatField( "QColorMask", formatList( fl ) );
240 }
241 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QDepthTest *>( rs ) )
242 {
243 sl += formatField( "QDepthTest", QMetaEnum::fromType<Qt3DRender::QDepthTest::DepthFunction>().valueToKey( rs_cast->depthFunction() ) );
244 }
245 else if ( qobject_cast<const Qt3DRender::QNoDepthMask *>( rs ) )
246 {
247 sl += formatField( "QNoDepthMask", "<no_value>" );
248 }
249 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QPointSize *>( rs ) )
250 {
251 QStringList fl;
252 fl += formatField( "sizeMode", QMetaEnum::fromType<Qt3DRender::QPointSize::SizeMode>().valueToKey( rs_cast->sizeMode() ) );
253 fl += formatField( "value", QString::number( rs_cast->value() ) );
254 sl += formatField( "QPointSize", formatList( fl ) );
255 }
256 else if ( const auto *rs_cast = qobject_cast<const Qt3DRender::QPolygonOffset *>( rs ) )
257 {
258 QStringList fl;
259 fl += formatField( "scaleFactor", QString::number( rs_cast->scaleFactor() ) );
260 fl += formatField( "depthSteps", QString::number( rs_cast->depthSteps() ) );
261 sl += formatField( "QPolygonOffset", formatList( fl ) );
262 }
263 else if ( qobject_cast<const Qt3DRender::QSeamlessCubemap *>( rs ) )
264 {
265 sl += formatField( "QSeamlessCubemap", "<no_value>" );
266 }
267 }
268 res += QString( " %1" ).arg( formatList( sl ) );
269 }
270
271 else if ( const auto *rs = qobject_cast<const Qt3DRender::QRenderTargetSelector *>( node ) )
272 {
273 if ( rs->target() )
274 {
275 QStringList sl;
276 const auto outputs = rs->target()->outputs();
277 for ( auto output : outputs )
278 {
279 sl += formatField( QMetaEnum::fromType<Qt3DRender::QRenderTargetOutput::AttachmentPoint>().valueToKey( output->attachmentPoint() ), formatIdName( context, output->texture() ) );
280 }
281 QStringList fl;
282 fl += formatField( "outputs"_L1, formatList( sl ) );
283 res += QString( " %1" ).arg( formatList( fl ) );
284 }
285 }
286 // if (!n->isEnabled())
287 // res += " [D]"_L1;
288 return res;
289}
290
291QStringList QgsFrameGraphUtils::dumpFG( FgDumpContext context, const Qt3DCore::QNode *node, int level )
292{
293 QStringList reply;
294
295 const Qt3DRender::QFrameGraphNode *fgNode = qobject_cast<const Qt3DRender::QFrameGraphNode *>( node );
296 if ( fgNode )
297 {
298 QString res = dumpFGNode( context, fgNode );
299 reply += res.rightJustified( res.length() + level * 2, ' ' );
300 }
301
302 const auto children = node->childNodes();
303 const int inc = fgNode ? 1 : 0;
304 for ( auto *child : children )
305 {
306 auto *childFGNode = qobject_cast<Qt3DCore::QNode *>( child );
307 if ( childFGNode )
308 reply += dumpFG( context, childFGNode, level + inc );
309 }
310
311 return reply;
312}
static QStringList dumpFrameGraph(const Qt3DCore::QNode *node, FgDumpContext context)
Returns a tree view of the frame graph starting from node. The object ids will be given relatively to...
static QStringList dumpSceneGraph(const Qt3DCore::QNode *node, FgDumpContext context)
Returns a tree view of the scene graph starting from node. The object ids will be given relatively to...