1 | // Copyright (C) 2019 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 | |
4 | #include "qsgdistancefieldglyphnode_p_p.h" |
5 | #include "qsgrhidistancefieldglyphcache_p.h" |
6 | #include <QtGui/qsurface.h> |
7 | #include <QtGui/qwindow.h> |
8 | #include <qmath.h> |
9 | |
10 | QT_BEGIN_NAMESPACE |
11 | |
12 | static float qt_sg_envFloat(const char *name, float defaultValue) |
13 | { |
14 | if (Q_LIKELY(!qEnvironmentVariableIsSet(name))) |
15 | return defaultValue; |
16 | bool ok = false; |
17 | const float value = qgetenv(varName: name).toFloat(ok: &ok); |
18 | return ok ? value : defaultValue; |
19 | } |
20 | |
21 | static float thresholdFunc(float glyphScale) |
22 | { |
23 | static const float base = qt_sg_envFloat(name: "QT_DF_BASE", defaultValue: 0.5f); |
24 | static const float baseDev = qt_sg_envFloat(name: "QT_DF_BASEDEVIATION", defaultValue: 0.065f); |
25 | static const float devScaleMin = qt_sg_envFloat(name: "QT_DF_SCALEFORMAXDEV", defaultValue: 0.15f); |
26 | static const float devScaleMax = qt_sg_envFloat(name: "QT_DF_SCALEFORNODEV", defaultValue: 0.3f); |
27 | return base - ((qBound(min: devScaleMin, val: glyphScale, max: devScaleMax) - devScaleMin) / (devScaleMax - devScaleMin) * -baseDev + baseDev); |
28 | } |
29 | |
30 | static float spreadFunc(float glyphScale) |
31 | { |
32 | static const float range = qt_sg_envFloat(name: "QT_DF_RANGE", defaultValue: 0.06f); |
33 | return range / glyphScale; |
34 | } |
35 | |
36 | class QSGDistanceFieldTextMaterialRhiShader : public QSGMaterialShader |
37 | { |
38 | public: |
39 | QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount); |
40 | |
41 | bool updateUniformData(RenderState &state, |
42 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
43 | |
44 | void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, |
45 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
46 | |
47 | protected: |
48 | float m_fontScale = 1.0; |
49 | float m_matrixScale = 1.0; |
50 | quint32 m_currentUbufOffset; |
51 | }; |
52 | |
53 | QSGDistanceFieldTextMaterialRhiShader::QSGDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount) |
54 | { |
55 | setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb"), viewCount); |
56 | if (alphaTexture) |
57 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a.frag.qsb"), viewCount); |
58 | else |
59 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.frag.qsb"), viewCount); |
60 | } |
61 | |
62 | bool QSGDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state, |
63 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
64 | { |
65 | Q_ASSERT(oldMaterial == nullptr || newMaterial->type() == oldMaterial->type()); |
66 | QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial); |
67 | QSGDistanceFieldTextMaterial *oldMat = static_cast<QSGDistanceFieldTextMaterial *>(oldMaterial); |
68 | |
69 | // updateUniformData() is called before updateSampledImage() by the |
70 | // renderer. Hence updating the glyph cache stuff here. |
71 | const bool textureUpdated = mat->updateTextureSizeAndWrapper(); |
72 | Q_ASSERT(mat->wrapperTexture()); |
73 | Q_ASSERT(oldMat == nullptr || oldMat->texture()); |
74 | |
75 | bool changed = false; |
76 | QByteArray *buf = state.uniformData(); |
77 | Q_ASSERT(buf->size() >= 104); |
78 | |
79 | bool updateRange = false; |
80 | if (!oldMat || mat->fontScale() != oldMat->fontScale()) { |
81 | m_fontScale = mat->fontScale(); |
82 | updateRange = true; |
83 | } |
84 | if (state.isMatrixDirty()) { |
85 | m_matrixScale = qSqrt(v: qAbs(t: state.determinant())) * state.devicePixelRatio(); |
86 | updateRange = true; |
87 | } |
88 | quint32 offset = 0; |
89 | const int matrixCount = qMin(a: state.projectionMatrixCount(), b: newMaterial->viewCount()); |
90 | for (int viewIndex = 0; viewIndex < matrixCount; ++viewIndex) { |
91 | if (state.isMatrixDirty()) { |
92 | const QMatrix4x4 m = state.combinedMatrix(index: viewIndex); |
93 | memcpy(dest: buf->data() + 64 * viewIndex, src: m.constData(), n: 64); |
94 | changed = true; |
95 | } |
96 | offset += 64; |
97 | } |
98 | if (textureUpdated || !oldMat || oldMat->texture()->texture != mat->texture()->texture) { |
99 | const QVector2D ts(1.0f / mat->textureSize().width(), 1.0f / mat->textureSize().height()); |
100 | Q_ASSERT(sizeof(ts) == 8); |
101 | memcpy(dest: buf->data() + offset, src: &ts, n: 8); |
102 | changed = true; |
103 | } |
104 | offset += 8 + 8; // 8 is padding for vec4 alignment |
105 | if (!oldMat || mat->color() != oldMat->color() || state.isOpacityDirty()) { |
106 | const QVector4D color = mat->color() * state.opacity(); |
107 | Q_ASSERT(sizeof(color) == 16); |
108 | memcpy(dest: buf->data() + offset, src: &color, n: 16); |
109 | changed = true; |
110 | } |
111 | offset += 16; |
112 | if (updateRange) { // deferred because depends on m_fontScale and m_matrixScale |
113 | const float combinedScale = m_fontScale * m_matrixScale; |
114 | const float base = thresholdFunc(glyphScale: combinedScale); |
115 | const float range = spreadFunc(glyphScale: combinedScale); |
116 | const QVector2D alphaMinMax(qMax(a: 0.0f, b: base - range), qMin(a: base + range, b: 1.0f)); |
117 | memcpy(dest: buf->data() + offset, src: &alphaMinMax, n: 8); |
118 | changed = true; |
119 | } |
120 | offset += 8; // not adding any padding here since we are not sure what comes afterwards in the subclasses' shaders |
121 | |
122 | // move texture uploads/copies onto the renderer's soon-to-be-committed list |
123 | static_cast<QSGRhiDistanceFieldGlyphCache *>(mat->glyphCache())->commitResourceUpdates(mergeInto: state.resourceUpdateBatch()); |
124 | |
125 | m_currentUbufOffset = offset; |
126 | return changed; |
127 | } |
128 | |
129 | void QSGDistanceFieldTextMaterialRhiShader::updateSampledImage(RenderState &state, int binding, QSGTexture **texture, |
130 | QSGMaterial *newMaterial, QSGMaterial *) |
131 | { |
132 | Q_UNUSED(state); |
133 | if (binding != 1) |
134 | return; |
135 | |
136 | QSGDistanceFieldTextMaterial *mat = static_cast<QSGDistanceFieldTextMaterial *>(newMaterial); |
137 | QSGTexture *t = mat->wrapperTexture(); |
138 | t->setFiltering(QSGTexture::Linear); |
139 | *texture = t; |
140 | } |
141 | |
142 | class DistanceFieldAnisotropicTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader |
143 | { |
144 | public: |
145 | DistanceFieldAnisotropicTextMaterialRhiShader(bool alphaTexture, int viewCount); |
146 | }; |
147 | |
148 | DistanceFieldAnisotropicTextMaterialRhiShader::DistanceFieldAnisotropicTextMaterialRhiShader(bool alphaTexture, int viewCount) |
149 | : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount) |
150 | { |
151 | setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext.vert.qsb"), viewCount); |
152 | if (alphaTexture) |
153 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_a_fwidth.frag.qsb"), viewCount); |
154 | else |
155 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldtext_fwidth.frag.qsb"), viewCount); |
156 | } |
157 | |
158 | QSGDistanceFieldTextMaterial::QSGDistanceFieldTextMaterial() |
159 | : m_glyph_cache(nullptr) |
160 | , m_texture(nullptr) |
161 | , m_fontScale(1.0) |
162 | , m_sgTexture(nullptr) |
163 | { |
164 | setFlag(flags: Blending | RequiresDeterminant, on: true); |
165 | } |
166 | |
167 | QSGDistanceFieldTextMaterial::~QSGDistanceFieldTextMaterial() |
168 | { |
169 | delete m_sgTexture; |
170 | } |
171 | |
172 | QSGMaterialType *QSGDistanceFieldTextMaterial::type() const |
173 | { |
174 | static QSGMaterialType type; |
175 | return &type; |
176 | } |
177 | |
178 | void QSGDistanceFieldTextMaterial::setColor(const QColor &color) |
179 | { |
180 | float r, g, b, a; |
181 | color.getRgbF(r: &r, g: &g, b: &b, a: &a); |
182 | m_color = QVector4D(r * a, g * a, b * a, a); |
183 | } |
184 | |
185 | QSGMaterialShader *QSGDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const |
186 | { |
187 | if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported()) |
188 | return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); |
189 | else |
190 | return new QSGDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); |
191 | } |
192 | |
193 | bool QSGDistanceFieldTextMaterial::updateTextureSize() |
194 | { |
195 | if (!m_texture) |
196 | m_texture = m_glyph_cache->glyphTexture(glyph: 0); // invalid texture |
197 | |
198 | if (m_texture->size != m_size) { |
199 | m_size = m_texture->size; |
200 | return true; |
201 | } |
202 | |
203 | return false; |
204 | } |
205 | |
206 | // When using the RHI we need a QSGTexture wrapping the QRhiTexture, just |
207 | // exposing a QRhiTexture * (which would be the equivalent of GLuint textureId) |
208 | // is not sufficient to play nice with the material. |
209 | bool QSGDistanceFieldTextMaterial::updateTextureSizeAndWrapper() |
210 | { |
211 | bool updated = updateTextureSize(); |
212 | if (updated) { |
213 | if (m_sgTexture) |
214 | delete m_sgTexture; |
215 | m_sgTexture = new QSGPlainTexture; |
216 | m_sgTexture->setTexture(m_texture->texture); |
217 | m_sgTexture->setTextureSize(m_size); |
218 | m_sgTexture->setOwnsTexture(false); |
219 | } |
220 | return updated; |
221 | } |
222 | |
223 | int QSGDistanceFieldTextMaterial::compare(const QSGMaterial *o) const |
224 | { |
225 | Q_ASSERT(o && type() == o->type()); |
226 | const QSGDistanceFieldTextMaterial *other = static_cast<const QSGDistanceFieldTextMaterial *>(o); |
227 | if (m_glyph_cache != other->m_glyph_cache) |
228 | return m_glyph_cache - other->m_glyph_cache; |
229 | if (m_fontScale != other->m_fontScale) { |
230 | return int(other->m_fontScale < m_fontScale) - int(m_fontScale < other->m_fontScale); |
231 | } |
232 | if (m_color != other->m_color) |
233 | return &m_color < &other->m_color ? -1 : 1; |
234 | qintptr t0 = m_texture ? qintptr(m_texture->texture) : 0; |
235 | qintptr t1 = other->m_texture ? qintptr(other->m_texture->texture) : 0; |
236 | const qintptr diff = t0 - t1; |
237 | return diff < 0 ? -1 : (diff > 0 ? 1 : 0); |
238 | } |
239 | class DistanceFieldStyledTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader |
240 | { |
241 | public: |
242 | DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture, int viewCount); |
243 | |
244 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
245 | }; |
246 | |
247 | DistanceFieldStyledTextMaterialRhiShader::DistanceFieldStyledTextMaterialRhiShader(bool alphaTexture, int viewCount) |
248 | : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount) |
249 | { |
250 | } |
251 | |
252 | bool DistanceFieldStyledTextMaterialRhiShader::updateUniformData(RenderState &state, |
253 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
254 | { |
255 | bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); |
256 | QSGDistanceFieldStyledTextMaterial *mat = static_cast<QSGDistanceFieldStyledTextMaterial *>(newMaterial); |
257 | QSGDistanceFieldStyledTextMaterial *oldMat = static_cast<QSGDistanceFieldStyledTextMaterial *>(oldMaterial); |
258 | |
259 | QByteArray *buf = state.uniformData(); |
260 | Q_ASSERT(buf->size() >= 128); |
261 | |
262 | // must add 8 bytes padding for vec4 alignment, the base class did not do this |
263 | m_currentUbufOffset += 8; // now at StyleColor |
264 | |
265 | if (!oldMat || mat->styleColor() != oldMat->styleColor() || state.isOpacityDirty()) { |
266 | QVector4D styleColor = mat->styleColor(); |
267 | styleColor *= state.opacity(); |
268 | |
269 | memcpy(dest: buf->data() + m_currentUbufOffset, src: &styleColor, n: 16); |
270 | changed = true; |
271 | } |
272 | m_currentUbufOffset += 16; |
273 | |
274 | return changed; |
275 | } |
276 | |
277 | QSGDistanceFieldStyledTextMaterial::QSGDistanceFieldStyledTextMaterial() |
278 | : QSGDistanceFieldTextMaterial() |
279 | { |
280 | } |
281 | |
282 | QSGDistanceFieldStyledTextMaterial::~QSGDistanceFieldStyledTextMaterial() |
283 | { |
284 | } |
285 | |
286 | void QSGDistanceFieldStyledTextMaterial::setStyleColor(const QColor &color) |
287 | { |
288 | float r, g, b, a; |
289 | color.getRgbF(r: &r, g: &g, b: &b, a: &a); |
290 | m_styleColor = QVector4D(r * a, g * a, b * a, a); |
291 | } |
292 | |
293 | int QSGDistanceFieldStyledTextMaterial::compare(const QSGMaterial *o) const |
294 | { |
295 | Q_ASSERT(o && type() == o->type()); |
296 | const QSGDistanceFieldStyledTextMaterial *other = static_cast<const QSGDistanceFieldStyledTextMaterial *>(o); |
297 | if (m_styleColor != other->m_styleColor) |
298 | return &m_styleColor < &other->m_styleColor ? -1 : 1; |
299 | return QSGDistanceFieldTextMaterial::compare(o); |
300 | } |
301 | |
302 | class DistanceFieldOutlineTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader |
303 | { |
304 | public: |
305 | DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount); |
306 | |
307 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
308 | }; |
309 | |
310 | DistanceFieldOutlineTextMaterialRhiShader::DistanceFieldOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount) |
311 | : DistanceFieldStyledTextMaterialRhiShader(alphaTexture, viewCount) |
312 | { |
313 | setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"), viewCount); |
314 | if (alphaTexture) |
315 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a.frag.qsb"), viewCount); |
316 | else |
317 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.frag.qsb"), viewCount); |
318 | } |
319 | |
320 | class DistanceFieldAnisotropicOutlineTextMaterialRhiShader : public DistanceFieldOutlineTextMaterialRhiShader |
321 | { |
322 | public: |
323 | DistanceFieldAnisotropicOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount); |
324 | }; |
325 | |
326 | DistanceFieldAnisotropicOutlineTextMaterialRhiShader::DistanceFieldAnisotropicOutlineTextMaterialRhiShader(bool alphaTexture, int viewCount) |
327 | : DistanceFieldOutlineTextMaterialRhiShader(alphaTexture, viewCount) |
328 | { |
329 | setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext.vert.qsb"), viewCount); |
330 | if (alphaTexture) |
331 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_a_fwidth.frag.qsb"), viewCount); |
332 | else |
333 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldoutlinetext_fwidth.frag.qsb"), viewCount); |
334 | } |
335 | |
336 | bool DistanceFieldOutlineTextMaterialRhiShader::updateUniformData(RenderState &state, |
337 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
338 | { |
339 | bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); |
340 | QSGDistanceFieldOutlineTextMaterial *mat = static_cast<QSGDistanceFieldOutlineTextMaterial *>(newMaterial); |
341 | QSGDistanceFieldOutlineTextMaterial *oldMat = static_cast<QSGDistanceFieldOutlineTextMaterial *>(oldMaterial); |
342 | |
343 | QByteArray *buf = state.uniformData(); |
344 | Q_ASSERT(buf->size() >= 136); |
345 | |
346 | if (!oldMat || mat->fontScale() != oldMat->fontScale() || state.isMatrixDirty()) { |
347 | float dfRadius = mat->glyphCache()->distanceFieldRadius(); |
348 | float combinedScale = m_fontScale * m_matrixScale; |
349 | float base = thresholdFunc(glyphScale: combinedScale); |
350 | float range = spreadFunc(glyphScale: combinedScale); |
351 | float outlineLimit = qMax(a: 0.2f, b: base - 0.5f / dfRadius / m_fontScale); |
352 | float alphaMin = qMax(a: 0.0f, b: base - range); |
353 | float styleAlphaMin0 = qMax(a: 0.0f, b: outlineLimit - range); |
354 | float styleAlphaMin1 = qMin(a: outlineLimit + range, b: alphaMin); |
355 | memcpy(dest: buf->data() + m_currentUbufOffset, src: &styleAlphaMin0, n: 4); |
356 | memcpy(dest: buf->data() + m_currentUbufOffset + 4, src: &styleAlphaMin1, n: 4); |
357 | changed = true; |
358 | } |
359 | |
360 | return changed; |
361 | } |
362 | |
363 | QSGDistanceFieldOutlineTextMaterial::QSGDistanceFieldOutlineTextMaterial() |
364 | : QSGDistanceFieldStyledTextMaterial() |
365 | { |
366 | } |
367 | |
368 | QSGDistanceFieldOutlineTextMaterial::~QSGDistanceFieldOutlineTextMaterial() |
369 | { |
370 | } |
371 | |
372 | QSGMaterialType *QSGDistanceFieldOutlineTextMaterial::type() const |
373 | { |
374 | static QSGMaterialType type; |
375 | return &type; |
376 | } |
377 | |
378 | QSGMaterialShader *QSGDistanceFieldOutlineTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const |
379 | { |
380 | if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported()) |
381 | return new DistanceFieldAnisotropicOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); |
382 | else |
383 | return new DistanceFieldOutlineTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); |
384 | } |
385 | |
386 | class DistanceFieldShiftedStyleTextMaterialRhiShader : public DistanceFieldStyledTextMaterialRhiShader |
387 | { |
388 | public: |
389 | DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture, int viewCount); |
390 | |
391 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
392 | }; |
393 | |
394 | DistanceFieldShiftedStyleTextMaterialRhiShader::DistanceFieldShiftedStyleTextMaterialRhiShader(bool alphaTexture, int viewCount) |
395 | : DistanceFieldStyledTextMaterialRhiShader(alphaTexture, viewCount) |
396 | { |
397 | setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"), viewCount); |
398 | if (alphaTexture) |
399 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a.frag.qsb"), viewCount); |
400 | else |
401 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.frag.qsb"), viewCount); |
402 | } |
403 | |
404 | bool DistanceFieldShiftedStyleTextMaterialRhiShader::updateUniformData(RenderState &state, |
405 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
406 | { |
407 | bool changed = DistanceFieldStyledTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); |
408 | QSGDistanceFieldShiftedStyleTextMaterial *mat = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(newMaterial); |
409 | QSGDistanceFieldShiftedStyleTextMaterial *oldMat = static_cast<QSGDistanceFieldShiftedStyleTextMaterial *>(oldMaterial); |
410 | |
411 | QByteArray *buf = state.uniformData(); |
412 | Q_ASSERT(buf->size() >= 136); |
413 | |
414 | if (!oldMat || oldMat->fontScale() != mat->fontScale() || oldMat->shift() != mat->shift() |
415 | || oldMat->textureSize() != mat->textureSize()) |
416 | { |
417 | QVector2D shift(1.0 / mat->fontScale() * mat->shift().x(), |
418 | 1.0 / mat->fontScale() * mat->shift().y()); |
419 | memcpy(dest: buf->data() + m_currentUbufOffset, src: &shift, n: 8); |
420 | changed = true; |
421 | } |
422 | |
423 | return changed; |
424 | } |
425 | |
426 | class DistanceFieldAnisotropicShiftedTextMaterialRhiShader : public DistanceFieldShiftedStyleTextMaterialRhiShader |
427 | { |
428 | public: |
429 | DistanceFieldAnisotropicShiftedTextMaterialRhiShader(bool alphaTexture, int viewCount); |
430 | }; |
431 | |
432 | DistanceFieldAnisotropicShiftedTextMaterialRhiShader::DistanceFieldAnisotropicShiftedTextMaterialRhiShader(bool alphaTexture, int viewCount) |
433 | : DistanceFieldShiftedStyleTextMaterialRhiShader(alphaTexture, viewCount) |
434 | { |
435 | setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext.vert.qsb"), viewCount); |
436 | if (alphaTexture) |
437 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_a_fwidth.frag.qsb"), viewCount); |
438 | else |
439 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/distancefieldshiftedtext_fwidth.frag.qsb"), viewCount); |
440 | } |
441 | |
442 | QSGDistanceFieldShiftedStyleTextMaterial::QSGDistanceFieldShiftedStyleTextMaterial() |
443 | : QSGDistanceFieldStyledTextMaterial() |
444 | { |
445 | } |
446 | |
447 | QSGDistanceFieldShiftedStyleTextMaterial::~QSGDistanceFieldShiftedStyleTextMaterial() |
448 | { |
449 | } |
450 | |
451 | QSGMaterialType *QSGDistanceFieldShiftedStyleTextMaterial::type() const |
452 | { |
453 | static QSGMaterialType type; |
454 | return &type; |
455 | } |
456 | |
457 | QSGMaterialShader *QSGDistanceFieldShiftedStyleTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const |
458 | { |
459 | if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported()) |
460 | return new DistanceFieldAnisotropicShiftedTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); |
461 | else |
462 | return new DistanceFieldShiftedStyleTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); |
463 | } |
464 | |
465 | int QSGDistanceFieldShiftedStyleTextMaterial::compare(const QSGMaterial *o) const |
466 | { |
467 | const QSGDistanceFieldShiftedStyleTextMaterial *other = static_cast<const QSGDistanceFieldShiftedStyleTextMaterial *>(o); |
468 | if (m_shift != other->m_shift) |
469 | return &m_shift < &other->m_shift ? -1 : 1; |
470 | return QSGDistanceFieldStyledTextMaterial::compare(o); |
471 | } |
472 | |
473 | class QSGHiQSubPixelDistanceFieldTextMaterialRhiShader : public QSGDistanceFieldTextMaterialRhiShader |
474 | { |
475 | public: |
476 | QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount); |
477 | |
478 | bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
479 | bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, |
480 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override; |
481 | }; |
482 | |
483 | QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount) |
484 | : QSGDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount) |
485 | { |
486 | setFlag(flags: UpdatesGraphicsPipelineState, on: true); |
487 | setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.vert.qsb"), viewCount); |
488 | if (alphaTexture) |
489 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext_a.frag.qsb"), viewCount); |
490 | else |
491 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/hiqsubpixeldistancefieldtext.frag.qsb"), viewCount); |
492 | } |
493 | |
494 | bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateUniformData(RenderState &state, |
495 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
496 | { |
497 | bool changed = QSGDistanceFieldTextMaterialRhiShader::updateUniformData(state, newMaterial, oldMaterial); |
498 | QSGHiQSubPixelDistanceFieldTextMaterial *mat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(newMaterial); |
499 | QSGHiQSubPixelDistanceFieldTextMaterial *oldMat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(oldMaterial); |
500 | |
501 | QByteArray *buf = state.uniformData(); |
502 | Q_ASSERT(buf->size() >= 128); |
503 | |
504 | if (!oldMat || mat->fontScale() != oldMat->fontScale()) { |
505 | float fontScale = mat->fontScale(); |
506 | memcpy(dest: buf->data() + m_currentUbufOffset, src: &fontScale, n: 4); |
507 | changed = true; |
508 | } |
509 | m_currentUbufOffset += 4 + 4; // 4 for padding for vec2 alignment |
510 | |
511 | if (!oldMat || state.isMatrixDirty()) { |
512 | int viewportWidth = state.viewportRect().width(); |
513 | QMatrix4x4 mat = state.combinedMatrix().inverted(); |
514 | QVector4D vecDelta = mat.column(index: 0) * (qreal(2) / viewportWidth); |
515 | memcpy(dest: buf->data() + m_currentUbufOffset, src: &vecDelta, n: 16); |
516 | } |
517 | |
518 | return changed; |
519 | } |
520 | |
521 | bool QSGHiQSubPixelDistanceFieldTextMaterialRhiShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps, |
522 | QSGMaterial *newMaterial, QSGMaterial *oldMaterial) |
523 | { |
524 | Q_UNUSED(state); |
525 | Q_UNUSED(oldMaterial); |
526 | QSGHiQSubPixelDistanceFieldTextMaterial *mat = static_cast<QSGHiQSubPixelDistanceFieldTextMaterial *>(newMaterial); |
527 | |
528 | ps->blendEnable = true; |
529 | ps->srcColor = GraphicsPipelineState::ConstantColor; |
530 | ps->dstColor = GraphicsPipelineState::OneMinusSrcColor; |
531 | |
532 | const QVector4D color = mat->color(); |
533 | // this is dynamic state but it's - magic! - taken care of by the renderer |
534 | ps->blendConstant = QColor::fromRgbF(r: color.x(), g: color.y(), b: color.z(), a: 1.0f); |
535 | |
536 | return true; |
537 | } |
538 | |
539 | QSGMaterialType *QSGHiQSubPixelDistanceFieldTextMaterial::type() const |
540 | { |
541 | static QSGMaterialType type; |
542 | return &type; |
543 | } |
544 | |
545 | QSGMaterialShader *QSGHiQSubPixelDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const |
546 | { |
547 | if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported()) |
548 | return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); |
549 | else |
550 | return new QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); |
551 | } |
552 | |
553 | class QSGLoQSubPixelDistanceFieldTextMaterialRhiShader : public QSGHiQSubPixelDistanceFieldTextMaterialRhiShader |
554 | { |
555 | public: |
556 | QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount); |
557 | }; |
558 | |
559 | QSGLoQSubPixelDistanceFieldTextMaterialRhiShader::QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(bool alphaTexture, int viewCount) |
560 | : QSGHiQSubPixelDistanceFieldTextMaterialRhiShader(alphaTexture, viewCount) |
561 | { |
562 | setShaderFileName(stage: VertexStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.vert.qsb"), viewCount); |
563 | if (alphaTexture) |
564 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext_a.frag.qsb"), viewCount); |
565 | else |
566 | setShaderFileName(stage: FragmentStage, QStringLiteral(":/qt-project.org/scenegraph/shaders_ng/loqsubpixeldistancefieldtext.frag.qsb"), viewCount); |
567 | } |
568 | |
569 | QSGMaterialType *QSGLoQSubPixelDistanceFieldTextMaterial::type() const |
570 | { |
571 | static QSGMaterialType type; |
572 | return &type; |
573 | } |
574 | |
575 | QSGMaterialShader *QSGLoQSubPixelDistanceFieldTextMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const |
576 | { |
577 | if (renderMode == QSGRendererInterface::RenderMode3D && m_glyph_cache->screenSpaceDerivativesSupported()) |
578 | return new DistanceFieldAnisotropicTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); |
579 | else |
580 | return new QSGLoQSubPixelDistanceFieldTextMaterialRhiShader(m_glyph_cache->eightBitFormatIsAlphaSwizzled(), viewCount()); |
581 | } |
582 | |
583 | QT_END_NAMESPACE |
584 |
Definitions
- qt_sg_envFloat
- thresholdFunc
- spreadFunc
- QSGDistanceFieldTextMaterialRhiShader
- QSGDistanceFieldTextMaterialRhiShader
- updateUniformData
- updateSampledImage
- DistanceFieldAnisotropicTextMaterialRhiShader
- DistanceFieldAnisotropicTextMaterialRhiShader
- QSGDistanceFieldTextMaterial
- ~QSGDistanceFieldTextMaterial
- type
- setColor
- createShader
- updateTextureSize
- updateTextureSizeAndWrapper
- compare
- DistanceFieldStyledTextMaterialRhiShader
- DistanceFieldStyledTextMaterialRhiShader
- updateUniformData
- QSGDistanceFieldStyledTextMaterial
- ~QSGDistanceFieldStyledTextMaterial
- setStyleColor
- compare
- DistanceFieldOutlineTextMaterialRhiShader
- DistanceFieldOutlineTextMaterialRhiShader
- DistanceFieldAnisotropicOutlineTextMaterialRhiShader
- DistanceFieldAnisotropicOutlineTextMaterialRhiShader
- updateUniformData
- QSGDistanceFieldOutlineTextMaterial
- ~QSGDistanceFieldOutlineTextMaterial
- type
- createShader
- DistanceFieldShiftedStyleTextMaterialRhiShader
- DistanceFieldShiftedStyleTextMaterialRhiShader
- updateUniformData
- DistanceFieldAnisotropicShiftedTextMaterialRhiShader
- DistanceFieldAnisotropicShiftedTextMaterialRhiShader
- QSGDistanceFieldShiftedStyleTextMaterial
- ~QSGDistanceFieldShiftedStyleTextMaterial
- type
- createShader
- compare
- QSGHiQSubPixelDistanceFieldTextMaterialRhiShader
- QSGHiQSubPixelDistanceFieldTextMaterialRhiShader
- updateUniformData
- updateGraphicsPipelineState
- type
- createShader
- QSGLoQSubPixelDistanceFieldTextMaterialRhiShader
- QSGLoQSubPixelDistanceFieldTextMaterialRhiShader
- type
Learn to use CMake with our Intro Training
Find out more