Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
qquickshapecurvenode_p.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
8
10
11namespace {
12
14 {
15 public:
17 bool includeStroke,
18 bool useDerivatives);
19
20 bool updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
21 void updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
22 QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
23 };
24
25 QQuickShapeCurveMaterialShader::QQuickShapeCurveMaterialShader(QQuickAbstractPathRenderer::FillGradientType gradientType,
26 bool includeStroke,
27 bool useDerivatives)
28 {
29 QString baseName = QStringLiteral(":/qt-project.org/shapes/shaders_ng/shapecurve");
30
32 baseName += QStringLiteral("_lg");
33 } else if (gradientType == QQuickAbstractPathRenderer::RadialGradient) {
34 baseName += QStringLiteral("_rg");
35 } else if (gradientType == QQuickAbstractPathRenderer::ConicalGradient) {
36 baseName += QStringLiteral("_cg");
37 }
38
39 if (includeStroke)
40 baseName += QStringLiteral("_stroke");
41
42 if (useDerivatives)
43 baseName += QStringLiteral("_derivatives");
44
45 setShaderFileName(VertexStage, baseName + QStringLiteral(".vert.qsb"));
46 setShaderFileName(FragmentStage, baseName + QStringLiteral(".frag.qsb"));
47 }
48
49 void QQuickShapeCurveMaterialShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
50 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
51 {
52 Q_UNUSED(oldMaterial);
53 const QQuickShapeCurveMaterial *m = static_cast<QQuickShapeCurveMaterial *>(newMaterial);
54 const QQuickShapeCurveNode *node = m->node();
55 if (binding != 1 || node->gradientType() == QQuickAbstractPathRenderer::NoGradient)
56 return;
57
58 const QQuickShapeGradientCacheKey cacheKey(node->fillGradient().stops,
59 node->fillGradient().spread);
61 t->commitTextureOperations(state.rhi(), state.resourceUpdateBatch());
62 *texture = t;
63 }
64
65 bool QQuickShapeCurveMaterialShader::updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
66 {
67 bool changed = false;
68 QByteArray *buf = state.uniformData();
69 Q_ASSERT(buf->size() >= 80);
70
71 int offset = 0;
72 float matrixScale = 0.0f;
73 if (state.isMatrixDirty()) {
74 const QMatrix4x4 m = state.combinedMatrix();
75
76 memcpy(buf->data() + offset, m.constData(), 64);
77 offset += 64;
78
79 matrixScale = qSqrt(qAbs(state.determinant()));
80 memcpy(buf->data() + offset, &matrixScale, 4);
81 offset += 4;
82
83 changed = true;
84 }
85
86 if (state.isOpacityDirty()) {
87 const float opacity = state.opacity();
88 memcpy(buf->data() + offset, &opacity, 4);
89 changed = true;
90 }
91 offset += 12;
92
93 QQuickShapeCurveMaterial *newMaterial = static_cast<QQuickShapeCurveMaterial *>(newEffect);
94 QQuickShapeCurveMaterial *oldMaterial = static_cast<QQuickShapeCurveMaterial *>(oldEffect);
95
96 QQuickShapeCurveNode *newNode = newMaterial != nullptr ? newMaterial->node() : nullptr;
97 QQuickShapeCurveNode *oldNode = oldMaterial != nullptr ? oldMaterial->node() : nullptr;
98
99 if (newNode == nullptr)
100 return changed;
101
102 if (newNode->hasStroke()) {
103 Q_ASSERT(buf->size() >= offset + 32);
104 QVector4D newStrokeColor(newNode->strokeColor().redF(),
105 newNode->strokeColor().greenF(),
106 newNode->strokeColor().blueF(),
107 newNode->strokeColor().alphaF());
108 QVector4D oldStrokeColor = oldNode != nullptr
109 ? QVector4D(oldNode->strokeColor().redF(),
110 oldNode->strokeColor().greenF(),
111 oldNode->strokeColor().blueF(),
112 oldNode->strokeColor().alphaF())
113 : QVector4D{};
114
115 if (oldNode == nullptr || oldStrokeColor != newStrokeColor) {
116 memcpy(buf->data() + offset, &newStrokeColor, 16);
117 changed = true;
118 }
119 offset += 16;
120
121 if (oldNode == nullptr
122 || !qFuzzyCompare(newNode->strokeWidth(), oldNode->strokeWidth())
123 || (state.isMatrixDirty() && newNode->strokeWidth() > 0.0f)) {
124 float w = newNode->strokeWidth() * matrixScale; // matrixScale calculated earlier
125 memcpy(buf->data() + offset, &w, 4);
126 changed = true;
127 }
128 offset += 16;
129 }
130
132 Q_ASSERT(buf->size() >= offset + 16);
133
134 QVector4D newColor = QVector4D(newNode->color().redF(),
135 newNode->color().greenF(),
136 newNode->color().blueF(),
137 newNode->color().alphaF());
138 QVector4D oldColor = oldNode != nullptr
139 ? QVector4D(oldNode->color().redF(),
140 oldNode->color().greenF(),
141 oldNode->color().blueF(),
142 oldNode->color().alphaF())
143 : QVector4D{};
144
145 if (oldNode == nullptr || oldColor != newColor) {
146 memcpy(buf->data() + offset, &newColor, 16);
147 changed = true;
148 }
149
150 offset += 16;
152 Q_ASSERT(buf->size() >= offset + 8 + 8);
153
154 QVector2D newGradientStart = QVector2D(newNode->fillGradient().a);
155 QVector2D oldGradientStart = oldNode != nullptr
156 ? QVector2D(oldNode->fillGradient().a)
157 : QVector2D{};
158
159 if (newGradientStart != oldGradientStart || oldEffect == nullptr) {
160 memcpy(buf->data() + offset, &newGradientStart, 8);
161 changed = true;
162 }
163 offset += 8;
164
165 QVector2D newGradientEnd = QVector2D(newNode->fillGradient().b);
166 QVector2D oldGradientEnd = oldNode!= nullptr
167 ? QVector2D(oldNode->fillGradient().b)
168 : QVector2D{};
169
170 if (newGradientEnd != oldGradientEnd || oldEffect == nullptr) {
171 memcpy(buf->data() + offset, &newGradientEnd, 8);
172 changed = true;
173 }
174
175 offset += 8;
177 Q_ASSERT(buf->size() >= offset + 8 + 8 + 4 + 4);
178
179 QVector2D newFocalPoint = QVector2D(newNode->fillGradient().b);
180 QVector2D oldFocalPoint = oldNode != nullptr
181 ? QVector2D(oldNode->fillGradient().b)
182 : QVector2D{};
183 if (oldNode == nullptr || newFocalPoint != oldFocalPoint) {
184 memcpy(buf->data() + offset, &newFocalPoint, 8);
185 changed = true;
186 }
187 offset += 8;
188
189 QVector2D newCenterPoint = QVector2D(newNode->fillGradient().a);
190 QVector2D oldCenterPoint = oldNode != nullptr
191 ? QVector2D(oldNode->fillGradient().a)
192 : QVector2D{};
193
194 QVector2D newCenterToFocal = newCenterPoint - newFocalPoint;
195 QVector2D oldCenterToFocal = oldCenterPoint - oldFocalPoint;
196 if (oldNode == nullptr || newCenterToFocal != oldCenterToFocal) {
197 memcpy(buf->data() + offset, &newCenterToFocal, 8);
198 changed = true;
199 }
200 offset += 8;
201
202 float newCenterRadius = newNode->fillGradient().v0;
203 float oldCenterRadius = oldNode != nullptr
204 ? oldNode->fillGradient().v0
205 : 0.0f;
206 if (oldNode == nullptr || !qFuzzyCompare(newCenterRadius, oldCenterRadius)) {
207 memcpy(buf->data() + offset, &newCenterRadius, 4);
208 changed = true;
209 }
210 offset += 4;
211
212 float newFocalRadius = newNode->fillGradient().v1;
213 float oldFocalRadius = oldNode != nullptr
214 ? oldNode->fillGradient().v1
215 : 0.0f;
216 if (oldNode == nullptr || !qFuzzyCompare(newFocalRadius, oldFocalRadius)) {
217 memcpy(buf->data() + offset, &newFocalRadius, 4);
218 changed = true;
219 }
220 offset += 4;
221
223 Q_ASSERT(buf->size() >= offset + 8 + 4);
224
225 QVector2D newFocalPoint = QVector2D(newNode->fillGradient().a);
226 QVector2D oldFocalPoint = oldNode != nullptr
227 ? QVector2D(oldNode->fillGradient().a)
228 : QVector2D{};
229 if (oldNode == nullptr || newFocalPoint != oldFocalPoint) {
230 memcpy(buf->data() + offset, &newFocalPoint, 8);
231 changed = true;
232 }
233 offset += 8;
234
235 float newAngle = newNode->fillGradient().v0;
236 float oldAngle = oldNode != nullptr
237 ? oldNode->fillGradient().v0
238 : 0.0f;
239 if (oldNode == nullptr || !qFuzzyCompare(newAngle, oldAngle)) {
240 newAngle = -qDegreesToRadians(newAngle);
241 memcpy(buf->data() + offset, &newAngle, 4);
242 changed = true;
243 }
244 offset += 4;
245 }
246
247 return changed;
248 }
249}
250
252 : m_node(node)
253{
254 setFlag(Blending, true);
256}
257
259{
260 if (other->type() != type())
261 return (type() - other->type());
262
263 const QQuickShapeCurveMaterial *otherMaterial =
264 static_cast<const QQuickShapeCurveMaterial *>(other);
265
267 QQuickShapeCurveNode *b = otherMaterial->node();
268 if (a == b)
269 return 0;
270
271 if (int d = a->strokeColor().rgba() - b->strokeColor().rgba())
272 return d;
273
274 if (a->gradientType() == QQuickAbstractPathRenderer::NoGradient) {
275 if (int d = a->color().red() - b->color().red())
276 return d;
277 if (int d = a->color().green() - b->color().green())
278 return d;
279 if (int d = a->color().blue() - b->color().blue())
280 return d;
281 if (int d = a->color().alpha() - b->color().alpha())
282 return d;
283 } else {
284 const QQuickAbstractPathRenderer::GradientDesc &ga = a->fillGradient();
285 const QQuickAbstractPathRenderer::GradientDesc &gb = b->fillGradient();
286
287 if (int d = ga.a.x() - gb.a.x())
288 return d;
289 if (int d = ga.a.y() - gb.a.y())
290 return d;
291 if (int d = ga.b.x() - gb.b.x())
292 return d;
293 if (int d = ga.b.y() - gb.b.y())
294 return d;
295
296 if (int d = ga.v0 - gb.v0)
297 return d;
298 if (int d = ga.v1 - gb.v1)
299 return d;
300
301 if (int d = ga.spread - gb.spread)
302 return d;
303
304 if (int d = ga.stops.size() - gb.stops.size())
305 return d;
306
307 for (int i = 0; i < ga.stops.size(); ++i) {
308 if (int d = ga.stops[i].first - gb.stops[i].first)
309 return d;
310 if (int d = ga.stops[i].second.rgba() - gb.stops[i].second.rgba())
311 return d;
312 }
313 }
314
315 return 0;
316}
317
319{
320 static QSGMaterialType type[8];
322 Q_ASSERT((index & ~3) == 0); // Only two first bits for gradient type
323
324 if (node()->hasStroke())
325 index |= 4;
326
327 return &type[index];
328}
329
331{
332 return new QQuickShapeCurveMaterialShader(node()->gradientType(),
333 node()->hasStroke(),
335}
336
337
\inmodule QtCore
Definition qbytearray.h:57
float greenF() const noexcept
Returns the green color component of this color.
Definition qcolor.cpp:1643
float redF() const noexcept
Returns the red color component of this color.
Definition qcolor.cpp:1611
float alphaF() const noexcept
Returns the alpha color component of this color.
Definition qcolor.cpp:1497
float blueF() const noexcept
Returns the blue color component of this color.
Definition qcolor.cpp:1675
qsizetype size() const noexcept
Definition qlist.h:386
T & first()
Definition qlist.h:628
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:333
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:338
int compare(const QSGMaterial *other) const override
Compares this material to other and returns 0 if they are equal; -1 if this material should sort befo...
QQuickShapeCurveNode * node() const
QSGMaterialShader * createShader(QSGRendererInterface::RenderMode renderMode) const override
This function returns a new instance of a the QSGMaterialShader implementation used to render geometr...
QQuickShapeCurveMaterial(QQuickShapeCurveNode *node)
QSGMaterialType * type() const override
This function is called by the scene graph to query an identifier that is unique to the QSGMaterialSh...
QQuickAbstractPathRenderer::FillGradientType gradientType() const
QQuickAbstractPathRenderer::GradientDesc fillGradient() const
QSGTexture * get(const QQuickShapeGradientCacheKey &grad)
static QQuickShapeGradientCache * cacheForRhi(QRhi *rhi)
Encapsulates the current rendering state during a call to QSGMaterialShader::updateUniformData() and ...
The QSGMaterialShader class represents a graphics API independent shader program.
The QSGMaterial class encapsulates rendering state for a shader program.
Definition qsgmaterial.h:15
void setFlag(Flags flags, bool on=true)
Sets the flags flags on this material if on is true; otherwise clears the attribute.
@ RequiresDeterminant
Definition qsgmaterial.h:19
RenderMode
\value RenderMode2D Normal 2D rendering \value RenderMode2DNoDepthBuffer Normal 2D rendering with dep...
\inmodule QtQuick
Definition qsgtexture.h:20
virtual void commitTextureOperations(QRhi *rhi, QRhiResourceUpdateBatch *resourceUpdates)
Call this function to enqueue image upload operations to resourceUpdates, in case there are any pendi...
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:127
The QVector2D class represents a vector or vertex in 2D space.
Definition qvectornd.h:31
The QVector4D class represents a vector or vertex in 4D space.
Definition qvectornd.h:330
else opt state
[0]
Combined button and popup list for selecting options.
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:287
qfloat16 qSqrt(qfloat16 f)
Definition qfloat16.h:243
constexpr float qDegreesToRadians(float degrees)
Definition qmath.h:260
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
GLboolean GLboolean GLboolean b
const GLfloat * m
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint index
[2]
GLenum type
GLenum GLuint GLenum GLsizei const GLchar * buf
GLenum GLuint texture
GLenum GLuint GLintptr offset
GLdouble GLdouble t
Definition qopenglext.h:243
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define QStringLiteral(str)
#define Q_UNUSED(x)
unsigned int uint
Definition qtypes.h:29
QSharedPointer< T > other(t)
[5]
QQuickShapeGradient::SpreadMode spread
The QSGMaterialType class is used as a unique type token in combination with QSGMaterial.