Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qsgcurvestrokenode_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// Qt-Security score:significant reason:default
4
7
8#include <private/qsgtexture_p.h>
9
10QT_BEGIN_NAMESPACE
11
12void QSGCurveStrokeMaterialShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture,
13 QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
14{
15 Q_UNUSED(oldMaterial);
16 QSGCurveStrokeMaterial *m = static_cast<QSGCurveStrokeMaterial *>(newMaterial);
17 const QSGCurveStrokeNode *node = m->node();
18 if (binding != 1 || node->gradientType() == QGradient::NoGradient)
19 return;
20
21 if (node->gradientType() != QGradient::NoGradient) {
22 const QSGGradientCacheKey cacheKey(node->strokeGradient()->stops,
23 node->strokeGradient()->spread);
24 QSGTexture *t = QSGGradientCache::cacheForRhi(state.rhi())->get(cacheKey);
25 t->commitTextureOperations(state.rhi(), state.resourceUpdateBatch());
26 *texture = t;
27 }
28}
29
30
31bool QSGCurveStrokeMaterialShader::updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
32{
33 bool changed = false;
34 QByteArray *buf = state.uniformData();
35 Q_ASSERT(buf->size() >= 64);
36 const int matrixCount = qMin(state.projectionMatrixCount(), newEffect->viewCount());
37
38 auto *newMaterial = static_cast<QSGCurveStrokeMaterial *>(newEffect);
39 auto *oldMaterial = static_cast<QSGCurveStrokeMaterial *>(oldEffect);
40
41 auto *newNode = newMaterial != nullptr ? newMaterial->node() : nullptr;
42 auto *oldNode = oldMaterial != nullptr ? oldMaterial->node() : nullptr;
43
44 if (state.isMatrixDirty()) {
45 float localScale = newNode != nullptr ? newNode->localScale() : 1.0f;
46 for (int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) {
47 QMatrix4x4 m = state.combinedMatrix(viewIndex);
48 m.scale(localScale);
49 memcpy(buf->data() + viewIndex * 64, m.constData(), 64);
50 }
51 // determinant is xscale * yscale, as long as Item.transform does not include shearing or rotation
52 float matrixScale = qSqrt(qAbs(state.determinant())) * state.devicePixelRatio() * localScale;
53 memcpy(buf->data() + matrixCount * 64, &matrixScale, 4);
54 float dpr = state.devicePixelRatio();
55 memcpy(buf->data() + matrixCount * 64 + 8, &dpr, 4);
56 changed = true;
57 }
58
59 if (state.isOpacityDirty()) {
60 const float opacity = state.opacity();
61 memcpy(buf->data() + matrixCount * 64 + 4, &opacity, 4);
62 changed = true;
63 }
64
65 if (oldNode == nullptr || newNode->strokeWidth() != oldNode->strokeWidth()) {
66 float w = newNode->strokeWidth();
67 memcpy(buf->data() + matrixCount * 64 + 12, &w, 4);
68 changed = true;
69 }
70
71 int offset = matrixCount * 64 + 16;
72 if (newNode == nullptr)
73 return changed;
74
75 if (newNode->gradientType() == QGradient::NoGradient) {
76 QVector4D newStrokeColor(newNode->color().redF(),
77 newNode->color().greenF(),
78 newNode->color().blueF(),
79 newNode->color().alphaF());
80 QVector4D oldStrokeColor = oldNode != nullptr
81 ? QVector4D(oldNode->color().redF(),
82 oldNode->color().greenF(),
83 oldNode->color().blueF(),
84 oldNode->color().alphaF())
85 : QVector4D{};
86 if (oldNode == nullptr || oldStrokeColor != newStrokeColor) {
87 memcpy(buf->data() + offset, &newStrokeColor, 16);
88 changed = true;
89 }
90 offset += 16;
91 } else if (newNode->gradientType() == QGradient::LinearGradient) {
92 Q_ASSERT(buf->size() >= offset + 8 + 8);
93
94 QVector2D newGradientStart = QVector2D(newNode->strokeGradient()->a);
95 QVector2D oldGradientStart = oldNode != nullptr
96 ? QVector2D(oldNode->strokeGradient()->a)
97 : QVector2D{};
98
99 if (newGradientStart != oldGradientStart || oldEffect == nullptr) {
100 memcpy(buf->data() + offset, &newGradientStart, 8);
101 changed = true;
102 }
103 offset += 8;
104
105 QVector2D newGradientEnd = QVector2D(newNode->strokeGradient()->b);
106 QVector2D oldGradientEnd = oldNode!= nullptr
107 ? QVector2D(oldNode->strokeGradient()->b)
108 : QVector2D{};
109
110 if (newGradientEnd != oldGradientEnd || oldEffect == nullptr) {
111 memcpy(buf->data() + offset, &newGradientEnd, 8);
112 changed = true;
113 }
114
115 offset += 8;
116 } else if (newNode->gradientType() == QGradient::RadialGradient) {
117 Q_ASSERT(buf->size() >= offset + 8 + 8 + 4 + 4 + 4);
118
119 QVector2D newFocalPoint = QVector2D(newNode->strokeGradient()->b);
120 QVector2D oldFocalPoint = oldNode != nullptr
121 ? QVector2D(oldNode->strokeGradient()->b)
122 : QVector2D{};
123 if (oldNode == nullptr || newFocalPoint != oldFocalPoint) {
124 memcpy(buf->data() + offset, &newFocalPoint, 8);
125 changed = true;
126 }
127 offset += 8;
128
129 QVector2D newCenterPoint = QVector2D(newNode->strokeGradient()->a);
130 QVector2D oldCenterPoint = oldNode != nullptr
131 ? QVector2D(oldNode->strokeGradient()->a)
132 : QVector2D{};
133
134 QVector2D newCenterToFocal = newCenterPoint - newFocalPoint;
135 QVector2D oldCenterToFocal = oldCenterPoint - oldFocalPoint;
136 if (oldNode == nullptr || newCenterToFocal != oldCenterToFocal) {
137 memcpy(buf->data() + offset, &newCenterToFocal, 8);
138 changed = true;
139 }
140 offset += 8;
141
142 float newCenterRadius = newNode->strokeGradient()->v0;
143 float oldCenterRadius = oldNode != nullptr
144 ? oldNode->strokeGradient()->v0
145 : 0.0f;
146 if (oldNode == nullptr || !qFuzzyCompare(newCenterRadius, oldCenterRadius)) {
147 memcpy(buf->data() + offset, &newCenterRadius, 4);
148 changed = true;
149 }
150 offset += 4;
151
152 float newFocalRadius = newNode->strokeGradient()->v1;
153 float oldFocalRadius = oldNode != nullptr
154 ? oldNode->strokeGradient()->v1
155 : 0.0f;
156 if (oldNode == nullptr || !qFuzzyCompare(newFocalRadius, oldFocalRadius)) {
157 memcpy(buf->data() + offset, &newFocalRadius, 4);
158 changed = true;
159 }
160 offset += 4;
161
162 // reserved
163 offset += 8;
164
165 } else if (newNode->gradientType() == QGradient::ConicalGradient) {
166 Q_ASSERT(buf->size() >= offset + 8 + 4 + 4);
167
168 QVector2D newFocalPoint = QVector2D(newNode->strokeGradient()->a);
169 QVector2D oldFocalPoint = oldNode != nullptr
170 ? QVector2D(oldNode->strokeGradient()->a)
171 : QVector2D{};
172 if (oldNode == nullptr || newFocalPoint != oldFocalPoint) {
173 memcpy(buf->data() + offset, &newFocalPoint, 8);
174 changed = true;
175 }
176 offset += 8;
177
178 float newAngle = newNode->strokeGradient()->v0;
179 float oldAngle = oldNode != nullptr
180 ? oldNode->strokeGradient()->v0
181 : 0.0f;
182 if (oldNode == nullptr || !qFuzzyCompare(newAngle, oldAngle)) {
183 newAngle = -qDegreesToRadians(newAngle);
184 memcpy(buf->data() + offset, &newAngle, 4);
185 changed = true;
186 }
187 offset += 4;
188
189 // Reserved
190 offset += 4;
191 }
192
193 if (oldNode == nullptr || newNode->debug() != oldNode->debug()) {
194 float w = newNode->debug();
195 memcpy(buf->data() + offset, &w, 4);
196 changed = true;
197 }
198
199 return changed;
200}
201
202QSGMaterialType *QSGCurveStrokeMaterial::type() const
203{
204 static QSGMaterialType types[8];
205 uint type = node()->gradientType();
206 Q_ASSERT((type & ~3) == 0); // Only two first bits for gradient type
207
208 uchar expanding = m_strokeExpanding ? 1 : 0;
209
210 uint index = (type << 1) | expanding;
211 Q_ASSERT(index < 8);
212
213 return &types[index];
214}
215
216int QSGCurveStrokeMaterial::compare(const QSGMaterial *other) const
217{
218 const QSGCurveStrokeMaterial *otherMaterial = static_cast<const QSGCurveStrokeMaterial *>(other);
219
220 QSGCurveStrokeNode *a = node();
221 QSGCurveStrokeNode *b = otherMaterial->node();
222 if (a == b)
223 return 0;
224
225 int typeDif = type() - other->type();
226 if (!typeDif) {
227 if (a->gradientType() == QGradient::NoGradient && a->color() != b->color())
228 return a->color().rgb() < b->color().rgb() ? -1 : 1;
229
230 if (a->gradientType() != QGradient::NoGradient) {
231 const QSGGradientCache::GradientDesc &ga = *a->strokeGradient();
232 const QSGGradientCache::GradientDesc &gb = *b->strokeGradient();
233
234 if (int d = ga.compare(gb))
235 return d;
236 }
237
238 if (a->strokeWidth() != b->strokeWidth())
239 return a->strokeWidth() < b->strokeWidth() ? -1 : 1;
240 }
241 return typeDif;
242}
243
244QSGMaterialShader *QSGCurveStrokeMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
245{
246 Q_UNUSED(renderMode);
247 int variant = int(QSGCurveStrokeMaterialShader::Variant::Default);
248 if (m_strokeExpanding)
249 variant |= int(QSGCurveStrokeMaterialShader::Variant::Expanding);
250 if (node()->useStandardDerivatives())
251 variant |= int(QSGCurveStrokeMaterialShader::Variant::Derivatives);
252 switch (node()->gradientType()) {
253 case QGradient::LinearGradient:
254 variant |= int(QSGCurveStrokeMaterialShader::Variant::LinearGradient);
255 break;
256 case QGradient::RadialGradient:
257 variant |= int(QSGCurveStrokeMaterialShader::Variant::RadialGradient);
258 break;
259 case QGradient::ConicalGradient:
260 variant |= int(QSGCurveStrokeMaterialShader::Variant::ConicalGradient);
261 break;
262 default:
263 break;
264 }
265
266 return new QSGCurveStrokeMaterialShader(variant, viewCount());
267}
268
269QT_END_NAMESPACE